Skip to content

Commit 1063222

Browse files
authored
[url_launcher] When not fully loaded, clicking close causes the callback to not be triggered correctly. (#8582)
When SFSafariViewController is loading a webpage, if the close button is clicked during the loading process, it can prevent the callback from being triggered correctly. *List which issues are fixed by this PR. You must list at least one issue.* - Fixes flutter/flutter#161790 - Fixes flutter/flutter#47271
1 parent f1b1eb5 commit 1063222

File tree

8 files changed

+36
-2
lines changed

8 files changed

+36
-2
lines changed

packages/url_launcher/url_launcher_ios/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
## NEXT
1+
## 6.3.3
22

33
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
4+
* Ensures the completion callback is invoked if the user dismisses the Safari view before the initial URL load completes.
45

56
## 6.3.2
67

packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@ final class URLLauncherTests: XCTestCase {
131131
XCTAssertEqual(launcher.passedOptions?[.universalLinksOnly] as? Bool, true)
132132
}
133133

134+
func testLaunchSafariViewControllerWithClose() {
135+
let launcher = FakeLauncher()
136+
let plugin = createPlugin(launcher: launcher)
137+
138+
let expectation = XCTestExpectation(description: "completion called")
139+
plugin.openUrlInSafariViewController(url: "https://flutter.dev") { result in
140+
switch result {
141+
case .success(let details):
142+
XCTAssertEqual(details, .dismissed)
143+
case .failure(let error):
144+
XCTFail("Unexpected error: \(error)")
145+
}
146+
expectation.fulfill()
147+
}
148+
plugin.closeSafariViewController()
149+
wait(for: [expectation], timeout: 30)
150+
}
151+
134152
}
135153

136154
final private class FakeLauncher: NSObject, Launcher {

packages/url_launcher/url_launcher_ios/ios/url_launcher_ios/Sources/url_launcher_ios/URLLaunchSession.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class URLLaunchSession: NSObject, SFSafariViewControllerDelegate {
1212

1313
private let completion: OpenInSafariCompletionHandler
1414
private let url: URL
15+
private var isLoadCompleted: Bool = false
1516

1617
/// The Safari view controller used for displaying the URL.
1718
let safariViewController: SFSafariViewController
@@ -46,12 +47,16 @@ final class URLLaunchSession: NSObject, SFSafariViewControllerDelegate {
4647
} else {
4748
completion(.success(.failedToLoad))
4849
}
50+
isLoadCompleted = true
4951
}
5052

5153
/// Called when the user finishes using the Safari view controller.
5254
///
5355
/// - Parameter controller: The Safari view controller.
5456
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
57+
if !isLoadCompleted {
58+
completion(.success(.dismissed))
59+
}
5560
controller.dismiss(animated: true, completion: nil)
5661
didFinish?()
5762
}

packages/url_launcher/url_launcher_ios/ios/url_launcher_ios/Sources/url_launcher_ios/messages.g.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ enum InAppLoadResult: Int {
8585
case failedToLoad = 1
8686
/// The URL could not be launched because it is invalid.
8787
case invalidUrl = 2
88+
/// The controller was closed before loading.
89+
case dismissed = 3
8890
}
8991

9092
private class messagesPigeonCodecReader: FlutterStandardReader {

packages/url_launcher/url_launcher_ios/lib/src/messages.g.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ enum InAppLoadResult {
4040

4141
/// The URL could not be launched because it is invalid.
4242
invalidUrl,
43+
44+
/// The controller was closed before loading.
45+
dismissed,
4346
}
4447

4548
class _PigeonCodec extends StandardMessageCodec {

packages/url_launcher/url_launcher_ios/lib/url_launcher_ios.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class UrlLauncherIOS extends UrlLauncherPlatform {
141141
throw _failedSafariViewControllerLoadException(url);
142142
case InAppLoadResult.invalidUrl:
143143
throw _invalidUrlException();
144+
case InAppLoadResult.dismissed:
145+
return false;
144146
}
145147
}
146148

packages/url_launcher/url_launcher_ios/pigeons/messages.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ enum InAppLoadResult {
3232

3333
/// The URL could not be launched because it is invalid.
3434
invalidUrl,
35+
36+
/// The controller was closed before loading.
37+
dismissed,
3538
}
3639

3740
@HostApi()

packages/url_launcher/url_launcher_ios/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: url_launcher_ios
22
description: iOS implementation of the url_launcher plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_ios
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
5-
version: 6.3.2
5+
version: 6.3.3
66

77
environment:
88
sdk: ^3.4.0

0 commit comments

Comments
 (0)