diff options
author | Mikhail Naganov <mnaganov@chromium.org> | 2014-11-19 22:02:19 +0000 |
---|---|---|
committer | Mikhail Naganov <mnaganov@chromium.org> | 2014-11-19 22:03:23 +0000 |
commit | 3506ad6f4d88fcdd1fae73bc521033017ef580f9 (patch) | |
tree | e379cdfe3ce1659e371f096f1a5da2c3ae9fe0fe | |
parent | 2049bd0db9121a90d94110aff8aa418c8e0e0dbe (diff) | |
download | chromium_src-3506ad6f4d88fcdd1fae73bc521033017ef580f9.zip chromium_src-3506ad6f4d88fcdd1fae73bc521033017ef580f9.tar.gz chromium_src-3506ad6f4d88fcdd1fae73bc521033017ef580f9.tar.bz2 |
[Android WebView] Store HTTP cache in a cache directory
Previously WebView was storing HTTP cache data in the app's data
directory. This change switches to use the directory provided by
Context.getCacheDir(). Also, after starting, WebView cleans up the
old cache directory to save space.
BUG=245549
Review URL: https://codereview.chromium.org/722413002
Cr-Commit-Position: refs/heads/master@{#304670}
(cherry picked from commit d98f8102de3fe1bf53313a64be3fb7cb17040f6a)
Review URL: https://codereview.chromium.org/743753004
Cr-Commit-Position: refs/branch-heads/2214@{#84}
Cr-Branched-From: 03655fd3f6d72165dc3c9bd2c89807305316fe6c-refs/heads/master@{#303346}
9 files changed, 180 insertions, 14 deletions
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index c386ad5..03b44ad 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc @@ -11,7 +11,9 @@ #include "android_webview/browser/jni_dependency_factory.h" #include "android_webview/browser/net/aw_url_request_context_getter.h" #include "android_webview/browser/net/init_native_callback.h" +#include "base/base_paths_android.h" #include "base/bind.h" +#include "base/path_service.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/prefs/pref_service_factory.h" @@ -43,6 +45,14 @@ namespace { void HandleReadError(PersistentPrefStore::PrefReadError error) { } +void DeleteDirRecursively(const base::FilePath& path) { + if (!base::DeleteFile(path, true)) { + // Deleting a non-existent file is considered successful, so this will + // trigger only in case of real errors. + LOG(WARNING) << "Failed to delete " << path.AsUTF8Unsafe(); + } +} + AwBrowserContext* g_browser_context = NULL; } // namespace @@ -50,6 +60,9 @@ AwBrowserContext* g_browser_context = NULL; // Data reduction proxy is disabled by default. bool AwBrowserContext::data_reduction_proxy_enabled_ = false; +// Delete the legacy cache dir (in the app data dir) in 10 seconds after init. +int AwBrowserContext::legacy_cache_removal_delay_ms_ = 10000; + AwBrowserContext::AwBrowserContext( const FilePath path, JniDependencyFactory* native_factory) @@ -102,6 +115,11 @@ void AwBrowserContext::SetDataReductionProxyEnabled(bool enabled) { proxy_settings->SetDataReductionProxyEnabled(data_reduction_proxy_enabled_); } +// static +void AwBrowserContext::SetLegacyCacheRemovalDelayForTest(int delay_ms) { + legacy_cache_removal_delay_ms_ = delay_ms; +} + void AwBrowserContext::PreMainMessageLoopRun() { cookie_store_ = CreateCookieStore(this); data_reduction_proxy_settings_.reset( @@ -127,8 +145,24 @@ void AwBrowserContext::PreMainMessageLoopRun() { data_reduction_proxy_configurator_.get()); } + FilePath cache_path; + const FilePath fallback_cache_dir = + GetPath().Append(FILE_PATH_LITERAL("Cache")); + if (PathService::Get(base::DIR_CACHE, &cache_path)) { + cache_path = cache_path.Append( + FILE_PATH_LITERAL("org.chromium.android_webview")); + // Delay the legacy dir removal to not impact startup performance. + BrowserThread::PostDelayedTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&DeleteDirRecursively, fallback_cache_dir), + base::TimeDelta::FromMilliseconds(legacy_cache_removal_delay_ms_)); + } else { + cache_path = fallback_cache_dir; + LOG(WARNING) << "Failed to get cache directory for Android WebView. " + << "Using app data directory as a fallback."; + } url_request_context_getter_ = - new AwURLRequestContextGetter(GetPath(), + new AwURLRequestContextGetter(cache_path, cookie_store_.get(), data_reduction_proxy_config_service.Pass()); diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h index 3f49765..66ac213 100644 --- a/android_webview/browser/aw_browser_context.h +++ b/android_webview/browser/aw_browser_context.h @@ -65,6 +65,7 @@ class AwBrowserContext : public content::BrowserContext, content::WebContents* web_contents); static void SetDataReductionProxyEnabled(bool enabled); + static void SetLegacyCacheRemovalDelayForTest(int delay_ms); // Maps to BrowserMainParts::PreMainMessageLoopRun. void PreMainMessageLoopRun(); @@ -120,6 +121,10 @@ class AwBrowserContext : public content::BrowserContext, void CreateDataReductionProxyStatisticsIfNecessary(); static bool data_reduction_proxy_enabled_; + // Delay, in milliseconds, before removing the legacy cache dir. + // This is non-const for testing purposes. + static int legacy_cache_removal_delay_ms_; + // The file path where data for this context is persisted. base::FilePath context_storage_path_; diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 1c74bd0..a170e19 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc @@ -175,10 +175,10 @@ scoped_ptr<net::URLRequestJobFactory> CreateJobFactory( } // namespace AwURLRequestContextGetter::AwURLRequestContextGetter( - const base::FilePath& partition_path, net::CookieStore* cookie_store, + const base::FilePath& cache_path, net::CookieStore* cookie_store, scoped_ptr<data_reduction_proxy::DataReductionProxyConfigService> config_service) - : partition_path_(partition_path), + : cache_path_(cache_path), cookie_store_(cookie_store), net_log_(new net::NetLog()) { data_reduction_proxy_config_service_ = config_service.Pass(); @@ -226,7 +226,7 @@ void AwURLRequestContextGetter::InitializeURLRequestContext() { new net::HttpCache::DefaultBackend( net::DISK_CACHE, net::CACHE_BACKEND_SIMPLE, - partition_path_.Append(FILE_PATH_LITERAL("Cache")), + cache_path_, 20 * 1024 * 1024, // 20M BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE))); diff --git a/android_webview/browser/net/aw_url_request_context_getter.h b/android_webview/browser/net/aw_url_request_context_getter.h index 25cfaae..b8afdf8 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.h +++ b/android_webview/browser/net/aw_url_request_context_getter.h @@ -35,7 +35,7 @@ class AwNetworkDelegate; class AwURLRequestContextGetter : public net::URLRequestContextGetter { public: AwURLRequestContextGetter( - const base::FilePath& partition_path, + const base::FilePath& cache_path, net::CookieStore* cookie_store, scoped_ptr<data_reduction_proxy::DataReductionProxyConfigService> config_service); @@ -72,7 +72,7 @@ class AwURLRequestContextGetter : public net::URLRequestContextGetter { void InitializeURLRequestContext(); - const base::FilePath partition_path_; + const base::FilePath cache_path_; scoped_refptr<net::CookieStore> cookie_store_; scoped_ptr<net::NetLog> net_log_; scoped_ptr<net::URLRequestContext> url_request_context_; diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java index a38451d..f13ecac 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java @@ -20,7 +20,8 @@ import java.util.UUID; * Wrapper for the steps needed to initialize the java and native sides of webview chromium. */ public abstract class AwBrowserProcess { - private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "webview"; + public static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "webview"; + private static final String TAG = "AwBrowserProcess"; /** diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java index 7800965..dab4274 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java @@ -81,6 +81,10 @@ public class AwContentsStatics { nativeRegisterCrashHandler(version); } + public static void setLegacyCacheRemovalDelayForTest(long timeoutMs) { + nativeSetLegacyCacheRemovalDelayForTest(timeoutMs); + } + //-------------------------------------------------------------------------------------------- // Native methods //-------------------------------------------------------------------------------------------- @@ -90,4 +94,5 @@ public class AwContentsStatics { private static native String nativeGetUnreachableWebDataUrl(); private static native void nativeSetRecordFullDocument(boolean recordFullDocument); private static native void nativeRegisterCrashHandler(String version); + private static native void nativeSetLegacyCacheRemovalDelayForTest(long timeoutMs); } diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java index 2e2c500..6bcbd44 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java @@ -49,16 +49,20 @@ public class AwTestBase protected void setUp() throws Exception { super.setUp(); if (needsBrowserProcessStarted()) { - final Context context = getActivity(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - AwBrowserProcess.start(context); - } - }); + startBrowserProcess(); } } + protected void startBrowserProcess() throws Exception { + final Context context = getActivity(); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + AwBrowserProcess.start(context); + } + }); + } + /* Override this to return false if the test doesn't want the browser startup sequence to * be run automatically. */ diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java new file mode 100644 index 0000000..8b28508 --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java @@ -0,0 +1,112 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview.test; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.android_webview.AwBrowserProcess; +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.AwContentsStatics; +import org.chromium.base.PathUtils; +import org.chromium.base.test.util.Feature; +import org.chromium.net.test.util.TestWebServer; + +import java.io.File; + +/** + * Test suite for the HTTP cache. + */ +public class HttpCacheTest extends AwTestBase { + + @Override + protected boolean needsBrowserProcessStarted() { + return false; + } + + @SmallTest + @Feature({"AndroidWebView"}) + public void testHttpCacheIsInsideCacheDir() throws Exception { + File webViewCacheDir = new File( + getInstrumentation().getTargetContext().getCacheDir().getPath(), + "org.chromium.android_webview"); + deleteDirectory(webViewCacheDir); + + startBrowserProcess(); + final TestAwContentsClient contentClient = new TestAwContentsClient(); + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentClient); + final AwContents awContents = testContainerView.getAwContents(); + + TestWebServer httpServer = null; + try { + httpServer = TestWebServer.start(); + final String pageUrl = "/page.html"; + final String pageHtml = "<body>Hello, World!</body>"; + final String fullPageUrl = httpServer.setResponse(pageUrl, pageHtml, null); + loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullPageUrl); + assertEquals(1, httpServer.getRequestCount(pageUrl)); + } finally { + if (httpServer != null) { + httpServer.shutdown(); + } + } + + assertTrue(webViewCacheDir.isDirectory()); + assertTrue(webViewCacheDir.list().length > 0); + } + + private void deleteDirectory(File dir) throws Exception { + if (!dir.exists()) + return; + assertTrue(dir.isDirectory()); + Process rmrf = Runtime.getRuntime().exec("rm -rf " + dir.getAbsolutePath()); + rmrf.waitFor(); + assertFalse(dir.exists()); + } + + @SmallTest + @Feature({"AndroidWebView"}) + public void testLegacyHttpCacheDirIsRemovedOnStartup() throws Exception { + PathUtils.setPrivateDataDirectorySuffix(AwBrowserProcess.PRIVATE_DATA_DIRECTORY_SUFFIX); + File webViewLegacyCacheDir = new File( + PathUtils.getDataDirectory(getInstrumentation().getTargetContext()), "Cache"); + if (!webViewLegacyCacheDir.isDirectory()) { + assertTrue(webViewLegacyCacheDir.mkdir()); + assertTrue(webViewLegacyCacheDir.isDirectory()); + } + File dummyCacheFile = File.createTempFile("test", null, webViewLegacyCacheDir); + assertTrue(dummyCacheFile.exists()); + + // Set up JNI bindings. + AwBrowserProcess.loadLibrary(); + // No delay before removing the legacy cache files. + AwContentsStatics.setLegacyCacheRemovalDelayForTest(0); + + startBrowserProcess(); + final TestAwContentsClient contentClient = new TestAwContentsClient(); + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentClient); + final AwContents awContents = testContainerView.getAwContents(); + + // Do some page loading to make sure that FILE thread has processed + // our directory removal task. + TestWebServer httpServer = null; + try { + httpServer = TestWebServer.start(); + final String pageUrl = "/page.html"; + final String pageHtml = "<body>Hello, World!</body>"; + final String fullPageUrl = httpServer.setResponse(pageUrl, pageHtml, null); + loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullPageUrl); + assertEquals(1, httpServer.getRequestCount(pageUrl)); + } finally { + if (httpServer != null) { + httpServer.shutdown(); + } + } + + assertFalse(webViewLegacyCacheDir.exists()); + assertFalse(dummyCacheFile.exists()); + } +} diff --git a/android_webview/native/aw_contents_statics.cc b/android_webview/native/aw_contents_statics.cc index ee61de6..e09fcb8c 100644 --- a/android_webview/native/aw_contents_statics.cc +++ b/android_webview/native/aw_contents_statics.cc @@ -96,6 +96,11 @@ void RegisterCrashHandler(JNIEnv* env, jclass, jstring version) { ConvertJavaStringToUTF8(env, version)); } +// static +void SetLegacyCacheRemovalDelayForTest(JNIEnv*, jclass, jlong delay_ms) { + AwBrowserContext::SetLegacyCacheRemovalDelayForTest(delay_ms); +} + bool RegisterAwContentsStatics(JNIEnv* env) { return RegisterNativesImpl(env); } |