| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IOS_WEB_JS_MESSAGING_WEB_FRAME_IMPL_H_ |
| #define IOS_WEB_JS_MESSAGING_WEB_FRAME_IMPL_H_ |
| |
| #import <map> |
| #import <string> |
| |
| #import "base/cancelable_callback.h" |
| #import "base/memory/raw_ptr.h" |
| #import "base/memory/weak_ptr.h" |
| #import "base/values.h" |
| #import "ios/web/js_messaging/web_frame_internal.h" |
| #import "ios/web/public/js_messaging/content_world.h" |
| #import "ios/web/public/js_messaging/web_frame.h" |
| #import "ios/web/public/web_state.h" |
| #import "ios/web/public/web_state_observer.h" |
| #import "url/gurl.h" |
| #import "url/origin.h" |
| |
| @class WKFrameInfo; |
| |
| namespace web { |
| |
| class JavaScriptContentWorld; |
| |
| class WebFrameImpl final : public WebFrame, |
| public WebFrameInternal, |
| public web::WebStateObserver { |
| public: |
| // Creates a new WebFrame. |
| WebFrameImpl(WKFrameInfo* frame_info, |
| const std::string& frame_id, |
| bool is_main_frame, |
| url::Origin security_origin, |
| web::WebState* web_state, |
| ContentWorld content_world); |
| |
| WebFrameImpl(const WebFrameImpl&) = delete; |
| WebFrameImpl& operator=(const WebFrameImpl&) = delete; |
| |
| ~WebFrameImpl() override; |
| |
| // The associated web state. |
| WebState* GetWebState(); |
| |
| // WebFrame: |
| WebFrameInternal* GetWebFrameInternal() override; |
| std::string GetFrameId() const override; |
| bool IsMainFrame() const override; |
| url::Origin GetSecurityOrigin() const override; |
| GURL GetUrl() const override; |
| BrowserState* GetBrowserState() override; |
| |
| bool CallJavaScriptFunction(const std::string& name, |
| const base::Value::List& parameters) override; |
| bool CallJavaScriptFunction( |
| const std::string& name, |
| const base::Value::List& parameters, |
| base::OnceCallback<void(const base::Value*)> callback, |
| base::TimeDelta timeout) override; |
| |
| bool ExecuteJavaScript(const std::u16string& script) override; |
| bool ExecuteJavaScript( |
| const std::u16string& script, |
| base::OnceCallback<void(const base::Value*)> callback) override; |
| bool ExecuteJavaScript(const std::u16string& script, |
| ExecuteJavaScriptCallbackWithError callback) override; |
| base::WeakPtr<WebFrame> AsWeakPtr() override; |
| |
| // WebFrameContentWorldAPI: |
| bool CallJavaScriptFunctionInContentWorld( |
| const std::string& name, |
| const base::Value::List& parameters, |
| JavaScriptContentWorld* content_world) override; |
| bool CallJavaScriptFunctionInContentWorld( |
| const std::string& name, |
| const base::Value::List& parameters, |
| JavaScriptContentWorld* content_world, |
| base::OnceCallback<void(const base::Value*)> callback, |
| base::TimeDelta timeout) override; |
| bool ExecuteJavaScriptInContentWorld( |
| const std::u16string& script, |
| JavaScriptContentWorld* content_world, |
| ExecuteJavaScriptCallbackWithError callback) override; |
| |
| // WebStateObserver: |
| void WebStateDestroyed(web::WebState* web_state) override; |
| |
| private: |
| // Calls the JavaScript function `name` in the frame context in the same |
| // manner as the inherited CallJavaScriptFunction functions. `content_world` |
| // is optional, but if specified, the function will be executed within that |
| // world. If `reply_with_result` is true, the return value of executing the |
| // function will be sent back to the receiver with `CompleteRequest()`. |
| bool CallJavaScriptFunctionInContentWorld( |
| const std::string& name, |
| const base::Value::List& parameters, |
| JavaScriptContentWorld* content_world, |
| bool reply_with_result); |
| |
| // Detaches the receiver from the associated WebState. |
| void DetachFromWebState(); |
| |
| // A structure to store the callbacks associated with the |
| // `CallJavaScriptFunction` requests. |
| typedef base::CancelableOnceCallback<void(void)> TimeoutCallback; |
| struct RequestCallbacks { |
| RequestCallbacks(base::OnceCallback<void(const base::Value*)> completion, |
| std::unique_ptr<TimeoutCallback>); |
| ~RequestCallbacks(); |
| base::OnceCallback<void(const base::Value*)> completion; |
| std::unique_ptr<TimeoutCallback> timeout_callback; |
| }; |
| |
| // Calls the JavaScript function `name` in the web state. If `content_world` |
| // is specified, the function will be executed within `content_world`. If |
| // `reply_with_result` is true, the return value of executing the function |
| // will be sent back to the receiver. |
| bool ExecuteJavaScriptFunction(JavaScriptContentWorld* content_world, |
| const std::string& name, |
| const base::Value::List& parameters, |
| int message_id, |
| bool reply_with_result); |
| |
| // Converts the given callback into a `ExecuteJavaScriptCallbackWithError` |
| // callback. This function improves code sharing by being a bridge |
| // between the various ExecuteJavaScript() functions. |
| ExecuteJavaScriptCallbackWithError ExecuteJavaScriptCallbackAdapter( |
| base::OnceCallback<void(const base::Value*)> callback); |
| // Prints the information about the error that was generated from the |
| // execution of the given arbitrary JavaScript string. |
| void LogScriptWarning(NSString* script, NSError* error); |
| |
| // Runs the request associated with the message with id `message_id`. The |
| // completion callback, if any, associated with `message_id` will be called |
| // with `result`. |
| void CompleteRequest(int message_id, const base::Value* result); |
| // Calls the completion block of `request_callbacks` with `result` value and |
| // removes the callbacks from `pending_requests`. |
| void CompleteRequest(std::unique_ptr<RequestCallbacks> request_callbacks, |
| const base::Value* result); |
| |
| // Cancels the request associated with the message with id `message_id`. The |
| // completion callback, if any, associated with `message_id` will be called |
| // with a null result value. Note that the JavaScript will still run to |
| // completion, but any future response will be ignored. |
| void CancelRequest(int message_id); |
| // Performs `CancelRequest` on all outstanding request callbacks in |
| // `pending_requests_`. |
| void CancelPendingRequests(); |
| |
| // The JavaScript requests awating a reply. |
| std::map<uint32_t, std::unique_ptr<struct RequestCallbacks>> |
| pending_requests_; |
| |
| // The frame info instance associated with this web frame. |
| WKFrameInfo* frame_info_; |
| // The frame identifier which uniquely identifies this frame across the |
| // application's lifetime. |
| std::string frame_id_; |
| // The message ID of the next JavaScript message to be sent. |
| int next_message_id_ = 0; |
| // Whether or not the receiver represents the main frame. |
| bool is_main_frame_ = false; |
| // The security origin associated with this frame. |
| url::Origin security_origin_; |
| // The associated web state. |
| raw_ptr<web::WebState> web_state_ = nullptr; |
| // The frame's content world. |
| ContentWorld content_world_; |
| |
| base::WeakPtrFactory<WebFrameImpl> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace web |
| |
| #endif // IOS_WEB_JS_MESSAGING_WEB_FRAME_IMPL_H_ |