diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index e360381053644..ab270725675be 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -16,6 +16,7 @@ constexpr char kTextPlainFormat[] = "text/plain"; const UInt32 kKeyPressClickSoundId = 1306; +const NSString* searchURLPrefix = @"x-web-search://?"; } // namespace @@ -115,6 +116,9 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { result([self clipboardHasStrings]); } else if ([method isEqualToString:@"LiveText.isLiveTextInputAvailable"]) { result(@([self isLiveTextInputAvailable])); + } else if ([method isEqualToString:@"SearchWeb.invoke"]) { + [self searchWeb:args]; + result(nil); } else if ([method isEqualToString:@"LookUp.invoke"]) { [self showLookUpViewController:args]; result(nil); @@ -123,6 +127,17 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } } +- (void)searchWeb:(NSString*)searchTerm { + NSString* escapedText = [searchTerm + stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet + URLHostAllowedCharacterSet]]; + NSString* searchURL = [NSString stringWithFormat:@"%@%@", searchURLPrefix, escapedText]; + + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:searchURL] + options:@{} + completionHandler:nil]; +} + - (void)playSystemSound:(NSString*)soundType { if ([soundType isEqualToString:@"SystemSoundType.click"]) { // All feedback types are specific to Android and are treated as equal on diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm index a50fefe335792..6ccbd8dd19a29 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm @@ -17,6 +17,7 @@ @interface FlutterPlatformPluginTest : XCTestCase @interface FlutterPlatformPlugin () - (BOOL)isLiveTextInputAvailable; +- (void)searchWeb:(NSString*)searchTerm; - (void)showLookUpViewController:(NSString*)term; @end @@ -27,6 +28,30 @@ - (void)presentViewController:(UIViewController*)viewControllerToPresent @end @implementation FlutterPlatformPluginTest +- (void)testSearchWebInvoked { + FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease]; + std::unique_ptr> _weakFactory = + std::make_unique>(engine); + [engine runWithEntrypoint:nil]; + + XCTestExpectation* invokeExpectation = + [self expectationWithDescription:@"Web search launched with search term"]; + + FlutterPlatformPlugin* plugin = + [[[FlutterPlatformPlugin alloc] initWithEngine:_weakFactory->GetWeakPtr()] autorelease]; + FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin); + + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"SearchWeb.invoke" + arguments:@"Test"]; + + FlutterResult result = ^(id result) { + OCMVerify([mockPlugin searchWeb:@"Test"]); + [invokeExpectation fulfill]; + }; + + [mockPlugin handleMethodCall:methodCall result:result]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +} - (void)testLookUpCallInitiated { FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease];