1 // Copyright 2022 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net.impl; 6 7 import static android.os.Process.THREAD_PRIORITY_BACKGROUND; 8 9 import java.time.Duration; 10 import java.util.regex.Matcher; 11 import java.util.regex.Pattern; 12 13 /** 14 * Base class for implementing a CronetLogger. 15 */ 16 public abstract class CronetLogger { 17 public static enum CronetSource { 18 // Safe default, don't use explicitly. 19 CRONET_SOURCE_UNSPECIFIED, 20 // The library is bundled with the application. 21 CRONET_SOURCE_STATICALLY_LINKED, 22 // The library is loaded from GooglePlayServices 23 CRONET_SOURCE_PLAY_SERVICES, 24 // The application is using the fallback implementation 25 CRONET_SOURCE_FALLBACK, 26 } 27 28 /** 29 * Logs a cronetEngine creation action with the details of the creation. 30 * 31 * @param cronetEngineId the id of the engine being created. 32 * @param engineBuilderInfo the configuration of the CronetEngine being created. See {@link 33 * CronetEngineBuilderInfo} 34 * @param version the version of cronet used for the engine. See {@link CronetVersion} 35 * @param source the source of the cronet provider for the engine. See {@link CronetSource} 36 */ logCronetEngineCreation(int cronetEngineId, CronetEngineBuilderInfo engineBuilderInfo, CronetVersion version, CronetSource source)37 public abstract void logCronetEngineCreation(int cronetEngineId, 38 CronetEngineBuilderInfo engineBuilderInfo, CronetVersion version, CronetSource source); 39 40 /** 41 * Logs a request/response action. 42 * @param cronetEngineId the id of the engine used for the request 43 * @param trafficInfo the associated traffic information. See {@link CronetTrafficInfo} 44 */ logCronetTrafficInfo(int cronetEngineId, CronetTrafficInfo trafficInfo)45 public abstract void logCronetTrafficInfo(int cronetEngineId, CronetTrafficInfo trafficInfo); 46 47 /** 48 * Aggregates the information about a CronetEngine configuration. 49 */ 50 public static class CronetEngineBuilderInfo { 51 private final boolean mPublicKeyPinningBypassForLocalTrustAnchorsEnabled; 52 private final String mUserAgent; 53 private final String mStoragePath; 54 private final boolean mQuicEnabled; 55 private final boolean mHttp2Enabled; 56 private final boolean mBrotiEnabled; 57 private final int mHttpCacheMode; 58 private final String mExperimentalOptions; 59 private final boolean mNetworkQualityEstimatorEnabled; 60 private final int mThreadPriority; 61 CronetEngineBuilderInfo(CronetEngineBuilderImpl builder)62 public CronetEngineBuilderInfo(CronetEngineBuilderImpl builder) { 63 mPublicKeyPinningBypassForLocalTrustAnchorsEnabled = 64 builder.publicKeyPinningBypassForLocalTrustAnchorsEnabled(); 65 mUserAgent = builder.getUserAgent(); 66 mStoragePath = builder.storagePath(); 67 mQuicEnabled = builder.quicEnabled(); 68 mHttp2Enabled = builder.http2Enabled(); 69 mBrotiEnabled = builder.brotliEnabled(); 70 mHttpCacheMode = builder.publicBuilderHttpCacheMode(); 71 mExperimentalOptions = builder.experimentalOptions(); 72 mNetworkQualityEstimatorEnabled = builder.networkQualityEstimatorEnabled(); 73 mThreadPriority = builder.threadPriority(THREAD_PRIORITY_BACKGROUND); 74 } 75 76 /** 77 * @return Whether public key pinning bypass for local trust anchors is enabled 78 */ isPublicKeyPinningBypassForLocalTrustAnchorsEnabled()79 public boolean isPublicKeyPinningBypassForLocalTrustAnchorsEnabled() { 80 return mPublicKeyPinningBypassForLocalTrustAnchorsEnabled; 81 } 82 /** 83 * @return User-Agent used for URLRequests created through this CronetEngine 84 */ getUserAgent()85 public String getUserAgent() { 86 return mUserAgent; 87 } 88 /** 89 * @return Path to the directory used for HTTP cache and Cookie storage 90 */ getStoragePath()91 public String getStoragePath() { 92 return mStoragePath; 93 } 94 95 /** 96 * @return Whether QUIC protocol is enabled 97 */ isQuicEnabled()98 public boolean isQuicEnabled() { 99 return mQuicEnabled; 100 } 101 102 /** 103 * @return Whether HTTP2 protocol is enabled 104 */ isHttp2Enabled()105 public boolean isHttp2Enabled() { 106 return mHttp2Enabled; 107 } 108 109 /** 110 * @return Whether Brotli compression is enabled 111 */ isBrotliEnabled()112 public boolean isBrotliEnabled() { 113 return mBrotiEnabled; 114 } 115 116 /** 117 * @return Whether caching of HTTP data and other information like QUIC server information 118 * is enabled 119 */ getHttpCacheMode()120 public int getHttpCacheMode() { 121 return mHttpCacheMode; 122 } 123 124 /** 125 * @return Experimental options configuration used by the CronetEngine 126 */ getExperimentalOptions()127 public String getExperimentalOptions() { 128 return mExperimentalOptions; 129 } 130 131 /** 132 * @return Whether network quality estimator is enabled 133 */ isNetworkQualityEstimatorEnabled()134 public boolean isNetworkQualityEstimatorEnabled() { 135 return mNetworkQualityEstimatorEnabled; 136 } 137 138 /** 139 * @return The thread priority of Cronet's internal thread 140 */ getThreadPriority()141 public int getThreadPriority() { 142 return mThreadPriority; 143 } 144 } 145 146 /** 147 * Aggregates the information about request and response traffic for a 148 * particular CronetEngine. 149 */ 150 public static class CronetTrafficInfo { 151 private final long mRequestHeaderSizeInBytes; 152 private final long mRequestBodySizeInBytes; 153 private final long mResponseHeaderSizeInBytes; 154 private final long mResponseBodySizeInBytes; 155 private final int mResponseStatusCode; 156 private final Duration mHeadersLatency; 157 private final Duration mTotalLatency; 158 private final String mNegotiatedProtocol; 159 private final boolean mWasConnectionMigrationAttempted; 160 private final boolean mDidConnectionMigrationSucceed; 161 CronetTrafficInfo(long requestHeaderSizeInBytes, long requestBodySizeInBytes, long responseHeaderSizeInBytes, long responseBodySizeInBytes, int responseStatusCode, Duration headersLatency, Duration totalLatency, String negotiatedProtocol, boolean wasConnectionMigrationAttempted, boolean didConnectionMigrationSucceed)162 public CronetTrafficInfo(long requestHeaderSizeInBytes, long requestBodySizeInBytes, 163 long responseHeaderSizeInBytes, long responseBodySizeInBytes, 164 int responseStatusCode, Duration headersLatency, Duration totalLatency, 165 String negotiatedProtocol, boolean wasConnectionMigrationAttempted, 166 boolean didConnectionMigrationSucceed) { 167 mRequestHeaderSizeInBytes = requestHeaderSizeInBytes; 168 mRequestBodySizeInBytes = requestBodySizeInBytes; 169 mResponseHeaderSizeInBytes = responseHeaderSizeInBytes; 170 mResponseBodySizeInBytes = responseBodySizeInBytes; 171 mResponseStatusCode = responseStatusCode; 172 mHeadersLatency = headersLatency; 173 mTotalLatency = totalLatency; 174 mNegotiatedProtocol = negotiatedProtocol; 175 mWasConnectionMigrationAttempted = wasConnectionMigrationAttempted; 176 mDidConnectionMigrationSucceed = didConnectionMigrationSucceed; 177 } 178 179 /** 180 * @return The total size of headers sent in bytes 181 */ getRequestHeaderSizeInBytes()182 public long getRequestHeaderSizeInBytes() { 183 return mRequestHeaderSizeInBytes; 184 } 185 186 /** 187 * @return The total size of request body sent, if any, in bytes 188 */ getRequestBodySizeInBytes()189 public long getRequestBodySizeInBytes() { 190 return mRequestBodySizeInBytes; 191 } 192 193 /** 194 * @return The total size of headers received in bytes 195 */ getResponseHeaderSizeInBytes()196 public long getResponseHeaderSizeInBytes() { 197 return mResponseHeaderSizeInBytes; 198 } 199 200 /** 201 * @return The total size of response body, if any, received in bytes 202 */ getResponseBodySizeInBytes()203 public long getResponseBodySizeInBytes() { 204 return mResponseBodySizeInBytes; 205 } 206 207 /** 208 * @return The response status code of the request 209 */ getResponseStatusCode()210 public int getResponseStatusCode() { 211 return mResponseStatusCode; 212 } 213 214 /** 215 * The time it took from starting the request to receiving the full set of 216 * response headers. 217 * 218 * @return The time to get response headers 219 */ getHeadersLatency()220 public Duration getHeadersLatency() { 221 return mHeadersLatency; 222 } 223 224 /** 225 * The time it took from starting the request to receiving the entire 226 * response. 227 * 228 * @return The time to get total response 229 */ getTotalLatency()230 public Duration getTotalLatency() { 231 return mTotalLatency; 232 } 233 234 /** 235 * @return The negotiated protocol used for the traffic 236 */ getNegotiatedProtocol()237 public String getNegotiatedProtocol() { 238 return mNegotiatedProtocol; 239 } 240 241 /** 242 * @return True if the connection migration was attempted, else False 243 */ wasConnectionMigrationAttempted()244 public boolean wasConnectionMigrationAttempted() { 245 return mWasConnectionMigrationAttempted; 246 } 247 248 /** 249 * @return True if the connection migration was attempted and succeeded, else False 250 */ didConnectionMigrationSucceed()251 public boolean didConnectionMigrationSucceed() { 252 return mDidConnectionMigrationSucceed; 253 } 254 } 255 256 /** 257 * Holds information about the cronet version used for a cronetEngine. 258 */ 259 public static class CronetVersion { 260 private static final Pattern VERSION_PATTERN = 261 Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); 262 263 private final int mMajorVersion; 264 private final int mMinorVersion; 265 private final int mBuildVersion; 266 private final int mPatchVersion; 267 268 /** 269 * Pass the cronet version string here and 270 * it would be split. The string comes in the format 271 * MAJOR.MINOR.BUILD.PATCH 272 */ CronetVersion(String version)273 public CronetVersion(String version) { 274 Matcher m = VERSION_PATTERN.matcher(version); 275 if (!m.matches()) { 276 throw new IllegalArgumentException( 277 "Invalid version: expected a string matching " + VERSION_PATTERN 278 + ", got " + version); 279 } 280 281 mMajorVersion = Integer.parseInt(m.group(1)); 282 mMinorVersion = Integer.parseInt(m.group(2)); 283 mBuildVersion = Integer.parseInt(m.group(3)); 284 mPatchVersion = Integer.parseInt(m.group(4)); 285 } 286 287 /** 288 * @return the MAJOR version of cronet used for the traffic 289 */ getMajorVersion()290 public int getMajorVersion() { 291 return mMajorVersion; 292 } 293 294 /** 295 * @return the MINOR version of cronet used for the traffic 296 */ getMinorVersion()297 public int getMinorVersion() { 298 return mMinorVersion; 299 } 300 301 /** 302 * @return the BUILD version of cronet used for the traffic 303 */ getBuildVersion()304 public int getBuildVersion() { 305 return mBuildVersion; 306 } 307 308 /** 309 * @return the PATCH version of cronet used for the traffic 310 */ getPatchVersion()311 public int getPatchVersion() { 312 return mPatchVersion; 313 } 314 315 @Override toString()316 public String toString() { 317 return "" + mMajorVersion + "." + mMinorVersion + "." + mBuildVersion + "." 318 + mPatchVersion; 319 } 320 } 321 } 322