memory_internals_proxy.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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;
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    for (int i = 0; i < model->GetTabCount(); ++i)
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      web_contents->insert(model->GetWebContentsAt(i));
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#else
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (TabContentsIterator iter; !iter.done(); iter.Next())
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    web_contents->insert(*iter);
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Add all the prerender pages.
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Profile*> profiles(
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < profiles.size(); ++i) {
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    prerender::PrerenderManager* prerender_manager =
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        prerender::PrerenderManagerFactory::GetForProfile(profiles[i]);
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!prerender_manager)
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::vector<content::WebContents*> contentses =
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        prerender_manager->GetAllPrerenderingContents();
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents->insert(contentses.begin(), contentses.end());
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
109c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#if defined(ENABLE_FULL_PRINTING)
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Add all the pages being background printed.
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  printing::BackgroundPrintingManager* printing_manager =
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      g_browser_process->background_printing_manager();
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<content::WebContents*> printing_contents =
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printing_manager->CurrentContentSet();
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents->insert(printing_contents.begin(), printing_contents.end());
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass RendererDetails : public content::NotificationObserver {
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef base::Callback<void(const base::ProcessId pid,
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              const size_t v8_allocated,
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              const size_t v8_used)> V8DataCallback;
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit RendererDetails(const V8DataCallback& callback)
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : callback_(callback) {
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    registrar_.Add(this, chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   content::NotificationService::AllSources());
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~RendererDetails() {}
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Request() {
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (std::set<content::WebContents*>::iterator iter = web_contents_.begin();
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         iter != web_contents_.end(); ++iter)
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (*iter)->GetRenderViewHost()->Send(new ChromeViewMsg_GetV8HeapStats);
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddWebContents(content::WebContents* content) {
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    web_contents_.insert(content);
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Clear() {
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    web_contents_.clear();
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void RemoveWebContents(base::ProcessId) {
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // We don't have to detect which content is the caller of this method.
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!web_contents_.empty())
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_contents_.erase(web_contents_.begin());
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int IsClean() {
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return web_contents_.empty();
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // NotificationObserver:
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void Observe(int type,
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       const content::NotificationSource& source,
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       const content::NotificationDetails& details) OVERRIDE {
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::ProcessId* pid =
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        content::Source<const base::ProcessId>(source).ptr();
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const ChromeRenderMessageFilter::V8HeapStatsDetails* v8_heap =
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        content::Details<const ChromeRenderMessageFilter::V8HeapStatsDetails>(
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            details).ptr();
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callback_.Run(*pid,
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  v8_heap->v8_memory_allocated(),
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  v8_heap->v8_memory_used());
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  V8DataCallback callback_;
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  content::NotificationRegistrar registrar_;
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::set<content::WebContents*> web_contents_;  // This class does not own
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(RendererDetails);
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMemoryInternalsProxy::MemoryInternalsProxy()
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : information_(new base::DictionaryValue()),
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      renderer_details_(new RendererDetails(
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          base::Bind(&MemoryInternalsProxy::OnRendererAvailable, this))) {}
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::Attach(MemoryInternalsHandler* handler) {
186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  handler_ = handler;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::Detach() {
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  handler_ = NULL;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::StartFetch(const base::ListValue* list) {
196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Clear previous information before fetching new information.
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Clear();
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<ProcessDetails> process(new ProcessDetails(
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&MemoryInternalsProxy::OnProcessAvailable, this)));
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process->StartFetch(MemoryDetails::SKIP_USER_METRICS);
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MemoryInternalsProxy::~MemoryInternalsProxy() {}
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::RequestRendererDetails() {
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->Clear();
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_ANDROID)
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (TabModelList::const_iterator iter = TabModelList::begin();
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       iter != TabModelList::end(); ++iter) {
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TabModel* model = *iter;
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (int i = 0; i < model->GetTabCount(); ++i)
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      renderer_details_->AddWebContents(model->GetWebContentsAt(i));
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#else
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (TabContentsIterator iter; !iter.done(); iter.Next())
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    renderer_details_->AddWebContents(*iter);
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->Request();
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::OnProcessAvailable(const ProcessData& browser) {
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* process_info = new base::ListValue();
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* extension_info = new base::ListValue();
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Set("processes", process_info);
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  information_->Set("extensions", extension_info);
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (PMIIterator iter = browser.processes.begin();
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       iter != browser.processes.end(); ++iter) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* process = new base::DictionaryValue();
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (iter->renderer_type == ProcessMemoryInformation::RENDERER_EXTENSION)
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      extension_info->Append(process);
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    else
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      process_info->Append(process);
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // From MemoryDetails.
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("pid", iter->pid);
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetString("type",
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       ProcessMemoryInformation::GetFullTypeNameInEnglish(
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           iter->process_type, iter->renderer_type));
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("memory_private", iter->working_set.priv);
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* titles = new base::ListValue();
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->Set("titles", titles);
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (size_t i = 0; i < iter->titles.size(); ++i)
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      titles->AppendString(iter->titles[i]);
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::set<content::WebContents*> web_contents;
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetAllWebContents(&web_contents);
253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ConvertTabsInformation(web_contents, process_info);
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  RequestRendererDetails();
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::OnRendererAvailable(const base::ProcessId pid,
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               const size_t v8_allocated,
2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               const size_t v8_used) {
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Do not update while no renderers are registered.
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (renderer_details_->IsClean())
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ListValue* processes;
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!information_->GetList("processes", &processes))
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t size = processes->GetSize();
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < size; ++i) {
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::DictionaryValue* process;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    processes->GetDictionary(i, &process);
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int id;
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!process->GetInteger("pid", &id) || id != static_cast<int>(pid))
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      continue;
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Convert units from Bytes to KiB.
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("v8_alloc", v8_allocated / 1024);
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    process->SetInteger("v8_used", v8_used / 1024);
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    break;
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  renderer_details_->RemoveWebContents(pid);
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (renderer_details_->IsClean())
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    FinishCollection();
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void MemoryInternalsProxy::ConvertTabsInformation(
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::set<content::WebContents*>& web_contents,
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* processes) {
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (std::set<content::WebContents*>::const_iterator
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           iter = web_contents.begin(); iter != web_contents.end(); ++iter) {
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    content::WebContents* web = *iter;
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const base::ProcessId pid = base::GetProcId(
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        web->GetRenderProcessHost()->GetHandle());
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Find which process renders the web contents.
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::DictionaryValue* process = FindProcessFromPid(processes, pid);
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!process)
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Prepare storage to register navigation histories.
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* tabs;
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!process->GetList("history", &tabs)) {
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      tabs = new base::ListValue();
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      process->Set("history", tabs);
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::DictionaryValue* tab = new base::DictionaryValue();
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tabs->Append(tab);
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* histories = new base::ListValue();
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tab->Set("history", histories);
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const content::NavigationController& controller = web->GetController();
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const int entry_size = controller.GetEntryCount();
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    for (int i = 0; i < entry_size; ++i) {
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::NavigationEntry *entry = controller.GetEntryAtIndex(i);
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::DictionaryValue* history = new base::DictionaryValue();
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      histories->Append(history);
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetString("url", entry->GetURL().spec());
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetString("title", entry->GetTitle());
322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      history->SetInteger("time", (base::Time::Now() -
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   entry->GetTimestamp()).InSeconds());
324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tab->SetInteger("index", controller.GetCurrentEntryIndex());
326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MemoryInternalsProxy::FinishCollection() {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetInteger("uptime", base::SysInfo::Uptime());
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetString("os", base::SysInfo::OperatingSystemName());
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  information_->SetString("os_version",
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          base::SysInfo::OperatingSystemVersion());
334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", *information_);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MemoryInternalsProxy::CallJavaScriptFunctionOnUIThread(
3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& function, const base::Value& args) {
340e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::vector<const base::Value*> args_vector(1, &args);
343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 update =
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      content::WebUI::GetJavascriptCall(function, args_vector);
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Don't forward updates to a destructed UI.
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (handler_)
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    handler_->OnUpdate(update);
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
349