WebCacheManager::ClearCacheOnNavigation() is used by webrequest api, which will be moved to //extensions. So we need to resolve its the dependency on WebCacheManager by moving WebCacheManager to //components.

There are two ipc messages sent in WebCacheManger:
-ChromeViewMsg_SetCacheCapacities
-ChromeViewMsg_ClearCache

Both ipc handlers were in ChromeRenderProcessObserver. These two ipcs are renamed as WebCacheMsg_XXX, and we introduce WebCacheRenderProcessObserver and handle these ipcs in //components.

BUG=352293,411437
[email protected]

Review URL: https://codereview.chromium.org/528363002

Cr-Commit-Position: refs/heads/master@{#294475}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7bcdff3a..411d9bcf 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -156,6 +156,7 @@
       "//components/url_matcher",
       "//components/visitedlink/browser",
       "//components/visitedlink/common",
+      "//components/web_cache/browser",
       "//components/web_modal",
       "//content/app/resources",
       "//media",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index c26cb58..70d74985 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -73,6 +73,7 @@
   "+components/user_manager",
   "+components/user_prefs",
   "+components/web_modal",
+  "+components/web_cache/browser",
   "+components/webdata/common",
   "+content/public/browser",
   "+content/test/net",
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index aa77030..401a6334 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/sessions/session_service.h"
@@ -50,6 +49,7 @@
 #include "components/nacl/browser/pnacl_host.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "content/public/browser/download_manager.h"
@@ -571,7 +571,7 @@
 
   if (remove_mask & REMOVE_CACHE) {
     // Tell the renderers to clear their cache.
-    WebCacheManager::GetInstance()->ClearCache();
+    web_cache::WebCacheManager::GetInstance()->ClearCache();
 
     // Invoke DoClearCache on the IO thread.
     waiting_for_clear_cache_ = true;
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
index 26f1ef6..38b176048 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "extensions/browser/extension_system.h"
@@ -42,7 +42,7 @@
 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies;
 
 void ClearCacheOnNavigationOnUI() {
-  WebCacheManager::GetInstance()->ClearCacheOnNavigation();
+  web_cache::WebCacheManager::GetInstance()->ClearCacheOnNavigation();
 }
 
 bool ParseCookieLifetime(net::ParsedCookie* cookie,
diff --git a/chrome/browser/extensions/api/web_request/web_request_time_tracker.cc b/chrome/browser/extensions/api/web_request/web_request_time_tracker.cc
index 0c7094a7..5daeaa40 100644
--- a/chrome/browser/extensions/api/web_request/web_request_time_tracker.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_time_tracker.cc
@@ -7,13 +7,8 @@
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/metrics/histogram.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "content/public/browser/browser_thread.h"
 #include "extensions/browser/warning_set.h"
 
-using content::BrowserThread;
 
 // TODO(mpcomplete): tweak all these constants.
 namespace {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 6f928e27..2dc4c325e 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -57,7 +57,6 @@
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/services/gcm/gcm_profile_service.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -261,7 +260,6 @@
   SigninManagerFactory::RegisterPrefs(registry);
   SSLConfigServiceManager::RegisterPrefs(registry);
   UpgradeDetector::RegisterPrefs(registry);
-  WebCacheManager::RegisterPrefs(registry);
 
 #if defined(ENABLE_AUTOFILL_DIALOG)
   autofill::AutofillDialogController::RegisterPrefs(registry);
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index c0e66d4..8c68b319 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -16,9 +16,9 @@
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/common/extensions/api/i18n/default_locale_handler.h"
 #include "chrome/common/render_messages.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 
@@ -134,7 +134,8 @@
 
 void ChromeRenderMessageFilter::OnUpdatedCacheStats(
     const WebCache::UsageStats& stats) {
-  WebCacheManager::GetInstance()->ObserveStats(render_process_id_, stats);
+  web_cache::WebCacheManager::GetInstance()->ObserveStats(
+      render_process_id_, stats);
 }
 
 void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated,
diff --git a/chrome/browser/renderer_host/web_cache_manager_browsertest.cc b/chrome/browser/renderer_host/web_cache_manager_browsertest.cc
deleted file mode 100644
index 7caee2f..0000000
--- a/chrome/browser/renderer_host/web_cache_manager_browsertest.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include <string>
-
-#include "base/message_loop/message_loop.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/result_codes.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using content::WebContents;
-
-class WebCacheManagerBrowserTest : public InProcessBrowserTest {
-};
-
-// Regression test for http://crbug.com/12362.  If a renderer crashes and the
-// user navigates to another tab and back, the browser doesn't crash.
-IN_PROC_BROWSER_TEST_F(WebCacheManagerBrowserTest, CrashOnceOnly) {
-  const base::FilePath kTestDir(FILE_PATH_LITERAL("google"));
-  const base::FilePath kTestFile(FILE_PATH_LITERAL("google.html"));
-  GURL url(ui_test_utils::GetTestUrl(kTestDir, kTestFile));
-
-  ui_test_utils::NavigateToURL(browser(), url);
-
-  chrome::NewTab(browser());
-  ui_test_utils::NavigateToURL(browser(), url);
-
-  WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(0);
-  ASSERT_TRUE(tab != NULL);
-  base::KillProcess(tab->GetRenderProcessHost()->GetHandle(),
-                    content::RESULT_CODE_KILLED, true);
-
-  browser()->tab_strip_model()->ActivateTabAt(0, true);
-  chrome::NewTab(browser());
-  ui_test_utils::NavigateToURL(browser(), url);
-
-  browser()->tab_strip_model()->ActivateTabAt(0, true);
-  chrome::NewTab(browser());
-  ui_test_utils::NavigateToURL(browser(), url);
-
-  // We would have crashed at the above line with the bug.
-
-  browser()->tab_strip_model()->ActivateTabAt(0, true);
-  chrome::CloseTab(browser());
-  browser()->tab_strip_model()->ActivateTabAt(0, true);
-  chrome::CloseTab(browser());
-  browser()->tab_strip_model()->ActivateTabAt(0, true);
-  chrome::CloseTab(browser());
-
-  ui_test_utils::NavigateToURL(browser(), url);
-
-  // Depending on the speed of execution of the unload event, we may have one or
-  // two active renderers at that point (one executing the unload event in
-  // background).
-  EXPECT_GE(WebCacheManager::GetInstance()->active_renderers_.size(), 1U);
-  EXPECT_LE(WebCacheManager::GetInstance()->active_renderers_.size(), 2U);
-  EXPECT_EQ(
-      WebCacheManager::GetInstance()->inactive_renderers_.size(), 0U);
-  EXPECT_GE(WebCacheManager::GetInstance()->stats_.size(), 1U);
-  EXPECT_LE(WebCacheManager::GetInstance()->stats_.size(), 2U);
-}
diff --git a/chrome/browser/task_manager/task_manager.h b/chrome/browser/task_manager/task_manager.h
index 082b9c9..eb5dce9 100644
--- a/chrome/browser/task_manager/task_manager.h
+++ b/chrome/browser/task_manager/task_manager.h
@@ -16,7 +16,6 @@
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/task_manager/resource_provider.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "content/public/common/gpu_memory_stats.h"
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc
index 466001e..ee360e9 100644
--- a/chrome/browser/ui/tab_contents/core_tab_helper.cc
+++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
@@ -21,6 +20,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -145,7 +145,7 @@
 }
 
 void CoreTabHelper::WasShown() {
-  WebCacheManager::GetInstance()->ObserveActivity(
+  web_cache::WebCacheManager::GetInstance()->ObserveActivity(
       web_contents()->GetRenderProcessHost()->GetID());
 }
 
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 448cc90..12cd53e 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1045,8 +1045,6 @@
       'browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm',
       'browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc',
       'browser/renderer_host/chrome_resource_dispatcher_host_delegate.h',
-      'browser/renderer_host/web_cache_manager.cc',
-      'browser/renderer_host/web_cache_manager.h',
       'browser/renderer_preferences_util.cc',
       'browser/renderer_preferences_util.h',
       'browser/resources_util.cc',
@@ -2879,6 +2877,7 @@
             '../components/components.gyp:url_matcher',
             '../components/components.gyp:visitedlink_browser',
             '../components/components.gyp:visitedlink_common',
+            '../components/components.gyp:web_cache_browser',
             '../components/components.gyp:web_modal',
             '../content/app/resources/content_resources.gyp:content_resources',
             '../media/cast/cast.gyp:cast_net',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 6176b2f..d840a3e 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -283,6 +283,7 @@
         '../components/components.gyp:translate_core_common',
         '../components/components.gyp:translate_core_language_detection',
         '../components/components.gyp:visitedlink_renderer',
+        '../components/components.gyp:web_cache_renderer',
         '../content/app/resources/content_resources.gyp:content_resources',
         '../content/app/strings/content_strings.gyp:content_strings',
         '../content/content.gyp:content_renderer',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index b904d85d..27db0cd 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -863,15 +863,6 @@
         '../apps/app_shim/test/app_shim_host_manager_test_api_mac.cc',
         '../apps/app_shim/test/app_shim_host_manager_test_api_mac.h',
         '../apps/load_and_launch_browsertest.cc',
-        '../extensions/browser/api/cast_channel/cast_channel_apitest.cc',
-        '../extensions/browser/api/serial/serial_apitest.cc',
-        '../extensions/browser/api/usb/usb_apitest.cc',
-        '../extensions/browser/api/usb/usb_manual_apitest.cc',
-        '../extensions/browser/app_window/app_window_browsertest.cc',
-        '../extensions/browser/guest_view/extension_options/extension_options_apitest.cc',
-        '../extensions/browser/test_extension_registry_observer.h',
-        '../extensions/browser/test_extension_registry_observer.cc',
-        '../extensions/renderer/script_context_browsertest.cc',
         # TODO(blundell): Bring up a components_browsertests target and move
         # this test to be in that target. crbug.com/283846
         '../components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc',
@@ -885,7 +876,16 @@
         '../extensions/browser/api/bluetooth/bluetooth_private_apitest.cc',
         '../extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc',
         '../extensions/browser/api/bluetooth_socket/bluetooth_socket_apitest.cc',
+        '../extensions/browser/api/cast_channel/cast_channel_apitest.cc',
         '../extensions/browser/api/runtime/runtime_apitest.cc',
+        '../extensions/browser/api/serial/serial_apitest.cc',
+        '../extensions/browser/api/usb/usb_apitest.cc',
+        '../extensions/browser/api/usb/usb_manual_apitest.cc',
+        '../extensions/browser/app_window/app_window_browsertest.cc',
+        '../extensions/browser/guest_view/extension_options/extension_options_apitest.cc',
+        '../extensions/browser/test_extension_registry_observer.h',
+        '../extensions/browser/test_extension_registry_observer.cc',
+        '../extensions/renderer/script_context_browsertest.cc',
         'app/chrome_command_ids.h',
         'app/chrome_dll.rc',
         'app/chrome_dll_resource.h',
@@ -1357,7 +1357,6 @@
         'browser/renderer_context_menu/spelling_menu_observer_browsertest.cc',
         'browser/renderer_host/chrome_resource_dispatcher_host_delegate_browsertest.cc',
         'browser/renderer_host/render_process_host_chrome_browsertest.cc',
-        'browser/renderer_host/web_cache_manager_browsertest.cc',
         'browser/repost_form_warning_browsertest.cc',
         'browser/resources/pdf/pdf_extension_test.cc',
         'browser/safe_browsing/local_safebrowsing_test_server.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 0a75fec..04f112a1cf7 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1164,7 +1164,6 @@
         'browser/renderer_context_menu/render_view_context_menu_test_util.cc',
         'browser/renderer_context_menu/render_view_context_menu_test_util.h',
         'browser/renderer_context_menu/render_view_context_menu_unittest.cc',
-        'browser/renderer_host/web_cache_manager_unittest.cc',
         'browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm',
         'browser/resources/chromeos/braille_ime/braille_ime.js',
         'browser/resources/chromeos/braille_ime/braille_ime_unittest.gtestjs',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 33ead5e..02fa6bd 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1417,10 +1417,6 @@
 // manager window to restore on startup.
 const char kTaskManagerWindowPlacement[] = "task_manager.window_placement";
 
-// An integer specifying the total number of bytes to be used by the
-// renderer's in-memory cache of objects.
-const char kMemoryCacheSize[] = "renderer.memory_cache.size";
-
 // String which specifies where to download files to by default.
 const char kDownloadDefaultDirectory[] = "download.default_directory";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 8b03da3..be3eadd0 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -468,7 +468,6 @@
 extern const char kBrowserWindowPlacement[];
 extern const char kBrowserWindowPlacementPopup[];
 extern const char kTaskManagerWindowPlacement[];
-extern const char kMemoryCacheSize[];
 
 extern const char kDownloadDefaultDirectory[];
 extern const char kDownloadExtensionsToOpen[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 1b085c99..0ff98888 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -191,16 +191,6 @@
 // RenderView messages
 // These are messages sent from the browser to the renderer process.
 
-// Tells the renderer to set its maximum cache size to the supplied value.
-IPC_MESSAGE_CONTROL3(ChromeViewMsg_SetCacheCapacities,
-                     size_t /* min_dead_capacity */,
-                     size_t /* max_dead_capacity */,
-                     size_t /* capacity */)
-
-// Tells the renderer to clear the cache.
-IPC_MESSAGE_CONTROL1(ChromeViewMsg_ClearCache,
-                     bool /* on_navigation */)
-
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 // For WebUI testing, this message requests JavaScript to be executed at a time
 // which is late enough to not be thrown out, and early enough to be before
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 33b1183b..1751d912 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -46,6 +46,7 @@
     "//components/translate/core/common",
     "//components/translate/core/language_detection",
     "//components/visitedlink/renderer",
+    "//components/web_cache/renderer",
     "//content/app/resources",
     "//content/app/strings",
     "//content/public/renderer",
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index 627c0a4..ee4ec44 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -20,6 +20,7 @@
   "+components/translate/core/common",
   "+components/translate/core/language_detection",
   "+components/visitedlink/renderer",
+  "+components/web_cache/renderer",
   "+content/app/resources/grit",  # For generated headers
   "+content/app/strings/grit",  # For generated headers
   "+content/public/child",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 367426a..e32b350 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -79,6 +79,7 @@
 #include "components/plugins/renderer/mobile_youtube_plugin.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/visitedlink/renderer/visitedlink_slave.h"
+#include "components/web_cache/renderer/web_cache_render_process_observer.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
@@ -287,6 +288,7 @@
   RenderThread* thread = RenderThread::Get();
 
   chrome_observer_.reset(new ChromeRenderProcessObserver(this));
+  web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver());
 
   extension_dispatcher_delegate_.reset(
       new ChromeExtensionsDispatcherDelegate());
@@ -321,6 +323,7 @@
   search_bouncer_.reset(new SearchBouncer());
 
   thread->AddObserver(chrome_observer_.get());
+  thread->AddObserver(web_cache_observer_.get());
   thread->AddObserver(extension_dispatcher_.get());
 #if defined(FULL_SAFE_BROWSING)
   thread->AddObserver(phishing_classifier_.get());
@@ -502,7 +505,7 @@
   if (command_line->HasSwitch(switches::kInstantProcess))
     new SearchBox(render_view);
 
-  new ChromeRenderViewObserver(render_view, chrome_observer_.get());
+  new ChromeRenderViewObserver(render_view, web_cache_observer_.get());
 
   new password_manager::CredentialManagerClient(render_view);
 }
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index c8792c1..7adff92 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -54,6 +54,10 @@
 class VisitedLinkSlave;
 }
 
+namespace web_cache {
+class WebCacheRenderProcessObserver;
+}
+
 namespace blink {
 class WebSecurityOrigin;
 }
@@ -196,6 +200,7 @@
                             blink::WebPluginParams* params);
 
   scoped_ptr<ChromeRenderProcessObserver> chrome_observer_;
+  scoped_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
   scoped_ptr<ChromeExtensionsDispatcherDelegate> extension_dispatcher_delegate_;
   scoped_ptr<extensions::Dispatcher> extension_dispatcher_;
   scoped_ptr<extensions::RendererPermissionsPolicyDelegate>
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc
index ed483c95..b9a4763 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -57,7 +57,6 @@
 namespace {
 
 const int kCacheStatsDelayMS = 2000;
-const size_t kUnitializedCacheCapacity = UINT_MAX;
 
 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
  public:
@@ -248,11 +247,7 @@
 ChromeRenderProcessObserver::ChromeRenderProcessObserver(
     ChromeContentRendererClient* client)
     : client_(client),
-      clear_cache_pending_(false),
-      webkit_initialized_(false),
-      pending_cache_min_dead_capacity_(0),
-      pending_cache_max_dead_capacity_(0),
-      pending_cache_capacity_(kUnitializedCacheCapacity) {
+      webkit_initialized_(false) {
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
 
 #if defined(ENABLE_AUTOFILL_DIALOG)
@@ -305,8 +300,6 @@
   IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
                         OnSetIsIncognitoProcess)
-    IPC_MESSAGE_HANDLER(ChromeViewMsg_SetCacheCapacities, OnSetCacheCapacities)
-    IPC_MESSAGE_HANDLER(ChromeViewMsg_ClearCache, OnClearCache)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
@@ -320,12 +313,6 @@
 
 void ChromeRenderProcessObserver::WebKitInitialized() {
   webkit_initialized_ = true;
-  if (pending_cache_capacity_ != kUnitializedCacheCapacity) {
-    WebCache::setCapacities(pending_cache_min_dead_capacity_,
-                            pending_cache_max_dead_capacity_,
-                            pending_cache_capacity_);
-  }
-
   // chrome-native: is a scheme used for placeholder navigations that allow
   // UIs to be drawn with platform native widgets instead of HTML.  These pages
   // should not be accessible, and should also be treated as empty documents
@@ -354,28 +341,6 @@
   content_setting_rules_ = rules;
 }
 
-void ChromeRenderProcessObserver::OnSetCacheCapacities(size_t min_dead_capacity,
-                                                       size_t max_dead_capacity,
-                                                       size_t capacity) {
-  if (!webkit_initialized_) {
-    pending_cache_min_dead_capacity_ = min_dead_capacity;
-    pending_cache_max_dead_capacity_ = max_dead_capacity;
-    pending_cache_capacity_ = capacity;
-    return;
-  }
-
-  WebCache::setCapacities(
-      min_dead_capacity, max_dead_capacity, capacity);
-}
-
-void ChromeRenderProcessObserver::OnClearCache(bool on_navigation) {
-  if (on_navigation || !webkit_initialized_) {
-    clear_cache_pending_ = true;
-  } else {
-    WebCache::clear();
-  }
-}
-
 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
   WebCache::ResourceTypeStats stats;
   if (webkit_initialized_)
@@ -400,13 +365,6 @@
   HeapStatisticsCollector::Instance()->InitiateCollection();
 }
 
-void ChromeRenderProcessObserver::ExecutePendingClearCache() {
-  if (clear_cache_pending_ && webkit_initialized_) {
-    clear_cache_pending_ = false;
-    WebCache::clear();
-  }
-}
-
 const RendererContentSettingRules*
 ChromeRenderProcessObserver::content_setting_rules() const {
   return &content_setting_rules_;
diff --git a/chrome/renderer/chrome_render_process_observer.h b/chrome/renderer/chrome_render_process_observer.h
index 91a1646a..643d747 100644
--- a/chrome/renderer/chrome_render_process_observer.h
+++ b/chrome/renderer/chrome_render_process_observer.h
@@ -33,10 +33,6 @@
 
   static bool is_incognito_process() { return is_incognito_process_; }
 
-  // Needs to be called by RenderViews in case of navigations to execute
-  // any 'clear cache' commands that were delayed until the next navigation.
-  void ExecutePendingClearCache();
-
   // Returns a pointer to the content setting rules owned by
   // |ChromeRenderProcessObserver|.
   const RendererContentSettingRules* content_setting_rules() const;
@@ -51,12 +47,6 @@
   void OnSetContentSettingsForCurrentURL(
       const GURL& url, const ContentSettings& content_settings);
   void OnSetContentSettingRules(const RendererContentSettingRules& rules);
-  void OnSetCacheCapacities(size_t min_dead_capacity,
-                            size_t max_dead_capacity,
-                            size_t capacity);
-  // If |on_navigation| is true, the clearing is delayed until the next
-  // navigation event.
-  void OnClearCache(bool on_navigation);
   void OnGetCacheResourceStats();
   void OnSetFieldTrialGroup(const std::string& fiel_trial_name,
                             const std::string& group_name);
@@ -70,9 +60,6 @@
   RendererContentSettingRules content_setting_rules_;
 
   bool webkit_initialized_;
-  size_t pending_cache_min_dead_capacity_;
-  size_t pending_cache_max_dead_capacity_;
-  size_t pending_cache_capacity_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeRenderProcessObserver);
 };
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index 5ab3470..fb0ecc5d 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -17,11 +17,11 @@
 #include "chrome/common/prerender_messages.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/renderer/chrome_render_process_observer.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
 #include "chrome/renderer/translate/translate_helper.h"
 #include "chrome/renderer/webview_color_overlay.h"
+#include "components/web_cache/renderer/web_cache_render_process_observer.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/render_frame.h"
@@ -154,9 +154,9 @@
 
 ChromeRenderViewObserver::ChromeRenderViewObserver(
     content::RenderView* render_view,
-    ChromeRenderProcessObserver* chrome_render_process_observer)
+    web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer)
     : content::RenderViewObserver(render_view),
