Index: content/browser/service_worker/service_worker_version.cc |
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc |
index f1760a0741437c088db3e0d90cc8fa1a4dc623a2..d06834168f2f7546d51c34a1c00c9c5c2aa1175b 100644 |
--- a/content/browser/service_worker/service_worker_version.cc |
+++ b/content/browser/service_worker/service_worker_version.cc |
@@ -23,6 +23,38 @@ namespace content { |
typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
typedef ServiceWorkerVersion::MessageCallback MessageCallback; |
+class ServiceWorkerVersion::GetClientInfoCallback { |
+ public: |
+ GetClientInfoCallback(int request_id) |
+ : request_id_(request_id) {} |
+ void Add(int client_request_id, int client_id) { |
+ pending_requests_[client_request_id] = client_id; |
+ } |
+ void Success(int client_request_id, const ServiceWorkerClientInfo& info) { |
+ auto found = pending_requests_.find(client_request_id); |
+ DCHECK(found != pending_requests_.end()); |
+ clients_.push_back(info); |
+ clients_.back().client_id = found->second; |
+ pending_requests_.erase(found); |
+ } |
+ void Error(int client_request_id) { Cancel(client_request_id); } |
+ void Cancel(int client_request_id) { |
+ auto found = pending_requests_.find(client_request_id); |
+ DCHECK(found != pending_requests_.end()); |
+ pending_requests_.erase(found); |
+ } |
+ int request_id() { return request_id_; } |
+ bool HasPendingRequests() { return !pending_requests_.empty(); } |
+ const std::vector<ServiceWorkerClientInfo>& clients() { return clients_; } |
+ |
+ static void ClearCallbacks(IDMap<GetClientInfoCallback>* callbacks); |
+ |
+ private: |
+ std::vector<ServiceWorkerClientInfo> clients_; |
+ int request_id_; |
+ std::map<int, int> pending_requests_; |
+}; |
+ |
namespace { |
// Default delay for scheduled stop. |
@@ -577,6 +609,8 @@ void ServiceWorkerVersion::OnStopped( |
RunIDMapCallbacks(&geofencing_callbacks_, |
SERVICE_WORKER_ERROR_FAILED); |
+ GetClientInfoCallback::ClearCallbacks(&get_client_info_callbacks_); |
+ |
FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); |
// There should be no more communication from/to a stopped worker. Deleting |
@@ -644,6 +678,10 @@ bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) { |
OnPostMessageToDocument) |
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FocusClient, |
OnFocusClient) |
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClientInfoSuccess, |
+ OnGetClientInfoSuccess) |
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClientInfoError, |
+ OnGetClientInfoError) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
return handled; |
@@ -685,19 +723,67 @@ void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker( |
} |
void ServiceWorkerVersion::OnGetClientDocuments(int request_id) { |
- std::vector<int> client_ids; |
+ if (controllee_by_id_.IsEmpty()) { |
+ if (running_status() == RUNNING) { |
+ embedded_worker_->SendMessage( |
+ ServiceWorkerMsg_DidGetClientDocuments(request_id, |
+ std::vector<ServiceWorkerClientInfo>())); |
+ } |
+ return; |
+ } |
+ GetClientInfoCallback* callback = new GetClientInfoCallback(request_id); |
ControlleeByIDMap::iterator it(&controllee_by_id_); |
TRACE_EVENT0("ServiceWorker", |
"ServiceWorkerVersion::OnGetClientDocuments"); |
while (!it.IsAtEnd()) { |
- client_ids.push_back(it.GetCurrentKey()); |
+ int client_request_id = get_client_info_callbacks_.Add(callback); |
+ callback->Add(client_request_id, it.GetCurrentKey()); |
+ it.GetCurrentValue()->GetClientInfo(embedded_worker_->embedded_worker_id(), |
+ client_request_id); |
it.Advance(); |
} |
+} |
+ |
+void ServiceWorkerVersion::OnGetClientInfoSuccess( |
+ int request_id, |
+ const ServiceWorkerClientInfo& info) { |
+ GetClientInfoCallback* callback = |
+ get_client_info_callbacks_.Lookup(request_id); |
+ if (!callback) |
+ return; |
nhiroki
2014/12/08 07:09:33
How about having a comment about why we can ignore
Kunihiko Sakamoto
2014/12/08 07:46:58
Done.
|
+ get_client_info_callbacks_.Remove(request_id); |
+ |
+ callback->Success(request_id, info); |
+ if (callback->HasPendingRequests()) |
+ return; |
+ |
+ // Don't bother if it's no longer running. |
+ if (running_status() == RUNNING) { |
+ embedded_worker_->SendMessage( |
+ ServiceWorkerMsg_DidGetClientDocuments(callback->request_id(), |
+ callback->clients())); |
+ } |
+ delete callback; |
+} |
+ |
+void ServiceWorkerVersion::OnGetClientInfoError(int request_id) { |
+ GetClientInfoCallback* callback = |
+ get_client_info_callbacks_.Lookup(request_id); |
+ if (!callback) |
nhiroki
2014/12/08 07:09:33
ditto.
Kunihiko Sakamoto
2014/12/08 07:46:58
Done.
|
+ return; |
+ get_client_info_callbacks_.Remove(request_id); |
+ |
+ callback->Error(request_id); |
+ if (callback->HasPendingRequests()) |
+ return; |
+ |
// Don't bother if it's no longer running. |
if (running_status() == RUNNING) { |
embedded_worker_->SendMessage( |
- ServiceWorkerMsg_DidGetClientDocuments(request_id, client_ids)); |
+ ServiceWorkerMsg_DidGetClientDocuments(callback->request_id(), |
+ callback->clients())); |
} |
+ delete callback; |
} |
void ServiceWorkerVersion::OnActivateEventFinished( |
@@ -900,4 +986,17 @@ void ServiceWorkerVersion::DoomInternal() { |
context_->storage()->PurgeResources(resources); |
} |
+void ServiceWorkerVersion::GetClientInfoCallback::ClearCallbacks( |
+ IDMap<GetClientInfoCallback>* callbacks) { |
+ IDMap<GetClientInfoCallback>::iterator iter(callbacks); |
+ while (!iter.IsAtEnd()) { |
+ GetClientInfoCallback* callback = iter.GetCurrentValue(); |
+ callback->Cancel(iter.GetCurrentKey()); |
+ if (!callback->HasPendingRequests()) |
+ delete callback; |
+ iter.Advance(); |
+ } |
+ callbacks->Clear(); |
+} |
+ |
} // namespace content |