ServiceWorker: Add UMA to track the execution time of onmessage event
[chromium-blink-merge.git] / content / renderer / service_worker / service_worker_script_context.cc
blob65fc5e7c5c46782a1d0a97fef686dbf4d96e399f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/service_worker/service_worker_script_context.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "content/child/thread_safe_sender.h"
11 #include "content/child/webmessageportchannel_impl.h"
12 #include "content/common/service_worker/service_worker_messages.h"
13 #include "content/renderer/service_worker/embedded_worker_context_client.h"
14 #include "ipc/ipc_message.h"
15 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
16 #include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
17 #include "third_party/WebKit/public/platform/WebString.h"
18 #include "third_party/WebKit/public/platform/WebURL.h"
19 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
20 #include "third_party/WebKit/public/web/WebServiceWorkerContextProxy.h"
22 namespace content {
24 namespace {
26 void SendPostMessageToDocumentOnMainThread(
27 ThreadSafeSender* sender,
28 int routing_id,
29 int client_id,
30 const base::string16& message,
31 scoped_ptr<blink::WebMessagePortChannelArray> channels) {
32 sender->Send(new ServiceWorkerHostMsg_PostMessageToDocument(
33 routing_id, client_id, message,
34 WebMessagePortChannelImpl::ExtractMessagePortIDs(channels.release())));
37 blink::WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode(
38 FetchRequestMode mode) {
39 return static_cast<blink::WebURLRequest::FetchRequestMode>(mode);
42 blink::WebURLRequest::FetchCredentialsMode GetBlinkFetchCredentialsMode(
43 FetchCredentialsMode credentials_mode) {
44 return static_cast<blink::WebURLRequest::FetchCredentialsMode>(
45 credentials_mode);
48 } // namespace
50 ServiceWorkerScriptContext::ServiceWorkerScriptContext(
51 EmbeddedWorkerContextClient* embedded_context,
52 blink::WebServiceWorkerContextProxy* proxy)
53 : cache_storage_dispatcher_(new ServiceWorkerCacheStorageDispatcher(this)),
54 embedded_context_(embedded_context),
55 proxy_(proxy) {
58 ServiceWorkerScriptContext::~ServiceWorkerScriptContext() {}
60 void ServiceWorkerScriptContext::OnMessageReceived(
61 const IPC::Message& message) {
62 bool handled = true;
63 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerScriptContext, message)
64 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEvent)
65 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEvent)
66 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
67 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SyncEvent, OnSyncEvent)
68 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEvent)
69 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
70 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClientDocuments,
71 OnDidGetClientDocuments)
72 IPC_MESSAGE_UNHANDLED(handled = false)
73 IPC_END_MESSAGE_MAP()
75 // TODO(gavinp): Would it be preferable to put an AddListener() method to
76 // EmbeddedWorkerContextClient?
77 if (!handled)
78 handled = cache_storage_dispatcher_->OnMessageReceived(message);
80 DCHECK(handled);
83 void ServiceWorkerScriptContext::DidHandleActivateEvent(
84 int request_id,
85 blink::WebServiceWorkerEventResult result) {
86 UMA_HISTOGRAM_TIMES(
87 "ServiceWorker.ActivateEventExecutionTime",
88 base::TimeTicks::Now() - activate_start_timings_[request_id]);
89 activate_start_timings_.erase(request_id);
91 Send(new ServiceWorkerHostMsg_ActivateEventFinished(
92 GetRoutingID(), request_id, result));
95 void ServiceWorkerScriptContext::DidHandleInstallEvent(
96 int request_id,
97 blink::WebServiceWorkerEventResult result) {
98 UMA_HISTOGRAM_TIMES(
99 "ServiceWorker.InstallEventExecutionTime",
100 base::TimeTicks::Now() - install_start_timings_[request_id]);
101 install_start_timings_.erase(request_id);
103 Send(new ServiceWorkerHostMsg_InstallEventFinished(
104 GetRoutingID(), request_id, result));
107 void ServiceWorkerScriptContext::DidHandleFetchEvent(
108 int request_id,
109 ServiceWorkerFetchEventResult result,
110 const ServiceWorkerResponse& response) {
111 UMA_HISTOGRAM_TIMES(
112 "ServiceWorker.FetchEventExecutionTime",
113 base::TimeTicks::Now() - fetch_start_timings_[request_id]);
114 fetch_start_timings_.erase(request_id);
116 Send(new ServiceWorkerHostMsg_FetchEventFinished(
117 GetRoutingID(), request_id, result, response));
120 void ServiceWorkerScriptContext::DidHandleSyncEvent(int request_id) {
121 Send(new ServiceWorkerHostMsg_SyncEventFinished(
122 GetRoutingID(), request_id));
125 void ServiceWorkerScriptContext::GetClientDocuments(
126 blink::WebServiceWorkerClientsCallbacks* callbacks) {
127 DCHECK(callbacks);
128 int request_id = pending_clients_callbacks_.Add(callbacks);
129 Send(new ServiceWorkerHostMsg_GetClientDocuments(
130 GetRoutingID(), request_id));
133 void ServiceWorkerScriptContext::PostMessageToDocument(
134 int client_id,
135 const base::string16& message,
136 scoped_ptr<blink::WebMessagePortChannelArray> channels) {
137 // This may send channels for MessagePorts, and all internal book-keeping
138 // messages for MessagePort (e.g. QueueMessages) are sent from main thread
139 // (with thread hopping), so we need to do the same thread hopping here not
140 // to overtake those messages.
141 embedded_context_->main_thread_proxy()->PostTask(
142 FROM_HERE,
143 base::Bind(&SendPostMessageToDocumentOnMainThread,
144 make_scoped_refptr(embedded_context_->thread_safe_sender()),
145 GetRoutingID(), client_id, message, base::Passed(&channels)));
148 void ServiceWorkerScriptContext::Send(IPC::Message* message) {
149 embedded_context_->Send(message);
152 int ServiceWorkerScriptContext::GetRoutingID() const {
153 return embedded_context_->embedded_worker_id();
156 void ServiceWorkerScriptContext::OnActivateEvent(int request_id) {
157 TRACE_EVENT0("ServiceWorker",
158 "ServiceWorkerScriptContext::OnActivateEvent");
159 activate_start_timings_[request_id] = base::TimeTicks::Now();
160 proxy_->dispatchActivateEvent(request_id);
163 void ServiceWorkerScriptContext::OnInstallEvent(int request_id,
164 int active_version_id) {
165 TRACE_EVENT0("ServiceWorker",
166 "ServiceWorkerScriptContext::OnInstallEvent");
167 install_start_timings_[request_id] = base::TimeTicks::Now();
168 proxy_->dispatchInstallEvent(request_id);
171 void ServiceWorkerScriptContext::OnFetchEvent(
172 int request_id,
173 const ServiceWorkerFetchRequest& request) {
174 blink::WebServiceWorkerRequest webRequest;
175 TRACE_EVENT0("ServiceWorker",
176 "ServiceWorkerScriptContext::OnFetchEvent");
177 webRequest.setURL(blink::WebURL(request.url));
178 webRequest.setMethod(blink::WebString::fromUTF8(request.method));
179 for (ServiceWorkerHeaderMap::const_iterator it = request.headers.begin();
180 it != request.headers.end();
181 ++it) {
182 webRequest.setHeader(blink::WebString::fromUTF8(it->first),
183 blink::WebString::fromUTF8(it->second));
185 if (!request.blob_uuid.empty()) {
186 webRequest.setBlob(blink::WebString::fromUTF8(request.blob_uuid),
187 request.blob_size);
189 webRequest.setReferrer(blink::WebString::fromUTF8(request.referrer.spec()),
190 blink::WebReferrerPolicyDefault);
191 webRequest.setMode(GetBlinkFetchRequestMode(request.mode));
192 webRequest.setCredentialsMode(
193 GetBlinkFetchCredentialsMode(request.credentials_mode));
194 webRequest.setIsReload(request.is_reload);
195 fetch_start_timings_[request_id] = base::TimeTicks::Now();
196 proxy_->dispatchFetchEvent(request_id, webRequest);
199 void ServiceWorkerScriptContext::OnSyncEvent(int request_id) {
200 TRACE_EVENT0("ServiceWorker",
201 "ServiceWorkerScriptContext::OnSyncEvent");
202 proxy_->dispatchSyncEvent(request_id);
205 void ServiceWorkerScriptContext::OnPushEvent(int request_id,
206 const std::string& data) {
207 TRACE_EVENT0("ServiceWorker",
208 "ServiceWorkerScriptContext::OnPushEvent");
209 proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
210 Send(new ServiceWorkerHostMsg_PushEventFinished(
211 GetRoutingID(), request_id));
214 void ServiceWorkerScriptContext::OnPostMessage(
215 const base::string16& message,
216 const std::vector<int>& sent_message_port_ids,
217 const std::vector<int>& new_routing_ids) {
218 TRACE_EVENT0("ServiceWorker",
219 "ServiceWorkerScriptContext::OnPostEvent");
220 std::vector<WebMessagePortChannelImpl*> ports;
221 if (!sent_message_port_ids.empty()) {
222 base::MessageLoopProxy* loop_proxy = embedded_context_->main_thread_proxy();
223 ports.resize(sent_message_port_ids.size());
224 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
225 ports[i] = new WebMessagePortChannelImpl(
226 new_routing_ids[i], sent_message_port_ids[i], loop_proxy);
230 // dispatchMessageEvent is expected to execute onmessage function
231 // synchronously.
232 base::TimeTicks before = base::TimeTicks::Now();
233 proxy_->dispatchMessageEvent(message, ports);
234 UMA_HISTOGRAM_TIMES(
235 "ServiceWorker.MessageEventExecutionTime",
236 base::TimeTicks::Now() - before);
239 void ServiceWorkerScriptContext::OnDidGetClientDocuments(
240 int request_id, const std::vector<int>& client_ids) {
241 TRACE_EVENT0("ServiceWorker",
242 "ServiceWorkerScriptContext::OnDidGetClientDocuments");
243 blink::WebServiceWorkerClientsCallbacks* callbacks =
244 pending_clients_callbacks_.Lookup(request_id);
245 if (!callbacks) {
246 NOTREACHED() << "Got stray response: " << request_id;
247 return;
249 scoped_ptr<blink::WebServiceWorkerClientsInfo> info(
250 new blink::WebServiceWorkerClientsInfo);
251 info->clientIDs = client_ids;
252 callbacks->onSuccess(info.release());
253 pending_clients_callbacks_.Remove(request_id);
256 } // namespace content