#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_manager_delegate.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()),
- client_count_(0) {
+ update_target_list_required_(false),
+ update_target_list_scheduled_(false),
+ update_target_list_callback_(base::Bind(
+ &DevToolsManager::UpdateTargetListThrottled,
+ base::Unretained(this))) {
}
DevToolsManager::~DevToolsManager() {
- DCHECK(!client_count_);
+ DCHECK(!attached_hosts_.size());
+ update_target_list_callback_.Cancel();
}
-void DevToolsManager::OnClientAttached() {
- if (!client_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&DevToolsNetLogObserver::Attach));
+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));
+ }
}
- client_count_++;
+
+ UpdateTargetList();
+}
+
+void DevToolsManager::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+ UpdateTargetList();
+}
+
+void DevToolsManager::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
}
-void DevToolsManager::OnClientDetached() {
- client_count_--;
- if (!client_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
+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,
- base::Bind(&DevToolsNetLogObserver::Detach));
+ 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