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.
4 
5 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
7 
8 #include <stddef.h>
9 #include <map>
10 #include <set>
11 
12 #include "base/macros.h"
13 #include "base/time/time.h"
14 #include "content/public/browser/service_worker_context.h"
15 #include "services/network/public/mojom/fetch_api.mojom.h"
16 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
17 #include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
18 #include "ui/base/page_transition_types.h"
19 
20 class GURL;
21 
22 namespace content {
23 
24 class ServiceWorkerMetrics {
25  public:
26   // Used for UMA. Append-only.
27   enum ReadResponseResult {
28     READ_OK,
29     READ_HEADERS_ERROR,
30     READ_DATA_ERROR,
31     NUM_READ_RESPONSE_RESULT_TYPES,
32   };
33 
34   // Used for UMA. Append-only.
35   enum WriteResponseResult {
36     WRITE_OK,
37     WRITE_HEADERS_ERROR,
38     WRITE_DATA_ERROR,
39     NUM_WRITE_RESPONSE_RESULT_TYPES,
40   };
41 
42   // Used for UMA. Append-only.
43   enum DeleteAndStartOverResult {
44     DELETE_OK,
45     DELETE_DATABASE_ERROR,
46     DELETE_DISK_CACHE_ERROR,
47     NUM_DELETE_AND_START_OVER_RESULT_TYPES,
48   };
49 
50   // Used for UMA. Append-only.
51   enum class StopStatus {
52     NORMAL,
53     DETACH_BY_REGISTRY,
54     TIMEOUT,
55     // Add new types here.
56     kMaxValue = TIMEOUT,
57   };
58 
59   // Used for UMA. Append-only.
60   // This class is used to indicate which event is fired/finished. Most events
61   // have only one request that starts the event and one response that finishes
62   // the event, but the fetch event has two responses, so there are two types of
63   // EventType to break down the measurement into two: FETCH and
64   // FETCH_WAITUNTIL. Moreover, FETCH is separated into the four: MAIN_FRAME,
65   // SUB_FRAME, SHARED_WORKER and SUB_RESOURCE for more detailed UMA.
66   enum class EventType {
67     ACTIVATE = 0,
68     INSTALL = 1,
69     // FETCH = 2,  // Obsolete
70     SYNC = 3,
71     NOTIFICATION_CLICK = 4,
72     PUSH = 5,
73     // GEOFENCING = 6,  // Obsolete
74     // SERVICE_PORT_CONNECT = 7,  // Obsolete
75     MESSAGE = 8,
76     NOTIFICATION_CLOSE = 9,
77     FETCH_MAIN_FRAME = 10,
78     FETCH_SUB_FRAME = 11,
79     FETCH_SHARED_WORKER = 12,
80     FETCH_SUB_RESOURCE = 13,
81     UNKNOWN = 14,  // Used when event type is not known.
82     // FOREIGN_FETCH = 15,  // Obsolete
83     FETCH_WAITUNTIL = 16,
84     // FOREIGN_FETCH_WAITUNTIL = 17,  // Obsolete
85     // NAVIGATION_HINT_LINK_MOUSE_DOWN = 18,  // Obsolete
86     // NAVIGATION_HINT_LINK_TAP_UNCONFIRMED = 19,  // Obsolete
87     // NAVIGATION_HINT_LINK_TAP_DOWN = 20,  // Obsolete
88     // Used when external consumers want to add a request to
89     // ServiceWorkerVersion to keep it alive.
90     EXTERNAL_REQUEST = 21,
91     PAYMENT_REQUEST = 22,
92     BACKGROUND_FETCH_ABORT = 23,
93     BACKGROUND_FETCH_CLICK = 24,
94     BACKGROUND_FETCH_FAIL = 25,
95     // BACKGROUND_FETCHED = 26,  // Obsolete
96     NAVIGATION_HINT = 27,
97     CAN_MAKE_PAYMENT = 28,
98     ABORT_PAYMENT = 29,
99     COOKIE_CHANGE = 30,
100     // LONG_RUNNING_MESSAGE = 31, // Obsolete
101     BACKGROUND_FETCH_SUCCESS = 32,
102     PERIODIC_SYNC = 33,
103     CONTENT_DELETE = 34,
104     // Add new events to record here.
105     kMaxValue = CONTENT_DELETE,
106   };
107 
108   // Used for UMA. Append only.
109   enum class Site {
110     OTHER,  // Obsolete for UMA. Use WITH_FETCH_HANDLER or
111             // WITHOUT_FETCH_HANDLER.
112     NEW_TAB_PAGE,
113     WITH_FETCH_HANDLER,
114     WITHOUT_FETCH_HANDLER,
115     PLUS,
116     INBOX,
117     DOCS,
118     kMaxValue = DOCS,
119   };
120 
121   // Not used for UMA.
122   enum class StartSituation {
123     // Failed to allocate a process.
124     UNKNOWN,
125     // The service worker started up during browser startup.
126     DURING_STARTUP,
127     // The service worker started up in a new process.
128     NEW_PROCESS,
129     // The service worker started up in an existing unready process. (Ex: The
130     // process was created for the navigation but the IPC connection is not
131     // established yet.)
132     EXISTING_UNREADY_PROCESS,
133     // The service worker started up in an existing ready process.
134     EXISTING_READY_PROCESS
135   };
136 
137   // Used for UMA. Append only.
138   // Describes the outcome of a time measurement taken between processes.
139   enum class CrossProcessTimeDelta {
140     NORMAL,
141     NEGATIVE,
142     INACCURATE_CLOCK,
143     // Add new types here.
144     kMaxValue = INACCURATE_CLOCK,
145   };
146 
147   // These are prefixed with "local" or "remote" to indicate whether the browser
148   // process or renderer process recorded the timing (browser is local).
149   struct StartTimes {
150     // The browser started the service worker startup sequence.
151     base::TimeTicks local_start;
152 
153     // The browser sent the start worker IPC to the renderer.
154     base::TimeTicks local_start_worker_sent;
155 
156     // The renderer received the start worker IPC.
157     base::TimeTicks remote_start_worker_received;
158 
159     // The renderer started script evaluation on the worker thread.
160     base::TimeTicks remote_script_evaluation_start;
161 
162     // The renderer finished script evaluation on the worker thread.
163     base::TimeTicks remote_script_evaluation_end;
164 
165     // The browser received the worker started IPC.
166     base::TimeTicks local_end;
167 
168     // Counts the time overhead of UI/IO thread hops during startup.
169     base::TimeDelta thread_hop_time;
170   };
171 
172   // Converts an event type to a string. Used for tracing.
173   static const char* EventTypeToString(EventType event_type);
174 
175   // Converts a start situation to a string. Used for tracing.
176   static const char* StartSituationToString(StartSituation start_situation);
177 
178   // If the |url| is not a special site, returns Site::OTHER.
179   static Site SiteFromURL(const GURL& url);
180 
181   // Used for ServiceWorkerDiskCache.
182   static void CountInitDiskCacheResult(bool result);
183   static void CountReadResponseResult(ReadResponseResult result);
184   static void CountWriteResponseResult(WriteResponseResult result);
185 
186   // Used for ServiceWorkerStorage.
187   static void RecordPurgeResourceResult(int net_error);
188   static void RecordDeleteAndStartOverResult(DeleteAndStartOverResult result);
189 
190   // Counts the number of page loads controlled by a Service Worker.
191   static void CountControlledPageLoad(Site site,
192                                       bool is_main_frame_load);
193 
194   // Records the result of trying to start an installed worker.
195   static void RecordStartInstalledWorkerStatus(
196       blink::ServiceWorkerStatusCode status,
197       EventType purpose);
198 
199   // Records the time taken to successfully start a worker. |is_installed|
200   // indicates whether the version has been installed.
201   //
202   // TODO(crbug.com/855952): Replace this with RecordStartWorkerTiming().
203   static void RecordStartWorkerTime(base::TimeDelta time,
204                                     bool is_installed,
205                                     StartSituation start_situation,
206                                     EventType purpose);
207 
208   // Records the result of trying to stop a worker.
209   static void RecordWorkerStopped(StopStatus status);
210 
211   // Records the time taken to successfully stop a worker.
212   static void RecordStopWorkerTime(base::TimeDelta time);
213 
214   static void RecordActivateEventStatus(blink::ServiceWorkerStatusCode status,
215                                         bool is_shutdown);
216   static void RecordInstallEventStatus(blink::ServiceWorkerStatusCode status);
217 
218   // Records the amount of time spent handling an event.
219   static void RecordEventDuration(EventType event,
220                                   base::TimeDelta time,
221                                   bool was_handled);
222 
223   // Records the result of dispatching a fetch event to a service worker.
224   static void RecordFetchEventStatus(bool is_main_resource,
225                                      blink::ServiceWorkerStatusCode status);
226 
227   static void RecordProcessCreated(bool is_new_process);
228 
229   CONTENT_EXPORT static void RecordStartWorkerTiming(const StartTimes& times,
230                                                      StartSituation situation);
231   static void RecordStartWorkerTimingClockConsistency(
232       CrossProcessTimeDelta type);
233 
234   // Records the result of a start attempt that occurred after the worker had
235   // failed |failure_count| consecutive times.
236   static void RecordStartStatusAfterFailure(
237       int failure_count,
238       blink::ServiceWorkerStatusCode status);
239 
240   // Records the size of Service-Worker-Navigation-Preload header when the
241   // navigation preload request is to be sent.
242   static void RecordNavigationPreloadRequestHeaderSize(size_t size);
243 
244   static void RecordRuntime(base::TimeDelta time);
245 
246   // Records the result of starting service worker for a navigation hint.
247   static void RecordStartServiceWorkerForNavigationHintResult(
248       StartServiceWorkerForNavigationHintResult result);
249 
250   // Records the number of origins with a registered service worker.
251   static void RecordRegisteredOriginCount(size_t origin_count);
252 
253   // Records the duration of looking up an existing registration.
254   // |status| is the result of lookup. The records for the cases where
255   // the registration is found (kOk), not found (kErrorNotFound), or an error
256   // happens (other errors) are saved separately into a relevant suffixed
257   // histogram.
258   static void RecordLookupRegistrationTime(
259       blink::ServiceWorkerStatusCode status,
260       base::TimeDelta duration);
261 
262   // Records the result of byte-for-byte update checking.
263   // |has_found_update| should be true when the update checking finds update of
264   // the script. It's recorded only when |status| is kOk.
265   // This is used only when ServiceWorkerImportedScriptUpdateCheck is enabled.
266   static void RecordByteForByteUpdateCheckStatus(
267       blink::ServiceWorkerStatusCode status,
268       bool has_found_update);
269 
270  private:
271   DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics);
272 };
273 
274 }  // namespace content
275 
276 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
277