-      chrome_render_process_observer_(chrome_render_process_observer),
+      web_cache_render_process_observer_(web_cache_render_process_observer),
       translate_helper_(new TranslateHelper(render_view)),
       phishing_classifier_(NULL),
       capture_timer_(false, false) {
@@ -285,8 +285,8 @@
 void ChromeRenderViewObserver::Navigate(const GURL& url) {
   // Execute cache clear operations that were postponed until a navigation
   // event (including tab reload).
-  if (chrome_render_process_observer_)
-    chrome_render_process_observer_->ExecutePendingClearCache();
+  if (web_cache_render_process_observer_)
+    web_cache_render_process_observer_->ExecutePendingClearCache();
   // Let translate_helper do any preparatory work for loading a URL.
   if (translate_helper_)
     translate_helper_->PrepareForUrl(url);
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index c4edee9..27d06a94 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -18,7 +18,6 @@
 #include "ui/gfx/size.h"
 #include "url/gurl.h"
 
-class ChromeRenderProcessObserver;
 class ContentSettingsObserver;
 class SkBitmap;
 class TranslateHelper;
@@ -34,6 +33,10 @@
 class PhishingClassifierDelegate;
 }
 
+namespace web_cache {
+class WebCacheRenderProcessObserver;
+}
+
 // This class holds the Chrome specific parts of RenderView, and has the same
 // lifetime.
 class ChromeRenderViewObserver : public content::RenderViewObserver {
@@ -41,7 +44,8 @@
   // translate_helper can be NULL.
   ChromeRenderViewObserver(
       content::RenderView* render_view,
-      ChromeRenderProcessObserver* chrome_render_process_observer);
+      web_cache::WebCacheRenderProcessObserver*
+          web_cache_render_process_observer);
   virtual ~ChromeRenderViewObserver();
 
  private:
@@ -91,7 +95,7 @@
   std::vector<base::string16> webui_javascript_;
 
   // Owned by ChromeContentRendererClient and outlive us.
-  ChromeRenderProcessObserver* chrome_render_process_observer_;
+  web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer_;
 
   // Have the same lifetime as us.
   TranslateHelper* translate_helper_;
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 6383b231..ec138a8 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -95,6 +95,9 @@
     "//components/visitedlink/browser",
     "//components/visitedlink/common",
     "//components/visitedlink/renderer",
+    "//components/web_cache/browser",
+    "//components/web_cache/common",
+    "//components/web_cache/renderer",
     "//components/web_modal",
     "//components/webdata/common",
     "//components/wifi",
@@ -171,6 +174,8 @@
       "//components/visitedlink/browser",  # Blocked on content.
       "//components/visitedlink/common",  # Blocked on content.
       "//components/visitedlink/renderer",  # Blocked on blink
+      "//components/web_cache/browser",  # Blocked on content and blink.
+      "//components/web_cache/renderer",  # Blocked on content and blink.
       "//components/web_modal",  # Blocked on content.
     ]
   }
diff --git a/components/components.gyp b/components/components.gyp
index 540babc..aa2136a 100644
--- a/components/components.gyp
+++ b/components/components.gyp
@@ -68,6 +68,7 @@
         'power.gypi',
         'sessions.gypi',
         'visitedlink.gypi',
+        'web_cache.gypi',
         'web_contents_delegate_android.gypi',
         'web_modal.gypi',
       ],
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index e7f99ef..caf822dc 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -247,6 +247,7 @@
             'variations/variations_seed_processor_unittest.cc',
             'variations/variations_seed_simulator_unittest.cc',
             'visitedlink/test/visitedlink_unittest.cc',
+            'web_cache/browser/web_cache_manager_unittest.cc',
             'web_modal/web_contents_modal_dialog_manager_unittest.cc',
             'webdata/common/web_database_migration_unittest.cc',
           ],
@@ -488,6 +489,9 @@
                 'components.gyp:visitedlink_browser',
                 'components.gyp:visitedlink_renderer',
 
+                # Dependencies of web_cache
+                'components.gyp:web_cache_browser',
+
                 # Dependencies of web_modal
                 'components.gyp:web_modal',
                 'components.gyp:web_modal_test_support',
diff --git a/components/web_cache.gypi b/components/web_cache.gypi
new file mode 100644
index 0000000..a42e344
--- /dev/null
+++ b/components/web_cache.gypi
@@ -0,0 +1,57 @@
+# Copyright (c) 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'web_cache_common',
+      'type': 'static_library',
+      'dependencies': [
+        '<(DEPTH)/ipc/ipc.gyp:ipc',
+      ],
+      'sources': [
+        'web_cache/common/web_cache_message_generator.cc',
+        'web_cache/common/web_cache_message_generator.h',
+        'web_cache/common/web_cache_messages.h',
+      ],
+    },
+    {
+      'target_name': 'web_cache_browser',
+      'type': 'static_library',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/content/content.gyp:content_browser',
+        '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
+        'web_cache_common',
+      ],
+      'sources': [
+        'web_cache/browser/web_cache_manager.cc',
+        'web_cache/browser/web_cache_manager.h',
+      ],
+      # Disable c4267 warnings until we fix size_t to int truncations.
+      'msvs_disabled_warnings': [ 4267, ],
+      'conditions': [
+        ['OS=="win" and win_use_allocator_shim==1', {
+          'dependencies': [
+            '../base/allocator/allocator.gyp:allocator',
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'web_cache_renderer',
+      'type': 'static_library',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/content/content.gyp:content_renderer',
+        '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
+        'web_cache_common',
+      ],
+      'sources': [
+        'web_cache/renderer/web_cache_render_process_observer.cc',
+        'web_cache/renderer/web_cache_render_process_observer.h',
+      ],
+    },
+  ],
+}
diff --git a/components/web_cache/OWNERS b/components/web_cache/OWNERS
new file mode 100644
index 0000000..de6caf7
--- /dev/null
+++ b/components/web_cache/OWNERS
@@ -0,0 +1,10 @@
+# Reviewers:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
+
+# Just owners:
[email protected]
[email protected]
diff --git a/components/web_cache/browser/BUILD.gn b/components/web_cache/browser/BUILD.gn
new file mode 100644
index 0000000..d001973
--- /dev/null
+++ b/components/web_cache/browser/BUILD.gn
@@ -0,0 +1,18 @@
+# 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.
+
+static_library("browser") {
+  output_name = "web_cache_browser"
+  sources = [
+    "web_cache_manager.cc",
+    "web_cache_manager.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/web_cache/common",
+    "//content/public/browser",
+    "//third_party/WebKit/public:blink",
+  ]
+}
diff --git a/components/web_cache/browser/DEPS b/components/web_cache/browser/DEPS
new file mode 100644
index 0000000..f6417ed
--- /dev/null
+++ b/components/web_cache/browser/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+content/public/browser",
+  "+content/public",
+  '+third_party/WebKit/public/web',
+]
diff --git a/chrome/browser/renderer_host/web_cache_manager.cc b/components/web_cache/browser/web_cache_manager.cc
similarity index 94%
rename from chrome/browser/renderer_host/web_cache_manager.cc
rename to components/web_cache/browser/web_cache_manager.cc
index a61a2c3..4acd209 100644
--- a/chrome/browser/renderer_host/web_cache_manager.cc
+++ b/components/web_cache/browser/web_cache_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/renderer_host/web_cache_manager.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 
 #include <algorithm>
 
@@ -15,18 +15,17 @@
 #include "base/prefs/pref_service.h"
 #include "base/sys_info.h"
 #include "base/time/time.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/render_messages.h"
+#include "components/web_cache/common/web_cache_messages.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 
 using base::Time;
 using base::TimeDelta;
 using blink::WebCache;
 
+namespace web_cache {
+
 static const int kReviseAllocationDelayMS = 200;
 
 // The default size limit of the in-memory cache is 8 MB
@@ -54,11 +53,6 @@
 }  // anonymous namespace
 
 // static
-void WebCacheManager::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterIntegerPref(prefs::kMemoryCacheSize, GetDefaultCacheSize());
-}
-
-// static
 WebCacheManager* WebCacheManager::GetInstance() {
   return Singleton<WebCacheManager>::get();
 }
@@ -183,10 +177,6 @@
 
 // static
 size_t WebCacheManager::GetDefaultGlobalSizeLimit() {
-  PrefService* perf_service = g_browser_process->local_state();
-  if (perf_service)
-    return perf_service->GetInteger(prefs::kMemoryCacheSize);
-
   return GetDefaultCacheSize();
 }
 
@@ -326,9 +316,9 @@
         max_dead_capacity = std::min(static_cast<size_t>(512 * 1024),
                                      max_dead_capacity);
       }
-      host->Send(new ChromeViewMsg_SetCacheCapacities(min_dead_capacity,
-                                                      max_dead_capacity,
-                                                      capacity));
+      host->Send(new WebCacheMsg_SetCacheCapacities(min_dead_capacity,
+                                                    max_dead_capacity,
+                                                    capacity));
     }
     ++allocation;
   }
@@ -342,7 +332,7 @@
     content::RenderProcessHost* host =
         content::RenderProcessHost::FromID(*iter);
     if (host)
-      host->Send(new ChromeViewMsg_ClearCache(occasion == ON_NAVIGATION));
+      host->Send(new WebCacheMsg_ClearCache(occasion == ON_NAVIGATION));
   }
 }
 
@@ -442,3 +432,5 @@
     ++iter;
   }
 }
+
+}  // namespace web_cache
diff --git a/chrome/browser/renderer_host/web_cache_manager.h b/components/web_cache/browser/web_cache_manager.h
similarity index 88%
rename from chrome/browser/renderer_host/web_cache_manager.h
rename to components/web_cache/browser/web_cache_manager.h
index b7a5909..0945ec5 100644
--- a/chrome/browser/renderer_host/web_cache_manager.h
+++ b/components/web_cache/browser/web_cache_manager.h
@@ -5,8 +5,8 @@
 // This is the browser side of the cache manager, it tracks the activity of the
 // render processes and allocates available memory cache resources.
 
-#ifndef CHROME_BROWSER_RENDERER_HOST_WEB_CACHE_MANAGER_H_
-#define CHROME_BROWSER_RENDERER_HOST_WEB_CACHE_MANAGER_H_
+#ifndef COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
+#define COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
 
 #include <list>
 #include <map>
@@ -25,13 +25,30 @@
 struct DefaultSingletonTraits;
 class PrefRegistrySimple;
 
+namespace web_cache {
+
 class WebCacheManager : public content::NotificationObserver {
   friend class WebCacheManagerTest;
-  FRIEND_TEST_ALL_PREFIXES(WebCacheManagerBrowserTest, CrashOnceOnly);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5);
+  FRIEND_TEST_ALL_PREFIXES(
+      WebCacheManagerTest,
+      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6);
 
  public:
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-
   // Gets the singleton WebCacheManager object.  The first time this method
   // is called, a WebCacheManager object is constructed and returned.
   // Subsequent calls will return the same object.
@@ -219,4 +236,6 @@
   DISALLOW_COPY_AND_ASSIGN(WebCacheManager);
 };
 
-#endif  // CHROME_BROWSER_RENDERER_HOST_WEB_CACHE_MANAGER_H_
+}  // namespace web_cache
+
+#endif  // COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
diff --git a/chrome/browser/renderer_host/web_cache_manager_unittest.cc b/components/web_cache/browser/web_cache_manager_unittest.cc
similarity index 64%
rename from chrome/browser/renderer_host/web_cache_manager_unittest.cc
rename to components/web_cache/browser/web_cache_manager_unittest.cc
index 81a20119..bc8bcbd 100644
--- a/chrome/browser/renderer_host/web_cache_manager_unittest.cc
+++ b/components/web_cache/browser/web_cache_manager_unittest.cc
@@ -5,7 +5,7 @@
 #include <string>
 
 #include "base/message_loop/message_loop.h"
-#include "chrome/browser/renderer_host/web_cache_manager.h"
+#include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -14,6 +14,8 @@
 using content::BrowserThread;
 using blink::WebCache;
 
