blob: c5ab39e88dd72a3f7c387e256f050534360bcf0a [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_WEB_WEB_STATE_WEB_FRAME_IMPL_H_
#define IOS_WEB_WEB_STATE_WEB_FRAME_IMPL_H_
#include "ios/web/public/web_state/web_frame.h"
#include <map>
#include <string>
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "crypto/symmetric_key.h"
#include "ios/web/public/web_state/web_state_observer.h"
#include "url/gurl.h"
namespace web {
class WebState;
class WebFrameImpl : public WebFrame, public web::WebStateObserver {
public:
// Creates a new WebFrame. |initial_message_id| will be used as the message ID
// of the next message sent to the frame with the |CallJavaScriptFunction|
// API.
WebFrameImpl(const std::string& frame_id,
bool is_main_frame,
GURL security_origin,
web::WebState* web_state);
~WebFrameImpl() override;
// Sets the value to use for the next message ID.
void SetNextMessageId(int message_id);
// Sets the key to use for message encryption.
void SetEncryptionKey(std::unique_ptr<crypto::SymmetricKey> frame_key);
// The associated web state.
WebState* GetWebState();
// WebFrame implementation
std::string GetFrameId() const override;
bool IsMainFrame() const override;
GURL GetSecurityOrigin() const override;
bool CanCallJavaScriptFunction() const override;
bool CallJavaScriptFunction(
const std::string& name,
const std::vector<base::Value>& parameters) override;
bool CallJavaScriptFunction(
std::string name,
const std::vector<base::Value>& parameters,
base::OnceCallback<void(const base::Value*)> callback,
base::TimeDelta timeout) override;
// WebStateObserver implementation
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. If
// |reply_with_result| is true, the return value of executing the function
// will be sent back to the receiver and handled by |OnJavaScriptReply|.
bool CallJavaScriptFunction(const std::string& name,
const std::vector<base::Value>& parameters,
bool reply_with_result);
// Detaches the receiver from the associated WebState.
void DetachFromWebState();
// Returns the script command name to use for this WebFrame.
const std::string GetScriptCommandPrefix();
// 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 (main frame). If
// |reply_with_result| is true, the return value of executing the function
// will be sent back to the receiver. This function is only used if the
// receiver does not have an encryption key. The JavaScript function is called
// directly and thus only works on the main frame. (Encryption is not required
// to securely communicate with the main frame because evaluating JavaScript
// on the WebState is already secure.)
bool ExecuteJavaScriptFunction(const std::string& name,
const std::vector<base::Value>& parameters,
int message_id,
bool reply_with_result);
// 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();
// Handles message from JavaScript with result of executing the function
// specified in CallJavaScriptFunction.
bool OnJavaScriptReply(web::WebState* web_state,
const base::DictionaryValue& command,
const GURL& page_url,
bool interacting,
bool is_main_frame,
WebFrame* sender_frame);
// The JavaScript requests awating a reply.
std::map<uint32_t, std::unique_ptr<struct RequestCallbacks>>
pending_requests_;
// The frame identifier which uniquely identifies this frame across the
// application's lifetime.
std::string frame_id_;
// The symmetric encryption key used to encrypt messages addressed to the
// frame. Stored in a base64 encoded string.
std::unique_ptr<crypto::SymmetricKey> frame_key_;
// 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.
GURL security_origin_;
// The associated web state.
web::WebState* web_state_ = nullptr;
base::WeakPtrFactory<WebFrameImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(WebFrameImpl);
};
} // namespace web
#endif // IOS_WEB_WEB_STATE_WEB_FRAME_IMPL_H_