lighthouse 11.3.0-dev.20231129 → 11.3.0-dev.20231201

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,6 +43,19 @@ export class ByteEfficiencyAudit extends Audit {
43
43
  * @return {number}
44
44
  */
45
45
  static estimateTransferSize(networkRecord: LH.Artifacts.NetworkRequest | undefined, totalBytes: number, resourceType?: LH.Crdp.Network.ResourceType | undefined): number;
46
+ /**
47
+ * Estimates the number of bytes the content of this network record would have consumed on the network based on the
48
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable,
49
+ * minus the size of the response headers.
50
+ *
51
+ * This differs from `estimateTransferSize` only in that is subtracts the response headers from the estimate.
52
+ *
53
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
54
+ * @param {number} totalBytes Uncompressed size of the resource
55
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
56
+ * @return {number}
57
+ */
58
+ static estimateCompressedContentSize(networkRecord: LH.Artifacts.NetworkRequest | undefined, totalBytes: number, resourceType?: LH.Crdp.Network.ResourceType | undefined): number;
46
59
  /**
47
60
  * @param {LH.Artifacts} artifacts
48
61
  * @param {LH.Audit.Context} context
@@ -99,4 +112,5 @@ export class ByteEfficiencyAudit extends Audit {
99
112
  static audit_(artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>, context: LH.Audit.Context): ByteEfficiencyProduct | Promise<ByteEfficiencyProduct>;
100
113
  }
101
114
  import { Audit } from '../audit.js';
115
+ import { NetworkRequest } from '../../lib/network-request.js';
102
116
  //# sourceMappingURL=byte-efficiency-audit.d.ts.map
@@ -13,6 +13,7 @@ import {PageDependencyGraph} from '../../computed/page-dependency-graph.js';
13
13
  import {LanternLargestContentfulPaint} from '../../computed/metrics/lantern-largest-contentful-paint.js';
14
14
  import {LanternFirstContentfulPaint} from '../../computed/metrics/lantern-first-contentful-paint.js';
15
15
  import {LCPImageRecord} from '../../computed/lcp-image-record.js';
16
+ import {NetworkRequest} from '../../lib/network-request.js';
16
17
 
17
18
  const str_ = i18n.createIcuMessageFn(import.meta.url, {});
18
19
 
@@ -100,6 +101,65 @@ class ByteEfficiencyAudit extends Audit {
100
101
  }
101
102
  }
102
103
 
104
+ /**
105
+ * Estimates the number of bytes the content of this network record would have consumed on the network based on the
106
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable,
107
+ * minus the size of the response headers.
108
+ *
109
+ * This differs from `estimateTransferSize` only in that is subtracts the response headers from the estimate.
110
+ *
111
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
112
+ * @param {number} totalBytes Uncompressed size of the resource
113
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
114
+ * @return {number}
115
+ */
116
+ static estimateCompressedContentSize(networkRecord, totalBytes, resourceType) {
117
+ if (!networkRecord) {
118
+ // We don't know how many bytes this asset used on the network, but we can guess it was
119
+ // roughly the size of the content gzipped.
120
+ // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples
121
+ // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers
122
+ switch (resourceType) {
123
+ case 'Stylesheet':
124
+ // Stylesheets tend to compress extremely well.
125
+ return Math.round(totalBytes * 0.2);
126
+ case 'Script':
127
+ case 'Document':
128
+ // Scripts and HTML compress fairly well too.
129
+ return Math.round(totalBytes * 0.33);
130
+ default:
131
+ // Otherwise we'll just fallback to the average savings in HTTPArchive
132
+ return Math.round(totalBytes * 0.5);
133
+ }
134
+ }
135
+
136
+ // Get the size of the response body on the network.
137
+ let contentTransferSize = networkRecord.transferSize || 0;
138
+ if (!NetworkRequest.isContentEncoded(networkRecord)) {
139
+ // This is not encoded, so we can use resourceSize directly.
140
+ // This would be equivalent to transfer size minus headers transfer size, but transfer size
141
+ // may also include bytes for SSL connection etc.
142
+ contentTransferSize = networkRecord.resourceSize;
143
+ } else if (networkRecord.responseHeadersTransferSize) {
144
+ // Subtract the size of the encoded headers.
145
+ contentTransferSize =
146
+ Math.max(0, contentTransferSize - networkRecord.responseHeadersTransferSize);
147
+ }
148
+
149
+ if (networkRecord.resourceType === resourceType) {
150
+ // This was a regular standalone asset, just use the transfer size.
151
+ return contentTransferSize;
152
+ } else {
153
+ // This was an asset that was inlined in a different resource type (e.g. HTML document).
154
+ // Use the compression ratio of the resource to estimate the total transferred bytes.
155
+ const resourceSize = networkRecord.resourceSize || 0;
156
+ // Get the compression ratio, if it's an invalid number, assume no compression.
157
+ const compressionRatio = Number.isFinite(resourceSize) && resourceSize > 0 ?
158
+ (contentTransferSize / resourceSize) : 1;
159
+ return Math.round(totalBytes * compressionRatio);
160
+ }
161
+ }
162
+
103
163
  /**
104
164
  * @param {LH.Artifacts} artifacts
105
165
  * @param {LH.Audit.Context} context
@@ -61,16 +61,18 @@ declare class LegacyJavascript extends ByteEfficiencyAudit {
61
61
  */
62
62
  static estimateWastedBytes(matches: PatternMatchResult[]): number;
63
63
  /**
64
- * Utility function to estimate transfer size and cache calculation.
64
+ * Utility function to estimate the ratio of the compression on the resource.
65
+ * This excludes the size of the response headers.
66
+ * Also caches the calculation.
65
67
  *
66
68
  * Note: duplicated-javascript does this exact thing. In the future, consider
67
- * making a generic estimator on ByteEfficienyAudit.
68
- * @param {Map<string, number>} transferRatioByUrl
69
+ * making a generic estimator on ByteEfficiencyAudit.
70
+ * @param {Map<string, number>} compressionRatioByUrl
69
71
  * @param {string} url
70
72
  * @param {LH.Artifacts} artifacts
71
73
  * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
72
74
  */
73
- static estimateTransferRatioForScript(transferRatioByUrl: Map<string, number>, url: string, artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>): Promise<number>;
75
+ static estimateCompressionRatioForContent(compressionRatioByUrl: Map<string, number>, url: string, artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>): Promise<number>;
74
76
  /**
75
77
  * @param {LH.Artifacts} artifacts
76
78
  * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
@@ -391,34 +391,37 @@ class LegacyJavascript extends ByteEfficiencyAudit {
391
391
  }
392
392
 
393
393
  /**
394
- * Utility function to estimate transfer size and cache calculation.
394
+ * Utility function to estimate the ratio of the compression on the resource.
395
+ * This excludes the size of the response headers.
396
+ * Also caches the calculation.
395
397
  *
396
398
  * Note: duplicated-javascript does this exact thing. In the future, consider
397
- * making a generic estimator on ByteEfficienyAudit.
398
- * @param {Map<string, number>} transferRatioByUrl
399
+ * making a generic estimator on ByteEfficiencyAudit.
400
+ * @param {Map<string, number>} compressionRatioByUrl
399
401
  * @param {string} url
400
402
  * @param {LH.Artifacts} artifacts
401
403
  * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
402
404
  */
403
- static async estimateTransferRatioForScript(transferRatioByUrl, url, artifacts, networkRecords) {
404
- let transferRatio = transferRatioByUrl.get(url);
405
- if (transferRatio !== undefined) return transferRatio;
405
+ static async estimateCompressionRatioForContent(compressionRatioByUrl, url,
406
+ artifacts, networkRecords) {
407
+ let compressionRatio = compressionRatioByUrl.get(url);
408
+ if (compressionRatio !== undefined) return compressionRatio;
406
409
 
407
410
  const script = artifacts.Scripts.find(script => script.url === url);
408
411
 
409
- if (!script || script.content === null) {
412
+ if (!script) {
410
413
  // Can't find content, so just use 1.
411
- transferRatio = 1;
414
+ compressionRatio = 1;
412
415
  } else {
413
416
  const networkRecord = getRequestForScript(networkRecords, script);
414
- const contentLength = script.length || 0;
415
- const transferSize =
416
- ByteEfficiencyAudit.estimateTransferSize(networkRecord, contentLength, 'Script');
417
- transferRatio = transferSize / contentLength;
417
+ const contentLength = networkRecord?.resourceSize || script.length || 0;
418
+ const compressedSize =
419
+ ByteEfficiencyAudit.estimateCompressedContentSize(networkRecord, contentLength, 'Script');
420
+ compressionRatio = compressedSize / contentLength;
418
421
  }
419
422
 
420
- transferRatioByUrl.set(url, transferRatio);
421
- return transferRatio;
423
+ compressionRatioByUrl.set(url, compressionRatio);
424
+ return compressionRatio;
422
425
  }
423
426
 
424
427
  /**
@@ -443,14 +446,14 @@ class LegacyJavascript extends ByteEfficiencyAudit {
443
446
  ]);
444
447
 
445
448
  /** @type {Map<string, number>} */
446
- const transferRatioByUrl = new Map();
449
+ const compressionRatioByUrl = new Map();
447
450
 
448
451
  const scriptToMatchResults =
449
452
  this.detectAcrossScripts(matcher, artifacts.Scripts, networkRecords, bundles);
450
453
  for (const [script, matches] of scriptToMatchResults.entries()) {
451
- const transferRatio = await this.estimateTransferRatioForScript(
452
- transferRatioByUrl, script.url, artifacts, networkRecords);
453
- const wastedBytes = Math.round(this.estimateWastedBytes(matches) * transferRatio);
454
+ const compressionRatio = await this.estimateCompressionRatioForContent(
455
+ compressionRatioByUrl, script.url, artifacts, networkRecords);
456
+ const wastedBytes = Math.round(this.estimateWastedBytes(matches) * compressionRatio);
454
457
  /** @type {typeof items[number]} */
455
458
  const item = {
456
459
  url: script.url,
@@ -59,7 +59,7 @@ class EntityClassification {
59
59
  // Make up an entity only for valid http/https URLs.
60
60
  if (!parsedUrl.protocol.startsWith('http')) return;
61
61
 
62
- const rootDomain = Util.getRootDomain(url);
62
+ const rootDomain = UrlUtils.getRootDomain(url);
63
63
  if (!rootDomain) return;
64
64
  if (entityCache.has(rootDomain)) return entityCache.get(rootDomain);
65
65
 
@@ -39,7 +39,6 @@ declare class ResourceSummary {
39
39
  budgets: LH.Util.ImmutableObject<LH.Budget[] | null>;
40
40
  }, context: LH.Artifacts.ComputedContext): Promise<Record<LH.Budget.ResourceType, ResourceEntry>>;
41
41
  }
42
- import { Util } from '../../shared/util.js';
43
42
  import { Budget } from '../config/budget.js';
44
43
  import { NetworkRequest } from '../lib/network-request.js';
45
44
  import { EntityClassification } from './entity-classification.js';
@@ -9,7 +9,7 @@ import {makeComputedArtifact} from './computed-artifact.js';
9
9
  import {NetworkRecords} from './network-records.js';
10
10
  import {NetworkRequest} from '../lib/network-request.js';
11
11
  import {Budget} from '../config/budget.js';
12
- import {Util} from '../../shared/util.js';
12
+ import UrlUtils from '../lib/url-utils.js';
13
13
 
14
14
  /** @typedef {{count: number, resourceSize: number, transferSize: number}} ResourceEntry */
15
15
 
@@ -59,7 +59,7 @@ class ResourceSummary {
59
59
  firstPartyHosts = budget.options.firstPartyHostnames;
60
60
  } else {
61
61
  firstPartyHosts = classifiedEntities.firstParty?.domains.map(domain => `*.${domain}`) ||
62
- [`*.${Util.getRootDomain(URLArtifact.finalDisplayedUrl)}`];
62
+ [`*.${UrlUtils.getRootDomain(URLArtifact.finalDisplayedUrl)}`];
63
63
  }
64
64
 
65
65
  networkRecords.filter(record => {
@@ -220,7 +220,7 @@ async function _navigation(navigationContext) {
220
220
 
221
221
  // Every required url is initialized to an empty string in `getBaseArtifacts`.
222
222
  // If we haven't set all the required urls yet, set them here.
223
- if (!Object.values(phaseState.baseArtifacts).every(Boolean)) {
223
+ if (!Object.values(phaseState.baseArtifacts.URL).every(Boolean)) {
224
224
  phaseState.baseArtifacts.URL = {
225
225
  requestedUrl: navigateResult.requestedUrl,
226
226
  mainDocumentUrl: navigateResult.mainDocumentUrl,
@@ -66,6 +66,14 @@ export class NetworkRecorder extends NetworkRecorder_base {
66
66
  targetType: LH.Protocol.TargetType;
67
67
  sessionId?: string;
68
68
  }): void;
69
+ /**
70
+ * @param {{params: LH.Crdp.Network.ResponseReceivedExtraInfoEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
71
+ */
72
+ onResponseReceivedExtraInfo(event: {
73
+ params: LH.Crdp.Network.ResponseReceivedExtraInfoEvent;
74
+ targetType: LH.Protocol.TargetType;
75
+ sessionId?: string;
76
+ }): void;
69
77
  /**
70
78
  * @param {{params: LH.Crdp.Network.DataReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
71
79
  */
@@ -138,6 +138,18 @@ class NetworkRecorder extends RequestEventEmitter {
138
138
  request.onResponseReceived(data);
139
139
  }
140
140
 
141
+ /**
142
+ * @param {{params: LH.Crdp.Network.ResponseReceivedExtraInfoEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
143
+ */
144
+ onResponseReceivedExtraInfo(event) {
145
+ const data = event.params;
146
+ const request = this._findRealRequestAndSetSession(
147
+ data.requestId, event.targetType, event.sessionId);
148
+ if (!request) return;
149
+ log.verbose('network', `${request.url} response received extra info`);
150
+ request.onResponseReceivedExtraInfo(data);
151
+ }
152
+
141
153
  /**
142
154
  * @param {{params: LH.Crdp.Network.DataReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
143
155
  */
@@ -196,6 +208,7 @@ class NetworkRecorder extends RequestEventEmitter {
196
208
  case 'Network.requestWillBeSent': return this.onRequestWillBeSent(event);
197
209
  case 'Network.requestServedFromCache': return this.onRequestServedFromCache(event);
198
210
  case 'Network.responseReceived': return this.onResponseReceived(event);
211
+ case 'Network.responseReceivedExtraInfo': return this.onResponseReceivedExtraInfo(event);
199
212
  case 'Network.dataReceived': return this.onDataReceived(event);
200
213
  case 'Network.loadingFinished': return this.onLoadingFinished(event);
201
214
  case 'Network.loadingFailed': return this.onLoadingFailed(event);
@@ -66,6 +66,12 @@ export class NetworkRequest {
66
66
  * @return {boolean}
67
67
  */
68
68
  static isHstsRequest(record: NetworkRequest): boolean;
69
+ /**
70
+ * Returns whether the network request was sent encoded.
71
+ * @param {NetworkRequest} record
72
+ * @return {boolean}
73
+ */
74
+ static isContentEncoded(record: NetworkRequest): boolean;
69
75
  /**
70
76
  * Resource size is almost always the right one to be using because of the below:
71
77
  * `transferSize = resourceSize + headers.length`.
@@ -98,6 +104,7 @@ export class NetworkRequest {
98
104
  /** When the last byte of the response body is received, in milliseconds. */
99
105
  networkEndTime: number;
100
106
  transferSize: number;
107
+ responseHeadersTransferSize: number;
101
108
  resourceSize: number;
102
109
  fromDiskCache: boolean;
103
110
  fromMemoryCache: boolean;
@@ -155,6 +162,10 @@ export class NetworkRequest {
155
162
  * @param {LH.Crdp.Network.ResponseReceivedEvent} data
156
163
  */
157
164
  onResponseReceived(data: LH.Crdp.Network.ResponseReceivedEvent): void;
165
+ /**
166
+ * @param {LH.Crdp.Network.ResponseReceivedExtraInfoEvent} data
167
+ */
168
+ onResponseReceivedExtraInfo(data: LH.Crdp.Network.ResponseReceivedExtraInfoEvent): void;
158
169
  /**
159
170
  * @param {LH.Crdp.Network.DataReceivedEvent} data
160
171
  */
@@ -135,6 +135,7 @@ class NetworkRequest {
135
135
 
136
136
  // Go read the comment on _updateTransferSizeForLightrider.
137
137
  this.transferSize = 0;
138
+ this.responseHeadersTransferSize = 0;
138
139
  this.resourceSize = 0;
139
140
  this.fromDiskCache = false;
140
141
  this.fromMemoryCache = false;
@@ -246,6 +247,13 @@ class NetworkRequest {
246
247
  this.frameId = data.frameId;
247
248
  }
248
249
 
250
+ /**
251
+ * @param {LH.Crdp.Network.ResponseReceivedExtraInfoEvent} data
252
+ */
253
+ onResponseReceivedExtraInfo(data) {
254
+ this.responseHeadersText = data.headersText || '';
255
+ }
256
+
249
257
  /**
250
258
  * @param {LH.Crdp.Network.DataReceivedEvent} data
251
259
  */
@@ -344,6 +352,7 @@ class NetworkRequest {
344
352
  this.responseHeadersEndTime = timestamp * 1000;
345
353
 
346
354
  this.transferSize = response.encodedDataLength;
355
+ this.responseHeadersTransferSize = response.encodedDataLength;
347
356
  if (typeof response.fromDiskCache === 'boolean') this.fromDiskCache = response.fromDiskCache;
348
357
  if (typeof response.fromPrefetchCache === 'boolean') {
349
358
  this.fromPrefetchCache = response.fromPrefetchCache;
@@ -354,7 +363,6 @@ class NetworkRequest {
354
363
  this.timing = response.timing;
355
364
  if (resourceType) this.resourceType = RESOURCE_TYPES[resourceType];
356
365
  this.mimeType = response.mimeType;
357
- this.responseHeadersText = response.headersText || '';
358
366
  this.responseHeaders = NetworkRequest._headersDictToHeadersArray(response.headers);
359
367
 
360
368
  this.fetchedViaServiceWorker = !!response.fromServiceWorker;
@@ -600,6 +608,15 @@ class NetworkRequest {
600
608
  return reason === 'HSTS' && NetworkRequest.isSecureRequest(destination);
601
609
  }
602
610
 
611
+ /**
612
+ * Returns whether the network request was sent encoded.
613
+ * @param {NetworkRequest} record
614
+ * @return {boolean}
615
+ */
616
+ static isContentEncoded(record) {
617
+ return record.responseHeaders.some(item => item.name === 'Content-Encoding');
618
+ }
619
+
603
620
  /**
604
621
  * Resource size is almost always the right one to be using because of the below:
605
622
  * `transferSize = resourceSize + headers.length`.
@@ -23,6 +23,12 @@ declare class UrlUtils {
23
23
  * @return {?string}
24
24
  */
25
25
  static getOrigin(url: string): string | null;
26
+ /**
27
+ * Returns a primary domain for provided hostname (e.g. www.example.com -> example.com).
28
+ * @param {string|URL} url hostname or URL object
29
+ * @return {string}
30
+ */
31
+ static getRootDomain(url: string | URL): string;
26
32
  /**
27
33
  * Check if rootDomains matches
28
34
  *
@@ -4,6 +4,8 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import {getDomain} from 'tldts';
8
+
7
9
  import {Util} from '../../shared/util.js';
8
10
  import {LighthouseError} from './lh-error.js';
9
11
 
@@ -99,6 +101,16 @@ class UrlUtils {
99
101
  }
100
102
  }
101
103
 
104
+ /**
105
+ * Returns a primary domain for provided hostname (e.g. www.example.com -> example.com).
106
+ * @param {string|URL} url hostname or URL object
107
+ * @return {string}
108
+ */
109
+ static getRootDomain(url) {
110
+ const parsedUrl = Util.createOrReturnURL(url);
111
+ return getDomain(parsedUrl.href) || parsedUrl.hostname;
112
+ }
113
+
102
114
  /**
103
115
  * Check if rootDomains matches
104
116
  *
@@ -120,8 +132,8 @@ class UrlUtils {
120
132
  }
121
133
 
122
134
  // get the string before the tld
123
- const urlARootDomain = Util.getRootDomain(urlAInfo);
124
- const urlBRootDomain = Util.getRootDomain(urlBInfo);
135
+ const urlARootDomain = UrlUtils.getRootDomain(urlAInfo);
136
+ const urlBRootDomain = UrlUtils.getRootDomain(urlBInfo);
125
137
 
126
138
  return urlARootDomain === urlBRootDomain;
127
139
  }
@@ -6,9 +6,22 @@
6
6
  ##
7
7
 
8
8
  # Download chrome inside of our CI env.
9
+ # Takes one arg - the location to extract ToT chrome to. Defaults to .tmp/chrome-tot
10
+ # If already exists, this script does nothing.
9
11
 
10
12
  set -euo pipefail
11
13
 
14
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
15
+ LH_ROOT_DIR="$SCRIPT_DIR/../.."
16
+
17
+ chrome_out=${1:-"$LH_ROOT_DIR/.tmp/chrome-tot"}
18
+ mkdir -p "$LH_ROOT_DIR/.tmp"
19
+
20
+ if [ -e "$chrome_out" ]; then
21
+ echo "cached chrome found"
22
+ exit 0
23
+ fi
24
+
12
25
  unameOut="$(uname -s)"
13
26
  case "${unameOut}" in
14
27
  Linux*) machine=Linux;;
@@ -17,24 +30,49 @@ case "${unameOut}" in
17
30
  *) machine="UNKNOWN:${unameOut}"
18
31
  esac
19
32
 
20
- if [ "$machine" == "MinGw" ]; then
21
- url="https://download-chromium.appspot.com/dl/Win?type=snapshots"
22
- elif [ "$machine" == "Linux" ]; then
23
- url="https://download-chromium.appspot.com/dl/Linux_x64?type=snapshots"
24
- elif [ "$machine" == "Mac" ]; then
25
- arch="$(uname -m)"
26
- if [ "$arch" == "arm64" ]; then
27
- url="https://download-chromium.appspot.com/dl/Mac_Arm?type=snapshots"
33
+ # Only set this to true when actual ToT is broken and we can't fix it yet.
34
+ should_hardcode_ci=true
35
+
36
+ if [[ "${CI:-}" ]] && [ "$should_hardcode_ci" == true ]; then
37
+ rev=1228630
38
+ if [ "$machine" == "MinGw" ]; then
39
+ url="http://commondatastorage.googleapis.com/chromium-browser-snapshots/Win_x64/$rev/chrome-win.zip"
40
+ elif [ "$machine" == "Linux" ]; then
41
+ url="http://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/$rev/chrome-linux.zip"
42
+ elif [ "$machine" == "Mac" ]; then
43
+ arch="$(uname -m)"
44
+ if [ "$arch" == "arm64" ]; then
45
+ url="http://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac_Arm/$rev/chrome-mac.zip"
46
+ else
47
+ url="http://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/$rev/chrome-mac.zip"
48
+ fi
28
49
  else
29
- url="https://download-chromium.appspot.com/dl/Mac?type=snapshots"
50
+ echo "unsupported platform"
51
+ exit 1
30
52
  fi
31
53
  else
32
- echo "unsupported platform"
33
- exit 1
54
+ if [ "$machine" == "MinGw" ]; then
55
+ url="https://download-chromium.appspot.com/dl/Win?type=snapshots"
56
+ elif [ "$machine" == "Linux" ]; then
57
+ url="https://download-chromium.appspot.com/dl/Linux_x64?type=snapshots"
58
+ elif [ "$machine" == "Mac" ]; then
59
+ arch="$(uname -m)"
60
+ if [ "$arch" == "arm64" ]; then
61
+ url="https://download-chromium.appspot.com/dl/Mac_Arm?type=snapshots"
62
+ else
63
+ url="https://download-chromium.appspot.com/dl/Mac?type=snapshots"
64
+ fi
65
+ else
66
+ echo "unsupported platform"
67
+ exit 1
68
+ fi
34
69
  fi
35
70
 
36
- if [ -e "$CHROME_PATH" ]; then
37
- echo "cached chrome found"
38
- else
39
- curl "$url" -Lo chrome.zip && unzip -q chrome.zip
40
- fi
71
+ echo "downloading $url"
72
+
73
+ mkdir -p .tmp-download && cd .tmp-download
74
+ curl "$url" -Lo chrome.zip && unzip -q chrome.zip && rm chrome.zip
75
+ mv * "$chrome_out"
76
+ cd - && rm -rf .tmp-download
77
+
78
+ ls "$chrome_out"