blob: 98ab3011652cfb788548ee695897a33380e4e56a [file] [log] [blame]
[email protected]6b4329a2012-01-25 10:51:281// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]0dd5dda02009-10-01 18:50:192// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/memory_purger.h"
6
[email protected]61a9b2d82010-02-26 00:31:087#include <set>
8
[email protected]237a14852012-04-28 02:56:389#include "base/allocator/allocator_extension.h"
[email protected]24d69692011-10-21 18:26:5110#include "base/bind.h"
[email protected]34b99632011-01-01 01:01:0611#include "base/threading/thread.h"
[email protected]3148c5d2009-11-18 19:32:5812#include "chrome/browser/browser_process.h"
[email protected]6a2c09f2013-01-25 04:50:0713#include "chrome/browser/history/history_service.h"
[email protected]65e338d712012-07-17 22:28:5914#include "chrome/browser/history/history_service_factory.h"
[email protected]8ecad5e2010-12-02 21:18:3315#include "chrome/browser/profiles/profile_manager.h"
[email protected]5006a412012-11-27 08:22:4016#include "chrome/browser/safe_browsing/database_manager.h"
[email protected]1962a9c2012-02-21 21:56:1517#include "chrome/browser/safe_browsing/safe_browsing_service.h"
[email protected]71b73f02011-04-06 15:57:2918#include "chrome/browser/ui/browser_list.h"
[email protected]dd3c53f2013-03-14 02:59:4119#include "chrome/browser/webdata/web_data_service.h"
20#include "chrome/browser/webdata/web_data_service_factory.h"
[email protected]3148c5d2009-11-18 19:32:5821#include "chrome/common/render_messages.h"
[email protected]f3b1a082011-11-18 00:34:3022#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3323#include "content/public/browser/render_widget_host.h"
[email protected]1962a9c2012-02-21 21:56:1524#include "content/public/browser/resource_context.h"
[email protected]3148c5d2009-11-18 19:32:5825#include "net/proxy/proxy_resolver.h"
[email protected]6104ea5d2011-04-27 21:37:1226#include "net/proxy/proxy_service.h"
[email protected]3148c5d2009-11-18 19:32:5827#include "net/url_request/url_request_context.h"
[email protected]abe2c032011-03-31 18:49:3428#include "net/url_request/url_request_context_getter.h"
[email protected]3148c5d2009-11-18 19:32:5829
[email protected]55eb70e762012-02-20 17:38:3930using content::BrowserContext;
[email protected]631bb742011-11-02 11:29:3931using content::BrowserThread;
[email protected]1962a9c2012-02-21 21:56:1532using content::ResourceContext;
[email protected]631bb742011-11-02 11:29:3933
[email protected]3148c5d2009-11-18 19:32:5834// PurgeMemoryHelper -----------------------------------------------------------
35
36// This is a small helper class used to ensure that the objects we want to use
37// on multiple threads are properly refed, so they don't get deleted out from
38// under us.
39class PurgeMemoryIOHelper
40 : public base::RefCountedThreadSafe<PurgeMemoryIOHelper> {
41 public:
[email protected]b864a412011-07-07 10:51:4842 PurgeMemoryIOHelper() {
[email protected]1962a9c2012-02-21 21:56:1543 safe_browsing_service_ = g_browser_process->safe_browsing_service();
[email protected]3148c5d2009-11-18 19:32:5844 }
45
[email protected]00cd9c42010-11-02 20:15:5746 void AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3447 scoped_refptr<net::URLRequestContextGetter> request_context_getter);
[email protected]3148c5d2009-11-18 19:32:5848
49 void PurgeMemoryOnIOThread();
50
51 private:
[email protected]649d1c02012-04-27 02:56:2152 friend class base::RefCountedThreadSafe<PurgeMemoryIOHelper>;
[email protected]3148c5d2009-11-18 19:32:5853
[email protected]649d1c02012-04-27 02:56:2154 virtual ~PurgeMemoryIOHelper() {}
55
56 typedef scoped_refptr<net::URLRequestContextGetter> RequestContextGetter;
[email protected]1962a9c2012-02-21 21:56:1557 std::vector<RequestContextGetter> request_context_getters_;
[email protected]649d1c02012-04-27 02:56:2158
[email protected]1962a9c2012-02-21 21:56:1559 scoped_refptr<SafeBrowsingService> safe_browsing_service_;
[email protected]3148c5d2009-11-18 19:32:5860
61 DISALLOW_COPY_AND_ASSIGN(PurgeMemoryIOHelper);
62};
63
64void PurgeMemoryIOHelper::AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3465 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
[email protected]1962a9c2012-02-21 21:56:1566 request_context_getters_.push_back(request_context_getter);
67}
68
[email protected]3148c5d2009-11-18 19:32:5869void PurgeMemoryIOHelper::PurgeMemoryOnIOThread() {
70 // Ask ProxyServices to purge any memory they can (generally garbage in the
71 // wrapped ProxyResolver's JS engine).
[email protected]1962a9c2012-02-21 21:56:1572 for (size_t i = 0; i < request_context_getters_.size(); ++i) {
73 request_context_getters_[i]->GetURLRequestContext()->proxy_service()->
74 PurgeMemory();
75 }
[email protected]3148c5d2009-11-18 19:32:5876
[email protected]6c521fed2012-11-29 17:00:0377#if defined(FULL_SAFE_BROWSING)
[email protected]5006a412012-11-27 08:22:4078 safe_browsing_service_->database_manager()->PurgeMemory();
[email protected]69c87ac2012-03-28 19:38:3079#endif
[email protected]3148c5d2009-11-18 19:32:5880}
81
82// -----------------------------------------------------------------------------
[email protected]0dd5dda02009-10-01 18:50:1983
84// static
[email protected]3148c5d2009-11-18 19:32:5885void MemoryPurger::PurgeAll() {
86 PurgeBrowser();
87 PurgeRenderers();
88
89 // TODO(pkasting):
90 // * Tell the plugin processes to release their free memory? Other stuff?
91 // * Enumerate what other processes exist and what to do for them.
[email protected]0dd5dda02009-10-01 18:50:1992}
93
[email protected]3148c5d2009-11-18 19:32:5894// static
95void MemoryPurger::PurgeBrowser() {
96 // Dump the backing stores.
[email protected]eaabba22012-03-07 15:02:1197 content::RenderWidgetHost::RemoveAllBackingStores();
[email protected]3148c5d2009-11-18 19:32:5898
99 // Per-profile cleanup.
100 scoped_refptr<PurgeMemoryIOHelper> purge_memory_io_helper(
[email protected]b864a412011-07-07 10:51:48101 new PurgeMemoryIOHelper());
[email protected]3148c5d2009-11-18 19:32:58102 ProfileManager* profile_manager = g_browser_process->profile_manager();
[email protected]844a1002011-04-19 11:37:21103 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
104 for (size_t i = 0; i < profiles.size(); ++i) {
[email protected]3148c5d2009-11-18 19:32:58105 purge_memory_io_helper->AddRequestContextGetter(
[email protected]844a1002011-04-19 11:37:21106 make_scoped_refptr(profiles[i]->GetRequestContext()));
[email protected]3148c5d2009-11-18 19:32:58107
108 // NOTE: Some objects below may be duplicates across profiles. We could
109 // conceivably put all these in sets and then iterate over the sets.
110
111 // Unload all history backends (freeing memory used to cache sqlite).
112 // Spinning up the history service is expensive, so we avoid doing it if it
113 // hasn't been done already.
114 HistoryService* history_service =
[email protected]65e338d712012-07-17 22:28:59115 HistoryServiceFactory::GetForProfileWithoutCreating(profiles[i]);
[email protected]3148c5d2009-11-18 19:32:58116 if (history_service)
117 history_service->UnloadBackend();
118
119 // Unload all web databases (freeing memory used to cache sqlite).
[email protected]e2b31052013-03-25 01:49:37120 WebDataServiceWrapper* wds_wrapper =
[email protected]dd3c53f2013-03-14 02:59:41121 WebDataServiceFactory::GetForProfileIfExists(
122 profiles[i], Profile::EXPLICIT_ACCESS);
[email protected]e2b31052013-03-25 01:49:37123 if (wds_wrapper && wds_wrapper->GetWebData())
124 wds_wrapper->GetWebData()->UnloadDatabase();
[email protected]3148c5d2009-11-18 19:32:58125
[email protected]6e2d3d22012-02-24 18:10:36126 BrowserContext::PurgeMemory(profiles[i]);
[email protected]3148c5d2009-11-18 19:32:58127 }
128
[email protected]24d69692011-10-21 18:26:51129 BrowserThread::PostTask(
130 BrowserThread::IO, FROM_HERE,
131 base::Bind(&PurgeMemoryIOHelper::PurgeMemoryOnIOThread,
132 purge_memory_io_helper.get()));
[email protected]3148c5d2009-11-18 19:32:58133
134 // TODO(pkasting):
135 // * Purge AppCache memory. Not yet implemented sufficiently.
136 // * Browser-side DatabaseTracker. Not implemented sufficiently.
137
[email protected]237a14852012-04-28 02:56:38138 // Tell our allocator to release any free pages it's still holding.
[email protected]0dd5dda02009-10-01 18:50:19139 //
[email protected]3148c5d2009-11-18 19:32:58140 // TODO(pkasting): A lot of the above calls kick off actions on other threads.
141 // Maybe we should find a way to avoid calling this until those actions
142 // complete?
[email protected]237a14852012-04-28 02:56:38143 base::allocator::ReleaseFreeMemory();
[email protected]0dd5dda02009-10-01 18:50:19144}
145
[email protected]3148c5d2009-11-18 19:32:58146// static
147void MemoryPurger::PurgeRenderers() {
148 // Direct all renderers to free everything they can.
[email protected]0dd5dda02009-10-01 18:50:19149 //
[email protected]3148c5d2009-11-18 19:32:58150 // Concern: Telling a bunch of renderer processes to destroy their data may
151 // cause them to page everything in to do it, which could take a lot of time/
152 // cause jank.
[email protected]f3b1a082011-11-18 00:34:30153 for (content::RenderProcessHost::iterator i(
154 content::RenderProcessHost::AllHostsIterator());
[email protected]3148c5d2009-11-18 19:32:58155 !i.IsAtEnd(); i.Advance())
156 PurgeRendererForHost(i.GetCurrentValue());
[email protected]0dd5dda02009-10-01 18:50:19157}
158
[email protected]3148c5d2009-11-18 19:32:58159// static
[email protected]f3b1a082011-11-18 00:34:30160void MemoryPurger::PurgeRendererForHost(content::RenderProcessHost* host) {
[email protected]3148c5d2009-11-18 19:32:58161 // Direct the renderer to free everything it can.
[email protected]2ccf45c2011-08-19 23:35:50162 host->Send(new ChromeViewMsg_PurgeMemory());
[email protected]0dd5dda02009-10-01 18:50:19163}