// Copyright (c) 2011 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 "chrome/browser/memory_purger.h"

#include <set>

#include "base/threading/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/render_messages.h"
#include "content/browser/in_process_webkit/webkit_context.h"
#include "content/browser/renderer_host/backing_store_manager.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
#include "content/common/notification_service.h"
#include "net/proxy/proxy_resolver.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "third_party/tcmalloc/chromium/src/google/malloc_extension.h"
#include "v8/include/v8.h"

// PurgeMemoryHelper -----------------------------------------------------------

// This is a small helper class used to ensure that the objects we want to use
// on multiple threads are properly refed, so they don't get deleted out from
// under us.
class PurgeMemoryIOHelper
    : public base::RefCountedThreadSafe<PurgeMemoryIOHelper> {
 public:
  explicit PurgeMemoryIOHelper(SafeBrowsingService* safe_browsing_service)
      : safe_browsing_service_(safe_browsing_service) {
  }

  void AddRequestContextGetter(
      scoped_refptr<net::URLRequestContextGetter> request_context_getter);

  void PurgeMemoryOnIOThread();

 private:
  typedef scoped_refptr<net::URLRequestContextGetter> RequestContextGetter;
  typedef std::set<RequestContextGetter> RequestContextGetters;

  RequestContextGetters request_context_getters_;
  scoped_refptr<SafeBrowsingService> safe_browsing_service_;

  DISALLOW_COPY_AND_ASSIGN(PurgeMemoryIOHelper);
};

void PurgeMemoryIOHelper::AddRequestContextGetter(
    scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
  request_context_getters_.insert(request_context_getter);
}

void PurgeMemoryIOHelper::PurgeMemoryOnIOThread() {
  // Ask ProxyServices to purge any memory they can (generally garbage in the
  // wrapped ProxyResolver's JS engine).
  for (RequestContextGetters::const_iterator i(
           request_context_getters_.begin());
       i != request_context_getters_.end(); ++i)
    (*i)->GetURLRequestContext()->proxy_service()->PurgeMemory();

  // Close the Safe Browsing database, freeing memory used to cache sqlite as
  // well as a number of in-memory structures.
  safe_browsing_service_->CloseDatabase();

  // The appcache service listens for this notification.
  NotificationService::current()->Notify(
      NotificationType::PURGE_MEMORY,
      Source<void>(NULL),
      NotificationService::NoDetails());
}

// -----------------------------------------------------------------------------

// static
void MemoryPurger::PurgeAll() {
  PurgeBrowser();
  PurgeRenderers();

  // TODO(pkasting):
  // * Tell the plugin processes to release their free memory?  Other stuff?
  // * Enumerate what other processes exist and what to do for them.
}

// static
void MemoryPurger::PurgeBrowser() {
  // Dump the backing stores.
  BackingStoreManager::RemoveAllBackingStores();

  // Per-profile cleanup.
  scoped_refptr<PurgeMemoryIOHelper> purge_memory_io_helper(
      new PurgeMemoryIOHelper(g_browser_process->resource_dispatcher_host()->
          safe_browsing_service()));
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
  for (size_t i = 0; i < profiles.size(); ++i) {
    purge_memory_io_helper->AddRequestContextGetter(
        make_scoped_refptr(profiles[i]->GetRequestContext()));

    // NOTE: Some objects below may be duplicates across profiles.  We could
    // conceivably put all these in sets and then iterate over the sets.

    // Unload all history backends (freeing memory used to cache sqlite).
    // Spinning up the history service is expensive, so we avoid doing it if it
    // hasn't been done already.
    HistoryService* history_service =
        profiles[i]->GetHistoryServiceWithoutCreating();
    if (history_service)
      history_service->UnloadBackend();

    // Unload all web databases (freeing memory used to cache sqlite).
    WebDataService* web_data_service =
        profiles[i]->GetWebDataServiceWithoutCreating();
    if (web_data_service)
      web_data_service->UnloadDatabase();

    // Ask all WebKitContexts to purge memory (freeing memory used to cache
    // the LocalStorage sqlite DB).  WebKitContext creation is basically free so
    // we don't bother with a "...WithoutCreating()" function.
    profiles[i]->GetWebKitContext()->PurgeMemory();
  }

  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(purge_memory_io_helper.get(),
                        &PurgeMemoryIOHelper::PurgeMemoryOnIOThread));

  // TODO(pkasting):
  // * Purge AppCache memory.  Not yet implemented sufficiently.
  // * Browser-side DatabaseTracker.  Not implemented sufficiently.

#if (defined(OS_WIN) || defined(OS_LINUX)) && defined(USE_TCMALLOC)
  // Tell tcmalloc to release any free pages it's still holding.
  //
  // TODO(pkasting): A lot of the above calls kick off actions on other threads.
  // Maybe we should find a way to avoid calling this until those actions
  // complete?
  MallocExtension::instance()->ReleaseFreeMemory();
#endif
}

// static
void MemoryPurger::PurgeRenderers() {
  // Direct all renderers to free everything they can.
  //
  // Concern: Telling a bunch of renderer processes to destroy their data may
  // cause them to page everything in to do it, which could take a lot of time/
  // cause jank.
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    PurgeRendererForHost(i.GetCurrentValue());
}

// static
void MemoryPurger::PurgeRendererForHost(RenderProcessHost* host) {
  // Direct the renderer to free everything it can.
  host->Send(new ViewMsg_PurgeMemory());
}
