diff --git a/dev/bots/service_worker_test.dart b/dev/bots/service_worker_test.dart index 9dec42d0b1e8..2f4d3b0a78e8 100644 --- a/dev/bots/service_worker_test.dart +++ b/dev/bots/service_worker_test.dart @@ -21,9 +21,11 @@ final String _testAppWebDirectory = path.join(_testAppDirectory, 'web'); final String _appBuildDirectory = path.join(_testAppDirectory, 'build', 'web'); final String _target = path.join('lib', 'service_worker_test.dart'); final String _targetWithCachedResources = path.join('lib', 'service_worker_test_cached_resources.dart'); +final String _targetWithBlockedServiceWorkers = path.join('lib', 'service_worker_test_blocked_service_workers.dart'); final String _targetPath = path.join(_testAppDirectory, _target); enum ServiceWorkerTestType { + blockedServiceWorkers, withoutFlutterJs, withFlutterJs, withFlutterJsShort, @@ -37,6 +39,7 @@ Future main() async { await runWebServiceWorkerTestWithCachingResources(headless: false, testType: ServiceWorkerTestType.withoutFlutterJs); await runWebServiceWorkerTestWithCachingResources(headless: false, testType: ServiceWorkerTestType.withFlutterJs); await runWebServiceWorkerTestWithCachingResources(headless: false, testType: ServiceWorkerTestType.withFlutterJsShort); + await runWebServiceWorkerTestWithBlockedServiceWorkers(headless: false); } Future _setAppVersion(int version) async { @@ -52,6 +55,9 @@ Future _setAppVersion(int version) async { String _testTypeToIndexFile(ServiceWorkerTestType type) { late String indexFile; switch (type) { + case ServiceWorkerTestType.blockedServiceWorkers: + indexFile = 'index_with_blocked_service_workers.html'; + break; case ServiceWorkerTestType.withFlutterJs: indexFile = 'index_with_flutterjs.html'; break; @@ -562,3 +568,89 @@ Future runWebServiceWorkerTestWithCachingResources({ print('END runWebServiceWorkerTestWithCachingResources(headless: $headless, testType: $testType)\n'); } + +Future runWebServiceWorkerTestWithBlockedServiceWorkers({ + required bool headless +}) async { + final Map requestedPathCounts = {}; + void expectRequestCounts(Map expectedCounts) => + _expectRequestCounts(expectedCounts, requestedPathCounts); + + AppServer? server; + Future waitForAppToLoad(Map waitForCounts) async => + _waitForAppToLoad(waitForCounts, requestedPathCounts, server); + + Future startAppServer({ + required String cacheControl, + }) async { + final int serverPort = await findAvailablePort(); + final int browserDebugPort = await findAvailablePort(); + server = await AppServer.start( + headless: headless, + cacheControl: cacheControl, + // TODO(yjbanov): use a better port disambiguation strategy than trying + // to guess what ports other tests use. + appUrl: 'http://localhost:$serverPort/index.html', + serverPort: serverPort, + browserDebugPort: browserDebugPort, + appDirectory: _appBuildDirectory, + additionalRequestHandlers: [ + (Request request) { + final String requestedPath = request.url.path; + requestedPathCounts.putIfAbsent(requestedPath, () => 0); + requestedPathCounts[requestedPath] = requestedPathCounts[requestedPath]! + 1; + if (requestedPath == 'CLOSE') { + return Response.ok('OK'); + } + return Response.notFound(''); + }, + ], + ); + } + + // Preserve old index.html as index_og.html so we can restore it later for other tests + await runCommand( + 'mv', + [ + 'index.html', + 'index_og.html', + ], + workingDirectory: _testAppWebDirectory, + ); + + print('BEGIN runWebServiceWorkerTestWithBlockedServiceWorkers(headless: $headless)\n'); + try { + await _rebuildApp(version: 1, testType: ServiceWorkerTestType.blockedServiceWorkers, target: _targetWithBlockedServiceWorkers); + + print('Ensure app starts (when service workers are blocked)'); + await startAppServer(cacheControl: 'max-age=3600'); + await waitForAppToLoad({ + 'CLOSE': 1, + }); + expectRequestCounts({ + 'index.html': 1, + 'flutter.js': 1, + 'main.dart.js': 1, + 'assets/FontManifest.json': 1, + 'assets/fonts/MaterialIcons-Regular.otf': 1, + 'CLOSE': 1, + // In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'. + if (!headless) + ...{ + 'manifest.json': 1, + 'favicon.ico': 1, + }, + }); + } finally { + await runCommand( + 'mv', + [ + 'index_og.html', + 'index.html', + ], + workingDirectory: _testAppWebDirectory, + ); + await server?.stop(); + } + print('END runWebServiceWorkerTestWithBlockedServiceWorkers(headless: $headless)\n'); +} diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 47b7d5331629..224d83501024 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -1087,6 +1087,7 @@ Future _runWebLongRunningTests() async { () => runWebServiceWorkerTestWithCachingResources(headless: true, testType: ServiceWorkerTestType.withoutFlutterJs), () => runWebServiceWorkerTestWithCachingResources(headless: true, testType: ServiceWorkerTestType.withFlutterJs), () => runWebServiceWorkerTestWithCachingResources(headless: true, testType: ServiceWorkerTestType.withFlutterJsShort), + () => runWebServiceWorkerTestWithBlockedServiceWorkers(headless: true), () => _runWebStackTraceTest('profile', 'lib/stack_trace.dart'), () => _runWebStackTraceTest('release', 'lib/stack_trace.dart'), () => _runWebStackTraceTest('profile', 'lib/framework_stack_trace.dart'), diff --git a/dev/integration_tests/web/lib/service_worker_test_blocked_service_workers.dart b/dev/integration_tests/web/lib/service_worker_test_blocked_service_workers.dart new file mode 100644 index 000000000000..f7c7e9129576 --- /dev/null +++ b/dev/integration_tests/web/lib/service_worker_test_blocked_service_workers.dart @@ -0,0 +1,10 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:html' as html; +Future main() async { + const String response = 'CLOSE?version=1'; + await html.HttpRequest.getString(response); + html.document.body?.appendHtml(response); +} diff --git a/dev/integration_tests/web/web/index_with_blocked_service_workers.html b/dev/integration_tests/web/web/index_with_blocked_service_workers.html new file mode 100644 index 000000000000..c590fdbd0a2d --- /dev/null +++ b/dev/integration_tests/web/web/index_with_blocked_service_workers.html @@ -0,0 +1,48 @@ + + + + + + + + Web Test + + + + + + + + + + + + + + + + diff --git a/packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart b/packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart index 6a5f761087e8..257cb42d3918 100644 --- a/packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart +++ b/packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart @@ -76,6 +76,7 @@ _flutter.loader = null; _loadEntrypoint(entrypointUrl) { if (!this._scriptLoaded) { + console.debug("Injecting