Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e747dd6 authored by Grace Kloba's avatar Grace Kloba Committed by Android (Google) Code Review
Browse files

Merge "Add a new WebCoreWorker thread to handle the tasks which should not...

Merge "Add a new WebCoreWorker thread to handle the tasks which should not block either UI or WebKit. It handles local file access, cache access and trim cache."
parents 1c63b341 2036dbab
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -189783,7 +189783,7 @@
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 deprecated="deprecated"
 visibility="public"
>
</method>
@@ -189835,7 +189835,7 @@
 synchronized="false"
 static="true"
 final="false"
 deprecated="not deprecated"
 deprecated="deprecated"
 visibility="public"
>
</method>
+2 −1
Original line number Diff line number Diff line
@@ -407,7 +407,8 @@ class BrowserFrame extends Handler {
                        }
                    }
                }
                CacheManager.trimCacheIfNeeded();
                WebViewWorker.getHandler().sendEmptyMessage(
                        WebViewWorker.MSG_TRIM_CACHE);
                break;
            }

+63 −29
Original line number Diff line number Diff line
@@ -25,10 +25,11 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@@ -200,9 +201,9 @@ public final class CacheManager {
            // the cache database. The directory could be recreated
            // because the system flushed all the data/cache directories
            // to free up disk space.
            WebViewCore.endCacheTransaction();
            mDataBase.clearCache();
            WebViewCore.startCacheTransaction();
            // delete rows in the cache database
            WebViewWorker.getHandler().sendEmptyMessage(
                    WebViewWorker.MSG_CLEAR_CACHE);
            return true;
        }
        return false;
@@ -223,7 +224,6 @@ public final class CacheManager {
     * 
     * @param disabled true to disable the cache
     */
    // only called from WebCore thread
    static void setCacheDisabled(boolean disabled) {
        if (disabled == mDisabled) {
            return;
@@ -243,7 +243,7 @@ public final class CacheManager {
        return mDisabled;
    }

    // only called from WebCore thread
    // only called from WebViewWorkerThread
    // make sure to call enableTransaction/disableTransaction in pair
    static boolean enableTransaction() {
        if (++mRefCount == 1) {
@@ -253,12 +253,9 @@ public final class CacheManager {
        return false;
    }

    // only called from WebCore thread
    // only called from WebViewWorkerThread
    // make sure to call enableTransaction/disableTransaction in pair
    static boolean disableTransaction() {
        if (mRefCount == 0) {
            Log.e(LOGTAG, "disableTransaction is out of sync");
        }
        if (--mRefCount == 0) {
            mDataBase.endCacheTransaction();
            return true;
@@ -266,15 +263,15 @@ public final class CacheManager {
        return false;
    }

    // only called from WebCore thread
    // make sure to call startCacheTransaction/endCacheTransaction in pair
    public static boolean startCacheTransaction() {
    // only called from WebViewWorkerThread
    // make sure to call startTransaction/endTransaction in pair
    static boolean startTransaction() {
        return mDataBase.startCacheTransaction();
    }

    // only called from WebCore thread
    // make sure to call startCacheTransaction/endCacheTransaction in pair
    public static boolean endCacheTransaction() {
    // only called from WebViewWorkerThread
    // make sure to call startTransaction/endTransaction in pair
    static boolean endTransaction() {
        boolean ret = mDataBase.endCacheTransaction();
        if (++mTrimCacheCount >= TRIM_CACHE_INTERVAL) {
            mTrimCacheCount = 0;
@@ -283,6 +280,26 @@ public final class CacheManager {
        return ret;
    }

    // only called from WebCore Thread
    // make sure to call startCacheTransaction/endCacheTransaction in pair
    /**
     * @deprecated
     */
    @Deprecated
    public static boolean startCacheTransaction() {
        return false;
    }

    // only called from WebCore Thread
    // make sure to call startCacheTransaction/endCacheTransaction in pair
    /**
     * @deprecated
     */
    @Deprecated
    public static boolean endCacheTransaction() {
        return false;
    }

    /**
     * Given a url, returns the CacheResult if exists. Otherwise returns null.
     * If headers are provided and a cache needs validation,
@@ -291,13 +308,11 @@ public final class CacheManager {
     * 
     * @return the CacheResult for a given url
     */
    // only called from WebCore thread
    public static CacheResult getCacheFile(String url,
            Map<String, String> headers) {
        return getCacheFile(url, 0, headers);
    }

    // only called from WebCore thread
    static CacheResult getCacheFile(String url, long postIdentifier,
            Map<String, String> headers) {
        if (mDisabled) {
@@ -368,14 +383,12 @@ public final class CacheManager {
     * @hide - hide createCacheFile since it has a parameter of type headers, which is
     * in a hidden package.
     */
    // only called from WebCore thread
    public static CacheResult createCacheFile(String url, int statusCode,
            Headers headers, String mimeType, boolean forceCache) {
        return createCacheFile(url, statusCode, headers, mimeType, 0,
                forceCache);
    }

    // only called from WebCore thread
    static CacheResult createCacheFile(String url, int statusCode,
            Headers headers, String mimeType, long postIdentifier,
            boolean forceCache) {
@@ -435,12 +448,10 @@ public final class CacheManager {
     * Save the info of a cache file for a given url to the CacheMap so that it
     * can be reused later
     */
    // only called from WebCore thread
    public static void saveCacheFile(String url, CacheResult cacheRet) {
        saveCacheFile(url, 0, cacheRet);
    }

    // only called from WebCore thread
    static void saveCacheFile(String url, long postIdentifier,
            CacheResult cacheRet) {
        try {
@@ -489,7 +500,6 @@ public final class CacheManager {
     * 
     * @return true if it succeeds
     */
    // only called from WebCore thread
    static boolean removeAllCacheFiles() {
        // Note, this is called before init() when the database is
        // created or upgraded.
@@ -499,7 +509,10 @@ public final class CacheManager {
            mClearCacheOnInit = true;
            return true;
        }
        // delete cache in a separate thread to not block UI.
        // delete rows in the cache database
        WebViewWorker.getHandler().sendEmptyMessage(
                WebViewWorker.MSG_CLEAR_CACHE);
        // delete cache files in a separate thread to not block UI.
        final Runnable clearCache = new Runnable() {
            public void run() {
                // delete all cache files
@@ -517,8 +530,6 @@ public final class CacheManager {
                } catch (SecurityException e) {
                    // Ignore SecurityExceptions.
                }
                // delete database
                mDataBase.clearCache();
            }
        };
        new Thread(clearCache).start();
@@ -528,15 +539,13 @@ public final class CacheManager {
    /**
     * Return true if the cache is empty.
     */
    // only called from WebCore thread
    static boolean cacheEmpty() {
        return mDataBase.hasCache();
    }

    // only called from WebCore thread
    static void trimCacheIfNeeded() {
        if (mDataBase.getCacheTotalSize() > CACHE_THRESHOLD) {
            ArrayList<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
            List<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
            int size = pathList.size();
            for (int i = 0; i < size; i++) {
                File f = new File(mBaseDir, pathList.get(i));
@@ -544,9 +553,34 @@ public final class CacheManager {
                    Log.e(LOGTAG, f.getPath() + " delete failed.");
                }
            }
            // remove the unreferenced files in the cache directory
            final List<String> fileList = mDataBase.getAllCacheFileNames();
            if (fileList == null) return;
            String[] toDelete = mBaseDir.list(new FilenameFilter() {
                public boolean accept(File dir, String filename) {
                    if (fileList.contains(filename)) {
                        return false;
                    } else {
                        return true;
                    }
                }
            });
            if (toDelete == null) return;
            size = toDelete.length;
            for (int i = 0; i < size; i++) {
                File f = new File(mBaseDir, toDelete[i]);
                if (!f.delete()) {
                    Log.e(LOGTAG, f.getPath() + " delete failed.");
                }
            }
        }
    }

    static void clearCache() {
        // delete database
        mDataBase.clearCache();
    }

    private static boolean checkCacheRedirect(int statusCode) {
        if (statusCode == 301 || statusCode == 302 || statusCode == 307) {
            // as 303 can't be cached, we do not return true
+24 −11
Original line number Diff line number Diff line
@@ -110,7 +110,9 @@ class FrameLoader {
                return false;
            }
            mNetwork = Network.getInstance(mListener.getContext());
            return handleHTTPLoad();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_HTTPLOADER, this).sendToTarget();
            return true;
        } else if (handleLocalFile(url, mListener, mSettings)) {
            return true;
        }
@@ -142,24 +144,33 @@ class FrameLoader {
        }
        if (URLUtil.isAssetUrl(url)) {
            // load asset in a separate thread as it involves IO
            new FileLoader(url, loadListener, FileLoader.TYPE_ASSET, true)
                    .enqueue();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_STREAMLOADER,
                    new FileLoader(url, loadListener, FileLoader.TYPE_ASSET,
                            true)).sendToTarget();
            return true;
        } else if (URLUtil.isResourceUrl(url)) {
            // load resource in a separate thread as it involves IO
            new FileLoader(url, loadListener, FileLoader.TYPE_RES, true)
                    .enqueue();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_STREAMLOADER,
                    new FileLoader(url, loadListener, FileLoader.TYPE_RES,
                            true)).sendToTarget();
            return true;
        } else if (URLUtil.isFileUrl(url)) {
            // load file in a separate thread as it involves IO
            new FileLoader(url, loadListener, FileLoader.TYPE_FILE, settings
                    .getAllowFileAccess()).enqueue();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_STREAMLOADER,
                    new FileLoader(url, loadListener, FileLoader.TYPE_FILE,
                            settings.getAllowFileAccess())).sendToTarget();
            return true;
        } else if (URLUtil.isContentUrl(url)) {
            // Send the raw url to the ContentLoader because it will do a
            // permission check and the url has to match.
            // load content in a separate thread as it involves IO
            new ContentLoader(loadListener.url(), loadListener).enqueue();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_ADD_STREAMLOADER,
                    new ContentLoader(loadListener.url(), loadListener))
                    .sendToTarget();
            return true;
        } else if (URLUtil.isDataUrl(url)) {
            // load data in the current thread to reduce the latency
@@ -173,7 +184,7 @@ class FrameLoader {
        return false;
    }

    private boolean handleHTTPLoad() {
    boolean handleHTTPLoad() {
        if (mHeaders == null) {
            mHeaders = new HashMap<String, String>();
        }
@@ -229,7 +240,9 @@ class FrameLoader {
        CacheLoader cacheLoader =
                new CacheLoader(mListener, result);
        mListener.setCacheLoader(cacheLoader);
        cacheLoader.load();
        // Load the cached file in a separate thread
        WebViewWorker.getHandler().obtainMessage(
                WebViewWorker.MSG_ADD_STREAMLOADER, cacheLoader).sendToTarget();
    }

    /*
+58 −60
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ class LoadListener extends Handler implements EventHandler {
    private boolean  mCancelled;  // The request has been cancelled.
    private boolean  mAuthFailed;  // indicates that the prev. auth failed
    private CacheLoader mCacheLoader;
    private CacheManager.CacheResult mCacheResult;
    private boolean  mFromCache = false;
    private HttpAuthHeader mAuthHeader;
    private int      mErrorID = OK;
@@ -301,6 +300,12 @@ class LoadListener extends Handler implements EventHandler {
     */
    public void headers(Headers headers) {
        if (DebugFlags.LOAD_LISTENER) Log.v(LOGTAG, "LoadListener.headers");
        // call db (setCookie) in the non-WebCore thread
        if (mCancelled) return;
        ArrayList<String> cookies = headers.getSetCookie();
        for (int i = 0; i < cookies.size(); ++i) {
            CookieManager.getInstance().setCookie(mUri, cookies.get(i));
        }
        sendMessageInternal(obtainMessage(MSG_CONTENT_HEADERS, headers));
    }

@@ -316,11 +321,6 @@ class LoadListener extends Handler implements EventHandler {
        if (mCancelled) return;
        mHeaders = headers;

        ArrayList<String> cookies = headers.getSetCookie();
        for (int i = 0; i < cookies.size(); ++i) {
            CookieManager.getInstance().setCookie(mUri, cookies.get(i));
        }

        long contentLength = headers.getContentLength();
        if (contentLength != Headers.NO_CONTENT_LENGTH) {
            mContentLength = contentLength;
@@ -454,12 +454,19 @@ class LoadListener extends Handler implements EventHandler {
            if (!mFromCache && mRequestHandle != null
                    && (!mRequestHandle.getMethod().equals("POST")
                            || mPostIdentifier != 0)) {
                mCacheResult = CacheManager.createCacheFile(mUrl, mStatusCode,
                        headers, mMimeType, mPostIdentifier, false);
            }
            if (mCacheResult != null) {
                mCacheResult.encoding = mEncoding;
            }
                WebViewWorker.CacheCreateData data = new WebViewWorker.CacheCreateData();
                data.mListener = this;
                data.mUrl = mUrl;
                data.mMimeType = mMimeType;
                data.mStatusCode = mStatusCode;
                data.mPostId = mPostIdentifier;
                data.mHeaders = headers;
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_CREATE_CACHE, data).sendToTarget();
            }
            WebViewWorker.CacheEncoding ce = new WebViewWorker.CacheEncoding();
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_UPDATE_CACHE_ENCODING, ce).sendToTarget();
        }
        commitHeadersCheckRedirect();
    }
@@ -649,7 +656,10 @@ class LoadListener extends Handler implements EventHandler {
                // ask for it, so make sure we have a valid CacheLoader
                // before calling it.
                if (mCacheLoader != null) {
                    mCacheLoader.load();
                    // Load the cached file in a separate thread
                    WebViewWorker.getHandler().obtainMessage(
                            WebViewWorker.MSG_ADD_STREAMLOADER, mCacheLoader)
                            .sendToTarget();
                    mFromCache = true;
                    if (DebugFlags.LOAD_LISTENER) {
                        Log.v(LOGTAG, "LoadListener cache load url=" + url());
@@ -708,8 +718,10 @@ class LoadListener extends Handler implements EventHandler {
                    Log.v(LOGTAG, "FrameLoader: HTTP URL in cache " +
                            "and usable: " + url());
                }
                // Load the cached file
                mCacheLoader.load();
                // Load the cached file in a separate thread
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_ADD_STREAMLOADER, mCacheLoader)
                        .sendToTarget();
                mFromCache = true;
                return true;
            }
@@ -934,12 +946,9 @@ class LoadListener extends Handler implements EventHandler {
     * WebCore.
     */
    void downloadFile() {
        // Setting the Cache Result to null ensures that this
        // content is not added to the cache
        if (mCacheResult != null) {
            CacheManager.cleanupCacheFile(mCacheResult);
            mCacheResult = null;
        }
        // remove the cache
        WebViewWorker.getHandler().obtainMessage(
                WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();

        // Inform the client that they should download a file
        mBrowserFrame.getCallbackProxy().onDownloadStart(url(), 
@@ -1098,24 +1107,15 @@ class LoadListener extends Handler implements EventHandler {
            if (c == null) break;

            if (c.mLength != 0) {
                if (mCacheResult != null) {
                    mCacheResult.contentLength += c.mLength;
                    if (mCacheResult.contentLength > CacheManager.CACHE_MAX_SIZE) {
                        CacheManager.cleanupCacheFile(mCacheResult);
                        mCacheResult = null;
                    } else {
                        try {
                            mCacheResult.outStream
                                    .write(c.mArray, 0, c.mLength);
                        } catch (IOException e) {
                            CacheManager.cleanupCacheFile(mCacheResult);
                            mCacheResult = null;
                        }
                    }
                }
                nativeAddData(c.mArray, c.mLength);
            }
                WebViewWorker.CacheData data = new WebViewWorker.CacheData();
                data.mListener = this;
                data.mChunk = c;
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_APPEND_CACHE, data).sendToTarget();
            } else {
                c.release();
            }
            checker.responseAlert("res nativeAddData");
        }
    }
@@ -1125,18 +1125,16 @@ class LoadListener extends Handler implements EventHandler {
     * cancellation or errors during the load.
     */
    void tearDown() {
        if (mCacheResult != null) {
        if (getErrorID() == OK) {
                CacheManager.saveCacheFile(mUrl, mPostIdentifier, mCacheResult);
            WebViewWorker.CacheSaveData data = new WebViewWorker.CacheSaveData();
            data.mListener = this;
            data.mUrl = mUrl;
            data.mPostId = mPostIdentifier;
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_SAVE_CACHE, data).sendToTarget();
        } else {
                CacheManager.cleanupCacheFile(mCacheResult);
            }

            // we need to reset mCacheResult to be null
            // resource loader's tearDown will call into WebCore's
            // nativeFinish, which in turn calls loader.cancel().
            // If we don't reset mCacheFile, the file will be deleted.
            mCacheResult = null;
            WebViewWorker.getHandler().obtainMessage(
                    WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
        }
        if (mNativeLoader != 0) {
            PerfChecker checker = new PerfChecker();
@@ -1194,10 +1192,8 @@ class LoadListener extends Handler implements EventHandler {
            mRequestHandle = null;
        }

        if (mCacheResult != null) {
            CacheManager.cleanupCacheFile(mCacheResult);
            mCacheResult = null;
        }
        WebViewWorker.getHandler().obtainMessage(
                WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
        mCancelled = true;

        clearNativeLoader();
@@ -1258,14 +1254,16 @@ class LoadListener extends Handler implements EventHandler {
            }

            // Cache the redirect response
            if (mCacheResult != null) {
            if (getErrorID() == OK) {
                    CacheManager.saveCacheFile(mUrl, mPostIdentifier,
                            mCacheResult);
                WebViewWorker.CacheSaveData data = new WebViewWorker.CacheSaveData();
                data.mListener = this;
                data.mUrl = mUrl;
                data.mPostId = mPostIdentifier;
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_SAVE_CACHE, data).sendToTarget();
            } else {
                    CacheManager.cleanupCacheFile(mCacheResult);
                }
                mCacheResult = null;
                WebViewWorker.getHandler().obtainMessage(
                        WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
            }

            // This will strip the anchor
Loading