Chromium Code Reviews| Index: content/browser/devtools/devtools_agent_host_impl.cc |
| diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc |
| index bcb60b55b7832b0348550bead85a164ffffc1539..e4776c022cfe270f9dfe5afff1cac73b10c84fa0 100644 |
| --- a/content/browser/devtools/devtools_agent_host_impl.cc |
| +++ b/content/browser/devtools/devtools_agent_host_impl.cc |
| @@ -5,6 +5,7 @@ |
| #include "content/browser/devtools/devtools_agent_host_impl.h" |
| #include <map> |
| +#include <vector> |
| #include "base/basictypes.h" |
| #include "base/guid.h" |
| @@ -12,17 +13,23 @@ |
| #include "content/browser/devtools/devtools_manager_impl.h" |
| #include "content/browser/devtools/forwarding_agent_host.h" |
| #include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/devtools_manager_delegate.h" |
| namespace content { |
| namespace { |
| typedef std::map<std::string, DevToolsAgentHostImpl*> Instances; |
| base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER; |
| + |
| +typedef std::vector<const DevToolsAgentHost::AgentStateCallback*> |
| + AgentStateCallbacks; |
| +base::LazyInstance<AgentStateCallbacks>::Leaky g_callbacks = |
| + LAZY_INSTANCE_INITIALIZER; |
| } // namespace |
| DevToolsAgentHostImpl::DevToolsAgentHostImpl() |
| - : close_listener_(NULL), |
| - id_(base::GenerateGUID()) { |
| + : id_(base::GenerateGUID()), |
| + client_(NULL) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| g_instances.Get()[id_] = this; |
| } |
| @@ -49,8 +56,27 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Create( |
| return new ForwardingAgentHost(delegate); |
| } |
| +void DevToolsAgentHostImpl::AttachClient(Client* client) { |
| + if (client_) { |
| + client_->AgentHostDetached(this, REPLACED_WITH_ANOTHER_CLIENT); |
| + NotifyCallbacks(this, false); |
| + Detach(); |
| + } else { |
| + // While client is attached, we should not die. |
| + AddRef(); // Balanced in DetachInternal. |
|
pfeldman
2014/08/07 15:40:30
Why is this necessary? Clients will hold agents to
dgozman
2014/08/07 16:51:52
Done.
|
| + DevToolsManagerImpl::GetInstance()->OnClientAttached(); |
| + } |
| + client_ = client; |
| + NotifyCallbacks(this, true); |
| + Attach(); |
| +} |
| + |
| +void DevToolsAgentHostImpl::DetachClient() { |
| + DetachInternal(DETACHED_BY_CLIENT, true); |
| +} |
| + |
| bool DevToolsAgentHostImpl::IsAttached() { |
| - return !!DevToolsManagerImpl::GetInstance()->GetDevToolsClientHostFor(this); |
| + return !!client_; |
| } |
| void DevToolsAgentHostImpl::InspectElement(int x, int y) { |
| @@ -72,12 +98,78 @@ bool DevToolsAgentHostImpl::IsWorker() const { |
| return false; |
| } |
| -void DevToolsAgentHostImpl::NotifyCloseListener() { |
| - if (close_listener_) { |
| - scoped_refptr<DevToolsAgentHostImpl> protect(this); |
| - close_listener_->AgentHostClosing(this); |
| - close_listener_ = NULL; |
| +void DevToolsAgentHostImpl::HostClosed() { |
| + // Don't call Detach, since host is already gone - nothing to detach from. |
| + DetachInternal(HOST_CLOSED, false); |
| +} |
| + |
| +void DevToolsAgentHostImpl::SendMessageToClient(const std::string& message) { |
| + if (!client_) |
| + return; |
| + client_->SendMessageFromAgentHost(this, message); |
| +} |
| + |
| +void DevToolsAgentHostImpl::DetachInternal( |
| + DetachReason reason, bool need_detach) { |
|
pfeldman
2014/08/07 15:40:30
This seems error-prone. The reason should be enoug
dgozman
2014/08/07 16:51:52
Done.
|
| + if (!client_) |
| + return; |
| + |
| + client_->AgentHostDetached(this, reason); |
| + client_ = NULL; |
| + NotifyCallbacks(this, false); |
| + if (need_detach) |
| + Detach(); |
| + Release(); // Balanced in AttachClient. |
| + DevToolsManagerImpl::GetInstance()->OnClientDetached(); |
| +} |
| + |
| +// static |
| +void DevToolsAgentHost::DetachAllClients() { |
| + if (g_instances == NULL) |
| + return; |
| + |
| + // Make a copy, since detaching may lead to agent destruction, which |
| + // removes it from the instances. |
| + Instances copy = g_instances.Get(); |
| + for (Instances::iterator it(copy.begin()); it != copy.end(); ++it) { |
| + it->second->DetachInternal(HOST_CLOSED, true); |
| } |
| } |
| +// static |
| +void DevToolsAgentHost::AddAgentStateCallback( |
| + const AgentStateCallback& callback) { |
| + g_callbacks.Get().push_back(&callback); |
| +} |
| + |
| +// static |
| +void DevToolsAgentHost::RemoveAgentStateCallback( |
| + const AgentStateCallback& callback) { |
| + if (g_callbacks == NULL) |
| + return; |
| + |
| + AgentStateCallbacks* callbacks_ = g_callbacks.Pointer(); |
| + AgentStateCallbacks::iterator it = |
| + std::find(callbacks_->begin(), callbacks_->end(), &callback); |
| + DCHECK(it != callbacks_->end()); |
| + callbacks_->erase(it); |
| +} |
| + |
| +// static |
| +void DevToolsAgentHostImpl::NotifyCallbacks( |
| + DevToolsAgentHostImpl* agent_host, bool attached) { |
| + AgentStateCallbacks copy = g_callbacks.Get(); |
| + DevToolsManagerImpl* manager = DevToolsManagerImpl::GetInstance(); |
| + if (manager->delegate()) |
| + manager->delegate()->DevToolsAgentStateChanged(agent_host, attached); |
| + for (AgentStateCallbacks::iterator it = copy.begin(); it != copy.end(); ++it) |
| + (*it)->Run(agent_host, attached); |
| +} |
| + |
| +void DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) { |
| + DevToolsManagerImpl* manager = DevToolsManagerImpl::GetInstance(); |
| + if (manager->delegate()) |
| + manager->delegate()->Inspect(browser_context, this); |
| +} |
| + |
| } // namespace content |