| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/debugger/devtools_manager.h" | 5 #include "chrome/browser/debugger/devtools_manager.h" |
| 6 | 6 |
| 7 #include "chrome/browser/debugger/devtools_window.h" | 7 #include "chrome/browser/debugger/devtools_window.h" |
| 8 #include "chrome/browser/debugger/devtools_client_host.h" |
| 8 #include "chrome/browser/renderer_host/render_view_host.h" | 9 #include "chrome/browser/renderer_host/render_view_host.h" |
| 9 #include "chrome/browser/tab_contents/tab_contents.h" | 10 #include "chrome/browser/tab_contents/tab_contents.h" |
| 10 #include "chrome/browser/tab_contents/web_contents.h" | 11 #include "chrome/browser/tab_contents/web_contents.h" |
| 11 #include "chrome/common/notification_registrar.h" | 12 #include "chrome/common/notification_registrar.h" |
| 12 #include "chrome/common/notification_type.h" | 13 #include "chrome/common/notification_type.h" |
| 13 | 14 |
| 14 | 15 DevToolsManager::DevToolsManager() : web_contents_listeners_(NULL) { |
| 15 class DevToolsInstanceDescriptorImpl : public DevToolsInstanceDescriptor { | |
| 16 public: | |
| 17 explicit DevToolsInstanceDescriptorImpl( | |
| 18 DevToolsManager* manager, | |
| 19 NavigationController* navigation_controller) | |
| 20 : manager_(manager), | |
| 21 navigation_controller_(navigation_controller), | |
| 22 devtools_host_(NULL), | |
| 23 devtools_window_(NULL) { | |
| 24 } | |
| 25 virtual ~DevToolsInstanceDescriptorImpl() {} | |
| 26 | |
| 27 virtual void SetDevToolsHost(RenderViewHost* render_view_host) { | |
| 28 devtools_host_ = render_view_host; | |
| 29 } | |
| 30 | |
| 31 virtual void SetDevToolsWindow(DevToolsWindow* window) { | |
| 32 devtools_window_ = window; | |
| 33 } | |
| 34 | |
| 35 virtual void Destroy() { | |
| 36 manager_->RemoveDescriptor(this); | |
| 37 delete this; | |
| 38 } | |
| 39 | |
| 40 RenderViewHost* devtools_host() const { | |
| 41 return devtools_host_; | |
| 42 } | |
| 43 | |
| 44 DevToolsWindow* devtools_window() const { | |
| 45 return devtools_window_; | |
| 46 } | |
| 47 | |
| 48 NavigationController* navigation_controller() const { | |
| 49 return navigation_controller_; | |
| 50 } | |
| 51 | |
| 52 private: | |
| 53 DevToolsManager* manager_; | |
| 54 NavigationController* navigation_controller_; | |
| 55 RenderViewHost* devtools_host_; | |
| 56 DevToolsWindow* devtools_window_; | |
| 57 | |
| 58 DISALLOW_COPY_AND_ASSIGN(DevToolsInstanceDescriptorImpl); | |
| 59 }; | |
| 60 | |
| 61 DevToolsManager::DevToolsManager(DevToolsWindowFactory* factory) | |
| 62 : web_contents_listeners_(NULL), | |
| 63 devtools_window_factory_(factory) { | |
| 64 } | 16 } |
| 65 | 17 |
| 66 DevToolsManager::~DevToolsManager() { | 18 DevToolsManager::~DevToolsManager() { |
| 67 DCHECK(!web_contents_listeners_.get()) << | 19 DCHECK(!web_contents_listeners_.get()) << |
| 68 "All devtools windows must alredy have been closed."; | 20 "All devtools client hosts must alredy have been destroyed."; |
| 69 } | 21 DCHECK(navcontroller_to_client_host_.empty()); |
| 70 | 22 DCHECK(client_host_to_navcontroller_.empty()); |
| 71 DevToolsWindow* DevToolsManager::CreateDevToolsWindow( | |
| 72 DevToolsInstanceDescriptor* descriptor) { | |
| 73 if (devtools_window_factory_) { | |
| 74 return devtools_window_factory_->CreateDevToolsWindow(descriptor); | |
| 75 } else { | |
| 76 return DevToolsWindow::Create(descriptor); | |
| 77 } | |
| 78 } | 23 } |
| 79 | 24 |
| 80 void DevToolsManager::Observe(NotificationType type, | 25 void DevToolsManager::Observe(NotificationType type, |
| 81 const NotificationSource& source, | 26 const NotificationSource& source, |
| 82 const NotificationDetails& details) { | 27 const NotificationDetails& details) { |
| 83 DCHECK(type == NotificationType::WEB_CONTENTS_DISCONNECTED); | 28 DCHECK(type == NotificationType::WEB_CONTENTS_DISCONNECTED); |
| 29 |
| 84 Source<WebContents> src(source); | 30 Source<WebContents> src(source); |
| 85 NavigationController* controller = src->controller(); | 31 DevToolsClientHost* client_host = GetDevToolsClientHostFor(*src.ptr()); |
| 86 DescriptorMap::const_iterator it = | 32 if (!client_host) { |
| 87 navcontroller_to_descriptor_.find(controller); | |
| 88 if (it == navcontroller_to_descriptor_.end()) { | |
| 89 return; | 33 return; |
| 90 } | 34 } |
| 35 |
| 36 NavigationController* controller = src->controller(); |
| 91 bool active = (controller->active_contents() == src.ptr()); | 37 bool active = (controller->active_contents() == src.ptr()); |
| 92 if (!active) { | 38 if (active) { |
| 93 return; | 39 // Active tab contents disconnecting from its renderer means that the tab |
| 40 // is closing. |
| 41 client_host->InspectedTabClosing(); |
| 94 } | 42 } |
| 95 // Active tab contents disconnecting from its renderer means that the tab | |
| 96 // is closing so we are closing devtools as well. | |
| 97 it->second->devtools_window()->Close(); | |
| 98 } | 43 } |
| 99 | 44 |
| 100 void DevToolsManager::ShowDevToolsForWebContents(WebContents* web_contents) { | 45 DevToolsClientHost* DevToolsManager::GetDevToolsClientHostFor( |
| 101 NavigationController* navigation_controller = web_contents->controller(); | 46 const WebContents& web_contents) { |
| 102 | 47 NavigationController* navigation_controller = web_contents.controller(); |
| 103 DevToolsWindow* window(NULL); | 48 ClientHostMap::const_iterator it = |
| 104 DevToolsInstanceDescriptorImpl* desc(NULL); | 49 navcontroller_to_client_host_.find(navigation_controller); |
| 105 DescriptorMap::const_iterator it = | 50 if (it != navcontroller_to_client_host_.end()) { |
| 106 navcontroller_to_descriptor_.find(navigation_controller); | 51 return it->second; |
| 107 if (it != navcontroller_to_descriptor_.end()) { | |
| 108 desc = it->second; | |
| 109 window = desc->devtools_window(); | |
| 110 } else { | |
| 111 desc = new DevToolsInstanceDescriptorImpl(this, navigation_controller); | |
| 112 navcontroller_to_descriptor_[navigation_controller] = desc; | |
| 113 | |
| 114 StartListening(navigation_controller); | |
| 115 | |
| 116 window = CreateDevToolsWindow(desc); | |
| 117 } | 52 } |
| 118 | 53 return NULL; |
| 119 window->Show(); | |
| 120 } | 54 } |
| 121 | 55 |
| 122 void DevToolsManager::ForwardToDevToolsAgent(RenderViewHost* from, | 56 void DevToolsManager::RegisterDevToolsClientHostFor( |
| 123 const IPC::Message& message) { | 57 const WebContents& web_contents, |
| 124 NavigationController* nav_controller(NULL); | 58 DevToolsClientHost* client_host) { |
| 125 for (DescriptorMap::const_iterator it = navcontroller_to_descriptor_.begin(); | 59 DCHECK(!GetDevToolsClientHostFor(web_contents)); |
| 126 it != navcontroller_to_descriptor_.end(); | 60 |
| 61 NavigationController* navigation_controller = web_contents.controller(); |
| 62 navcontroller_to_client_host_[navigation_controller] = client_host; |
| 63 client_host_to_navcontroller_[client_host] = navigation_controller; |
| 64 client_host->set_close_listener(this); |
| 65 |
| 66 StartListening(navigation_controller); |
| 67 } |
| 68 |
| 69 void DevToolsManager::ForwardToDevToolsAgent( |
| 70 const RenderViewHost& client_rvh, |
| 71 const IPC::Message& message) { |
| 72 for (ClientHostMap::const_iterator it = |
| 73 navcontroller_to_client_host_.begin(); |
| 74 it != navcontroller_to_client_host_.end(); |
| 127 ++it) { | 75 ++it) { |
| 128 if (it->second->devtools_host() == from) { | 76 DevToolsWindow* win = it->second->AsDevToolsWindow(); |
| 129 nav_controller = it->second->navigation_controller(); | 77 if (!win) { |
| 130 break; | 78 continue; |
| 79 } |
| 80 if (win->HasRenderViewHost(client_rvh)) { |
| 81 ForwardToDevToolsAgent(*win, message); |
| 82 return; |
| 131 } | 83 } |
| 132 } | 84 } |
| 85 } |
| 133 | 86 |
| 87 void DevToolsManager::ForwardToDevToolsAgent(const DevToolsClientHost& from, |
| 88 const IPC::Message& message) { |
| 89 NavigationController* nav_controller = |
| 90 GetDevToolsAgentNavigationController(from); |
| 134 if (!nav_controller) { | 91 if (!nav_controller) { |
| 135 NOTREACHED(); | 92 NOTREACHED(); |
| 136 return; | 93 return; |
| 137 } | 94 } |
| 138 | 95 |
| 139 // TODO(yurys): notify client that the agent is no longer available | 96 // TODO(yurys): notify client that the agent is no longer available |
| 140 TabContents* tc = nav_controller->active_contents(); | 97 TabContents* tc = nav_controller->active_contents(); |
| 141 if (!tc) { | 98 if (!tc) { |
| 142 return; | 99 return; |
| 143 } | 100 } |
| 144 WebContents* wc = tc->AsWebContents(); | 101 WebContents* wc = tc->AsWebContents(); |
| 145 if (!wc) { | 102 if (!wc) { |
| 146 return; | 103 return; |
| 147 } | 104 } |
| 148 RenderViewHost* target_host = wc->render_view_host(); | 105 RenderViewHost* target_host = wc->render_view_host(); |
| 149 if (!target_host) { | 106 if (!target_host) { |
| 150 return; | 107 return; |
| 151 } | 108 } |
| 152 | 109 |
| 153 IPC::Message* m = new IPC::Message(message); | 110 IPC::Message* m = new IPC::Message(message); |
| 154 m->set_routing_id(target_host->routing_id()); | 111 m->set_routing_id(target_host->routing_id()); |
| 155 target_host->Send(m); | 112 target_host->Send(m); |
| 156 } | 113 } |
| 157 | 114 |
| 158 void DevToolsManager::ForwardToDevToolsClient(RenderViewHost* from, | 115 void DevToolsManager::ForwardToDevToolsClient(const RenderViewHost& from, |
| 159 const IPC::Message& message) { | 116 const IPC::Message& message) { |
| 160 WebContents* wc = from->delegate()->GetAsWebContents(); | 117 WebContents* wc = from.delegate()->GetAsWebContents(); |
| 161 if (!wc) { | 118 if (!wc) { |
| 162 NOTREACHED(); | 119 NOTREACHED(); |
| 163 return; | 120 return; |
| 164 } | 121 } |
| 165 | 122 DevToolsClientHost* target_host = GetDevToolsClientHostFor(*wc); |
| 166 NavigationController* navigation_controller = wc->controller(); | 123 if (!target_host) { |
| 167 | |
| 168 DescriptorMap::const_iterator it = | |
| 169 navcontroller_to_descriptor_.find(navigation_controller); | |
| 170 if (it == navcontroller_to_descriptor_.end()) { | |
| 171 NOTREACHED(); | 124 NOTREACHED(); |
| 172 return; | 125 return; |
| 173 } | 126 } |
| 174 | 127 target_host->SendMessageToClient(message); |
| 175 RenderViewHost* target_host = it->second->devtools_host(); | |
| 176 IPC::Message* m = new IPC::Message(message); | |
| 177 m->set_routing_id(target_host->routing_id()); | |
| 178 target_host->Send(m); | |
| 179 } | 128 } |
| 180 | 129 |
| 181 void DevToolsManager::RemoveDescriptor( | 130 void DevToolsManager::ClientHostClosing(DevToolsClientHost* host) { |
| 182 DevToolsInstanceDescriptorImpl* descriptor) { | 131 NavigationController* controller = GetDevToolsAgentNavigationController( |
| 183 NavigationController* navigation_controller = | 132 *host); |
| 184 descriptor->navigation_controller(); | 133 DCHECK(controller); |
| 134 |
| 185 // This should be done before StopListening as the latter checks number of | 135 // This should be done before StopListening as the latter checks number of |
| 186 // alive devtools instances. | 136 // alive devtools instances. |
| 187 navcontroller_to_descriptor_.erase(navigation_controller); | 137 navcontroller_to_client_host_.erase(controller); |
| 188 StopListening(navigation_controller); | 138 client_host_to_navcontroller_.erase(host); |
| 139 |
| 140 StopListening(controller); |
| 189 } | 141 } |
| 190 | 142 |
| 143 NavigationController* DevToolsManager::GetDevToolsAgentNavigationController( |
| 144 const DevToolsClientHost& client_host) { |
| 145 NavControllerMap::const_iterator it = |
| 146 client_host_to_navcontroller_.find(&client_host); |
| 147 if (it != client_host_to_navcontroller_.end()) { |
| 148 return it->second; |
| 149 } |
| 150 return NULL; |
| 151 } |
| 191 | 152 |
| 192 void DevToolsManager::StartListening( | 153 void DevToolsManager::StartListening( |
| 193 NavigationController* navigation_controller) { | 154 NavigationController* navigation_controller) { |
| 194 // TODO(yurys): add render host change listener | 155 // TODO(yurys): add render host change listener |
| 195 if (!web_contents_listeners_.get()) { | 156 if (!web_contents_listeners_.get()) { |
| 196 web_contents_listeners_.reset(new NotificationRegistrar); | 157 web_contents_listeners_.reset(new NotificationRegistrar); |
| 197 web_contents_listeners_->Add( | 158 web_contents_listeners_->Add( |
| 198 this, | 159 this, |
| 199 NotificationType::WEB_CONTENTS_DISCONNECTED, | 160 NotificationType::WEB_CONTENTS_DISCONNECTED, |
| 200 NotificationService::AllSources()); | 161 NotificationService::AllSources()); |
| 201 } | 162 } |
| 202 } | 163 } |
| 203 | 164 |
| 204 void DevToolsManager::StopListening( | 165 void DevToolsManager::StopListening( |
| 205 NavigationController* navigation_controller) { | 166 NavigationController* navigation_controller) { |
| 206 DCHECK(web_contents_listeners_.get()); | 167 DCHECK(web_contents_listeners_.get()); |
| 207 if (navcontroller_to_descriptor_.empty()) { | 168 if (navcontroller_to_client_host_.empty()) { |
| 169 DCHECK(client_host_to_navcontroller_.empty()); |
| 208 web_contents_listeners_.reset(); | 170 web_contents_listeners_.reset(); |
| 209 } | 171 } |
| 210 } | 172 } |
| OLD | NEW |