OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // Implements the Chrome Extensions Debugger API. | 5 // Implements the Chrome Extensions Debugger API. |
6 | 6 |
7 #include "chrome/browser/extensions/api/debugger/debugger_api.h" | 7 #include "chrome/browser/extensions/api/debugger/debugger_api.h" |
8 | 8 |
9 #include <map> | 9 #include <map> |
10 #include <set> | 10 #include <set> |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 int ExtensionDevToolsInfoBarDelegate::GetButtons() const { | 144 int ExtensionDevToolsInfoBarDelegate::GetButtons() const { |
145 return BUTTON_CANCEL; | 145 return BUTTON_CANCEL; |
146 } | 146 } |
147 | 147 |
148 bool ExtensionDevToolsInfoBarDelegate::Cancel() { | 148 bool ExtensionDevToolsInfoBarDelegate::Cancel() { |
149 InfoBarDismissed(); | 149 InfoBarDismissed(); |
150 // InfoBarDismissed() will have closed us already. | 150 // InfoBarDismissed() will have closed us already. |
151 return false; | 151 return false; |
152 } | 152 } |
153 | 153 |
| 154 // ExtensionDevToolsInfoBar --------------------------------------------------- |
| 155 |
| 156 class ExtensionDevToolsInfoBar; |
| 157 using ExtensionInfoBars = |
| 158 std::map<std::string, ExtensionDevToolsInfoBar*>; |
| 159 base::LazyInstance<ExtensionInfoBars>::Leaky g_extension_info_bars = |
| 160 LAZY_INSTANCE_INITIALIZER; |
| 161 |
| 162 class ExtensionDevToolsInfoBar { |
| 163 public: |
| 164 static ExtensionDevToolsInfoBar* Create( |
| 165 const std::string& extension_id, |
| 166 const std::string& extension_name, |
| 167 ExtensionDevToolsClientHost* client_host, |
| 168 const base::Closure& dismissed_callback); |
| 169 void Remove(ExtensionDevToolsClientHost* client_host); |
| 170 |
| 171 private: |
| 172 ExtensionDevToolsInfoBar(const std::string& extension_id, |
| 173 const std::string& extension_name); |
| 174 ~ExtensionDevToolsInfoBar(); |
| 175 void InfoBarDismissed(); |
| 176 |
| 177 std::string extension_id_; |
| 178 std::map<ExtensionDevToolsClientHost*, base::Closure> callbacks_; |
| 179 base::WeakPtr<GlobalConfirmInfoBar> infobar_; |
| 180 }; |
| 181 |
| 182 // static |
| 183 ExtensionDevToolsInfoBar* ExtensionDevToolsInfoBar::Create( |
| 184 const std::string& extension_id, |
| 185 const std::string& extension_name, |
| 186 ExtensionDevToolsClientHost* client_host, |
| 187 const base::Closure& dismissed_callback) { |
| 188 ExtensionInfoBars::iterator it = |
| 189 g_extension_info_bars.Get().find(extension_id); |
| 190 ExtensionDevToolsInfoBar* infobar = nullptr; |
| 191 if (it != g_extension_info_bars.Get().end()) |
| 192 infobar = it->second; |
| 193 else |
| 194 infobar = new ExtensionDevToolsInfoBar(extension_id, extension_name); |
| 195 infobar->callbacks_[client_host] = dismissed_callback; |
| 196 return infobar; |
| 197 } |
| 198 |
| 199 ExtensionDevToolsInfoBar::ExtensionDevToolsInfoBar( |
| 200 const std::string& extension_id, |
| 201 const std::string& extension_name) |
| 202 : extension_id_(extension_id) { |
| 203 g_extension_info_bars.Get()[extension_id] = this; |
| 204 |
| 205 // This class closes the |infobar_|, so it's safe to pass Unretained(this). |
| 206 scoped_ptr<ExtensionDevToolsInfoBarDelegate> delegate( |
| 207 new ExtensionDevToolsInfoBarDelegate( |
| 208 base::Bind(&ExtensionDevToolsInfoBar::InfoBarDismissed, |
| 209 base::Unretained(this)), |
| 210 extension_name)); |
| 211 infobar_ = GlobalConfirmInfoBar::Show(delegate.Pass()); |
| 212 } |
| 213 |
| 214 ExtensionDevToolsInfoBar::~ExtensionDevToolsInfoBar() { |
| 215 g_extension_info_bars.Get().erase(extension_id_); |
| 216 if (infobar_) |
| 217 infobar_->Close(); |
| 218 } |
| 219 |
| 220 void ExtensionDevToolsInfoBar::Remove( |
| 221 ExtensionDevToolsClientHost* client_host) { |
| 222 callbacks_.erase(client_host); |
| 223 if (!callbacks_.size()) |
| 224 delete this; |
| 225 } |
| 226 |
| 227 void ExtensionDevToolsInfoBar::InfoBarDismissed() { |
| 228 std::map<ExtensionDevToolsClientHost*, base::Closure> copy = callbacks_; |
| 229 for (const auto& pair: copy) |
| 230 pair.second.Run(); |
| 231 } |
| 232 |
154 } // namespace | 233 } // namespace |
155 | 234 |
156 // ExtensionDevToolsClientHost ------------------------------------------------ | 235 // ExtensionDevToolsClientHost ------------------------------------------------ |
157 | 236 |
158 using AttachedClientHosts = std::set<ExtensionDevToolsClientHost*>; | 237 using AttachedClientHosts = std::set<ExtensionDevToolsClientHost*>; |
159 base::LazyInstance<AttachedClientHosts>::Leaky g_attached_client_hosts = | 238 base::LazyInstance<AttachedClientHosts>::Leaky g_attached_client_hosts = |
160 LAZY_INSTANCE_INITIALIZER; | 239 LAZY_INSTANCE_INITIALIZER; |
161 | 240 |
162 class ExtensionDevToolsClientHost : public content::DevToolsAgentHostClient, | 241 class ExtensionDevToolsClientHost : public content::DevToolsAgentHostClient, |
163 public content::NotificationObserver, | 242 public content::NotificationObserver, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 const Extension* extension, | 282 const Extension* extension, |
204 UnloadedExtensionInfo::Reason reason) override; | 283 UnloadedExtensionInfo::Reason reason) override; |
205 | 284 |
206 Profile* profile_; | 285 Profile* profile_; |
207 scoped_refptr<DevToolsAgentHost> agent_host_; | 286 scoped_refptr<DevToolsAgentHost> agent_host_; |
208 std::string extension_id_; | 287 std::string extension_id_; |
209 Debuggee debuggee_; | 288 Debuggee debuggee_; |
210 content::NotificationRegistrar registrar_; | 289 content::NotificationRegistrar registrar_; |
211 int last_request_id_; | 290 int last_request_id_; |
212 PendingRequests pending_requests_; | 291 PendingRequests pending_requests_; |
213 base::WeakPtr<GlobalConfirmInfoBar> infobar_; | 292 ExtensionDevToolsInfoBar* infobar_; |
214 api::debugger::DetachReason detach_reason_; | 293 api::debugger::DetachReason detach_reason_; |
215 | 294 |
216 // Listen to extension unloaded notification. | 295 // Listen to extension unloaded notification. |
217 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> | 296 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
218 extension_registry_observer_; | 297 extension_registry_observer_; |
219 | 298 |
220 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); | 299 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); |
221 }; | 300 }; |
222 | 301 |
223 // ExtensionDevToolsClientHost ------------------------------------------------ | 302 // ExtensionDevToolsClientHost ------------------------------------------------ |
224 | 303 |
225 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( | 304 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
226 Profile* profile, | 305 Profile* profile, |
227 DevToolsAgentHost* agent_host, | 306 DevToolsAgentHost* agent_host, |
228 const std::string& extension_id, | 307 const std::string& extension_id, |
229 const std::string& extension_name, | 308 const std::string& extension_name, |
230 const Debuggee& debuggee) | 309 const Debuggee& debuggee) |
231 : profile_(profile), | 310 : profile_(profile), |
232 agent_host_(agent_host), | 311 agent_host_(agent_host), |
233 extension_id_(extension_id), | 312 extension_id_(extension_id), |
234 last_request_id_(0), | 313 last_request_id_(0), |
| 314 infobar_(nullptr), |
235 detach_reason_(api::debugger::DETACH_REASON_TARGET_CLOSED), | 315 detach_reason_(api::debugger::DETACH_REASON_TARGET_CLOSED), |
236 extension_registry_observer_(this) { | 316 extension_registry_observer_(this) { |
237 CopyDebuggee(&debuggee_, debuggee); | 317 CopyDebuggee(&debuggee_, debuggee); |
238 | 318 |
239 g_attached_client_hosts.Get().insert(this); | 319 g_attached_client_hosts.Get().insert(this); |
240 | 320 |
241 // ExtensionRegistryObserver listen extension unloaded and detach debugger | 321 // ExtensionRegistryObserver listen extension unloaded and detach debugger |
242 // from there. | 322 // from there. |
243 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); | 323 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
244 | 324 |
245 // RVH-based agents disconnect from their clients when the app is terminating | 325 // RVH-based agents disconnect from their clients when the app is terminating |
246 // but shared worker-based agents do not. | 326 // but shared worker-based agents do not. |
247 // Disconnect explicitly to make sure that |this| observer is not leaked. | 327 // Disconnect explicitly to make sure that |this| observer is not leaked. |
248 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, | 328 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
249 content::NotificationService::AllSources()); | 329 content::NotificationService::AllSources()); |
250 | 330 |
251 // Attach to debugger and tell it we are ready. | 331 // Attach to debugger and tell it we are ready. |
252 agent_host_->AttachClient(this); | 332 agent_host_->AttachClient(this); |
253 | 333 |
254 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 334 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
255 ::switches::kSilentDebuggerExtensionAPI)) { | 335 ::switches::kSilentDebuggerExtensionAPI)) { |
256 // This class closes the |infobar_|, so it's safe to pass Unretained(this). | 336 infobar_ = ExtensionDevToolsInfoBar::Create( |
257 scoped_ptr<ExtensionDevToolsInfoBarDelegate> delegate( | 337 extension_id, extension_name, this, |
258 new ExtensionDevToolsInfoBarDelegate( | 338 base::Bind(&ExtensionDevToolsClientHost::InfoBarDismissed, |
259 base::Bind(&ExtensionDevToolsClientHost::InfoBarDismissed, | 339 base::Unretained(this))); |
260 base::Unretained(this)), | |
261 extension_name)); | |
262 infobar_ = GlobalConfirmInfoBar::Show(delegate.Pass()); | |
263 } | 340 } |
264 } | 341 } |
265 | 342 |
266 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { | 343 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { |
267 if (infobar_) | 344 if (infobar_) |
268 infobar_->Close(); | 345 infobar_->Remove(this); |
269 g_attached_client_hosts.Get().erase(this); | 346 g_attached_client_hosts.Get().erase(this); |
270 } | 347 } |
271 | 348 |
272 // DevToolsAgentHostClient implementation. | 349 // DevToolsAgentHostClient implementation. |
273 void ExtensionDevToolsClientHost::AgentHostClosed( | 350 void ExtensionDevToolsClientHost::AgentHostClosed( |
274 DevToolsAgentHost* agent_host, bool replaced_with_another_client) { | 351 DevToolsAgentHost* agent_host, bool replaced_with_another_client) { |
275 DCHECK(agent_host == agent_host_.get()); | 352 DCHECK(agent_host == agent_host_.get()); |
276 if (replaced_with_another_client) | 353 if (replaced_with_another_client) |
277 detach_reason_ = api::debugger::DETACH_REASON_REPLACED_WITH_DEVTOOLS; | 354 detach_reason_ = api::debugger::DETACH_REASON_REPLACED_WITH_DEVTOOLS; |
278 SendDetachedEvent(); | 355 SendDetachedEvent(); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 const std::vector<DevToolsTargetImpl*>& target_list) { | 716 const std::vector<DevToolsTargetImpl*>& target_list) { |
640 scoped_ptr<base::ListValue> result(new base::ListValue()); | 717 scoped_ptr<base::ListValue> result(new base::ListValue()); |
641 for (size_t i = 0; i < target_list.size(); ++i) | 718 for (size_t i = 0; i < target_list.size(); ++i) |
642 result->Append(SerializeTarget(*target_list[i])); | 719 result->Append(SerializeTarget(*target_list[i])); |
643 STLDeleteContainerPointers(target_list.begin(), target_list.end()); | 720 STLDeleteContainerPointers(target_list.begin(), target_list.end()); |
644 SetResult(result.release()); | 721 SetResult(result.release()); |
645 SendResponse(true); | 722 SendResponse(true); |
646 } | 723 } |
647 | 724 |
648 } // namespace extensions | 725 } // namespace extensions |
OLD | NEW |