// Copyright 2021 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_TEST_FAKES_FAKE_WEB_FRAME_IMPL_H_
#define IOS_WEB_TEST_FAKES_FAKE_WEB_FRAME_IMPL_H_

#include <map>
#include <vector>

#include "base/values.h"
#include "ios/web/js_messaging/web_frame_internal.h"
#include "ios/web/public/test/fakes/fake_web_frame.h"

namespace web {

class JavaScriptContentWorld;

class FakeWebFrameImpl : public FakeWebFrame, public WebFrameInternal {
 public:
  FakeWebFrameImpl(const std::string& frame_id,
                   bool is_main_frame,
                   GURL security_origin);

  // Returns the JavaScriptContentWorld parameter value received in the last
  // call to |CallJavaScriptFunctionInContentWorld|.
  JavaScriptContentWorld* last_received_content_world();

  // WebFrame:
  WebFrameInternal* GetWebFrameInternal() override;
  std::string GetFrameId() const override;
  bool IsMainFrame() const override;
  GURL GetSecurityOrigin() const override;
  bool CanCallJavaScriptFunction() const override;
  BrowserState* GetBrowserState() override;
  bool CallJavaScriptFunction(
      const std::string& name,
      const std::vector<base::Value>& parameters) override;
  bool CallJavaScriptFunction(
      const std::string& name,
      const std::vector<base::Value>& parameters,
      base::OnceCallback<void(const base::Value*)> callback,
      base::TimeDelta timeout) override;
  bool ExecuteJavaScript(const std::string& script) override;
  bool ExecuteJavaScript(
      const std::string& script,
      base::OnceCallback<void(const base::Value*)> callback) override;
  bool ExecuteJavaScript(
      const std::string& script,
      base::OnceCallback<void(const base::Value*, bool)> callback) override;

  // FakeWebFrame:
  std::string GetLastJavaScriptCall() const override;
  const std::vector<std::string>& GetJavaScriptCallHistory() override;
  void set_browser_state(BrowserState* browser_state) override;
  void AddJsResultForFunctionCall(base::Value* js_result,
                                  const std::string& function_name) override;
  void set_force_timeout(bool force_timeout) override;
  void set_can_call_function(bool can_call_function) override;
  void set_call_java_script_function_callback(
      base::RepeatingClosure callback) override;

  // WebFrameInternal:
  // If |CanCallJavaScriptFunction()| is true, the JavaScript call which would
  // be executed by a real WebFrame will be added to |java_script_calls_|.
  // Returns the value of |CanCallJavaScriptFunction()|. |content_world| is
  // stored to |last_received_content_world_|.
  bool CallJavaScriptFunctionInContentWorld(
      const std::string& name,
      const std::vector<base::Value>& parameters,
      JavaScriptContentWorld* content_world) override;
  // If |CanCallJavaScriptFunction()| is true, the JavaScript call which would
  // be executed by a real WebFrame will be added to |java_script_calls_|.
  // Returns the value of |CanCallJavaScriptFunction()|.
  // |callback| will be executed with the value passed in to
  // AddJsResultForFunctionCall() or null if no such result has been added.
  // |content_world| is stored to |last_received_content_world_|.
  bool CallJavaScriptFunctionInContentWorld(
      const std::string& name,
      const std::vector<base::Value>& parameters,
      JavaScriptContentWorld* content_world,
      base::OnceCallback<void(const base::Value*)> callback,
      base::TimeDelta timeout) override;

  ~FakeWebFrameImpl() override;

 private:
  // Map holding values to be passed in CallJavaScriptFunction() callback. Keyed
  // by JavaScript function |name| expected to be passed into
  // CallJavaScriptFunction().
  std::map<std::string, base::Value*> result_map_;
  // The frame identifier which uniquely identifies this frame across the
  // application's lifetime.
  std::string frame_id_;
  // Whether or not the receiver represents the main frame.
  bool is_main_frame_ = false;
  // The security origin associated with this frame.
  GURL security_origin_;
  // Vector holding history of all javascript handler calls made in this frame.
  // The calls are sorted with the most recent appended at the end.
  std::vector<std::string> java_script_calls_;
  // The return value of CanCallJavaScriptFunction().
  bool can_call_function_ = true;
  // When set to true, will force calls to CallJavaScriptFunction to fail with
  // timeout.
  bool force_timeout_ = false;
  BrowserState* browser_state_;

  JavaScriptContentWorld* last_received_content_world_;
  base::RepeatingClosure call_java_script_function_callback_;
};

}  // namespace web

#endif  // IOS_WEB_TEST_FAKES_FAKE_WEB_FRAME_IMPL_H_
