1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <set>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/sys_info.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_process.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/memory_details.h"
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h"
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager_factory.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/profiles/profile.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/profiles/profile_manager.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/android/tab_model/tab_model.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/webui/memory_internals/memory_internals_handler.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/render_messages.h"
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_observer.h"
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_registrar.h"
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_service.h"
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/render_view_host.h"
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/web_contents.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/web_ui.h"
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#if defined(ENABLE_FULL_PRINTING)
41c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "chrome/browser/printing/background_printing_manager.h"
42c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#endif
43c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::BrowserThread;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class Profile;
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass ProcessDetails : public MemoryDetails {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef base::Callback<void(const ProcessData&)> DataCallback;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit ProcessDetails(const DataCallback& callback)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : callback_(callback) {}
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // MemoryDetails:
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnDetailsAvailable() OVERRIDE {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<ProcessData>& browser_processes = processes();
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // [0] means Chrome.
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Run(browser_processes[0]);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~ProcessDetails() {}
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DataCallback callback_;
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ProcessDetails);
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::DictionaryValue* FindProcessFromPid(base::ListValue* processes,
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          base::ProcessId pid) {
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const size_t n = processes->GetSize();
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < n; ++i) {
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::DictionaryValue* process;
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!processes->GetDictionary(i, &process))
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return NULL;
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int id;
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (process->GetInteger("pid", &id) && id == static_cast<int>(pid))
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return process;
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return NULL;
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void GetAllWebContents(std::set<content::WebContents*>* web_contents) {
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Add all the existing WebContentses.
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_ANDROID)
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (TabModelList::const_iterator iter = TabModelList::begin();
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       iter != TabModelList::end(); ++iter) {
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    TabModel* model = *iter;
9029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    for (int i = 0; i < model->GetTabCount(); ++i) {
9129b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      content::WebContents* tab_web_contents = model->GetWebContentsAt(i);
9229b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      if (tab_web_contents)
9329b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch        web_contents->insert(tab_web_contents);
9429b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    }
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#else
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (TabContentsIterator iter; !iter.done(); iter.Next())
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    web_contents->insert(*iter);
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Add all the prerender pages.
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Profile*> profiles(
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < profiles.size(); ++i) {
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    prerender::PrerenderManager* prerender_manager =
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!prerender_manager)
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::vector<content::WebContents*> contentses =
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        prerender_manager->GetAllPrerenderingContents();
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents->insert(contentses.begin(), contentses.end());
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
112c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#if defined(ENABLE_FULL_PRINTING)
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Add all the pages being background printed.
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  printing::BackgroundPrintingManager* printing_manager =
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      g_browser_process->background_printing_manager();
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<content::WebContents*> printing_contents =
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printing_manager->CurrentContentSet();
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents->insert(printing_contents.begin(), printing_contents.end());
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass RendererDetails : public content::NotificationObserver {
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef base::Callback<void(const base::ProcessId pid,
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              const size_t v8_allocated,
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              const size_t v8_used)> V8DataCallback;
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit RendererDetails(const V8DataCallback& callback)
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callback_(callback) {
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    registrar_.Add(this, chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   content::NotificationService::AllSources());
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~RendererDetails() {}
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Request() {
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::set<content::WebContents*>::iterator iter = web_contents_.begin();
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         iter != web_contents_.end(); ++iter)
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*iter)->GetRenderViewHost()->Send(new ChromeViewMsg_GetV8HeapStats);
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddWebContents(content::WebContents* content) {
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    web_contents_.insert(content);
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Clear() {
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    web_contents_.clear();
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void RemoveWebContents(base::ProcessId) {
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // We don't have to detect which content is the caller of this method.
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!web_contents_.empty())
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_contents_.erase(web_contents_.begin());
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int IsClean() {
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return web_contents_.empty();
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // NotificationObserver:
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void Observe(int type,
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       const content::NotificationSource& source,
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       const content::NotificationDetails& details) OVERRIDE {
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::ProcessId* pid =
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        content::Source<const base::ProcessId>(source).ptr();
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const ChromeRenderMessageFilter::V8HeapStatsDetails* v8_heap =
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        content::Details<const ChromeRenderMessageFilter::V8HeapStatsDetails>(
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            details).ptr();
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callback_.Run(*pid,
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  v8_heap->v8_memory_allocated(),
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  v8_heap->v8_memory_used());
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  V8DataCallback callback_;
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  content::NotificationRegistrar registrar_;
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::set<content::WebContents*> web_contents_;  // This class does not own
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(RendererDetails);
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMemoryInternalsProxy::MemoryInternalsProxy()
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : information_(new base::DictionaryValue()),
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      renderer_details_(new RendererDetails(
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          base::Bind(&MemoryInternalsProxy::OnRendererAvailable, this))) {}
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::Attach(MemoryInternalsHandler* handler) {
189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  handler_ = handler;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::Detach() {
194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  handler_ = NULL;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::StartFetch(const base::ListValue* list) {
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Clear previous information before fetching new information.
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Clear();
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<ProcessDetails> process(new ProcessDetails(
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&MemoryInternalsProxy::OnProcessAvailable, this)));
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process->StartFetch(MemoryDetails::SKIP_USER_METRICS);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MemoryInternalsProxy::~MemoryInternalsProxy() {}
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::RequestRendererDetails() {
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->Clear();
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_ANDROID)
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (TabModelList::const_iterator iter = TabModelList::begin();
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       iter != TabModelList::end(); ++iter) {
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TabModel* model = *iter;
21729b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    for (int i = 0; i < model->GetTabCount(); ++i) {
21829b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      content::WebContents* tab_web_contents = model->GetWebContentsAt(i);
21929b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      if (tab_web_contents)
22029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch        renderer_details_->AddWebContents(tab_web_contents);
22129b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    }
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#else
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (TabContentsIterator iter; !iter.done(); iter.Next())
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    renderer_details_->AddWebContents(*iter);
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->Request();
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::OnProcessAvailable(const ProcessData& browser) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* process_info = new base::ListValue();
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* extension_info = new base::ListValue();
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Set("processes", process_info);
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Set("extensions", extension_info);
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (PMIIterator iter = browser.processes.begin();
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       iter != browser.processes.end(); ++iter) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* process = new base::DictionaryValue();
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (iter->renderer_type == ProcessMemoryInformation::RENDERER_EXTENSION)
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      extension_info->Append(process);
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    else
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      process_info->Append(process);
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // From MemoryDetails.
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("pid", iter->pid);
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetString("type",
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       ProcessMemoryInformation::GetFullTypeNameInEnglish(
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           iter->process_type, iter->renderer_type));
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("memory_private", iter->working_set.priv);
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* titles = new base::ListValue();
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->Set("titles", titles);
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (size_t i = 0; i < iter->titles.size(); ++i)
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      titles->AppendString(iter->titles[i]);
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::set<content::WebContents*> web_contents;
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetAllWebContents(&web_contents);
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ConvertTabsInformation(web_contents, process_info);
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  RequestRendererDetails();
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::OnRendererAvailable(const base::ProcessId pid,
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               const size_t v8_allocated,
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               const size_t v8_used) {
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Do not update while no renderers are registered.
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (renderer_details_->IsClean())
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ListValue* processes;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!information_->GetList("processes", &processes))
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t size = processes->GetSize();
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < size; ++i) {
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::DictionaryValue* process;
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    processes->GetDictionary(i, &process);
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int id;
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!process->GetInteger("pid", &id) || id != static_cast<int>(pid))
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      continue;
2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Convert units from Bytes to KiB.
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("v8_alloc", v8_allocated / 1024);
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("v8_used", v8_used / 1024);
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    break;
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->RemoveWebContents(pid);
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (renderer_details_->IsClean())
2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    FinishCollection();
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void MemoryInternalsProxy::ConvertTabsInformation(
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::set<content::WebContents*>& web_contents,
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* processes) {
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (std::set<content::WebContents*>::const_iterator
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           iter = web_contents.begin(); iter != web_contents.end(); ++iter) {
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    content::WebContents* web = *iter;
29929b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    content::RenderProcessHost* process_host = web->GetRenderProcessHost();
30029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    if (!process_host)
30129b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch        continue;
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Find which process renders the web contents.
30429b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    const base::ProcessId pid = base::GetProcId(process_host->GetHandle());
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::DictionaryValue* process = FindProcessFromPid(processes, pid);
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!process)
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Prepare storage to register navigation histories.
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* tabs;
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!process->GetList("history", &tabs)) {
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      tabs = new base::ListValue();
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      process->Set("history", tabs);
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::DictionaryValue* tab = new base::DictionaryValue();
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tabs->Append(tab);
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* histories = new base::ListValue();
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tab->Set("history", histories);
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const content::NavigationController& controller = web->GetController();
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const int entry_size = controller.GetEntryCount();
324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    for (int i = 0; i < entry_size; ++i) {
325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::NavigationEntry *entry = controller.GetEntryAtIndex(i);
326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::DictionaryValue* history = new base::DictionaryValue();
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      histories->Append(history);
328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetString("url", entry->GetURL().spec());
329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetString("title", entry->GetTitle());
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetInteger("time", (base::Time::Now() -
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   entry->GetTimestamp()).InSeconds());
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tab->SetInteger("index", controller.GetCurrentEntryIndex());
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::FinishCollection() {
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetInteger("uptime", base::SysInfo::Uptime());
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetString("os", base::SysInfo::OperatingSystemName());
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetString("os_version",
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          base::SysInfo::OperatingSystemVersion());
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", *information_);
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::CallJavaScriptFunctionOnUIThread(
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& function, const base::Value& args) {
348e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::vector<const base::Value*> args_vector(1, &args);
351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 update =
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      content::WebUI::GetJavascriptCall(function, args_vector);
3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Don't forward updates to a destructed UI.
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (handler_)
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    handler_->OnUpdate(update);
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
357