Skip to content

Commit

Permalink
Update FlutterAppDelegate.mm
Browse files Browse the repository at this point in the history
  • Loading branch information
hangyujin committed May 8, 2024
1 parent 842cf25 commit c762720
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 50 deletions.
49 changes: 37 additions & 12 deletions shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,14 @@ - (void)userNotificationCenter:(UNUserNotificationCenter*)center
}
}

- (BOOL)openURL:(NSURL*)url {
- (void)openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenExternalURLOptionsKey, id>*)options
completionHandler:(void (^)(BOOL success))completion {
NSNumber* isDeepLinkingEnabled =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"];
if (!isDeepLinkingEnabled.boolValue) {
// Not set or NO.
return NO;
completion(NO);
} else {
FlutterViewController* flutterViewController = [self rootFlutterViewController];
if (flutterViewController) {
Expand All @@ -149,29 +151,46 @@ - (BOOL)openURL:(NSURL*)url {
if (didTimeout) {
FML_LOG(ERROR)
<< "Timeout waiting for the first frame when launching an URL.";
completion(NO);
} else {
// invove the method and get the result
[flutterViewController.engine.navigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{
@"location" : url.absoluteString ?: [NSNull null],
}];
}
result:^(id _Nullable result) {
BOOL success = [result isKindOfClass:[NSNumber class]] &&
[result boolValue];
if (!success) {
// Logging the error if the result is not successful
FML_LOG(ERROR)
<< "Failed to handle route information in Flutter.";
}
completion(success);
}];
}
}];
return YES;
} else {
FML_LOG(ERROR) << "Attempting to open an URL without a Flutter RootViewController.";
return NO;
completion(NO);
}
}
}

- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options {
openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options
completionHandler:(void (^)(BOOL success))completion {
if ([_lifeCycleDelegate application:application openURL:url options:options]) {
return YES;
completion(YES);
} else {
[self openURL:url
options:options
completionHandler:^(BOOL success) {
completion(success);
}];
}
return [self openURL:url];
}

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
Expand Down Expand Up @@ -208,13 +227,19 @@ - (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:
(void (^)(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects))
restorationHandler {
restorationHandler
completionHandler:(void (^)(BOOL success))completion {
if ([_lifeCycleDelegate application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler]) {
return YES;
completion(YES);
}
return [self openURL:userActivity.webpageURL];

[self openURL:userActivity.webpageURL
options:@{}
completionHandler:^(BOOL success) {
completion(success);
}];
}

#pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController
Expand Down
108 changes: 70 additions & 38 deletions shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,48 @@ - (void)testLaunchUrl {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@YES);

BOOL result =
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}];
XCTAssertTrue(result);
OCMVerify([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
OCMStub([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
.andReturn(@YES);

[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertTrue(success);
}];

OCMVerifyAll(self.mockNavigationChannel);
}

- (void)testLaunchUrlWithNavigationChannelReturningFalse {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@YES);

OCMStub([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
.andReturn(@NO);

[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertFalse(success);
}];
}

- (void)testLaunchUrlWithDeepLinkingNotSet {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(nil);

BOOL result =
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}];
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertFalse(success);
}];
XCTAssertFalse(result);
OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
}
Expand All @@ -88,40 +112,47 @@ - (void)testLaunchUrlWithDeepLinkingDisabled {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@NO);

BOOL result =
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}];
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertFalse(success);
}];
XCTAssertFalse(result);
OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
}

- (void)testLaunchUrlWithQueryParameterAndFragment {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@YES);

BOOL result = [self.appDelegate
application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
options:@{}];
XCTAssertTrue(result);
OCMVerify([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test#fragment"}]);
OCMStub([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
.andReturn(@YES);
[self.appDelegate
application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertTrue(success);
}];
OCMVerifyAll(self.mockNavigationChannel);
}

- (void)testLaunchUrlWithFragmentNoQueryParameter {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@YES);

BOOL result =
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
options:@{}];
XCTAssertTrue(result);
OCMVerify([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route#fragment"}]);
OCMStub([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
.andReturn(@YES);
[self.appDelegate application:[UIApplication sharedApplication]
openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
options:@{}
completionHandler:^(BOOL success) {
XCTAssertTrue(success);
}];
OCMVerifyAll(self.mockNavigationChannel);
}

- (void)testReleasesWindowOnDealloc {
Expand All @@ -145,7 +176,10 @@ - (void)testReleasesWindowOnDealloc {
- (void)testUniversalLinkPushRouteInformation {
OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
.andReturn(@YES);

OCMStub([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
.andReturn(@YES);
NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.example.test"];
userActivity.webpageURL = [NSURL URLWithString:@"http://myApp/custom/route?query=test"];
BOOL result = [self.appDelegate
Expand All @@ -154,9 +188,7 @@ - (void)testUniversalLinkPushRouteInformation {
restorationHandler:^(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects){
}];
XCTAssertTrue(result);
OCMVerify([self.mockNavigationChannel
invokeMethod:@"pushRouteInformation"
arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
OCMVerifyAll(self.mockNavigationChannel);
}

@end

0 comments on commit c762720

Please sign in to comment.