| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/browser/devtools/protocol/service_worker_handler.h" | 5 #include "content/browser/devtools/protocol/service_worker_handler.h" |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/strings/string_number_conversions.h" |
| 7 #include "content/browser/devtools/service_worker_devtools_agent_host.h" | 9 #include "content/browser/devtools/service_worker_devtools_agent_host.h" |
| 8 #include "content/browser/devtools/service_worker_devtools_manager.h" | 10 #include "content/browser/devtools/service_worker_devtools_manager.h" |
| 11 #include "content/browser/service_worker/service_worker_context_observer.h" |
| 12 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 13 #include "content/public/browser/browser_context.h" |
| 14 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/browser/devtools_agent_host.h" |
| 16 #include "content/public/browser/render_frame_host.h" |
| 17 #include "content/public/browser/render_process_host.h" |
| 18 #include "content/public/browser/storage_partition.h" |
| 19 #include "url/gurl.h" |
| 20 |
| 21 // Windows headers will redefine SendMessage. |
| 22 #ifdef SendMessage |
| 23 #undef SendMessage |
| 24 #endif |
| 9 | 25 |
| 10 namespace content { | 26 namespace content { |
| 11 namespace devtools { | 27 namespace devtools { |
| 12 namespace service_worker { | 28 namespace service_worker { |
| 13 | 29 |
| 30 namespace { |
| 31 |
| 32 const std::string GetVersionRunningStatusString( |
| 33 content::ServiceWorkerVersion::RunningStatus running_status) { |
| 34 switch (running_status) { |
| 35 case content::ServiceWorkerVersion::STOPPED: |
| 36 return service_worker_version::kRunningStatusStopped; |
| 37 case content::ServiceWorkerVersion::STARTING: |
| 38 return service_worker_version::kRunningStatusStarting; |
| 39 case content::ServiceWorkerVersion::RUNNING: |
| 40 return service_worker_version::kRunningStatusRunning; |
| 41 case content::ServiceWorkerVersion::STOPPING: |
| 42 return service_worker_version::kRunningStatusStopping; |
| 43 } |
| 44 return ""; |
| 45 } |
| 46 |
| 47 const std::string GetVersionStatusString( |
| 48 content::ServiceWorkerVersion::Status status) { |
| 49 switch (status) { |
| 50 case content::ServiceWorkerVersion::NEW: |
| 51 return service_worker_version::kStatusNew; |
| 52 case content::ServiceWorkerVersion::INSTALLING: |
| 53 return service_worker_version::kStatusInstalling; |
| 54 case content::ServiceWorkerVersion::INSTALLED: |
| 55 return service_worker_version::kStatusInstalled; |
| 56 case content::ServiceWorkerVersion::ACTIVATING: |
| 57 return service_worker_version::kStatusActivating; |
| 58 case content::ServiceWorkerVersion::ACTIVATED: |
| 59 return service_worker_version::kStatusActivated; |
| 60 case content::ServiceWorkerVersion::REDUNDANT: |
| 61 return service_worker_version::kStatusRedundant; |
| 62 } |
| 63 return ""; |
| 64 } |
| 65 |
| 66 scoped_refptr<ServiceWorkerVersion> CreateVersionDictionaryValue( |
| 67 const ServiceWorkerVersionInfo& version_info) { |
| 68 scoped_refptr<ServiceWorkerVersion> version( |
| 69 ServiceWorkerVersion::Create() |
| 70 ->set_version_id(base::Int64ToString(version_info.version_id)) |
| 71 ->set_registration_id( |
| 72 base::Int64ToString(version_info.registration_id)) |
| 73 ->set_script_url(version_info.script_url.spec()) |
| 74 ->set_running_status( |
| 75 GetVersionRunningStatusString(version_info.running_status)) |
| 76 ->set_status(GetVersionStatusString(version_info.status))); |
| 77 return version; |
| 78 } |
| 79 |
| 80 scoped_refptr<ServiceWorkerRegistration> CreateRegistrationDictionaryValue( |
| 81 const ServiceWorkerRegistrationInfo& registration_info) { |
| 82 scoped_refptr<ServiceWorkerRegistration> registration( |
| 83 ServiceWorkerRegistration::Create() |
| 84 ->set_registration_id( |
| 85 base::Int64ToString(registration_info.registration_id)) |
| 86 ->set_scope_url(registration_info.pattern.spec())); |
| 87 if (registration_info.active_version.version_id != |
| 88 kInvalidServiceWorkerVersionId) { |
| 89 registration->set_active_version( |
| 90 CreateVersionDictionaryValue(registration_info.active_version)); |
| 91 } |
| 92 if (registration_info.waiting_version.version_id != |
| 93 kInvalidServiceWorkerVersionId) { |
| 94 registration->set_waiting_version( |
| 95 CreateVersionDictionaryValue(registration_info.waiting_version)); |
| 96 } |
| 97 if (registration_info.installing_version.version_id != |
| 98 kInvalidServiceWorkerVersionId) { |
| 99 registration->set_installing_version( |
| 100 CreateVersionDictionaryValue(registration_info.installing_version)); |
| 101 } |
| 102 return registration; |
| 103 } |
| 104 |
| 105 } // namespace |
| 106 |
| 14 using Response = DevToolsProtocolClient::Response; | 107 using Response = DevToolsProtocolClient::Response; |
| 15 | 108 |
| 109 class ServiceWorkerHandler::ContextObserver |
| 110 : public ServiceWorkerContextObserver, |
| 111 public base::RefCountedThreadSafe<ContextObserver> { |
| 112 public: |
| 113 ContextObserver(scoped_refptr<ServiceWorkerContextWrapper> context, |
| 114 base::WeakPtr<ServiceWorkerHandler> handler); |
| 115 void Start(); |
| 116 void Stop(); |
| 117 |
| 118 private: |
| 119 friend class base::RefCountedThreadSafe<ContextObserver>; |
| 120 ~ContextObserver() override; |
| 121 void GetStoredRegistrationsOnIOThread(); |
| 122 void OnStoredRegistrationsOnIOThread( |
| 123 const std::vector<ServiceWorkerRegistrationInfo>& registrations); |
| 124 void StopOnIOThread(); |
| 125 |
| 126 void OnVersionUpdated(int64 version_id); |
| 127 void OnRegistrationUpdated(int64 registration_id); |
| 128 |
| 129 // ServiceWorkerContextObserver implements |
| 130 void OnRunningStateChanged(int64 version_id) override; |
| 131 void OnVersionStateChanged(int64 version_id) override; |
| 132 void OnRegistrationStored(int64 registration_id, |
| 133 const GURL& pattern) override; |
| 134 void OnRegistrationDeleted(int64 registration_id, |
| 135 const GURL& pattern) override; |
| 136 |
| 137 scoped_refptr<ServiceWorkerContextWrapper> context_; |
| 138 base::WeakPtr<ServiceWorkerHandler> handler_; |
| 139 }; |
| 140 |
| 141 ServiceWorkerHandler::ContextObserver::ContextObserver( |
| 142 scoped_refptr<ServiceWorkerContextWrapper> context, |
| 143 base::WeakPtr<ServiceWorkerHandler> handler) |
| 144 : context_(context), handler_(handler) { |
| 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 146 } |
| 147 |
| 148 void ServiceWorkerHandler::ContextObserver::Start() { |
| 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 150 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 151 base::Bind(&ServiceWorkerHandler::ContextObserver:: |
| 152 GetStoredRegistrationsOnIOThread, |
| 153 this)); |
| 154 } |
| 155 |
| 156 void ServiceWorkerHandler::ContextObserver::Stop() { |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 158 BrowserThread::PostTask( |
| 159 BrowserThread::IO, FROM_HERE, |
| 160 base::Bind(&ServiceWorkerHandler::ContextObserver::StopOnIOThread, this)); |
| 161 } |
| 162 |
| 163 void ServiceWorkerHandler::ContextObserver::GetStoredRegistrationsOnIOThread() { |
| 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 165 context_->context()->storage()->GetAllRegistrations(base::Bind( |
| 166 &ServiceWorkerHandler::ContextObserver::OnStoredRegistrationsOnIOThread, |
| 167 this)); |
| 168 } |
| 169 |
| 170 void ServiceWorkerHandler::ContextObserver::OnStoredRegistrationsOnIOThread( |
| 171 const std::vector<ServiceWorkerRegistrationInfo>& registrations) { |
| 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 173 context_->AddObserver(this); |
| 174 BrowserThread::PostTask( |
| 175 BrowserThread::UI, FROM_HERE, |
| 176 base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| 177 registrations)); |
| 178 BrowserThread::PostTask( |
| 179 BrowserThread::UI, FROM_HERE, |
| 180 base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| 181 context_->context()->GetAllLiveRegistrationInfo())); |
| 182 BrowserThread::PostTask( |
| 183 BrowserThread::UI, FROM_HERE, |
| 184 base::Bind(&ServiceWorkerHandler::OnWorkerVersionUpdated, handler_, |
| 185 context_->context()->GetAllLiveVersionInfo())); |
| 186 } |
| 187 |
| 188 void ServiceWorkerHandler::ContextObserver::StopOnIOThread() { |
| 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 190 context_->RemoveObserver(this); |
| 191 } |
| 192 |
| 193 ServiceWorkerHandler::ContextObserver::~ContextObserver() { |
| 194 } |
| 195 |
| 196 void ServiceWorkerHandler::ContextObserver::OnVersionUpdated(int64 version_id) { |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 198 content::ServiceWorkerVersion* version = |
| 199 context_->context()->GetLiveVersion(version_id); |
| 200 if (!version) |
| 201 return; |
| 202 OnRegistrationUpdated(version->registration_id()); |
| 203 std::vector<ServiceWorkerVersionInfo> versions; |
| 204 versions.push_back(version->GetInfo()); |
| 205 BrowserThread::PostTask( |
| 206 BrowserThread::UI, FROM_HERE, |
| 207 base::Bind(&ServiceWorkerHandler::OnWorkerVersionUpdated, handler_, |
| 208 versions)); |
| 209 } |
| 210 |
| 211 void ServiceWorkerHandler::ContextObserver::OnRegistrationUpdated( |
| 212 int64 registration_id) { |
| 213 content::ServiceWorkerRegistration* registration = |
| 214 context_->context()->GetLiveRegistration(registration_id); |
| 215 if (!registration) |
| 216 return; |
| 217 std::vector<ServiceWorkerRegistrationInfo> registrations; |
| 218 registrations.push_back(registration->GetInfo()); |
| 219 BrowserThread::PostTask( |
| 220 BrowserThread::UI, FROM_HERE, |
| 221 base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| 222 registrations)); |
| 223 } |
| 224 |
| 225 void ServiceWorkerHandler::ContextObserver::OnRunningStateChanged( |
| 226 int64 version_id) { |
| 227 OnVersionUpdated(version_id); |
| 228 } |
| 229 |
| 230 void ServiceWorkerHandler::ContextObserver::OnVersionStateChanged( |
| 231 int64 version_id) { |
| 232 OnVersionUpdated(version_id); |
| 233 } |
| 234 |
| 235 void ServiceWorkerHandler::ContextObserver::OnRegistrationStored( |
| 236 int64 registration_id, |
| 237 const GURL& pattern) { |
| 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 239 content::ServiceWorkerRegistration* registration = |
| 240 context_->context()->GetLiveRegistration(registration_id); |
| 241 DCHECK(registration); |
| 242 std::vector<ServiceWorkerRegistrationInfo> registrations; |
| 243 registrations.push_back(registration->GetInfo()); |
| 244 BrowserThread::PostTask( |
| 245 BrowserThread::UI, FROM_HERE, |
| 246 base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated, handler_, |
| 247 registrations)); |
| 248 } |
| 249 |
| 250 void ServiceWorkerHandler::ContextObserver::OnRegistrationDeleted( |
| 251 int64 registration_id, |
| 252 const GURL& pattern) { |
| 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 254 BrowserThread::PostTask( |
| 255 BrowserThread::UI, FROM_HERE, |
| 256 base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationDeleted, handler_, |
| 257 registration_id)); |
| 258 } |
| 259 |
| 16 ServiceWorkerHandler::ServiceWorkerHandler() | 260 ServiceWorkerHandler::ServiceWorkerHandler() |
| 17 : enabled_(false) { | 261 : enabled_(false), weak_factory_(this) { |
| 18 } | 262 } |
| 19 | 263 |
| 20 ServiceWorkerHandler::~ServiceWorkerHandler() { | 264 ServiceWorkerHandler::~ServiceWorkerHandler() { |
| 21 Disable(); | 265 Disable(); |
| 22 } | 266 } |
| 23 | 267 |
| 24 void ServiceWorkerHandler::SetClient( | 268 void ServiceWorkerHandler::SetRenderFrameHost( |
| 25 scoped_ptr<Client> client) { | 269 RenderFrameHost* render_frame_host) { |
| 270 if (!render_frame_host) { |
| 271 context_ = nullptr; |
| 272 return; |
| 273 } |
| 274 StoragePartition* partition = BrowserContext::GetStoragePartition( |
| 275 render_frame_host->GetProcess()->GetBrowserContext(), |
| 276 render_frame_host->GetSiteInstance()); |
| 277 DCHECK(partition); |
| 278 context_ = static_cast<ServiceWorkerContextWrapper*>( |
| 279 partition->GetServiceWorkerContext()); |
| 280 } |
| 281 |
| 282 void ServiceWorkerHandler::SetClient(scoped_ptr<Client> client) { |
| 26 client_.swap(client); | 283 client_.swap(client); |
| 27 } | 284 } |
| 28 | 285 |
| 29 void ServiceWorkerHandler::SetURL(const GURL& url) { | 286 void ServiceWorkerHandler::SetURL(const GURL& url) { |
| 30 url_ = url; | 287 url_ = url; |
| 31 if (enabled_) { | 288 if (enabled_) { |
| 32 for (auto pair : attached_hosts_) { | 289 for (auto pair : attached_hosts_) { |
| 33 if (!MatchesInspectedPage(pair.second.get())) | 290 if (!MatchesInspectedPage(pair.second.get())) |
| 34 WorkerDestroyed(pair.second.get()); | 291 WorkerDestroyed(pair.second.get()); |
| 35 } | 292 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 50 } | 307 } |
| 51 } | 308 } |
| 52 | 309 |
| 53 void ServiceWorkerHandler::Detached() { | 310 void ServiceWorkerHandler::Detached() { |
| 54 Disable(); | 311 Disable(); |
| 55 } | 312 } |
| 56 | 313 |
| 57 Response ServiceWorkerHandler::Enable() { | 314 Response ServiceWorkerHandler::Enable() { |
| 58 if (enabled_) | 315 if (enabled_) |
| 59 return Response::OK(); | 316 return Response::OK(); |
| 317 if (!context_) |
| 318 return Response::InternalError("Could not connect to the context"); |
| 60 enabled_ = true; | 319 enabled_ = true; |
| 61 | 320 |
| 62 ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this); | 321 ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this); |
| 63 | 322 |
| 64 ServiceWorkerDevToolsAgentHost::List agent_hosts; | 323 ServiceWorkerDevToolsAgentHost::List agent_hosts; |
| 65 ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&agent_hosts); | 324 ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&agent_hosts); |
| 66 for (auto host : agent_hosts) | 325 for (auto host : agent_hosts) |
| 67 WorkerReadyForInspection(host.get()); | 326 WorkerReadyForInspection(host.get()); |
| 327 |
| 328 context_observer_ = new ContextObserver(context_, weak_factory_.GetWeakPtr()); |
| 329 context_observer_->Start(); |
| 68 return Response::OK(); | 330 return Response::OK(); |
| 69 } | 331 } |
| 70 | 332 |
| 71 Response ServiceWorkerHandler::Disable() { | 333 Response ServiceWorkerHandler::Disable() { |
| 72 if (!enabled_) | 334 if (!enabled_) |
| 73 return Response::OK(); | 335 return Response::OK(); |
| 74 enabled_ = false; | 336 enabled_ = false; |
| 75 | 337 |
| 76 ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this); | 338 ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this); |
| 77 for (const auto& pair : attached_hosts_) | 339 for (const auto& pair : attached_hosts_) |
| 78 pair.second->DetachClient(); | 340 pair.second->DetachClient(); |
| 79 attached_hosts_.clear(); | 341 attached_hosts_.clear(); |
| 342 DCHECK(context_observer_); |
| 343 context_observer_->Stop(); |
| 344 context_observer_ = nullptr; |
| 80 return Response::OK(); | 345 return Response::OK(); |
| 81 } | 346 } |
| 82 | 347 |
| 83 Response ServiceWorkerHandler::SendMessage( | 348 Response ServiceWorkerHandler::SendMessage( |
| 84 const std::string& worker_id, | 349 const std::string& worker_id, |
| 85 const std::string& message) { | 350 const std::string& message) { |
| 86 auto it = attached_hosts_.find(worker_id); | 351 auto it = attached_hosts_.find(worker_id); |
| 87 if (it == attached_hosts_.end()) | 352 if (it == attached_hosts_.end()) |
| 88 return Response::InternalError("Not connected to the worker"); | 353 return Response::InternalError("Not connected to the worker"); |
| 89 it->second->DispatchProtocolMessage(message); | 354 it->second->DispatchProtocolMessage(message); |
| 90 return Response::OK(); | 355 return Response::OK(); |
| 91 } | 356 } |
| 92 | 357 |
| 93 Response ServiceWorkerHandler::Stop( | 358 Response ServiceWorkerHandler::Stop( |
| 94 const std::string& worker_id) { | 359 const std::string& worker_id) { |
| 95 auto it = attached_hosts_.find(worker_id); | 360 auto it = attached_hosts_.find(worker_id); |
| 96 if (it == attached_hosts_.end()) | 361 if (it == attached_hosts_.end()) |
| 97 return Response::InternalError("Not connected to the worker"); | 362 return Response::InternalError("Not connected to the worker"); |
| 98 it->second->Close(); | 363 it->second->Close(); |
| 99 return Response::OK(); | 364 return Response::OK(); |
| 100 } | 365 } |
| 101 | 366 |
| 367 void ServiceWorkerHandler::OnWorkerRegistrationUpdated( |
| 368 const std::vector<ServiceWorkerRegistrationInfo>& registrations) { |
| 369 std::vector<scoped_refptr<ServiceWorkerRegistration>> registration_values; |
| 370 for (const auto& registration : registrations) { |
| 371 registration_values.push_back( |
| 372 CreateRegistrationDictionaryValue(registration)); |
| 373 } |
| 374 client_->WorkerRegistrationUpdated( |
| 375 WorkerRegistrationUpdatedParams::Create()->set_registrations( |
| 376 registration_values)); |
| 377 } |
| 378 |
| 379 void ServiceWorkerHandler::OnWorkerVersionUpdated( |
| 380 const std::vector<ServiceWorkerVersionInfo>& versions) { |
| 381 std::vector<scoped_refptr<ServiceWorkerVersion>> version_values; |
| 382 for (const auto& version : versions) { |
| 383 version_values.push_back(CreateVersionDictionaryValue(version)); |
| 384 } |
| 385 client_->WorkerVersionUpdated( |
| 386 WorkerVersionUpdatedParams::Create()->set_versions(version_values)); |
| 387 } |
| 388 |
| 389 void ServiceWorkerHandler::OnWorkerRegistrationDeleted(int64 registration_id) { |
| 390 client_->WorkerRegistrationDeleted( |
| 391 WorkerRegistrationDeletedParams::Create()->set_registration_id( |
| 392 base::Int64ToString(registration_id))); |
| 393 } |
| 394 |
| 102 void ServiceWorkerHandler::DispatchProtocolMessage( | 395 void ServiceWorkerHandler::DispatchProtocolMessage( |
| 103 DevToolsAgentHost* host, | 396 DevToolsAgentHost* host, |
| 104 const std::string& message) { | 397 const std::string& message) { |
| 105 | 398 |
| 106 auto it = attached_hosts_.find(host->GetId()); | 399 auto it = attached_hosts_.find(host->GetId()); |
| 107 if (it == attached_hosts_.end()) | 400 if (it == attached_hosts_.end()) |
| 108 return; // Already disconnected. | 401 return; // Already disconnected. |
| 109 | 402 |
| 110 client_->DispatchMessage( | 403 client_->DispatchMessage( |
| 111 DispatchMessageParams::Create()-> | 404 DispatchMessageParams::Create()-> |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 bool ServiceWorkerHandler::MatchesInspectedPage( | 445 bool ServiceWorkerHandler::MatchesInspectedPage( |
| 153 ServiceWorkerDevToolsAgentHost* host) { | 446 ServiceWorkerDevToolsAgentHost* host) { |
| 154 // TODO(pfeldman): match based on scope. | 447 // TODO(pfeldman): match based on scope. |
| 155 // TODO(pfeldman): match iframes. | 448 // TODO(pfeldman): match iframes. |
| 156 return host->GetURL().host() == url_.host(); | 449 return host->GetURL().host() == url_.host(); |
| 157 } | 450 } |
| 158 | 451 |
| 159 } // namespace service_worker | 452 } // namespace service_worker |
| 160 } // namespace devtools | 453 } // namespace devtools |
| 161 } // namespace content | 454 } // namespace content |
| OLD | NEW |