+namespace web_cache {
+
 class WebCacheManagerTest : public testing::Test {
  protected:
   typedef WebCacheManager::StatsMap StatsMap;
@@ -309,3 +311,156 @@
   manager()->Remove(kRendererID);
   manager()->Remove(kRendererID2);
 }
+
+// Regression test for http://crbug.com/12362.
+// There are three operations in the following order will cause the crash:
+// Remove(kRendererID) -> ObserveActivity(kRendererID) -> Remove(kRendererID2)
+// To prevent similar failures in the future, 6 tests are added in total to
+// cover all the possible orderings of these three operations.
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  // The following order will cause a crash in http://crbug.com/12362.
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+}
+
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+       CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6) {
+  EXPECT_EQ(0U, active_renderers(manager()).size());
+  EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+  // Add, Remove, and ObserveActivity trigger deferred
+  // calls to ReviseAllocationStrategy and that we call it directly after each
+  // operation to sidestep the need to wait for an unobservable background
+  // operation.
+  manager()->Add(kRendererID);
+  manager()->ReviseAllocationStrategy();
+  manager()->Add(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID2);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->Remove(kRendererID);
+  manager()->ReviseAllocationStrategy();
+
+  manager()->ObserveActivity(kRendererID);
+  manager()->ReviseAllocationStrategy();
+}
+
+}  // namespace web_cache
diff --git a/components/web_cache/common/BUILD.gn b/components/web_cache/common/BUILD.gn
new file mode 100644
index 0000000..5c7b2ef
--- /dev/null
+++ b/components/web_cache/common/BUILD.gn
@@ -0,0 +1,16 @@
+# 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.
+
+static_library("common") {
+  output_name = "web_cache_common"
+  sources = [
+    "web_cache_message_generator.cc",
+    "web_cache_message_generator.h",
+    "web_cache_messages.h",
+  ]
+
+  deps = [
+    "//ipc",
+  ]
+}
diff --git a/components/web_cache/common/DEPS b/components/web_cache/common/DEPS
new file mode 100644
index 0000000..1c40d98
--- /dev/null
+++ b/components/web_cache/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ipc",
+]
diff --git a/components/web_cache/common/OWNERS b/components/web_cache/common/OWNERS
new file mode 100644
index 0000000..5ecb406
--- /dev/null
+++ b/components/web_cache/common/OWNERS
@@ -0,0 +1,11 @@
+# Changes to IPC messages require a security review to avoid introducing
+# new sandbox escapes.
+per-file *_messages*.h=set noparent
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
+per-file *_messages*[email protected]
diff --git a/components/web_cache/common/web_cache_message_generator.cc b/components/web_cache/common/web_cache_message_generator.cc
new file mode 100644
index 0000000..b4b2d26
--- /dev/null
+++ b/components/web_cache/common/web_cache_message_generator.cc
@@ -0,0 +1,33 @@
+// 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+}  // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+}  // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+}  // namespace IPC
diff --git a/components/web_cache/common/web_cache_message_generator.h b/components/web_cache/common/web_cache_message_generator.h
new file mode 100644
index 0000000..d88eb86
--- /dev/null
+++ b/components/web_cache/common/web_cache_message_generator.h
@@ -0,0 +1,7 @@
+// 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.
+
+// Multiply-included file, no traditional include guard.
+
+#include "components/web_cache/common/web_cache_messages.h"
diff --git a/components/web_cache/common/web_cache_messages.h b/components/web_cache/common/web_cache_messages.h
new file mode 100644
index 0000000..a5213991
--- /dev/null
+++ b/components/web_cache/common/web_cache_messages.h
@@ -0,0 +1,23 @@
+// Copyright (c) 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.
+
+// Multiply-included file, no traditional include guard.
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+
+#define IPC_MESSAGE_START WebCacheMsgStart
+
+//-----------------------------------------------------------------------------
+// RenderView messages
+// These are messages sent from the browser to the renderer process.
+
+// Tells the renderer to set its maximum cache size to the supplied value.
+IPC_MESSAGE_CONTROL3(WebCacheMsg_SetCacheCapacities,
+                     size_t /* min_dead_capacity */,
+                     size_t /* max_dead_capacity */,
+                     size_t /* capacity */)
+
+// Tells the renderer to clear the cache.
+IPC_MESSAGE_CONTROL1(WebCacheMsg_ClearCache,
+                     bool /* on_navigation */)
diff --git a/components/web_cache/renderer/BUILD.gn b/components/web_cache/renderer/BUILD.gn
new file mode 100644
index 0000000..cdd703a
--- /dev/null
+++ b/components/web_cache/renderer/BUILD.gn
@@ -0,0 +1,17 @@
+# 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.
+
+static_library("renderer") {
+  output_name = "web_cache_renderer"
+  sources = [
+    "web_cache_render_process_observer.cc",
+    "web_cache_render_process_observer.h",
+  ]
+
+  deps = [
+    "//components/web_cache/common",
+    "//content/public/renderer",
+    "//third_party/WebKit/public:blink",
+  ]
+}
diff --git a/components/web_cache/renderer/DEPS b/components/web_cache/renderer/DEPS
new file mode 100644
index 0000000..100b3d3a
--- /dev/null
+++ b/components/web_cache/renderer/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+content/public/renderer",
+  "+third_party/WebKit/public/web",
+]
diff --git a/components/web_cache/renderer/web_cache_render_process_observer.cc b/components/web_cache/renderer/web_cache_render_process_observer.cc
new file mode 100644
index 0000000..a273817
--- /dev/null
+++ b/components/web_cache/renderer/web_cache_render_process_observer.cc
@@ -0,0 +1,84 @@
+// 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.
+
+#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+
+#include <limits>
+
+#include "components/web_cache/common/web_cache_messages.h"
+#include "third_party/WebKit/public/web/WebCache.h"
+
+using blink::WebCache;
+
+namespace web_cache {
+
+namespace {
+const size_t kUnitializedCacheCapacity = UINT_MAX;
+}
+
+WebCacheRenderProcessObserver::WebCacheRenderProcessObserver()
+  : clear_cache_pending_(false),
+    webkit_initialized_(false),
+    pending_cache_min_dead_capacity_(0),
+    pending_cache_max_dead_capacity_(0),
+    pending_cache_capacity_(kUnitializedCacheCapacity) {
+}
+
+WebCacheRenderProcessObserver::~WebCacheRenderProcessObserver() {
+}
+
+void WebCacheRenderProcessObserver::ExecutePendingClearCache() {
+  if (clear_cache_pending_ && webkit_initialized_) {
+    clear_cache_pending_ = false;
+    WebCache::clear();
+  }
+}
+
+bool WebCacheRenderProcessObserver::OnControlMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(WebCacheRenderProcessObserver, message)
+    IPC_MESSAGE_HANDLER(WebCacheMsg_SetCacheCapacities, OnSetCacheCapacities)
+    IPC_MESSAGE_HANDLER(WebCacheMsg_ClearCache, OnClearCache)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void WebCacheRenderProcessObserver::WebKitInitialized() {
+  webkit_initialized_ = true;
+  if (pending_cache_capacity_ != kUnitializedCacheCapacity) {
+    WebCache::setCapacities(pending_cache_min_dead_capacity_,
+                            pending_cache_max_dead_capacity_,
+                            pending_cache_capacity_);
+  }
+}
+
+void WebCacheRenderProcessObserver::OnRenderProcessShutdown() {
+  webkit_initialized_ = false;
+}
+
+void WebCacheRenderProcessObserver::OnSetCacheCapacities(
+    size_t min_dead_capacity,
+    size_t max_dead_capacity,
+    size_t capacity) {
+  if (!webkit_initialized_) {
+    pending_cache_min_dead_capacity_ = min_dead_capacity;
+    pending_cache_max_dead_capacity_ = max_dead_capacity;
+    pending_cache_capacity_ = capacity;
+    return;
+  }
+
+  WebCache::setCapacities(
+      min_dead_capacity, max_dead_capacity, capacity);
+}
+
+void WebCacheRenderProcessObserver::OnClearCache(bool on_navigation) {
+  if (on_navigation || !webkit_initialized_)
+    clear_cache_pending_ = true;
+  else
+    WebCache::clear();
+}
+
+}  // namespace web_cache
diff --git a/components/web_cache/renderer/web_cache_render_process_observer.h b/components/web_cache/renderer/web_cache_render_process_observer.h
new file mode 100644
index 0000000..6f49a3c
--- /dev/null
+++ b/components/web_cache/renderer/web_cache_render_process_observer.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+#define COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "content/public/renderer/render_process_observer.h"
+
+namespace web_cache {
+
+// This class filters the incoming cache related control messages.
+class WebCacheRenderProcessObserver : public content::RenderProcessObserver {
+ public:
+  WebCacheRenderProcessObserver();
+  virtual ~WebCacheRenderProcessObserver();
+
+  // Needs to be called by RenderViews in case of navigations to execute
+  // any 'clear cache' commands that were delayed until the next navigation.
+  void ExecutePendingClearCache();
+
+ private:
+  // RenderProcessObserver implementation.
+  virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void WebKitInitialized() OVERRIDE;
+  virtual void OnRenderProcessShutdown() OVERRIDE;
+
+  // Message handlers.
+  void OnSetCacheCapacities(size_t min_dead_capacity,
+                            size_t max_dead_capacity,
+                            size_t capacity);
+  // If |on_navigation| is true, the clearing is delayed until the next
+  // navigation event.
+  void OnClearCache(bool on_navigation);
+
+  // If true, the web cache shall be cleared before the next navigation event.
+  bool clear_cache_pending_;
+  bool webkit_initialized_;
+  size_t pending_cache_min_dead_capacity_;
+  size_t pending_cache_max_dead_capacity_;
+  size_t pending_cache_capacity_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebCacheRenderProcessObserver);
+};
+
+}  // namespace web_cache
+
+#endif  // COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index 000c6e3..872eb31 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -47,6 +47,7 @@
         '../cc/blink/cc_blink.gyp:cc_blink',
         '../cc/cc.gyp:cc',
         '../components/components.gyp:crash_component',
