Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
b1b1ee9c
Unverified
Commit
b1b1ee9c
authored
Jun 17, 2022
by
David Iglesias
Committed by
GitHub
Jun 17, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[web] Fix JS crash when FF blocks service workers. (#106072)
parent
2c15e3ca
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
160 additions
and
3 deletions
+160
-3
service_worker_test.dart
dev/bots/service_worker_test.dart
+92
-0
test.dart
dev/bots/test.dart
+1
-0
service_worker_test_blocked_service_workers.dart
.../web/lib/service_worker_test_blocked_service_workers.dart
+10
-0
index_with_blocked_service_workers.html
...ion_tests/web/web/index_with_blocked_service_workers.html
+48
-0
flutter_js.dart
...flutter_tools/lib/src/web/file_generators/flutter_js.dart
+9
-3
No files found.
dev/bots/service_worker_test.dart
View file @
b1b1ee9c
...
...
@@ -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<void> 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
<
void
>
_setAppVersion
(
int
version
)
async
{
...
...
@@ -52,6 +55,9 @@ Future<void> _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<void> runWebServiceWorkerTestWithCachingResources({
print
(
'END runWebServiceWorkerTestWithCachingResources(headless:
$headless
, testType:
$testType
)
\n
'
);
}
Future
<
void
>
runWebServiceWorkerTestWithBlockedServiceWorkers
({
required
bool
headless
})
async
{
final
Map
<
String
,
int
>
requestedPathCounts
=
<
String
,
int
>{};
void
expectRequestCounts
(
Map
<
String
,
int
>
expectedCounts
)
=>
_expectRequestCounts
(
expectedCounts
,
requestedPathCounts
);
AppServer
?
server
;
Future
<
void
>
waitForAppToLoad
(
Map
<
String
,
int
>
waitForCounts
)
async
=>
_waitForAppToLoad
(
waitForCounts
,
requestedPathCounts
,
server
);
Future
<
void
>
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:
<
Handler
>[
(
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'
,
<
String
>[
'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
(<
String
,
int
>{
'CLOSE'
:
1
,
});
expectRequestCounts
(<
String
,
int
>{
'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
)
...<
String
,
int
>{
'manifest.json'
:
1
,
'favicon.ico'
:
1
,
},
});
}
finally
{
await
runCommand
(
'mv'
,
<
String
>[
'index_og.html'
,
'index.html'
,
],
workingDirectory:
_testAppWebDirectory
,
);
await
server
?.
stop
();
}
print
(
'END runWebServiceWorkerTestWithBlockedServiceWorkers(headless:
$headless
)
\n
'
);
}
dev/bots/test.dart
View file @
b1b1ee9c
...
...
@@ -1087,6 +1087,7 @@ Future<void> _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'
),
...
...
dev/integration_tests/web/lib/service_worker_test_blocked_service_workers.dart
0 → 100644
View file @
b1b1ee9c
// 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
<
void
>
main
()
async
{
const
String
response
=
'CLOSE?version=1'
;
await
html
.
HttpRequest
.
getString
(
response
);
html
.
document
.
body
?.
appendHtml
(
response
);
}
dev/integration_tests/web/web/index_with_blocked_service_workers.html
0 → 100644
View file @
b1b1ee9c
<!DOCTYPE HTML>
<!-- 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. -->
<html>
<head>
<meta
charset=
"UTF-8"
>
<meta
content=
"IE=Edge"
http-equiv=
"X-UA-Compatible"
>
<title>
Web Test
</title>
<!-- iOS meta tags & icons -->
<meta
name=
"apple-mobile-web-app-capable"
content=
"yes"
>
<meta
name=
"apple-mobile-web-app-status-bar-style"
content=
"black"
>
<meta
name=
"apple-mobile-web-app-title"
content=
"Web Test"
>
<link
rel=
"manifest"
href=
"manifest.json"
>
<script>
// This is to break the serviceWorker registration, and make it throw a DOMException!
// Test for issue https://github.com/flutter/flutter/issues/103972
window
.
navigator
.
serviceWorker
.
register
=
(
url
)
=>
{
console
.
error
(
'Failed to register/update a ServiceWorker for scope '
,
url
,
': Storage access is restricted in this context due to user settings or private browsing mode.'
);
return
Promise
.
reject
(
new
DOMException
(
'The operation is insecure.'
));
}
</script>
<script>
// The value below is injected by flutter build, do not touch.
var
serviceWorkerVersion
=
null
;
</script>
<!-- This script adds the flutter initialization JS code -->
<script
src=
"flutter.js"
defer
></script>
</head>
<body>
<script>
window
.
addEventListener
(
'load'
,
function
(
ev
)
{
// Download main.dart.js
_flutter
.
loader
.
loadEntrypoint
({
serviceWorker
:
{
serviceWorkerVersion
:
serviceWorkerVersion
,
}
}).
then
(
function
(
engineInitializer
)
{
return
engineInitializer
.
autoStart
();
});
});
</script>
</body>
</html>
packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart
View file @
b1b1ee9c
...
...
@@ -76,6 +76,7 @@ _flutter.loader = null;
_loadEntrypoint
(
entrypointUrl
)
{
if
(!
this
.
_scriptLoaded
)
{
console
.
debug
(
"Injecting <script> tag."
);
this
.
_scriptLoaded
=
new
Promise
((
resolve
,
reject
)
=>
{
let
scriptTag
=
document
.
createElement
(
"script"
);
scriptTag
.
src
=
entrypointUrl
;
...
...
@@ -96,7 +97,7 @@ _flutter.loader = null;
_waitForServiceWorkerActivation
(
serviceWorker
,
entrypointUrl
)
{
if
(!
serviceWorker
||
serviceWorker
.
state
==
"activated"
)
{
if
(!
serviceWorker
)
{
console
.
warn
(
"Cannot activate a null service worker.
Falling back to plain <script> tag.
"
);
console
.
warn
(
"Cannot activate a null service worker."
);
}
else
{
console
.
debug
(
"Service worker already active."
);
}
...
...
@@ -114,7 +115,7 @@ _flutter.loader = null;
_loadWithServiceWorker
(
entrypointUrl
,
serviceWorkerOptions
)
{
if
(!(
"serviceWorker"
in
navigator
)
||
serviceWorkerOptions
==
null
)
{
console
.
warn
(
"Service worker not supported (or configured).
Falling back to plain <script> tag.
"
,
serviceWorkerOptions
);
console
.
warn
(
"Service worker not supported (or configured)."
,
serviceWorkerOptions
);
return
this
.
_loadEntrypoint
(
entrypointUrl
);
}
...
...
@@ -145,6 +146,11 @@ _flutter.loader = null;
console
.
debug
(
"Loading app from service worker."
);
return
this
.
_loadEntrypoint
(
entrypointUrl
);
}
})
.
catch
((
error
)
=>
{
// Some exception happened while registering/activating the service worker.
console
.
warn
(
"Failed to register or activate service worker:"
,
error
);
return
this
.
_loadEntrypoint
(
entrypointUrl
);
});
// Timeout race promise
...
...
@@ -153,7 +159,7 @@ _flutter.loader = null;
timeout
=
new
Promise
((
resolve
,
_
)
=>
{
setTimeout
(()
=>
{
if
(!
this
.
_scriptLoaded
)
{
console
.
warn
(
"
Failed to load app from service worker. Falling back to plain <script> tag
."
);
console
.
warn
(
"
Loading from service worker timed out after"
,
timeoutMillis
,
"milliseconds
."
);
resolve
(
this
.
_loadEntrypoint
(
entrypointUrl
));
}
},
timeoutMillis
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment