|  | // Copyright 2021 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #import "ios/web/js_messaging/scoped_wk_script_message_handler.h" | 
|  |  | 
|  | #import "ios/web/js_messaging/web_view_js_utils.h" | 
|  |  | 
|  | @interface CRWScriptMessageHandler : NSObject <WKScriptMessageHandler> | 
|  |  | 
|  | - (instancetype)init NS_UNAVAILABLE; | 
|  |  | 
|  | - (instancetype)initWithCallback:(ScriptMessageCallback)callback | 
|  | NS_DESIGNATED_INITIALIZER; | 
|  |  | 
|  | @property(nonatomic) ScriptMessageCallback callback; | 
|  |  | 
|  | @end | 
|  |  | 
|  | @implementation CRWScriptMessageHandler | 
|  |  | 
|  | - (instancetype)initWithCallback:(ScriptMessageCallback)callback { | 
|  | if ((self = [super init])) { | 
|  | _callback = callback; | 
|  | } | 
|  | return self; | 
|  | } | 
|  |  | 
|  | - (void)userContentController:(WKUserContentController*)userContentController | 
|  | didReceiveScriptMessage:(WKScriptMessage*)message { | 
|  | _callback.Run(message); | 
|  | } | 
|  |  | 
|  | @end | 
|  |  | 
|  | @interface CRWScriptMessageHandlerWithReply | 
|  | : NSObject <WKScriptMessageHandlerWithReply> | 
|  |  | 
|  | - (instancetype)init NS_UNAVAILABLE; | 
|  |  | 
|  | - (instancetype)initWithCallback:(ScriptMessageWithReplyCallback)callback | 
|  | NS_DESIGNATED_INITIALIZER; | 
|  |  | 
|  | @property(nonatomic) ScriptMessageWithReplyCallback callback; | 
|  |  | 
|  | @end | 
|  |  | 
|  | @implementation CRWScriptMessageHandlerWithReply | 
|  |  | 
|  | - (instancetype)initWithCallback:(ScriptMessageWithReplyCallback)callback { | 
|  | if ((self = [super init])) { | 
|  | _callback = callback; | 
|  | } | 
|  | return self; | 
|  | } | 
|  |  | 
|  | - (void)userContentController:(WKUserContentController*)userContentController | 
|  | didReceiveScriptMessage:(WKScriptMessage*)message | 
|  | replyHandler:(void (^)(id, NSString*))replyHandler { | 
|  | ScriptMessageReplyHandler replyValueHandler = | 
|  | ^(const base::Value* reply, NSString* error_message) { | 
|  | // Per the API documentation, specify the result as nil if an error | 
|  | // occurred. | 
|  | id wkResult = error_message ? nil : web::NSObjectFromValueResult(reply); | 
|  | replyHandler(wkResult, error_message); | 
|  | }; | 
|  | _callback.Run(message, replyValueHandler); | 
|  | } | 
|  |  | 
|  | @end | 
|  |  | 
|  | ScopedWKScriptMessageHandler::ScopedWKScriptMessageHandler( | 
|  | WKUserContentController* user_content_controller, | 
|  | NSString* script_handler_name, | 
|  | ScriptMessageCallback callback) | 
|  | : user_content_controller_(user_content_controller), | 
|  | script_handler_name_(script_handler_name), | 
|  | script_message_handler_( | 
|  | [[CRWScriptMessageHandler alloc] initWithCallback:callback]) { | 
|  | DCHECK(callback); | 
|  | [user_content_controller_ addScriptMessageHandler:script_message_handler_ | 
|  | name:script_handler_name_]; | 
|  | } | 
|  |  | 
|  | ScopedWKScriptMessageHandler::ScopedWKScriptMessageHandler( | 
|  | WKUserContentController* user_content_controller, | 
|  | NSString* script_handler_name, | 
|  | WKContentWorld* content_world, | 
|  | ScriptMessageCallback callback) | 
|  | : content_world_(content_world), | 
|  | user_content_controller_(user_content_controller), | 
|  | script_handler_name_(script_handler_name), | 
|  | script_message_handler_( | 
|  | [[CRWScriptMessageHandler alloc] initWithCallback:callback]) { | 
|  | DCHECK(callback); | 
|  | if (content_world_) { | 
|  | [user_content_controller_ addScriptMessageHandler:script_message_handler_ | 
|  | contentWorld:content_world_ | 
|  | name:script_handler_name_]; | 
|  | } else { | 
|  | [user_content_controller_ addScriptMessageHandler:script_message_handler_ | 
|  | name:script_handler_name_]; | 
|  | } | 
|  | } | 
|  |  | 
|  | ScopedWKScriptMessageHandler::ScopedWKScriptMessageHandler( | 
|  | WKUserContentController* user_content_controller, | 
|  | NSString* script_handler_name, | 
|  | WKContentWorld* content_world, | 
|  | ScriptMessageWithReplyCallback callback) | 
|  | : content_world_(content_world), | 
|  | user_content_controller_(user_content_controller), | 
|  | script_handler_name_(script_handler_name), | 
|  | script_message_handler_with_reply_( | 
|  | [[CRWScriptMessageHandlerWithReply alloc] | 
|  | initWithCallback:callback]) { | 
|  | DCHECK(content_world); | 
|  | DCHECK(callback); | 
|  | [user_content_controller | 
|  | addScriptMessageHandlerWithReply:script_message_handler_with_reply_ | 
|  | contentWorld:content_world_ | 
|  | name:script_handler_name_]; | 
|  | } | 
|  |  | 
|  | ScopedWKScriptMessageHandler::~ScopedWKScriptMessageHandler() { | 
|  | if (content_world_) { | 
|  | [user_content_controller_ | 
|  | removeScriptMessageHandlerForName:script_handler_name_ | 
|  | contentWorld:content_world_]; | 
|  | } else { | 
|  | [user_content_controller_ | 
|  | removeScriptMessageHandlerForName:script_handler_name_]; | 
|  | } | 
|  | } |