+        '../components/components.gyp:web_cache_renderer',
         '../gin/gin.gyp:gin',
         '../gpu/gpu.gyp:gpu',
         '../ipc/ipc.gyp:ipc',
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index bcd91f2..0f8286a 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -209,6 +209,7 @@
     "//base/third_party/dynamic_annotations",
     "//cc",
     "//components/crash/app",
+    "//components/web_cache/renderer",
     "//content:resources",
     "//content/app/resources",
     "//content/app/strings",
diff --git a/content/shell/renderer/DEPS b/content/shell/renderer/DEPS
index b462077..8b18709 100644
--- a/content/shell/renderer/DEPS
+++ b/content/shell/renderer/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+gin",
+  "+components/web_cache/renderer",
 ]
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index 7c2f316..ed7f15b5 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -7,9 +7,11 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
+#include "components/web_cache/renderer/web_cache_render_process_observer.h"
 #include "content/common/sandbox_win.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/test/layouttest_support.h"
 #include "content/shell/common/shell_switches.h"
@@ -84,12 +86,15 @@
 }
 
 void ShellContentRendererClient::RenderThreadStarted() {
+  RenderThread* thread = RenderThread::Get();
   shell_observer_.reset(new ShellRenderProcessObserver());
+  web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver());
 #if defined(OS_MACOSX)
   // We need to call this once before the sandbox was initialized to cache the
   // value.
   base::debug::BeingDebugged();
 #endif
+  thread->AddObserver(web_cache_observer_.get());
 }
 
 void ShellContentRendererClient::RenderFrameCreated(RenderFrame* render_frame) {
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 1764630..8e1b482 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -15,6 +15,10 @@
 struct WebPluginParams;
 }
 
+namespace web_cache {
+class WebCacheRenderProcessObserver;
+}
+
 namespace content {
 
 class MockWebClipboardImpl;
@@ -53,6 +57,7 @@
  private:
   void WebTestProxyCreated(RenderView* render_view, WebTestProxyBase* proxy);
 
+  scoped_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
   scoped_ptr<ShellRenderProcessObserver> shell_observer_;
   scoped_ptr<MockWebClipboardImpl> clipboard_;
 };
diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp
index f524156..2e79810 100644
--- a/extensions/shell/app_shell.gyp
+++ b/extensions/shell/app_shell.gyp
@@ -18,6 +18,7 @@
         '<(DEPTH)/components/components.gyp:omaha_query_params',
         '<(DEPTH)/components/components.gyp:pref_registry',
         '<(DEPTH)/components/components.gyp:user_prefs',
+        '<(DEPTH)/components/components.gyp:web_cache_renderer',
         '<(DEPTH)/content/content.gyp:content',
         '<(DEPTH)/content/content.gyp:content_gpu',
         '<(DEPTH)/content/content.gyp:content_ppapi_plugin',
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 5acf8c1..3c28ad9 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -108,6 +108,7 @@
   PlatformNotificationMsgStart,
   CredentialManagerMsgStart,
   PDFMsgStart,
+  WebCacheMsgStart,
   LastIPCMsgStart  // Must come last.
 };