diff options
Diffstat (limited to 'core/java/android/webkit/LoadListener.java')
-rw-r--r-- | core/java/android/webkit/LoadListener.java | 108 |
1 files changed, 69 insertions, 39 deletions
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index 4c17f99..938df95 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -78,7 +78,7 @@ class LoadListener extends Handler implements EventHandler { private static int sNativeLoaderCount; - private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder(8192); + private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder(); private String mUrl; private WebAddress mUri; @@ -104,6 +104,7 @@ class LoadListener extends Handler implements EventHandler { private SslError mSslError; private RequestHandle mRequestHandle; private RequestHandle mSslErrorRequestHandle; + private long mPostIdentifier; // Request data. It is only valid when we are doing a load from the // cache. It is needed if the cache returns a redirect @@ -123,13 +124,13 @@ class LoadListener extends Handler implements EventHandler { // Public functions // ========================================================================= - public static LoadListener getLoadListener( - Context context, BrowserFrame frame, String url, - int nativeLoader, boolean synchronous, boolean isMainPageLoader) { + public static LoadListener getLoadListener(Context context, + BrowserFrame frame, String url, int nativeLoader, + boolean synchronous, boolean isMainPageLoader, long postIdentifier) { sNativeLoaderCount += 1; - return new LoadListener( - context, frame, url, nativeLoader, synchronous, isMainPageLoader); + return new LoadListener(context, frame, url, nativeLoader, synchronous, + isMainPageLoader, postIdentifier); } public static int getNativeLoaderCount() { @@ -137,7 +138,8 @@ class LoadListener extends Handler implements EventHandler { } LoadListener(Context context, BrowserFrame frame, String url, - int nativeLoader, boolean synchronous, boolean isMainPageLoader) { + int nativeLoader, boolean synchronous, boolean isMainPageLoader, + long postIdentifier) { if (DebugFlags.LOAD_LISTENER) { Log.v(LOGTAG, "LoadListener constructor url=" + url); } @@ -150,6 +152,7 @@ class LoadListener extends Handler implements EventHandler { mMessageQueue = new Vector<Message>(); } mIsMainPageLoader = isMainPageLoader; + mPostIdentifier = postIdentifier; } /** @@ -408,9 +411,14 @@ class LoadListener extends Handler implements EventHandler { mStatusCode == HTTP_MOVED_PERMANENTLY || mStatusCode == HTTP_TEMPORARY_REDIRECT) && mNativeLoader != 0) { - if (!mFromCache && mRequestHandle != null) { + // for POST request, only cache the result if there is an identifier + // associated with it. postUrl() or form submission should set the + // identifier while XHR POST doesn't. + if (!mFromCache && mRequestHandle != null + && (!mRequestHandle.getMethod().equals("POST") + || mPostIdentifier != 0)) { mCacheResult = CacheManager.createCacheFile(mUrl, mStatusCode, - headers, mMimeType, false); + headers, mMimeType, mPostIdentifier, false); } if (mCacheResult != null) { mCacheResult.encoding = mEncoding; @@ -522,17 +530,18 @@ class LoadListener extends Handler implements EventHandler { * IMPORTANT: as this is called from network thread, can't call native * directly * XXX: Unlike the other network thread methods, this method can do the - * work of decoding the data and appending it to the data builder because - * mDataBuilder is a thread-safe structure. + * work of decoding the data and appending it to the data builder. */ public void data(byte[] data, int length) { if (DebugFlags.LOAD_LISTENER) { Log.v(LOGTAG, "LoadListener.data(): url: " + url()); } - // Synchronize on mData because commitLoad may write mData to WebCore - // and we don't want to replace mData or mDataLength at the same time - // as a write. + // The reason isEmpty() and append() need to synchronized together is + // because it is possible for getFirstChunk() to be called multiple + // times between isEmpty() and append(). This could cause commitLoad() + // to finish before processing the newly appended data and no message + // will be sent. boolean sendMessage = false; synchronized (mDataBuilder) { sendMessage = mDataBuilder.isEmpty(); @@ -636,7 +645,7 @@ class LoadListener extends Handler implements EventHandler { */ boolean checkCache(Map<String, String> headers) { // Get the cache file name for the current URL - CacheResult result = CacheManager.getCacheFile(url(), + CacheResult result = CacheManager.getCacheFile(url(), mPostIdentifier, headers); // Go ahead and set the cache loader to null in case the result is @@ -861,6 +870,10 @@ class LoadListener extends Handler implements EventHandler { } } + long postIdentifier() { + return mPostIdentifier; + } + void attachRequestHandle(RequestHandle requestHandle) { if (DebugFlags.LOAD_LISTENER) { Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " + @@ -907,8 +920,9 @@ class LoadListener extends Handler implements EventHandler { * be used. This is just for forward/back navigation to a POST * URL. */ - static boolean willLoadFromCache(String url) { - boolean inCache = CacheManager.getCacheFile(url, null) != null; + static boolean willLoadFromCache(String url, long identifier) { + boolean inCache = + CacheManager.getCacheFile(url, identifier, null) != null; if (DebugFlags.LOAD_LISTENER) { Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " + inCache); @@ -1009,28 +1023,34 @@ class LoadListener extends Handler implements EventHandler { if (mIsMainPageLoader) { String type = sCertificateTypeMap.get(mMimeType); if (type != null) { - // In the case of downloading certificate, we will save it to - // the KeyStore and stop the current loading so that it will not - // generate a new history page - byte[] cert = new byte[mDataBuilder.getByteSize()]; - int offset = 0; - while (true) { - ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk(); - if (c == null) break; - - if (c.mLength != 0) { - System.arraycopy(c.mArray, 0, cert, offset, c.mLength); - offset += c.mLength; + // This must be synchronized so that no more data can be added + // after getByteSize returns. + synchronized (mDataBuilder) { + // In the case of downloading certificate, we will save it + // to the KeyStore and stop the current loading so that it + // will not generate a new history page + byte[] cert = new byte[mDataBuilder.getByteSize()]; + int offset = 0; + while (true) { + ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk(); + if (c == null) break; + + if (c.mLength != 0) { + System.arraycopy(c.mArray, 0, cert, offset, c.mLength); + offset += c.mLength; + } + c.release(); } - mDataBuilder.releaseChunk(c); + CertTool.addCertificate(mContext, type, cert); + mBrowserFrame.stopLoading(); + return; } - CertTool.addCertificate(mContext, type, cert); - mBrowserFrame.stopLoading(); - return; } } - // Give the data to WebKit now + // Give the data to WebKit now. We don't have to synchronize on + // mDataBuilder here because pulling each chunk removes it from the + // internal list so it cannot be modified. PerfChecker checker = new PerfChecker(); ByteArrayBuilder.Chunk c; while (true) { @@ -1047,7 +1067,7 @@ class LoadListener extends Handler implements EventHandler { } nativeAddData(c.mArray, c.mLength); } - mDataBuilder.releaseChunk(c); + c.release(); checker.responseAlert("res nativeAddData"); } } @@ -1059,7 +1079,7 @@ class LoadListener extends Handler implements EventHandler { void tearDown() { if (mCacheResult != null) { if (getErrorID() == OK) { - CacheManager.saveCacheFile(mUrl, mCacheResult); + CacheManager.saveCacheFile(mUrl, mPostIdentifier, mCacheResult); } // we need to reset mCacheResult to be null @@ -1187,7 +1207,8 @@ class LoadListener extends Handler implements EventHandler { // Cache the redirect response if (mCacheResult != null) { if (getErrorID() == OK) { - CacheManager.saveCacheFile(mUrl, mCacheResult); + CacheManager.saveCacheFile(mUrl, mPostIdentifier, + mCacheResult); } mCacheResult = null; } @@ -1210,8 +1231,17 @@ class LoadListener extends Handler implements EventHandler { // mRequestHandle can be null when the request was satisfied // by the cache, and the cache returned a redirect if (mRequestHandle != null) { - mRequestHandle.setupRedirect(mUrl, mStatusCode, - mRequestHeaders); + try { + mRequestHandle.setupRedirect(mUrl, mStatusCode, + mRequestHeaders); + } catch(RuntimeException e) { + Log.e(LOGTAG, e.getMessage()); + // Signal a bad url error if we could not load the + // redirection. + handleError(EventHandler.ERROR_BAD_URL, + mContext.getString(R.string.httpErrorBadUrl)); + return; + } } else { // If the original request came from the cache, there is no // RequestHandle, we have to create a new one through |