| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 using content::WorkerService; | 61 using content::WorkerService; |
| 62 using extensions::ErrorUtils; | 62 using extensions::ErrorUtils; |
| 63 | 63 |
| 64 namespace keys = debugger_api_constants; | 64 namespace keys = debugger_api_constants; |
| 65 namespace Attach = extensions::api::debugger::Attach; | 65 namespace Attach = extensions::api::debugger::Attach; |
| 66 namespace Detach = extensions::api::debugger::Detach; | 66 namespace Detach = extensions::api::debugger::Detach; |
| 67 namespace OnDetach = extensions::api::debugger::OnDetach; | 67 namespace OnDetach = extensions::api::debugger::OnDetach; |
| 68 namespace OnEvent = extensions::api::debugger::OnEvent; | 68 namespace OnEvent = extensions::api::debugger::OnEvent; |
| 69 namespace SendCommand = extensions::api::debugger::SendCommand; | 69 namespace SendCommand = extensions::api::debugger::SendCommand; |
| 70 | 70 |
| 71 namespace { | |
| 72 class ExtensionDevToolsInfoBarDelegate; | |
| 73 } // namespace | |
| 74 | |
| 75 | 71 |
| 76 // ExtensionDevToolsClientHost ------------------------------------------------ | 72 // ExtensionDevToolsClientHost ------------------------------------------------ |
| 77 | 73 |
| 78 class ExtensionDevToolsClientHost : public DevToolsClientHost, | 74 class ExtensionDevToolsClientHost : public DevToolsClientHost, |
| 79 public content::NotificationObserver { | 75 public content::NotificationObserver { |
| 80 public: | 76 public: |
| 81 ExtensionDevToolsClientHost( | 77 ExtensionDevToolsClientHost( |
| 82 Profile* profile, | 78 Profile* profile, |
| 83 DevToolsAgentHost* agent_host, | 79 DevToolsAgentHost* agent_host, |
| 84 const std::string& extension_id, | 80 const std::string& extension_id, |
| 85 const std::string& extension_name, | 81 const std::string& extension_name, |
| 86 const Debuggee& debuggee, | 82 const Debuggee& debuggee, |
| 87 ExtensionDevToolsInfoBarDelegate* infobar); | 83 InfoBar* infobar); |
| 88 | 84 |
| 89 virtual ~ExtensionDevToolsClientHost(); | 85 virtual ~ExtensionDevToolsClientHost(); |
| 90 | 86 |
| 91 const std::string& extension_id() { return extension_id_; } | 87 const std::string& extension_id() { return extension_id_; } |
| 92 void Close(); | 88 void Close(); |
| 93 void SendMessageToBackend(DebuggerSendCommandFunction* function, | 89 void SendMessageToBackend(DebuggerSendCommandFunction* function, |
| 94 const std::string& method, | 90 const std::string& method, |
| 95 SendCommand::Params::CommandParams* command_params); | 91 SendCommand::Params::CommandParams* command_params); |
| 96 | 92 |
| 97 // Marks connection as to-be-terminated by the user. | 93 // Marks connection as to-be-terminated by the user. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 112 | 108 |
| 113 Profile* profile_; | 109 Profile* profile_; |
| 114 scoped_refptr<DevToolsAgentHost> agent_host_; | 110 scoped_refptr<DevToolsAgentHost> agent_host_; |
| 115 std::string extension_id_; | 111 std::string extension_id_; |
| 116 Debuggee debuggee_; | 112 Debuggee debuggee_; |
| 117 content::NotificationRegistrar registrar_; | 113 content::NotificationRegistrar registrar_; |
| 118 int last_request_id_; | 114 int last_request_id_; |
| 119 typedef std::map<int, scoped_refptr<DebuggerSendCommandFunction> > | 115 typedef std::map<int, scoped_refptr<DebuggerSendCommandFunction> > |
| 120 PendingRequests; | 116 PendingRequests; |
| 121 PendingRequests pending_requests_; | 117 PendingRequests pending_requests_; |
| 122 ExtensionDevToolsInfoBarDelegate* infobar_; | 118 InfoBar* infobar_; |
| 123 OnDetach::Reason detach_reason_; | 119 OnDetach::Reason detach_reason_; |
| 124 | 120 |
| 125 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); | 121 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); |
| 126 }; | 122 }; |
| 127 | 123 |
| 128 // The member function declarations come after the other class declarations, so | 124 // The member function declarations come after the other class declarations, so |
| 129 // they can call members on them. | 125 // they can call members on them. |
| 130 | 126 |
| 131 | 127 |
| 132 namespace { | 128 namespace { |
| 133 | 129 |
| 134 // Helpers -------------------------------------------------------------------- | 130 // Helpers -------------------------------------------------------------------- |
| 135 | 131 |
| 136 void CopyDebuggee(Debuggee* dst, const Debuggee& src) { | 132 void CopyDebuggee(Debuggee* dst, const Debuggee& src) { |
| 137 if (src.tab_id) | 133 if (src.tab_id) |
| 138 dst->tab_id.reset(new int(*src.tab_id)); | 134 dst->tab_id.reset(new int(*src.tab_id)); |
| 139 if (src.extension_id) | 135 if (src.extension_id) |
| 140 dst->extension_id.reset(new std::string(*src.extension_id)); | 136 dst->extension_id.reset(new std::string(*src.extension_id)); |
| 141 if (src.target_id) | 137 if (src.target_id) |
| 142 dst->target_id.reset(new std::string(*src.target_id)); | 138 dst->target_id.reset(new std::string(*src.target_id)); |
| 143 } | 139 } |
| 144 | 140 |
| 145 | 141 |
| 146 // ExtensionDevToolsInfoBarDelegate ------------------------------------------- | 142 // ExtensionDevToolsInfoBarDelegate ------------------------------------------- |
| 147 | 143 |
| 148 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { | 144 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { |
| 149 public: | 145 public: |
| 150 // Creates an extension dev tools infobar delegate and adds it to the | 146 // Creates an extension dev tools infobar and delegate and adds the infobar to |
| 151 // InfoBarService associated with |rvh|. Returns the delegate if it was | 147 // the InfoBarService associated with |rvh|. Returns the infobar if it was |
| 152 // successfully added. | 148 // successfully added. |
| 153 static ExtensionDevToolsInfoBarDelegate* Create( | 149 static InfoBar* Create(RenderViewHost* rvh, const std::string& client_name); |
| 154 RenderViewHost* rvh, | |
| 155 const std::string& client_name); | |
| 156 | 150 |
| 157 void set_client_host(ExtensionDevToolsClientHost* client_host) { | 151 void set_client_host(ExtensionDevToolsClientHost* client_host) { |
| 158 client_host_ = client_host; | 152 client_host_ = client_host; |
| 159 } | 153 } |
| 160 | 154 |
| 161 private: | 155 private: |
| 162 ExtensionDevToolsInfoBarDelegate(InfoBarService* infobar_service, | 156 explicit ExtensionDevToolsInfoBarDelegate(const std::string& client_name); |
| 163 const std::string& client_name); | |
| 164 virtual ~ExtensionDevToolsInfoBarDelegate(); | 157 virtual ~ExtensionDevToolsInfoBarDelegate(); |
| 165 | 158 |
| 166 // ConfirmInfoBarDelegate: | 159 // ConfirmInfoBarDelegate: |
| 167 virtual void InfoBarDismissed() OVERRIDE; | 160 virtual void InfoBarDismissed() OVERRIDE; |
| 168 virtual Type GetInfoBarType() const OVERRIDE; | 161 virtual Type GetInfoBarType() const OVERRIDE; |
| 169 virtual bool ShouldExpireInternal( | 162 virtual bool ShouldExpireInternal( |
| 170 const content::LoadCommittedDetails& details) const OVERRIDE; | 163 const content::LoadCommittedDetails& details) const OVERRIDE; |
| 171 virtual string16 GetMessageText() const OVERRIDE; | 164 virtual string16 GetMessageText() const OVERRIDE; |
| 172 virtual int GetButtons() const OVERRIDE; | 165 virtual int GetButtons() const OVERRIDE; |
| 173 virtual bool Cancel() OVERRIDE; | 166 virtual bool Cancel() OVERRIDE; |
| 174 | 167 |
| 175 std::string client_name_; | 168 std::string client_name_; |
| 176 ExtensionDevToolsClientHost* client_host_; | 169 ExtensionDevToolsClientHost* client_host_; |
| 177 | 170 |
| 178 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); | 171 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); |
| 179 }; | 172 }; |
| 180 | 173 |
| 181 // static | 174 // static |
| 182 ExtensionDevToolsInfoBarDelegate* ExtensionDevToolsInfoBarDelegate::Create( | 175 InfoBar* ExtensionDevToolsInfoBarDelegate::Create( |
| 183 RenderViewHost* rvh, | 176 RenderViewHost* rvh, |
| 184 const std::string& client_name) { | 177 const std::string& client_name) { |
| 185 if (!rvh) | 178 if (!rvh) |
| 186 return NULL; | 179 return NULL; |
| 187 | 180 |
| 188 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); | 181 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); |
| 189 if (!web_contents) | 182 if (!web_contents) |
| 190 return NULL; | 183 return NULL; |
| 191 | 184 |
| 192 InfoBarService* infobar_service = | 185 InfoBarService* infobar_service = |
| 193 InfoBarService::FromWebContents(web_contents); | 186 InfoBarService::FromWebContents(web_contents); |
| 194 if (!infobar_service) | 187 if (!infobar_service) |
| 195 return NULL; | 188 return NULL; |
| 196 | 189 |
| 197 return static_cast<ExtensionDevToolsInfoBarDelegate*>( | 190 return infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar( |
| 198 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( | 191 scoped_ptr<ConfirmInfoBarDelegate>( |
| 199 new ExtensionDevToolsInfoBarDelegate(infobar_service, client_name)))); | 192 new ExtensionDevToolsInfoBarDelegate(client_name)))); |
| 200 } | 193 } |
| 201 | 194 |
| 202 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( | 195 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( |
| 203 InfoBarService* infobar_service, | |
| 204 const std::string& client_name) | 196 const std::string& client_name) |
| 205 : ConfirmInfoBarDelegate(infobar_service), | 197 : ConfirmInfoBarDelegate(), |
| 206 client_name_(client_name), | 198 client_name_(client_name), |
| 207 client_host_(NULL) { | 199 client_host_(NULL) { |
| 208 } | 200 } |
| 209 | 201 |
| 210 ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { | 202 ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { |
| 211 } | 203 } |
| 212 | 204 |
| 213 void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() { | 205 void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() { |
| 214 if (client_host_) | 206 if (client_host_) |
| 215 client_host_->MarkAsDismissed(); | 207 client_host_->MarkAsDismissed(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 290 |
| 299 | 291 |
| 300 // ExtensionDevToolsClientHost ------------------------------------------------ | 292 // ExtensionDevToolsClientHost ------------------------------------------------ |
| 301 | 293 |
| 302 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( | 294 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
| 303 Profile* profile, | 295 Profile* profile, |
| 304 DevToolsAgentHost* agent_host, | 296 DevToolsAgentHost* agent_host, |
| 305 const std::string& extension_id, | 297 const std::string& extension_id, |
| 306 const std::string& extension_name, | 298 const std::string& extension_name, |
| 307 const Debuggee& debuggee, | 299 const Debuggee& debuggee, |
| 308 ExtensionDevToolsInfoBarDelegate* infobar) | 300 InfoBar* infobar) |
| 309 : profile_(profile), | 301 : profile_(profile), |
| 310 agent_host_(agent_host), | 302 agent_host_(agent_host), |
| 311 extension_id_(extension_id), | 303 extension_id_(extension_id), |
| 312 last_request_id_(0), | 304 last_request_id_(0), |
| 313 infobar_(infobar), | 305 infobar_(infobar), |
| 314 detach_reason_(OnDetach::REASON_TARGET_CLOSED) { | 306 detach_reason_(OnDetach::REASON_TARGET_CLOSED) { |
| 315 CopyDebuggee(&debuggee_, debuggee); | 307 CopyDebuggee(&debuggee_, debuggee); |
| 316 | 308 |
| 317 AttachedClientHosts::GetInstance()->Add(this); | 309 AttachedClientHosts::GetInstance()->Add(this); |
| 318 | 310 |
| 319 // Detach from debugger when extension unloads. | 311 // Detach from debugger when extension unloads. |
| 320 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 312 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 321 content::Source<Profile>(profile_)); | 313 content::Source<Profile>(profile_)); |
| 322 | 314 |
| 323 // RVH-based agents disconnect from their clients when the app is terminating | 315 // RVH-based agents disconnect from their clients when the app is terminating |
| 324 // but shared worker-based agents do not. | 316 // but shared worker-based agents do not. |
| 325 // Disconnect explicitly to make sure that |this| observer is not leaked. | 317 // Disconnect explicitly to make sure that |this| observer is not leaked. |
| 326 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, | 318 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
| 327 content::NotificationService::AllSources()); | 319 content::NotificationService::AllSources()); |
| 328 | 320 |
| 329 // Attach to debugger and tell it we are ready. | 321 // Attach to debugger and tell it we are ready. |
| 330 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( | 322 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( |
| 331 agent_host_.get(), this); | 323 agent_host_.get(), this); |
| 332 | 324 |
| 333 if (infobar_) { | 325 if (infobar_) { |
| 334 infobar_->set_client_host(this); | 326 static_cast<ExtensionDevToolsInfoBarDelegate*>( |
| 327 infobar_->delegate())->set_client_host(this); |
| 335 registrar_.Add( | 328 registrar_.Add( |
| 336 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 329 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
| 337 content::Source<InfoBarService>(InfoBarService::FromWebContents( | 330 content::Source<InfoBarService>(InfoBarService::FromWebContents( |
| 338 WebContents::FromRenderViewHost( | 331 WebContents::FromRenderViewHost( |
| 339 agent_host_->GetRenderViewHost())))); | 332 agent_host_->GetRenderViewHost())))); |
| 340 } | 333 } |
| 341 } | 334 } |
| 342 | 335 |
| 343 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { | 336 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { |
| 344 // Ensure calling RemoveInfoBar() below won't result in Observe() trying to | 337 // Ensure calling RemoveInfoBar() below won't result in Observe() trying to |
| 345 // Close() us. | 338 // Close() us. |
| 346 registrar_.RemoveAll(); | 339 registrar_.RemoveAll(); |
| 347 | 340 |
| 348 if (infobar_) { | 341 if (infobar_) { |
| 349 infobar_->set_client_host(NULL); | 342 static_cast<ExtensionDevToolsInfoBarDelegate*>( |
| 343 infobar_->delegate())->set_client_host(NULL); |
| 350 InfoBarService::FromWebContents(WebContents::FromRenderViewHost( | 344 InfoBarService::FromWebContents(WebContents::FromRenderViewHost( |
| 351 agent_host_->GetRenderViewHost()))->RemoveInfoBar(infobar_); | 345 agent_host_->GetRenderViewHost()))->RemoveInfoBar(infobar_); |
| 352 } | 346 } |
| 353 AttachedClientHosts::GetInstance()->Remove(this); | 347 AttachedClientHosts::GetInstance()->Remove(this); |
| 354 } | 348 } |
| 355 | 349 |
| 356 // DevToolsClientHost interface | 350 // DevToolsClientHost interface |
| 357 void ExtensionDevToolsClientHost::InspectedContentsClosing() { | 351 void ExtensionDevToolsClientHost::InspectedContentsClosing() { |
| 358 SendDetachedEvent(); | 352 SendDetachedEvent(); |
| 359 delete this; | 353 delete this; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 const content::NotificationSource& source, | 403 const content::NotificationSource& source, |
| 410 const content::NotificationDetails& details) { | 404 const content::NotificationDetails& details) { |
| 411 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { | 405 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
| 412 if (content::Details<extensions::UnloadedExtensionInfo>(details)-> | 406 if (content::Details<extensions::UnloadedExtensionInfo>(details)-> |
| 413 extension->id() == extension_id_) | 407 extension->id() == extension_id_) |
| 414 Close(); | 408 Close(); |
| 415 } else if (type == chrome::NOTIFICATION_APP_TERMINATING) { | 409 } else if (type == chrome::NOTIFICATION_APP_TERMINATING) { |
| 416 Close(); | 410 Close(); |
| 417 } else { | 411 } else { |
| 418 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); | 412 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); |
| 419 if (content::Details<InfoBarRemovedDetails>(details)->first == infobar_) { | 413 if (content::Details<InfoBar::RemovedDetails>(details)->first == infobar_) { |
| 420 infobar_ = NULL; | 414 infobar_ = NULL; |
| 421 SendDetachedEvent(); | 415 SendDetachedEvent(); |
| 422 Close(); | 416 Close(); |
| 423 } | 417 } |
| 424 } | 418 } |
| 425 } | 419 } |
| 426 | 420 |
| 427 void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend( | 421 void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend( |
| 428 const std::string& message) { | 422 const std::string& message) { |
| 429 if (!extensions::ExtensionSystem::Get(profile_)->event_router()) | 423 if (!extensions::ExtensionSystem::Get(profile_)->event_router()) |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 keys::kProtocolVersionNotSupportedError, | 553 keys::kProtocolVersionNotSupportedError, |
| 560 params->required_version); | 554 params->required_version); |
| 561 return false; | 555 return false; |
| 562 } | 556 } |
| 563 | 557 |
| 564 if (agent_host_->IsAttached()) { | 558 if (agent_host_->IsAttached()) { |
| 565 FormatErrorMessage(keys::kAlreadyAttachedError); | 559 FormatErrorMessage(keys::kAlreadyAttachedError); |
| 566 return false; | 560 return false; |
| 567 } | 561 } |
| 568 | 562 |
| 569 ExtensionDevToolsInfoBarDelegate* infobar = NULL; | 563 InfoBar* infobar = NULL; |
| 570 if (!CommandLine::ForCurrentProcess()-> | 564 if (!CommandLine::ForCurrentProcess()-> |
| 571 HasSwitch(switches::kSilentDebuggerExtensionAPI)) { | 565 HasSwitch(switches::kSilentDebuggerExtensionAPI)) { |
| 572 // Do not attach to the target if for any reason the infobar cannot be shown | 566 // Do not attach to the target if for any reason the infobar cannot be shown |
| 573 // for this WebContents instance. | 567 // for this WebContents instance. |
| 574 infobar = ExtensionDevToolsInfoBarDelegate::Create( | 568 infobar = ExtensionDevToolsInfoBarDelegate::Create( |
| 575 agent_host_->GetRenderViewHost(), GetExtension()->name()); | 569 agent_host_->GetRenderViewHost(), GetExtension()->name()); |
| 576 if (!infobar) { | 570 if (!infobar) { |
| 577 error_ = ErrorUtils::FormatErrorMessage( | 571 error_ = ErrorUtils::FormatErrorMessage( |
| 578 keys::kSilentDebuggingRequired, | 572 keys::kSilentDebuggingRequired, |
| 579 switches::kSilentDebuggerExtensionAPI); | 573 switches::kSilentDebuggerExtensionAPI); |
| 580 return false; | 574 return false; |
| 581 } | 575 } |
| 582 } | 576 } |
| 583 | 577 |
| 584 new ExtensionDevToolsClientHost(profile(), agent_host_.get(), | 578 new ExtensionDevToolsClientHost(profile(), agent_host_.get(), |
| 585 GetExtension()->id(), GetExtension()->name(), | 579 GetExtension()->id(), GetExtension()->name(), |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 } | 770 } |
| 777 | 771 |
| 778 void DebuggerGetTargetsFunction::SendTargetList( | 772 void DebuggerGetTargetsFunction::SendTargetList( |
| 779 base::ListValue* list, | 773 base::ListValue* list, |
| 780 const WorkerInfoList& worker_info) { | 774 const WorkerInfoList& worker_info) { |
| 781 for (size_t i = 0; i < worker_info.size(); ++i) | 775 for (size_t i = 0; i < worker_info.size(); ++i) |
| 782 list->Append(SerializeWorkerInfo(worker_info[i])); | 776 list->Append(SerializeWorkerInfo(worker_info[i])); |
| 783 SetResult(list); | 777 SetResult(list); |
| 784 SendResponse(true); | 778 SendResponse(true); |
| 785 } | 779 } |
| OLD | NEW |