Commit 963710c4 authored by afakhry's avatar afakhry Committed by Commit bot

New Task Manager - Phase 1.1: Implement Browser Process Task Providing

R=nick@chromium.org
BUG=470956
TEST=unit_tests --gtest_filter=BrowserProcessTaskProviderTest.*

Review URL: https://codereview.chromium.org/1038033002

Cr-Commit-Position: refs/heads/master@{#323929}
parent de8b6d82
afakhry@chromium.org
nick@chromium.org
// Copyright 2015 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/task_management/providers/browser_process_task.h"
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/proxy/proxy_resolver_v8.h"
#include "third_party/sqlite/sqlite3.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#if defined(OS_MACOSX)
#include "ui/gfx/image/image_skia_util_mac.h"
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
#include "chrome/browser/app_icon_win.h"
#include "ui/gfx/icon_util.h"
#endif // defined(OS_WIN)
namespace task_management {
namespace {
gfx::ImageSkia* g_default_icon = nullptr;
gfx::ImageSkia* GetDefaultIcon() {
if (!g_default_icon) {
#if defined(OS_WIN)
HICON icon = GetAppIcon();
if (icon) {
scoped_ptr<SkBitmap> bitmap(IconUtil::CreateSkBitmapFromHICON(icon));
g_default_icon = new gfx::ImageSkia(gfx::ImageSkiaRep(*bitmap, 1.0f));
}
#elif defined(OS_POSIX)
if (ResourceBundle::HasSharedInstance()) {
g_default_icon = ResourceBundle::GetSharedInstance().
GetImageSkiaNamed(IDR_PRODUCT_LOGO_16);
}
#else
// TODO(port): Port icon code.
NOTIMPLEMENTED();
#endif // defined(OS_WIN)
if (g_default_icon)
g_default_icon->MakeThreadSafe();
}
return g_default_icon;
}
bool ReportsV8Stats() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
return !command_line->HasSwitch(switches::kWinHttpProxyResolver) &&
!command_line->HasSwitch(switches::kSingleProcess);
}
} // namespace
BrowserProcessTask::BrowserProcessTask()
: Task(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT),
*GetDefaultIcon(),
base::GetCurrentProcessHandle()),
allocated_v8_memory_(-1),
used_v8_memory_(-1),
used_sqlite_memory_(-1),
reports_v8_stats_(ReportsV8Stats()){
}
BrowserProcessTask::~BrowserProcessTask() {
}
void BrowserProcessTask::Refresh(const base::TimeDelta& update_interval) {
Task::Refresh(update_interval);
// TODO(afakhry): Add code to skip v8 and sqlite stats update if they have
// never been requested.
if (reports_v8_stats_) {
allocated_v8_memory_ =
static_cast<int64>(net::ProxyResolverV8::GetTotalHeapSize());
used_v8_memory_ =
static_cast<int64>(net::ProxyResolverV8::GetUsedHeapSize());
}
used_sqlite_memory_ = static_cast<int64>(sqlite3_memory_used());
}
Task::Type BrowserProcessTask::GetType() const {
return Task::BROWSER;
}
int BrowserProcessTask::GetChildProcessUniqueID() const {
return 0;
}
int64 BrowserProcessTask::GetSqliteMemoryUsed() const {
return used_sqlite_memory_;
}
int64 BrowserProcessTask::GetV8MemoryAllocated() const {
return allocated_v8_memory_;
}
int64 BrowserProcessTask::GetV8MemoryUsed() const {
return used_v8_memory_;
}
} // namespace task_management
// Copyright 2015 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.
#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_H_
#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_H_
#include "chrome/browser/task_management/providers/task.h"
namespace task_management {
// Defines the task that represents the one and only browser main process.
class BrowserProcessTask : public Task {
public:
BrowserProcessTask();
~BrowserProcessTask() override;
// task_management::Task:
void Refresh(const base::TimeDelta& update_interval) override;
Type GetType() const override;
int GetChildProcessUniqueID() const override;
int64 GetSqliteMemoryUsed() const override;
int64 GetV8MemoryAllocated() const override;
int64 GetV8MemoryUsed() const override;
private:
int64 allocated_v8_memory_;
int64 used_v8_memory_;
int64 used_sqlite_memory_;
bool reports_v8_stats_;
DISALLOW_COPY_AND_ASSIGN(BrowserProcessTask);
};
} // namespace task_management
#endif // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_H_
// Copyright 2015 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/task_management/providers/browser_process_task_provider.h"
namespace task_management {
BrowserProcessTaskProvider::BrowserProcessTaskProvider()
: browser_process_task_() {
}
BrowserProcessTaskProvider::~BrowserProcessTaskProvider() {
}
Task* BrowserProcessTaskProvider::GetTaskOfUrlRequest(int origin_pid,
int child_id,
int route_id) {
if (origin_pid == 0 && child_id == -1)
return &browser_process_task_;
return nullptr;
}
void BrowserProcessTaskProvider::StartUpdating() {
NotifyObserverTaskAdded(&browser_process_task_);
}
void BrowserProcessTaskProvider::StopUpdating() {
// There's nothing to do here. The browser process task live as long as the
// browser lives and when StopUpdating() is called the |observer_| has already
// been cleared.
}
} // namespace task_management
// Copyright 2015 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.
#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_PROVIDER_H_
#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_PROVIDER_H_
#include "chrome/browser/task_management/providers/browser_process_task.h"
#include "chrome/browser/task_management/providers/task_provider.h"
namespace task_management {
// This provides the browser process task which lives as long as the browser
// lives.
class BrowserProcessTaskProvider : public TaskProvider {
public:
BrowserProcessTaskProvider();
~BrowserProcessTaskProvider() override;
// task_management::TaskProvider:
Task* GetTaskOfUrlRequest(int origin_pid,
int child_id,
int route_id) override;
private:
// task_management::TaskProvider:
void StartUpdating() override;
void StopUpdating() override;
// This is the task that represents the one and only main browser process. It
// lives as long as the browser lives.
BrowserProcessTask browser_process_task_;
DISALLOW_COPY_AND_ASSIGN(BrowserProcessTaskProvider);
};
} // namespace task_management
#endif // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_BROWSER_PROCESS_TASK_PROVIDER_H_
// Copyright 2015 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/task_management/providers/browser_process_task_provider.h"
#include "chrome/grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
namespace task_management {
class BrowserProcessTaskProviderTest
: public testing::Test,
public TaskProviderObserver {
public:
BrowserProcessTaskProviderTest()
: provided_task_(nullptr) {
}
~BrowserProcessTaskProviderTest() override {}
// task_management::TaskProviderObserver:
void TaskAdded(Task* task) override {
provided_task_ = task;
}
void TaskRemoved(Task* task) override {
// This will never be called in the case of a browser process task provider.
FAIL();
}
protected:
Task* provided_task_;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserProcessTaskProviderTest);
};
// Tests the browser process task provider and browser process task itself.
TEST_F(BrowserProcessTaskProviderTest, TestObserving) {
BrowserProcessTaskProvider provider;
EXPECT_EQ(nullptr, provided_task_);
provider.SetObserver(this);
EXPECT_NE(nullptr, provided_task_);
provider.ClearObserver();
EXPECT_NE(nullptr, provided_task_);
}
// Testing retrieving the task from the provider using the ids of a URL request.
TEST_F(BrowserProcessTaskProviderTest, GetTaskOfUrlRequest) {
BrowserProcessTaskProvider provider;
EXPECT_EQ(nullptr, provided_task_);
provider.SetObserver(this);
EXPECT_NE(nullptr, provided_task_);
Task* result = provider.GetTaskOfUrlRequest(1, 0, 0);
EXPECT_EQ(nullptr, result);
result = provider.GetTaskOfUrlRequest(0, -1, 0);
EXPECT_EQ(provided_task_, result);
}
// Test the provided browser process task itself.
TEST_F(BrowserProcessTaskProviderTest, TestProvidedTask) {
BrowserProcessTaskProvider provider;
EXPECT_EQ(nullptr, provided_task_);
provider.SetObserver(this);
ASSERT_NE(nullptr, provided_task_);
EXPECT_EQ(base::GetCurrentProcessHandle(), provided_task_->process_handle());
EXPECT_FALSE(provided_task_->ReportsWebCacheStats());
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT),
provided_task_->title());
EXPECT_EQ(Task::BROWSER, provided_task_->GetType());
EXPECT_EQ(0, provided_task_->GetChildProcessUniqueID());
EXPECT_EQ(0, provided_task_->GetRoutingID());
const int received_bytes = 1024;
EXPECT_FALSE(provided_task_->ReportsNetworkUsage());
EXPECT_EQ(-1, provided_task_->network_usage());
provided_task_->OnNetworkBytesRead(received_bytes);
// Do a refresh with a 1-second update time.
provided_task_->Refresh(base::TimeDelta::FromSeconds(1));
EXPECT_TRUE(provided_task_->ReportsNetworkUsage());
EXPECT_EQ(received_bytes, provided_task_->network_usage());
}
} // namespace task_management
// Copyright 2015 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/task_management/providers/task.h"
namespace task_management {
namespace {
// The last ID given to the previously created task.
int64 g_last_id = 0;
} // namespace
Task::Task(const base::string16& title,
const gfx::ImageSkia& icon,
base::ProcessHandle handle)
: task_id_(g_last_id++),
network_usage_(-1),
current_byte_count_(-1),
title_(title),
icon_(icon),
process_handle_(handle) {
}
Task::~Task() {
}
void Task::Refresh(const base::TimeDelta& update_interval) {
// TODO(afakhry): Add code here to skip this when network usage refresh has
// never been requested.
if (current_byte_count_ == -1)
return;
network_usage_ =
(current_byte_count_ * base::TimeDelta::FromSeconds(1)) / update_interval;
// Reset the current byte count for this task.
current_byte_count_ = 0;
}
void Task::OnNetworkBytesRead(int64 bytes_read) {
if (current_byte_count_ == -1)
current_byte_count_ = 0;
current_byte_count_ += bytes_read;
}
base::string16 Task::GetProfileName() const {
return base::string16();
}
int Task::GetRoutingID() const {
return 0;
}
bool Task::ReportsSqliteMemory() const {
return GetSqliteMemoryUsed() != -1;
}
int64 Task::GetSqliteMemoryUsed() const {
return -1;
}
bool Task::ReportsV8Memory() const {
return GetV8MemoryAllocated() != -1;
}
int64 Task::GetV8MemoryAllocated() const {
return -1;
}
int64 Task::GetV8MemoryUsed() const {
return -1;
}
bool Task::ReportsWebCacheStats() const {
return false;
}
blink::WebCache::ResourceTypeStats Task::GetWebCacheStats() const {
return blink::WebCache::ResourceTypeStats();
}
bool Task::ReportsNetworkUsage() const {
return network_usage_ != -1;
}
} // namespace task_management
// Copyright 2015 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.
#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_H_
#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_H_
#include "base/basictypes.h"
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "third_party/WebKit/public/web/WebCache.h"
#include "ui/gfx/image/image_skia.h"
namespace task_management {
// Defines a task that corresponds to a tab, an app, an extension, ... etc. It
// represents one row in the task manager table. Multiple tasks can share the
// same process, in which case they're grouped together in the task manager
// table. See |task_management::TaskGroup| which represents a process possibly
// shared by multiple tasks.
class Task {
public:
enum Type {
UNKNOWN = 0,
BROWSER, /* The main browser process. */
RENDERER, /* A normal WebContents renderer process. */
EXTENSION, /* An extension or app process. */
GUEST, /* A browser plugin guest process. */
PLUGIN, /* A plugin process. */
WORKER, /* A web worker process. */
NACL, /* A NativeClient loader or broker process. */
UTILITY, /* A browser utility process. */
ZYGOTE, /* A Linux zygote process. */
SANDBOX_HELPER, /* A sandbox helper process. */
GPU, /* A graphics process. */
};
// Create a task with the given |title| and the given Fav |icon|. This task
// runs on a process whose handle is |handle|.
Task(const base::string16& title,
const gfx::ImageSkia& icon,
base::ProcessHandle handle);
virtual ~Task();
// Will be called to let the task refresh itself between refresh cycles.
// |update_interval| is the time since the last task manager refresh.
virtual void Refresh(const base::TimeDelta& update_interval);
// Will receive this notification through the task manager from
// |ChromeNetworkDelegate::OnRawBytesRead()|. The task will add to the
// |current_byte_count_| in this refresh cycle.
void OnNetworkBytesRead(int64 bytes_read);
// Returns the task type.
virtual Type GetType() const = 0;
// This is the unique ID of the BrowserChildProcessHost/RenderProcessHost. It
// is not the PID nor the handle of the process.
// For a task that represents the browser process, the return value is 0. For
// other tasks that represent renderers and other child processes, the return
// value is whatever unique IDs of their hosts in the browser process.
virtual int GetChildProcessUniqueID() const = 0;
// The name of the profile associated with the browser context of the render
// view host that this task represents (if this task represents a renderer).
virtual base::string16 GetProfileName() const;
// If this task represents a renderer process, this would the return the
// routing ID of the RenderViewHost, otherwise it will return 0.
virtual int GetRoutingID() const;
// Getting the Sqlite used memory (in bytes). Not all tasks reports Sqlite
// memory, in this case a default invalid value of -1 will be returned.
// Check for whether the task reports it or not first.
bool ReportsSqliteMemory() const;
virtual int64 GetSqliteMemoryUsed() const;
// Getting the allocated and used V8 memory (in bytes). Not all tasks reports
// V8 memory, in this case a default invalid value of -1 will be returned.
// Check for whether the task reports it or not first.
bool ReportsV8Memory() const;
virtual int64 GetV8MemoryAllocated() const;
virtual int64 GetV8MemoryUsed() const;
// Checking if the task reports Webkit resource cache statistics and getting
// them if it does.
virtual bool ReportsWebCacheStats() const;
virtual blink::WebCache::ResourceTypeStats GetWebCacheStats() const;
// Checking whether the task reports network usage.
bool ReportsNetworkUsage() const;
int64 task_id() const { return task_id_; }
int64 network_usage() const { return network_usage_; }
const base::string16& title() const { return title_; }
const gfx::ImageSkia& icon() const { return icon_; }
const base::ProcessHandle& process_handle() const { return process_handle_; }
private:
// The unique ID of this task.
const int64 task_id_;
// The task's network usage in the current refresh cycle measured in bytes per
// second. A value of -1 means this task doesn't report network usage data.
int64 network_usage_;
// The current network bytes received by this task during the current refresh
// cycle. A value of -1 means this task has never been notified of any network
// usage.
int64 current_byte_count_;
// The title of the task.
base::string16 title_;
// The Fav icon.
gfx::ImageSkia icon_;
// The handle of the process on which this task is running.
const base::ProcessHandle process_handle_;
DISALLOW_COPY_AND_ASSIGN(Task);
};
} // namespace task_management
#endif // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_H_
// Copyright 2015 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/task_management/providers/task_provider.h"
namespace task_management {
TaskProvider::TaskProvider()
: observer_(nullptr) {
}
TaskProvider::~TaskProvider() {
}
void TaskProvider::SetObserver(TaskProviderObserver* observer) {
DCHECK(observer);
DCHECK(!observer_);
observer_ = observer;
StartUpdating();
}
void TaskProvider::ClearObserver() {
DCHECK(observer_);
observer_ = nullptr;
StopUpdating();
}
void TaskProvider::NotifyObserverTaskAdded(Task* task) const {
DCHECK(observer_);
observer_->TaskAdded(task);
}
void TaskProvider::NotifyObserverTaskRemoved(Task* task) const {
DCHECK(observer_);
observer_->TaskRemoved(task);
}
} // namespace task_management
// Copyright 2015 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.
#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_H_
#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_H_
#include "chrome/browser/task_management/providers/task_provider_observer.h"
namespace task_management {
// Defines the interface for task providers. A concrete task provider must be
// able to collect all the tasks of a particular type which this provider
// supports as well as track any tasks addition / removal. Once StartUpdating()
// is called, the provider is responsible for notifying the observer about the
// tasks it's tracking. The TaskProviders own the tasks they provide.
class TaskProvider {
public:
TaskProvider();
virtual ~TaskProvider();
// Should return the task associated to the specified IDs from a
// |content::ResourceRequestInfo| that represents a |URLRequest|. A value of
// nullptr will be returned if the desired task does not belong to this
// provider.
//
// |origin_pid| is the PID of the originating process of the URLRequest, if
// the request is sent on behalf of another process. Otherwise it's 0.
// |child_id| is the unique ID of the host of the child process requestor.
// |route_id| is the ID of the IPC route for the URLRequest (this identifies
// the RenderView or like-thing in the renderer that the request gets routed
// to).
virtual Task* GetTaskOfUrlRequest(int origin_pid,
int child_id,
int route_id) = 0;
// Set the sole observer of this provider. It's an error to set an observer
// if there's already one there.
void SetObserver(TaskProviderObserver* observer);
// Clears the currently set observer for this provider. It's an error to clear
// the observer if there's no one set.
void ClearObserver();
protected:
// Used by concrete task providers to notify the observer of tasks addition/
// removal. These methods should only be called after StartUpdating() has been
// called and before StopUpdating() is called.
void NotifyObserverTaskAdded(Task* task) const;
void NotifyObserverTaskRemoved(Task* task) const;
private:
// This will be called once an observer is set for this provider. When it is
// called, the concrete provider must notify the observer of all pre-existing
// tasks as well as track new addition and terminations and notify the
// observer of these changes.
virtual void StartUpdating() = 0;
// This will be called once the observer is cleared, at which point the
// provider can stop tracking tasks addition / removal and can clear its own
// resources.
virtual void StopUpdating() = 0;
// We support only one single obsever which will be the sampler in this case.
TaskProviderObserver* observer_;
DISALLOW_COPY_AND_ASSIGN(TaskProvider);
};
} // namespace task_management
#endif // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_H_
// Copyright 2015 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.
#ifndef CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_OBSERVER_H_
#define CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_OBSERVER_H_
#include "chrome/browser/task_management/providers/task.h"
namespace task_management {
// Defines an interface for observing tasks addition / removal.
class TaskProviderObserver {
public:
TaskProviderObserver() {}
virtual ~TaskProviderObserver() {}
// This notifies of the event that a new |task| has been created.
virtual void TaskAdded(Task* task) = 0;
// This notifies of the event that a |task| is about to be removed. The task
// is still valid during this call, after that it may never be used again by
// the observer and references to it must not be kept.
virtual void TaskRemoved(Task* task) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(TaskProviderObserver);
};
} // namespace task_management
#endif // CHROME_BROWSER_TASK_MANAGEMENT_PROVIDERS_TASK_PROVIDER_OBSERVER_H_
......@@ -2850,6 +2850,18 @@
'browser/sync/sync_type_preference_provider.h',
],
'chrome_browser_task_manager_sources': [
# New Task Manager Sources:
'browser/task_management/providers/browser_process_task_provider.cc',
'browser/task_management/providers/browser_process_task_provider.h',
'browser/task_management/providers/browser_process_task.cc',
'browser/task_management/providers/browser_process_task.h',
'browser/task_management/providers/task_provider_observer.h',
'browser/task_management/providers/task_provider.cc',
'browser/task_management/providers/task_provider.h',
'browser/task_management/providers/task.cc',
'browser/task_management/providers/task.h',
# Old Task Manager Sources:
'browser/task_manager/background_information.cc',
'browser/task_manager/background_information.h',
'browser/task_manager/browser_process_resource_provider.cc',
......
......@@ -954,6 +954,10 @@
'browser/ui/window_sizer/window_sizer_ash_unittest.cc',
],
'chrome_unit_tests_task_manager_sources': [
# New Task Manager Tests Sources:
'browser/task_management/providers/browser_process_task_unittest.cc',
# Old Task Manager Tests Sources:
'browser/task_manager/task_manager_unittest.cc',
'browser/task_manager/task_manager_util_unittest.cc',
],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment