blob: 2fd534b16ef18f1a1bb0ec4d76ed9f95582012fc [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]24d69692011-10-21 18:26:519#include "base/bind.h"
[email protected]34b99632011-01-01 01:01:0610#include "base/threading/thread.h"
[email protected]3148c5d2009-11-18 19:32:5811#include "chrome/browser/browser_process.h"
12#include "chrome/browser/history/history.h"
[email protected]8ecad5e2010-12-02 21:18:3313#include "chrome/browser/profiles/profile_manager.h"
[email protected]1962a9c2012-02-21 21:56:1514#include "chrome/browser/safe_browsing/safe_browsing_service.h"
[email protected]71b73f02011-04-06 15:57:2915#include "chrome/browser/ui/browser_list.h"
[email protected]3148c5d2009-11-18 19:32:5816#include "chrome/browser/webdata/web_data_service.h"
17#include "chrome/common/render_messages.h"
[email protected]f3b1a082011-11-18 00:34:3018#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3319#include "content/public/browser/render_widget_host.h"
[email protected]1962a9c2012-02-21 21:56:1520#include "content/public/browser/resource_context.h"
[email protected]3148c5d2009-11-18 19:32:5821#include "net/proxy/proxy_resolver.h"
[email protected]6104ea5d2011-04-27 21:37:1222#include "net/proxy/proxy_service.h"
[email protected]3148c5d2009-11-18 19:32:5823#include "net/url_request/url_request_context.h"
[email protected]abe2c032011-03-31 18:49:3424#include "net/url_request/url_request_context_getter.h"
[email protected]25f59902012-03-03 07:58:3025#include "third_party/tcmalloc/chromium/src/google/malloc_extension.h"
[email protected]3148c5d2009-11-18 19:32:5826
[email protected]55eb70e762012-02-20 17:38:3927using content::BrowserContext;
[email protected]631bb742011-11-02 11:29:3928using content::BrowserThread;
[email protected]1962a9c2012-02-21 21:56:1529using content::ResourceContext;
[email protected]631bb742011-11-02 11:29:3930
[email protected]3148c5d2009-11-18 19:32:5831// PurgeMemoryHelper -----------------------------------------------------------
32
33// This is a small helper class used to ensure that the objects we want to use
34// on multiple threads are properly refed, so they don't get deleted out from
35// under us.
36class PurgeMemoryIOHelper
37 : public base::RefCountedThreadSafe<PurgeMemoryIOHelper> {
38 public:
[email protected]b864a412011-07-07 10:51:4839 PurgeMemoryIOHelper() {
[email protected]1962a9c2012-02-21 21:56:1540 safe_browsing_service_ = g_browser_process->safe_browsing_service();
[email protected]3148c5d2009-11-18 19:32:5841 }
42
[email protected]00cd9c42010-11-02 20:15:5743 void AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3444 scoped_refptr<net::URLRequestContextGetter> request_context_getter);
[email protected]3148c5d2009-11-18 19:32:5845
[email protected]3148c5d2009-11-18 19:32:5846 void PurgeMemoryOnIOThread();
47
48 private:
[email protected]abe2c032011-03-31 18:49:3449 typedef scoped_refptr<net::URLRequestContextGetter> RequestContextGetter;
[email protected]3148c5d2009-11-18 19:32:5850
[email protected]1962a9c2012-02-21 21:56:1551 std::vector<RequestContextGetter> request_context_getters_;
[email protected]1962a9c2012-02-21 21:56:1552 scoped_refptr<SafeBrowsingService> safe_browsing_service_;
[email protected]3148c5d2009-11-18 19:32:5853
54 DISALLOW_COPY_AND_ASSIGN(PurgeMemoryIOHelper);
55};
56
57void PurgeMemoryIOHelper::AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3458 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
[email protected]1962a9c2012-02-21 21:56:1559 request_context_getters_.push_back(request_context_getter);
60}
61
[email protected]3148c5d2009-11-18 19:32:5862void PurgeMemoryIOHelper::PurgeMemoryOnIOThread() {
63 // Ask ProxyServices to purge any memory they can (generally garbage in the
64 // wrapped ProxyResolver's JS engine).
[email protected]1962a9c2012-02-21 21:56:1565 for (size_t i = 0; i < request_context_getters_.size(); ++i) {
66 request_context_getters_[i]->GetURLRequestContext()->proxy_service()->
67 PurgeMemory();
68 }
[email protected]3148c5d2009-11-18 19:32:5869
[email protected]1962a9c2012-02-21 21:56:1570 safe_browsing_service_->PurgeMemory();
[email protected]3148c5d2009-11-18 19:32:5871}
72
73// -----------------------------------------------------------------------------
[email protected]0dd5dda02009-10-01 18:50:1974
75// static
[email protected]3148c5d2009-11-18 19:32:5876void MemoryPurger::PurgeAll() {
77 PurgeBrowser();
78 PurgeRenderers();
79
80 // TODO(pkasting):
81 // * Tell the plugin processes to release their free memory? Other stuff?
82 // * Enumerate what other processes exist and what to do for them.
[email protected]0dd5dda02009-10-01 18:50:1983}
84
[email protected]3148c5d2009-11-18 19:32:5885// static
86void MemoryPurger::PurgeBrowser() {
87 // Dump the backing stores.
[email protected]0b07be452012-02-29 01:14:4288 RenderWidgetHost::RemoveAllBackingStores();
[email protected]3148c5d2009-11-18 19:32:5889
90 // Per-profile cleanup.
91 scoped_refptr<PurgeMemoryIOHelper> purge_memory_io_helper(
[email protected]b864a412011-07-07 10:51:4892 new PurgeMemoryIOHelper());
[email protected]3148c5d2009-11-18 19:32:5893 ProfileManager* profile_manager = g_browser_process->profile_manager();
[email protected]844a1002011-04-19 11:37:2194 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
95 for (size_t i = 0; i < profiles.size(); ++i) {
[email protected]3148c5d2009-11-18 19:32:5896 purge_memory_io_helper->AddRequestContextGetter(
[email protected]844a1002011-04-19 11:37:2197 make_scoped_refptr(profiles[i]->GetRequestContext()));
[email protected]3148c5d2009-11-18 19:32:5898
99 // NOTE: Some objects below may be duplicates across profiles. We could
100 // conceivably put all these in sets and then iterate over the sets.
101
102 // Unload all history backends (freeing memory used to cache sqlite).
103 // Spinning up the history service is expensive, so we avoid doing it if it
104 // hasn't been done already.
105 HistoryService* history_service =
[email protected]844a1002011-04-19 11:37:21106 profiles[i]->GetHistoryServiceWithoutCreating();
[email protected]3148c5d2009-11-18 19:32:58107 if (history_service)
108 history_service->UnloadBackend();
109
110 // Unload all web databases (freeing memory used to cache sqlite).
111 WebDataService* web_data_service =
[email protected]844a1002011-04-19 11:37:21112 profiles[i]->GetWebDataServiceWithoutCreating();
[email protected]3148c5d2009-11-18 19:32:58113 if (web_data_service)
114 web_data_service->UnloadDatabase();
115
[email protected]6e2d3d22012-02-24 18:10:36116 BrowserContext::PurgeMemory(profiles[i]);
[email protected]3148c5d2009-11-18 19:32:58117 }
118
[email protected]24d69692011-10-21 18:26:51119 BrowserThread::PostTask(
120 BrowserThread::IO, FROM_HERE,
121 base::Bind(&PurgeMemoryIOHelper::PurgeMemoryOnIOThread,
122 purge_memory_io_helper.get()));
[email protected]3148c5d2009-11-18 19:32:58123
124 // TODO(pkasting):
125 // * Purge AppCache memory. Not yet implemented sufficiently.
126 // * Browser-side DatabaseTracker. Not implemented sufficiently.
127
[email protected]1fd5302c2011-05-28 04:06:43128#if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
[email protected]3148c5d2009-11-18 19:32:58129 // Tell tcmalloc to release any free pages it's still holding.
[email protected]0dd5dda02009-10-01 18:50:19130 //
[email protected]3148c5d2009-11-18 19:32:58131 // TODO(pkasting): A lot of the above calls kick off actions on other threads.
132 // Maybe we should find a way to avoid calling this until those actions
133 // complete?
134 MallocExtension::instance()->ReleaseFreeMemory();
135#endif
[email protected]0dd5dda02009-10-01 18:50:19136}
137
[email protected]3148c5d2009-11-18 19:32:58138// static
139void MemoryPurger::PurgeRenderers() {
140 // Direct all renderers to free everything they can.
[email protected]0dd5dda02009-10-01 18:50:19141 //
[email protected]3148c5d2009-11-18 19:32:58142 // Concern: Telling a bunch of renderer processes to destroy their data may
143 // cause them to page everything in to do it, which could take a lot of time/
144 // cause jank.
[email protected]f3b1a082011-11-18 00:34:30145 for (content::RenderProcessHost::iterator i(
146 content::RenderProcessHost::AllHostsIterator());
[email protected]3148c5d2009-11-18 19:32:58147 !i.IsAtEnd(); i.Advance())
148 PurgeRendererForHost(i.GetCurrentValue());
[email protected]0dd5dda02009-10-01 18:50:19149}
150
[email protected]3148c5d2009-11-18 19:32:58151// static
[email protected]f3b1a082011-11-18 00:34:30152void MemoryPurger::PurgeRendererForHost(content::RenderProcessHost* host) {
[email protected]3148c5d2009-11-18 19:32:58153 // Direct the renderer to free everything it can.
[email protected]2ccf45c2011-08-19 23:35:50154 host->Send(new ChromeViewMsg_PurgeMemory());
[email protected]0dd5dda02009-10-01 18:50:19155}