[flutter_tool] Don't download CanvasKit if it's already in flutter_web_sdk (#113072)

diff --git a/packages/flutter_tools/lib/src/flutter_cache.dart b/packages/flutter_tools/lib/src/flutter_cache.dart
index 22609b8..973d3ef 100644
--- a/packages/flutter_tools/lib/src/flutter_cache.dart
+++ b/packages/flutter_tools/lib/src/flutter_cache.dart
@@ -206,13 +206,20 @@
       }
     }
 
-    final String canvasKitVersion = cache.getVersionFor('canvaskit')!;
-    final String canvasKitUrl = '${cache.cipdBaseUrl}/flutter/web/canvaskit_bundle/+/$canvasKitVersion';
-    return artifactUpdater.downloadZipArchive(
-      'Downloading CanvasKit...',
-      Uri.parse(canvasKitUrl),
-      location,
-    );
+    // If the flutter_web_sdk folder doesn't already contain CanvasKit, then
+    // download it from CIPD.
+    // TODO(hterkelsen): This whole section can be removed when we are always building
+    //   CanvasKit as part of flutter_web_sdk. See https://github.com/flutter/flutter/issues/113073
+    final File expectedCanvasKitFile = fileSystem.file(fileSystem.path.join(location.path, 'canvaskit', 'canvaskit.wasm'));
+    if (!expectedCanvasKitFile.existsSync()) {
+      final String canvasKitVersion = cache.getVersionFor('canvaskit')!;
+      final String canvasKitUrl = '${cache.cipdBaseUrl}/flutter/web/canvaskit_bundle/+/$canvasKitVersion';
+      return artifactUpdater.downloadZipArchive(
+        'Downloading CanvasKit...',
+        Uri.parse(canvasKitUrl),
+        location,
+      );
+    }
   }
 }
 
diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart
index c72aee9..9ae8672 100644
--- a/packages/flutter_tools/test/general.shard/cache_test.dart
+++ b/packages/flutter_tools/test/general.shard/cache_test.dart
@@ -840,6 +840,55 @@
     ]);
   });
 
+  testWithoutContext('FlutterWebSdk does not download CanvasKit if it is already in flutter_web_sdk', () async {
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    final Directory internalDir = fileSystem.currentDirectory
+      .childDirectory('cache')
+      .childDirectory('bin')
+      .childDirectory('internal');
+    final File canvasKitVersionFile = internalDir.childFile('canvaskit.version');
+    canvasKitVersionFile.createSync(recursive: true);
+    canvasKitVersionFile.writeAsStringSync('abcdefg');
+
+    final File engineVersionFile = internalDir.childFile('engine.version');
+    engineVersionFile.createSync(recursive: true);
+    engineVersionFile.writeAsStringSync('hijklmnop');
+
+    final Cache cache = Cache.test(processManager: FakeProcessManager.any(), fileSystem: fileSystem);
+    final FakeArtifactUpdater artifactUpdater = FakeArtifactUpdater();
+    final FlutterWebSdk webSdk = FlutterWebSdk(cache, platform: FakePlatform());
+
+    final List<String> messages = <String>[];
+    final List<String> downloads = <String>[];
+    final List<String> locations = <String>[];
+    artifactUpdater.onDownloadZipArchive = (String message, Uri uri, Directory location) {
+      messages.add(message);
+      downloads.add(uri.toString());
+      locations.add(location.path);
+      location.createSync(recursive: true);
+      location.childDirectory('canvaskit').createSync();
+      location.childDirectory('canvaskit').childFile('canvaskit.js').createSync();
+      location.childDirectory('canvaskit').childFile('canvaskit.wasm').createSync();
+      location.childDirectory('canvaskit').childDirectory('profiling').createSync();
+      location.childDirectory('canvaskit').childDirectory('profiling').childFile('canvaskit.js').createSync();
+      location.childDirectory('canvaskit').childDirectory('profiling').childFile('canvaskit.wasm').createSync();
+    };
+
+    await webSdk.updateInner(artifactUpdater, fileSystem, FakeOperatingSystemUtils());
+
+    expect(messages, <String>[
+      'Downloading Web SDK...',
+    ]);
+
+    expect(downloads, <String>[
+      'https://storage.googleapis.com/flutter_infra_release/flutter/hijklmnop/flutter-web-sdk-linux-x64.zip',
+    ]);
+
+    expect(locations, <String>[
+      'cache/bin/cache/flutter_web_sdk',
+    ]);
+  });
+
   testWithoutContext('FlutterWebSdk uses tryToDelete to handle directory edge cases', () async {
     final FileExceptionHandler handler = FileExceptionHandler();
     final MemoryFileSystem fileSystem = MemoryFileSystem.test(opHandle: handler.opHandle);