blob: f405185a24d3c43c8165cf1a6a65a843d8330ee1 [file] [log] [blame]
// Copyright (c) 2012 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 "content/browser/devtools/devtools_manager.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_netlog_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_target.h"
namespace content {
namespace {
int kObserverThrottleInterval = 500; // ms
} // namespace
// static
DevToolsManager* DevToolsManager::GetInstance() {
return Singleton<DevToolsManager>::get();
}
DevToolsManager::DevToolsManager()
: delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()),
update_target_list_required_(false),
update_target_list_scheduled_(false),
update_target_list_callback_(base::Bind(
&DevToolsManager::UpdateTargetListThrottled,
base::Unretained(this))) {
}
DevToolsManager::~DevToolsManager() {
DCHECK(!attached_hosts_.size());
update_target_list_callback_.Cancel();
}
void DevToolsManager::RenderViewCreated(
WebContents* web_contents, RenderViewHost* rvh) {
if (observer_list_.might_have_observers()) {
// Force agent host creation.
DevToolsAgentHost::GetOrCreateFor(web_contents);
}
}
void DevToolsManager::AgentHostChanged(
scoped_refptr<DevToolsAgentHost> agent_host) {
bool was_attached =
attached_hosts_.find(agent_host.get()) != attached_hosts_.end();
if (agent_host->IsAttached() && !was_attached) {
if (!attached_hosts_.size()) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&DevToolsNetLogObserver::Attach));
}
attached_hosts_.insert(agent_host.get());
} else if (!agent_host->IsAttached() && was_attached) {
attached_hosts_.erase(agent_host.get());
if (!attached_hosts_.size()) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&DevToolsNetLogObserver::Detach));
}
}
UpdateTargetList();
}
void DevToolsManager::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
UpdateTargetList();
}
void DevToolsManager::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void DevToolsManager::UpdateTargetList() {
if (!observer_list_.might_have_observers())
return;
update_target_list_required_ = true;
if (!update_target_list_scheduled_)
UpdateTargetListThrottled();
}
void DevToolsManager::UpdateTargetListThrottled() {
if (!update_target_list_required_) {
update_target_list_scheduled_ = false;
return;
}
update_target_list_scheduled_ = true;
if (scheduler_.is_null()) {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
update_target_list_callback_.callback(),
base::TimeDelta::FromMilliseconds(kObserverThrottleInterval));
} else {
scheduler_.Run(update_target_list_callback_.callback());
}
update_target_list_required_ = false;
if (!delegate_) {
Observer::TargetList empty_list;
NotifyTargetListChanged(empty_list);
return;
}
delegate_->EnumerateTargets(base::Bind(
&DevToolsManager::NotifyTargetListChanged,
base::Unretained(this)));
}
void DevToolsManager::NotifyTargetListChanged(
const Observer::TargetList& targets) {
FOR_EACH_OBSERVER(Observer, observer_list_, TargetListChanged(targets));
STLDeleteContainerPointers(targets.begin(), targets.end());
}
void DevToolsManager::SetSchedulerForTest(Scheduler scheduler) {
scheduler_ = scheduler;
}
} // namespace content