Chromium Code Reviews| Index: content/browser/devtools/protocol/service_worker_handler.cc |
| diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc |
| index 985d991963775057126d94d4475ee47469145305..513577d8ab8052afefb71d669e3457fa918a2bc4 100644 |
| --- a/content/browser/devtools/protocol/service_worker_handler.cc |
| +++ b/content/browser/devtools/protocol/service_worker_handler.cc |
| @@ -4,23 +4,272 @@ |
| #include "content/browser/devtools/protocol/service_worker_handler.h" |
| +#include "base/bind.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "content/browser/devtools/service_worker_devtools_manager.h" |
| +#include "content/browser/service_worker/service_worker_context_observer.h" |
| +#include "content/browser/service_worker/service_worker_context_wrapper.h" |
| +#include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/devtools_agent_host.h" |
| +#include "content/public/browser/render_frame_host.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/storage_partition.h" |
| +#include "url/gurl.h" |
| + |
| +// Windows headers will redefine SendMessage. |
| +#ifdef SendMessage |
| +#undef SendMessage |
| +#endif |
| namespace content { |
| namespace devtools { |
| namespace service_worker { |
| +namespace { |
| + |
| +const char* GetVersionRunningStatusString( |
|
pfeldman
2015/03/09 19:16:49
std::string ?
horo
2015/03/10 01:34:07
Done.
|
| + content::ServiceWorkerVersion::RunningStatus running_status) { |
| + switch (running_status) { |
| + case content::ServiceWorkerVersion::STOPPED: |
| + return service_worker_version::kRunningStatusStopped; |
| + case content::ServiceWorkerVersion::STARTING: |
| + return service_worker_version::kRunningStatusStarting; |
| + case content::ServiceWorkerVersion::RUNNING: |
| + return service_worker_version::kRunningStatusRunning; |
| + case content::ServiceWorkerVersion::STOPPING: |
| + return service_worker_version::kRunningStatusStopping; |
| + } |
| + return ""; |
| +} |
| + |
| +const char* GetVersionStatusString( |
|
pfeldman
2015/03/09 19:16:49
ditto
horo
2015/03/10 01:34:07
Done.
|
| + content::ServiceWorkerVersion::Status status) { |
| + switch (status) { |
| + case content::ServiceWorkerVersion::NEW: |
| + return service_worker_version::kStatusNew; |
| + case content::ServiceWorkerVersion::INSTALLING: |
| + return service_worker_version::kStatusInstalling; |
| + case content::ServiceWorkerVersion::INSTALLED: |
| + return service_worker_version::kStatusInstalled; |
| + case content::ServiceWorkerVersion::ACTIVATING: |
| + return service_worker_version::kStatusActivating; |
| + case content::ServiceWorkerVersion::ACTIVATED: |
| + return service_worker_version::kStatusActivated; |
| + case content::ServiceWorkerVersion::REDUNDANT: |
| + return service_worker_version::kStatusRedundant; |
| + } |
| + return ""; |
| +} |
| + |
| +scoped_refptr<ServiceWorkerVersion> CreateVersionDictionaryValue( |
| + const ServiceWorkerVersionInfo& version_info) { |
| + scoped_refptr<ServiceWorkerVersion> version( |
| + ServiceWorkerVersion::Create() |
| + ->set_version_id(base::Int64ToString(version_info.version_id)) |
| + ->set_registration_id( |
| + base::Int64ToString(version_info.registration_id)) |
| + ->set_script_url(version_info.script_url.spec()) |
| + ->set_running_status( |
| + GetVersionRunningStatusString(version_info.running_status)) |
| + ->set_status(GetVersionStatusString(version_info.status))); |
| + return version; |
| +} |
| + |
| +scoped_refptr<ServiceWorkerRegistration> CreateRegistrationDictionaryValue( |
| + const ServiceWorkerRegistrationInfo& registration_info) { |
| + scoped_refptr<ServiceWorkerRegistration> registration( |
| + ServiceWorkerRegistration::Create() |
| + ->set_registration_id( |
| + base::Int64ToString(registration_info.registration_id)) |
| + ->set_scope_url(registration_info.pattern.spec())); |
| + if (registration_info.active_version.version_id != |
| + kInvalidServiceWorkerVersionId) { |
| + registration->set_active_version( |
| + CreateVersionDictionaryValue(registration_info.active_version)); |
| + } |
| + if (registration_info.waiting_version.version_id != |
| + kInvalidServiceWorkerVersionId) { |
| + registration->set_waiting_version( |
| + CreateVersionDictionaryValue(registration_info.waiting_version)); |
| + } |
| + if (registration_info.installing_version.version_id != |
| + kInvalidServiceWorkerVersionId) { |
| + registration->set_installing_version( |
| + CreateVersionDictionaryValue(registration_info.installing_version)); |
| + } |
| + return registration; |
| +} |
| + |
| +} // namespace |
| + |
| using Response = DevToolsProtocolClient::Response; |
| -ServiceWorkerHandler::ServiceWorkerHandler() { |
| +class ServiceWorkerHandler::ContextObserver |
| + : public ServiceWorkerContextObserver, |
| + public base::RefCountedThreadSafe<ContextObserver> { |
| + public: |
| + ContextObserver(scoped_refptr<ServiceWorkerContextWrapper> context, |
| + base::WeakPtr<ServiceWorkerHandler> handler); |
| + void Start(); |
| + void Stop(); |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<ContextObserver>; |
| + ~ContextObserver(); |
| + void GetStoredRegistrationsOnIOThread(); |
| + void OnStoredRegistrationsOnIOThread( |
| + const std::vector<ServiceWorkerRegistrationInfo>& registrations); |
| + void StopOnIOThread(); |
| + |
| + void OnVersionUpdated(int64 version_id); |
| + void OnRegistrationUpdated(int64 registration_id); |
| + |
| + // ServiceWorkerContextObserver implements |
| + void OnRunningStateChanged(int64 version_id) override; |
| + void OnVersionStateChanged(int64 version_id) override; |
| + void OnRegistrationStored(int64 registration_id, |
| + const GURL& pattern) override; |
| + void OnRegistrationDeleted(int64 registration_id, |
| + const GURL& pattern) override; |
| + |
| + scoped_refptr<ServiceWorkerContextWrapper> context_; |
| + base::WeakPtr<ServiceWorkerHandler> handler_; |
| +}; |
| + |
| +ServiceWorkerHandler::ContextObserver::ContextObserver( |
| + scoped_refptr<ServiceWorkerContextWrapper> context, |
| + base::WeakPtr<ServiceWorkerHandler> handler) |
| + : context_(context), handler_(handler) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::Start() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::ContextObserver:: |
| + GetStoredRegistrationsOnIOThread, |
| + this)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::Stop() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::ContextObserver::StopOnIOThread, this)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::GetStoredRegistrationsOnIOThread() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->context()->storage()->GetAllRegistrations(base::Bind( |
| + &ServiceWorkerHandler::ContextObserver::OnStoredRegistrationsOnIOThread, |
| + this)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnStoredRegistrationsOnIOThread( |
| + const std::vector<ServiceWorkerRegistrationInfo>& registrations) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->AddObserver(this); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| + registrations)); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| + context_->context()->GetAllLiveRegistrationInfo())); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerVersionUpdated, handler_, |
| + context_->context()->GetAllLiveVersionInfo())); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::StopOnIOThread() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->RemoveObserver(this); |
| +} |
| + |
| +ServiceWorkerHandler::ContextObserver::~ContextObserver() { |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnVersionUpdated(int64 version_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + content::ServiceWorkerVersion* version = |
| + context_->context()->GetLiveVersion(version_id); |
| + if (!version) |
| + return; |
| + OnRegistrationUpdated(version->registration_id()); |
| + std::vector<ServiceWorkerVersionInfo> versions; |
| + versions.push_back(version->GetInfo()); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerVersionUpdated, handler_, |
| + versions)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnRegistrationUpdated( |
| + int64 registration_id) { |
| + content::ServiceWorkerRegistration* registration = |
| + context_->context()->GetLiveRegistration(registration_id); |
| + if (!registration) |
| + return; |
| + std::vector<ServiceWorkerRegistrationInfo> registrations; |
| + registrations.push_back(registration->GetInfo()); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| + registrations)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnRunningStateChanged( |
| + int64 version_id) { |
| + OnVersionUpdated(version_id); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnVersionStateChanged( |
| + int64 version_id) { |
| + OnVersionUpdated(version_id); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnRegistrationStored( |
| + int64 registration_id, |
| + const GURL& pattern) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + content::ServiceWorkerRegistration* registration = |
| + context_->context()->GetLiveRegistration(registration_id); |
| + DCHECK(registration); |
| + std::vector<ServiceWorkerRegistrationInfo> registrations; |
| + registrations.push_back(registration->GetInfo()); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| + registrations)); |
| +} |
| + |
| +void ServiceWorkerHandler::ContextObserver::OnRegistrationDeleted( |
| + int64 registration_id, |
| + const GURL& pattern) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationDeleted, handler_, |
| + registration_id)); |
| +} |
| + |
| +ServiceWorkerHandler::ServiceWorkerHandler() |
| + : render_frame_host_(nullptr), weak_factory_(this) { |
| } |
| ServiceWorkerHandler::~ServiceWorkerHandler() { |
| Disable(); |
| } |
| -void ServiceWorkerHandler::SetClient( |
| - scoped_ptr<Client> client) { |
| +void ServiceWorkerHandler::SetRenderFrameHost( |
| + RenderFrameHost* render_frame_host) { |
| + render_frame_host_ = render_frame_host; |
|
pfeldman
2015/03/09 19:16:49
This will change on the render swap, so you want t
horo
2015/03/10 01:34:07
Done.
|
| +} |
| + |
| +void ServiceWorkerHandler::SetClient(scoped_ptr<Client> client) { |
| client_.swap(client); |
| } |
| @@ -29,9 +278,19 @@ void ServiceWorkerHandler::Detached() { |
| } |
| Response ServiceWorkerHandler::Enable() { |
| + if (!render_frame_host_) |
| + return Response::InternalError("Could not connect to frame"); |
| DevToolsAgentHost::List agent_hosts; |
| ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&agent_hosts); |
| ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this); |
| + StoragePartition* partition = BrowserContext::GetStoragePartition( |
| + render_frame_host_->GetProcess()->GetBrowserContext(), |
| + render_frame_host_->GetSiteInstance()); |
| + scoped_refptr<ServiceWorkerContextWrapper> context = |
| + static_cast<ServiceWorkerContextWrapper*>( |
| + partition->GetServiceWorkerContext()); |
| + context_observer_ = new ContextObserver(context, weak_factory_.GetWeakPtr()); |
| + context_observer_->Start(); |
| for (auto host : agent_hosts) |
| WorkerCreated(host.get()); |
| return Response::OK(); |
| @@ -42,6 +301,10 @@ Response ServiceWorkerHandler::Disable() { |
| for (const auto& pair : attached_hosts_) |
| pair.second->DetachClient(); |
| attached_hosts_.clear(); |
| + if (context_observer_) { |
|
pfeldman
2015/03/09 19:16:49
The ToT has enabled_ check, so you would not need
horo
2015/03/10 01:34:07
Done.
|
| + context_observer_->Stop(); |
| + context_observer_ = nullptr; |
| + } |
| return Response::OK(); |
| } |
| @@ -80,6 +343,34 @@ Response ServiceWorkerHandler::Detach(const std::string& worker_id) { |
| return Response::OK(); |
| } |
| +void ServiceWorkerHandler::OnWorkerRegistrationUpdated( |
| + const std::vector<ServiceWorkerRegistrationInfo>& registrations) { |
| + std::vector<scoped_refptr<ServiceWorkerRegistration>> registration_values; |
| + for (const auto& registration : registrations) { |
| + registration_values.push_back( |
| + CreateRegistrationDictionaryValue(registration)); |
| + } |
| + client_->WorkerRegistrationUpdated( |
| + WorkerRegistrationUpdatedParams::Create()->set_registrations( |
| + registration_values)); |
| +} |
| + |
| +void ServiceWorkerHandler::OnWorkerVersionUpdated( |
| + const std::vector<ServiceWorkerVersionInfo>& versions) { |
| + std::vector<scoped_refptr<ServiceWorkerVersion>> version_values; |
| + for (const auto& version : versions) { |
| + version_values.push_back(CreateVersionDictionaryValue(version)); |
| + } |
| + client_->WorkerVersionUpdated( |
| + WorkerVersionUpdatedParams::Create()->set_versions(version_values)); |
| +} |
| + |
| +void ServiceWorkerHandler::OnWorkerRegistrationDeleted(int64 registration_id) { |
| + client_->WorkerRegistrationDeleted( |
| + WorkerRegistrationDeletedParams::Create()->set_registration_id( |
| + base::Int64ToString(registration_id))); |
| +} |
| + |
| void ServiceWorkerHandler::DispatchProtocolMessage( |
| DevToolsAgentHost* host, |
| const std::string& message) { |