// 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.

#include "chrome/browser/autofill/captured_sites_test_utils.h"

#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/app_modal/javascript_app_modal_dialog.h"
#include "components/app_modal/native_app_modal_dialog.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
#include "ipc/ipc_channel_factory.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_sync_message.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/keycodes/keyboard_codes.h"

namespace {
// The maximum amount of time to wait for Chrome to finish autofilling a form.
const base::TimeDelta kAutofillActionWaitForVisualUpdateTimeout =
    base::TimeDelta::FromSeconds(3);

// The number of tries the TestRecipeReplayer should perform when executing an
// Chrome Autofill action.
// Chrome Autofill can be flaky on some real-world pages. The Captured Site
// Automation Framework will retry an autofill action a couple times before
// concluding that Chrome Autofill does not work.
const int kAutofillActionNumRetries = 5;
}  // namespace

namespace captured_sites_test_utils {

constexpr base::TimeDelta PageActivityObserver::kPaintEventCheckInterval;

std::string FilePathToUTF8(const base::FilePath::StringType& str) {
#if defined(OS_WIN)
  return base::WideToUTF8(str);
#else
  return str;
#endif
}

// PageActivityObserver -------------------------------------------------------
PageActivityObserver::PageActivityObserver(content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents) {}

PageActivityObserver::PageActivityObserver(content::RenderFrameHost* frame)
    : content::WebContentsObserver(
          content::WebContents::FromRenderFrameHost(frame)) {}

void PageActivityObserver::WaitTillPageIsIdle(
    base::TimeDelta continuous_paint_timeout) {
  base::TimeTicks finished_load_time = base::TimeTicks::Now();
  bool page_is_loading = false;
  do {
    paint_occurred_during_last_loop_ = false;
    base::RunLoop heart_beat;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, heart_beat.QuitClosure(), kPaintEventCheckInterval);
    heart_beat.Run();
    page_is_loading =
        web_contents()->IsWaitingForResponse() || web_contents()->IsLoading();
    if (page_is_loading) {
      finished_load_time = base::TimeTicks::Now();
    } else if ((base::TimeTicks::Now() - finished_load_time) >
               continuous_paint_timeout) {
      // |continuous_paint_timeout| has expired since Chrome loaded the page.
      // During this period of time, Chrome has been continuously painting
      // the page. In this case, the page is probably idle, but a bug, a
      // blinking caret or a persistent animation is making Chrome paint at
      // regular intervals. Exit.
      break;
    }
  } while (page_is_loading || paint_occurred_during_last_loop_);
}

bool PageActivityObserver::WaitForVisualUpdate(base::TimeDelta timeout) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  while (!paint_occurred_during_last_loop_) {
    base::RunLoop heart_beat;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, heart_beat.QuitClosure(), kPaintEventCheckInterval);
    heart_beat.Run();
    if ((base::TimeTicks::Now() - start_time) > timeout) {
      return false;
    }
  }
  return true;
}

void PageActivityObserver::DidCommitAndDrawCompositorFrame() {
  paint_occurred_during_last_loop_ = true;
}

// FrameObserver --------------------------------------------------------------
IFrameWaiter::IFrameWaiter(content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents),
      query_type_(URL),
      target_frame_(nullptr) {}

IFrameWaiter::~IFrameWaiter() {}

content::RenderFrameHost* IFrameWaiter::WaitForFrameMatchingName(
    const std::string& name,
    const base::TimeDelta timeout) {
  content::RenderFrameHost* frame = FrameMatchingPredicate(
      web_contents(), base::BindRepeating(&content::FrameMatchesName, name));
  if (frame) {
    return frame;
  } else {
    query_type_ = NAME;
    frame_name_ = name;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop_.QuitClosure(), timeout);
    run_loop_.Run();
    return target_frame_;
  }
}

content::RenderFrameHost* IFrameWaiter::WaitForFrameMatchingOrigin(
    const GURL origin,
    const base::TimeDelta timeout) {
  content::RenderFrameHost* frame = FrameMatchingPredicate(
      web_contents(), base::BindRepeating(&FrameHasOrigin, origin));
  if (frame) {
    return frame;
  } else {
    query_type_ = ORIGIN;
    origin_ = origin;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop_.QuitClosure(), timeout);
    run_loop_.Run();
    return target_frame_;
  }
}

content::RenderFrameHost* IFrameWaiter::WaitForFrameMatchingUrl(
    const GURL url,
    const base::TimeDelta timeout) {
  content::RenderFrameHost* frame = FrameMatchingPredicate(
      web_contents(), base::BindRepeating(&content::FrameHasSourceUrl, url));
  if (frame) {
    return frame;
  } else {
    query_type_ = URL;
    url_ = url;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop_.QuitClosure(), timeout);
    run_loop_.Run();
    return target_frame_;
  }
}

void IFrameWaiter::RenderFrameCreated(
    content::RenderFrameHost* render_frame_host) {
  if (!run_loop_.running())
    return;
  switch (query_type_) {
    case NAME:
      if (FrameMatchesName(frame_name_, render_frame_host))
        run_loop_.Quit();
      break;
    case ORIGIN:
      if (render_frame_host->GetLastCommittedURL().GetOrigin() == origin_)
        run_loop_.Quit();
      break;
    case URL:
      if (FrameHasSourceUrl(url_, render_frame_host))
        run_loop_.Quit();
      break;
    default:
      break;
  }
}

void IFrameWaiter::DidFinishLoad(content::RenderFrameHost* render_frame_host,
                                 const GURL& validated_url) {
  if (!run_loop_.running())
    return;
  switch (query_type_) {
    case ORIGIN:
      if (validated_url.GetOrigin() == origin_)
        run_loop_.Quit();
      break;
    case URL:
      if (FrameHasSourceUrl(validated_url, render_frame_host))
        run_loop_.Quit();
      break;
    default:
      break;
  }
}

void IFrameWaiter::FrameNameChanged(content::RenderFrameHost* render_frame_host,
                                    const std::string& name) {
  if (!run_loop_.running())
    return;
  switch (query_type_) {
    case NAME:
      if (FrameMatchesName(name, render_frame_host))
        run_loop_.Quit();
      break;
    default:
      break;
  }
}

bool IFrameWaiter::FrameHasOrigin(const GURL& origin,
                                  content::RenderFrameHost* frame) {
  GURL url = frame->GetLastCommittedURL();
  return (url.GetOrigin() == origin.GetOrigin());
}

// TestRecipeReplayer ---------------------------------------------------------
TestRecipeReplayer::TestRecipeReplayer(
    Browser* browser,
    TestRecipeReplayChromeFeatureActionExecutor* feature_action_executor)
    : browser_(browser), feature_action_executor_(feature_action_executor) {}

TestRecipeReplayer::~TestRecipeReplayer() {}

bool TestRecipeReplayer::ReplayTest(const base::FilePath capture_file_path,
                                    const base::FilePath recipe_file_path) {
  if (!StartWebPageReplayServer(capture_file_path))
    return false;

  return ReplayRecordedActions(recipe_file_path);
}

// static
void TestRecipeReplayer::SetUpCommandLine(base::CommandLine* command_line) {
  // Direct traffic to the Web Page Replay server.
  command_line->AppendSwitchASCII(
      network::switches::kHostResolverRules,
      base::StringPrintf(
          "MAP *:80 127.0.0.1:%d,"
          "MAP *:443 127.0.0.1:%d,"
          // Uncomment to use the live autofill prediction server.
          // "EXCLUDE clients1.google.com,"
          "EXCLUDE localhost",
          kHostHttpPort, kHostHttpsPort));
}

void TestRecipeReplayer::Setup() {
  EXPECT_TRUE(InstallWebPageReplayServerRootCert())
      << "Cannot install the root certificate "
      << "for the local web page replay server.";
  CleanupSiteData();

  // Bypass permission dialogs.
  PermissionRequestManager::FromWebContents(GetWebContents())
      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
}

void TestRecipeReplayer::Cleanup() {
  // If there are still cookies at the time the browser test shuts down,
  // Chrome's SQL lite persistent cookie store will crash.
  CleanupSiteData();
  EXPECT_TRUE(StopWebPageReplayServer())
      << "Cannot stop the local Web Page Replay server.";
  EXPECT_TRUE(RemoveWebPageReplayServerRootCert())
      << "Cannot remove the root certificate "
      << "for the local Web Page Replay server.";
}

TestRecipeReplayChromeFeatureActionExecutor*
TestRecipeReplayer::feature_action_executor() {
  return feature_action_executor_;
}

Browser* TestRecipeReplayer::browser() {
  return browser_;
}

content::WebContents* TestRecipeReplayer::GetWebContents() {
  return browser_->tab_strip_model()->GetActiveWebContents();
}

void TestRecipeReplayer::CleanupSiteData() {
  // Navigate to about:blank, then clear the browser cache.
  // Navigating to about:blank before clearing the cache ensures that
  // the cleanup is thorough and nothing is held.
  ui_test_utils::NavigateToURL(browser_, GURL(url::kAboutBlankURL));
  content::BrowsingDataRemover* remover =
      content::BrowserContext::GetBrowsingDataRemover(browser_->profile());
  content::BrowsingDataRemoverCompletionObserver completion_observer(remover);
  remover->RemoveAndReply(
      base::Time(), base::Time::Max(),
      content::BrowsingDataRemover::DATA_TYPE_COOKIES,
      content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
      &completion_observer);
  completion_observer.BlockUntilCompletion();
}

bool TestRecipeReplayer::StartWebPageReplayServer(
    const base::FilePath& capture_file_path) {
  std::vector<std::string> args;
  base::FilePath src_dir;
  if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) {
    ADD_FAILURE() << "Failed to extract the Chromium source directory!";
    return false;
  }

  args.push_back(base::StringPrintf("--http_port=%d", kHostHttpPort));
  args.push_back(base::StringPrintf("--https_port=%d", kHostHttpsPort));
  args.push_back(base::StringPrintf(
      "--inject_scripts=%s,%s",
      FilePathToUTF8(
          src_dir.AppendASCII("third_party/catapult/web_page_replay_go")
              .AppendASCII("deterministic.js")
              .value())
          .c_str(),
      FilePathToUTF8(
          src_dir
              .AppendASCII("chrome/test/data/web_page_replay_go_helper_scripts")
              .AppendASCII("automation_helper.js")
              .value())
          .c_str()));

  // Specify the capture file.
  args.push_back(base::StringPrintf(
      "%s", FilePathToUTF8(capture_file_path.value()).c_str()));
  if (!RunWebPageReplayCmd("replay", args, &web_page_replay_server_))
    return false;

  // Sleep 20 seconds to wait for the web page replay server to start.
  // TODO(crbug.com/847910): create a process std stream reader class to use the
  // process output to determine when the server is ready
  base::RunLoop wpr_launch_waiter;
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, wpr_launch_waiter.QuitClosure(),
      base::TimeDelta::FromSeconds(20));
  wpr_launch_waiter.Run();

  if (!web_page_replay_server_.IsValid()) {
    ADD_FAILURE() << "Failed to start the WPR replay server!";
    return false;
  }

  return true;
}

bool TestRecipeReplayer::StopWebPageReplayServer() {
  if (web_page_replay_server_.IsValid()) {
    if (!web_page_replay_server_.Terminate(0, true)) {
      ADD_FAILURE() << "Failed to terminate the WPR replay server!";
      return false;
    }
  }

  // The test server hasn't started, no op.
  return true;
}

bool TestRecipeReplayer::InstallWebPageReplayServerRootCert() {
  return RunWebPageReplayCmdAndWaitForExit("installroot",
                                           std::vector<std::string>());
}

bool TestRecipeReplayer::RemoveWebPageReplayServerRootCert() {
  return RunWebPageReplayCmdAndWaitForExit("removeroot",
                                           std::vector<std::string>());
}

bool TestRecipeReplayer::RunWebPageReplayCmdAndWaitForExit(
    const std::string& cmd,
    const std::vector<std::string>& args,
    const base::TimeDelta& timeout) {
  base::Process process;
  int exit_code;

  if (RunWebPageReplayCmd(cmd, args, &process) && process.IsValid() &&
      process.WaitForExitWithTimeout(timeout, &exit_code) && exit_code == 0) {
    return true;
  }

  ADD_FAILURE() << "Failed to run WPR command: '" << cmd << "'!";
  return false;
}

bool TestRecipeReplayer::RunWebPageReplayCmd(
    const std::string& cmd,
    const std::vector<std::string>& args,
    base::Process* process) {
  base::LaunchOptions options = base::LaunchOptionsForTest();
  base::FilePath exe_dir;
  if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &exe_dir)) {
    ADD_FAILURE() << "Failed to extract the Chromium source directory!";
    return false;
  }

  base::FilePath web_page_replay_binary_dir = exe_dir.AppendASCII(
      "third_party/catapult/telemetry/telemetry/internal/bin");
  options.current_directory = web_page_replay_binary_dir;

#if defined(OS_WIN)
  std::string wpr_executable_binary = "win/x86_64/wpr";
#elif defined(OS_MACOSX)
  std::string wpr_executable_binary = "mac/x86_64/wpr";
#elif defined(OS_POSIX)
  std::string wpr_executable_binary = "linux/x86_64/wpr";
#else
#error Plaform is not supported.
#endif
  base::CommandLine full_command(
      web_page_replay_binary_dir.AppendASCII(wpr_executable_binary));
  full_command.AppendArg(cmd);

  // Ask web page replay to use the custom certifcate and key files used to
  // make the web page captures.
  // The capture files used in these browser tests are also used on iOS to
  // test autofill.
  // The custom cert and key files are different from those of the offical
  // WPR releases. The custom files are made to work on iOS.
  base::FilePath src_dir;
  if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) {
    ADD_FAILURE() << "Failed to extract the Chromium source directory!";
    return false;
  }

  base::FilePath web_page_replay_support_file_dir = src_dir.AppendASCII(
      "components/test/data/autofill/web_page_replay_support_files");
  full_command.AppendArg(base::StringPrintf(
      "--https_cert_file=%s",
      FilePathToUTF8(
          web_page_replay_support_file_dir.AppendASCII("wpr_cert.pem").value())
          .c_str()));
  full_command.AppendArg(base::StringPrintf(
      "--https_key_file=%s",
      FilePathToUTF8(
          web_page_replay_support_file_dir.AppendASCII("wpr_key.pem").value())
          .c_str()));

  for (const auto arg : args)
    full_command.AppendArg(arg);

  *process = base::LaunchProcess(full_command, options);
  return true;
}

bool TestRecipeReplayer::ReplayRecordedActions(
    const base::FilePath& recipe_file_path) {
  // Read the text of the recipe file.
  base::ThreadRestrictions::SetIOAllowed(true);
  std::string json_text;
  if (!base::ReadFileToString(recipe_file_path, &json_text)) {
    ADD_FAILURE() << "Failed to read recipe file '" << recipe_file_path << "'!";
    return false;
  }

  // Convert the file text into a json object.
  std::unique_ptr<base::DictionaryValue> recipe =
      base::DictionaryValue::From(base::JSONReader().ReadToValue(json_text));
  if (!recipe) {
    ADD_FAILURE() << "Failed to deserialize json text!";
    return false;
  }

  if (!InitializeBrowserToExecuteRecipe(recipe))
    return false;

  // Iterate through and execute each action in the recipe.
  base::Value* action_list_container = recipe->FindKey("actions");
  if (!action_list_container) {
    ADD_FAILURE() << "Failed to extract action list from the recipe!";
    return false;
  }

  if (base::Value::Type::LIST != action_list_container->type()) {
    ADD_FAILURE() << "The recipe's actions object is not a list!";
    return false;
  }

  base::Value::ListStorage& action_list = action_list_container->GetList();

  for (auto it_action = action_list.begin(); it_action != action_list.end();
       ++it_action) {
    base::DictionaryValue* action;
    if (!it_action->GetAsDictionary(&action)) {
      ADD_FAILURE()
          << "Failed to extract an individual action from the recipe!";
      return false;
    }

    base::Value* type_container = action->FindKey("type");
    if (!type_container) {
      ADD_FAILURE() << "Failed to extract action type from the recipe!";
      return false;
    }
    if (base::Value::Type::STRING != type_container->type()) {
      ADD_FAILURE() << "Action type is not a string!";
      return false;
    }
    std::string type = type_container->GetString();

    if (base::CompareCaseInsensitiveASCII(type, "autofill") == 0) {
      if (!ExecuteAutofillAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "click") == 0) {
      if (!ExecuteClickAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "executeScript") == 0) {
      if (!ExecuteRunCommandAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "hover") == 0) {
      if (!ExecuteHoverAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "loadPage") == 0) {
      // Load page is an no-op action.
    } else if (base::CompareCaseInsensitiveASCII(type, "pressEnter") == 0) {
      if (!ExecutePressEnterAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "savePassword") == 0) {
      if (!ExecuteSavePasswordAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "select") == 0) {
      if (!ExecuteSelectDropdownAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "type") == 0) {
      if (!ExecuteTypeAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "typePassword") == 0) {
      if (!ExecuteTypePasswordAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "updatePassword") == 0) {
      if (!ExecuteUpdatePasswordAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "validateField") == 0) {
      if (!ExecuteValidateFieldValueAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(
                   type, "validateNoSavePasswordPrompt") == 0) {
      if (!ExecuteValidateNoSavePasswordPromptAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(
                   type, "validatePasswordSaveFallback") == 0) {
      if (!ExecuteValidateSaveFallbackAction(*action))
        return false;
    } else if (base::CompareCaseInsensitiveASCII(type, "waitFor") == 0) {
      if (!ExecuteWaitForStateAction(*action))
        return false;
    } else {
      ADD_FAILURE() << "Unrecognized action type: " << type;
    }
  }  // end foreach action

  // Dismiss the beforeUnloadDialog if the last page of the test has a
  // beforeUnload function.
  if (recipe->FindKey("dismissBeforeUnload")) {
    NavigateAwayAndDismissBeforeUnloadDialog();
  }

  return true;
}

// Functions for deserializing and executing actions from the test recipe
// JSON object.
bool TestRecipeReplayer::InitializeBrowserToExecuteRecipe(
    std::unique_ptr<base::DictionaryValue>& recipe) {
  // Setup any saved address and credit card at the start of the test.
  const base::Value* autofill_profile_container =
      recipe->FindKey("autofillProfile");

  if (autofill_profile_container &&
      !SetupSavedAutofillProfile(*autofill_profile_container))
    return false;

  // Setup any saved passwords at the start of the test.
  const base::Value* saved_password_container =
      recipe->FindKey("passwordManagerProfiles");

  if (saved_password_container &&
      !SetupSavedPasswords(*saved_password_container))
    return false;

  // Extract the starting URL from the test recipe.
  base::Value* starting_url_container = recipe->FindKey("startingURL");
  if (!starting_url_container) {
    ADD_FAILURE() << "Failed to extract the starting url from the recipe!";
    return false;
  }

  if (base::Value::Type::STRING != starting_url_container->type()) {
    ADD_FAILURE() << "Starting url is not a string!";
    return false;
  }

  std::string starting_url = starting_url_container->GetString();

  // Navigate to the starting URL, wait for the page to complete loading.
  PageActivityObserver page_activity_observer(GetWebContents());
  if (!content::ExecuteScript(GetWebContents(),
                              base::StringPrintf("window.location.href = '%s';",
                                                 starting_url.c_str()))) {
    ADD_FAILURE() << "Failed to navigate Chrome to '" << starting_url << "'!";
    return false;
  }

  page_activity_observer.WaitTillPageIsIdle();
  return true;
}

bool TestRecipeReplayer::ExecuteAutofillAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  std::vector<std::string> frame_path;
  if (!GetIFramePathFromAction(action, &frame_path))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Invoking Chrome Autofill on `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);
  // Clear the input box first, in case a previous value is there.
  // If the text input box is not clear, pressing the down key will not
  // bring up the autofill suggestion box.
  // This can happen on sites that requires the user to sign in. After
  // signing in, the site fills the form with the user's profile
  // information.
  if (!ExecuteJavaScriptOnElementByXpath(
          frame, xpath,
          "automation_helper.setInputElementValue(target, ``);")) {
    ADD_FAILURE() << "Failed to clear the input field value!";
    return false;
  }

  if (!feature_action_executor()->AutofillForm(frame, xpath, frame_path,
                                               kAutofillActionNumRetries))
    return false;
  page_activity_observer.WaitTillPageIsIdle(
      kAutofillActionWaitForVisualUpdateTimeout);
  return true;
}

bool TestRecipeReplayer::ExecuteClickAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Left mouse clicking `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);
  if (!ExecuteJavaScriptOnElementByXpath(frame, xpath, "target.click();")) {
    ADD_FAILURE() << "Failed to left click element with JavaScript!";
    return false;
  }

  page_activity_observer.WaitTillPageIsIdle();
  return true;
}

bool TestRecipeReplayer::ExecuteHoverAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Hovering over `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);

  gfx::Rect rect;
  if (!GetBoundingRectOfTargetElement(frame, xpath, &rect))
    return false;

  if (!SimulateMouseHoverAt(frame, rect.CenterPoint()))
    return false;

  if (!page_activity_observer.WaitForVisualUpdate()) {
    ADD_FAILURE() << "The page did not respond to a mouse hover action!";
    return false;
  }

  return true;
}

bool TestRecipeReplayer::ExecutePressEnterAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  std::vector<std::string> frame_path;
  if (!GetIFramePathFromAction(action, &frame_path))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Press 'Enter' on `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);
  if (!PlaceFocusOnElement(frame, xpath, frame_path))
    return false;

  ui::DomKey key = ui::DomKey::ENTER;
  ui::KeyboardCode key_code = ui::NonPrintableDomKeyToKeyboardCode(key);
  ui::DomCode code = ui::UsLayoutKeyboardCodeToDomCode(key_code);
  SimulateKeyPress(content::WebContents::FromRenderFrameHost(frame), key, code,
                   key_code, false, false, false, false);
  page_activity_observer.WaitTillPageIsIdle();
  return true;
}

bool TestRecipeReplayer::ExecuteRunCommandAction(
    const base::DictionaryValue& action) {
  // Extract the list of JavaScript commands into a vector.
  std::vector<std::string> commands;

  const base::Value* commands_list_container = action.FindKey("commands");
  if (!commands_list_container) {
    ADD_FAILURE()
        << "Failed to extract the list of commands from the run command "
        << "action!";
    return false;
  }

  if (base::Value::Type::LIST != commands_list_container->type()) {
    ADD_FAILURE() << "commands is not an array!";
    return false;
  }

  const base::Value::ListStorage& commands_list =
      commands_list_container->GetList();
  for (auto it_command = commands_list.begin();
       it_command != commands_list.end(); ++it_command) {
    if (base::Value::Type::STRING != it_command->type()) {
      ADD_FAILURE() << "command is not a string!";
      return false;
    }
    commands.push_back(it_command->GetString());
  }

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame)) {
    return false;
  }

  VLOG(1) << "Running JavaScript commands on the page.";

  // Execute the commands.
  PageActivityObserver page_activity_observer(frame);
  for (const std::string& command : commands) {
    if (!content::ExecuteScript(frame, command)) {
      ADD_FAILURE() << "Failed to execute JavaScript command `" << command
                    << "`!";
      return false;
    }
    // Wait in case the JavaScript command triggers page load or layout
    // changes.
    page_activity_observer.WaitTillPageIsIdle();
  }

  return true;
}

bool TestRecipeReplayer::ExecuteSavePasswordAction(
    const base::DictionaryValue& action) {
  VLOG(1) << "Save password.";

  if (!feature_action_executor()->SavePassword())
    return false;

  bool stored_cred;
  if (!HasChromeStoredCredential(action, &stored_cred))
    return false;

  if (!stored_cred) {
    ADD_FAILURE() << "Chrome did not save the credential!";
    return false;
  }

  return true;
}

bool TestRecipeReplayer::ExecuteSelectDropdownAction(
    const base::DictionaryValue& action) {
  const base::Value* index_container = action.FindKey("index");
  if (!index_container) {
    ADD_FAILURE()
        << "Failed to extract selection index from the select action!";
    return false;
  }

  if (base::Value::Type::INTEGER != index_container->type()) {
    ADD_FAILURE() << "Selection index is not an integer!";
    return false;
  }

  int index = index_container->GetInt();

  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Select option '" << index << "' from `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);
  if (!ExecuteJavaScriptOnElementByXpath(
          frame, xpath,
          base::StringPrintf(
              "automation_helper"
              "  .selectOptionFromDropDownElementByIndex(target, %d);",
              index_container->GetInt()))) {
    ADD_FAILURE() << "Failed to select drop down option with JavaScript!";
    return false;
  }

  page_activity_observer.WaitTillPageIsIdle();
  return true;
}

bool TestRecipeReplayer::ExecuteTypeAction(
    const base::DictionaryValue& action) {
  const base::Value* value_container = action.FindKey("value");
  if (!value_container) {
    ADD_FAILURE() << "Failed to extract value from the type action!";
    return false;
  }

  if (base::Value::Type::STRING != value_container->type()) {
    ADD_FAILURE() << "Value is not a string!";
    return false;
  }

  std::string value = value_container->GetString();

  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  VLOG(1) << "Typing '" << value << "' inside `" << xpath << "`.";
  PageActivityObserver page_activity_observer(frame);
  if (!ExecuteJavaScriptOnElementByXpath(
          frame, xpath,
          base::StringPrintf(
              "automation_helper.setInputElementValue(target, `%s`);",
              value.c_str()))) {
    ADD_FAILURE() << "Failed to type inside input element with JavaScript!";
    return false;
  }

  page_activity_observer.WaitTillPageIsIdle();
  return true;
}

bool TestRecipeReplayer::ExecuteTypePasswordAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  std::vector<std::string> frame_path;
  if (!GetIFramePathFromAction(action, &frame_path))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  const base::Value* value_container = action.FindKey("value");
  if (!value_container) {
    ADD_FAILURE() << "Failed to extract the value from the type password"
                  << " action!";
    return false;
  }

  if (base::Value::Type::STRING != value_container->type()) {
    ADD_FAILURE() << "Value is not a string!";
    return false;
  }

  std::string value = value_container->GetString();

  // Clear the password field first, in case a previous value is there.
  if (!ExecuteJavaScriptOnElementByXpath(
          frame, xpath,
          "automation_helper.setInputElementValue(target, ``);")) {
    ADD_FAILURE() << "Failed to execute JavaScript to clear the input value!";
    return false;
  }

  if (!PlaceFocusOnElement(frame, xpath, frame_path))
    return false;

  VLOG(1) << "Typing '" << value << "' inside `" << xpath << "`.";

  const char* c_array = value.c_str();
  for (size_t index = 0; index < value.size(); index++) {
    ui::DomKey key = ui::DomKey::FromCharacter(c_array[index]);
    ui::KeyboardCode key_code = ui::NonPrintableDomKeyToKeyboardCode(key);
    ui::DomCode code = ui::UsLayoutKeyboardCodeToDomCode(key_code);
    SimulateKeyPress(content::WebContents::FromRenderFrameHost(frame), key,
                     code, key_code, false, false, false, false);
  }

  return true;
}

bool TestRecipeReplayer::ExecuteUpdatePasswordAction(
    const base::DictionaryValue& action) {
  VLOG(1) << "Update password.";

  if (!feature_action_executor()->UpdatePassword())
    return false;

  bool stored_cred;
  if (!HasChromeStoredCredential(action, &stored_cred))
    return false;

  if (!stored_cred) {
    ADD_FAILURE() << "Chrome did not update the credential!";
    return false;
  }

  return true;
}

bool TestRecipeReplayer::ExecuteValidateFieldValueAction(
    const base::DictionaryValue& action) {
  std::string xpath;
  if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
    return false;

  int visibility_enum_val;
  if (!GetTargetHTMLElementVisibilityEnumFromAction(action,
                                                    &visibility_enum_val))
    return false;

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  if (!WaitForElementToBeReady(frame, xpath, visibility_enum_val))
    return false;

  const base::Value* autofill_prediction_container =
      action.FindKey("expectedAutofillType");
  if (autofill_prediction_container) {
    if (base::Value::Type::STRING != autofill_prediction_container->type()) {
      ADD_FAILURE() << "Autofill prediction is not a string!";
      return false;
    }

    // If we are validating the value of a Chrome autofilled field, print the
    // Chrome Autofill's field annotation for debugging purpose.
    std::string title;
    if (GetElementProperty(frame, xpath, "return target.getAttribute('title');",
                           &title)) {
      VLOG(1) << title;
    } else {
      ADD_FAILURE()
          << "Failed to obtain the field's Chrome Autofill annotation!";
    }

    std::string expected_autofill_prediction_type =
        autofill_prediction_container->GetString();
    VLOG(1) << "Checking the field `" << xpath << "` has the autofill type '"
            << expected_autofill_prediction_type << "'";
    ExpectElementPropertyEquals(
        frame, xpath.c_str(),
        "return target.getAttribute('autofill-prediction');",
        expected_autofill_prediction_type, true);
  }

  const base::Value* expected_value_container = action.FindKey("expectedValue");
  if (!expected_value_container) {
    ADD_FAILURE() << "Failed to extract the expected value field from the "
                     "validate field value action!";
    return false;
  }

  if (base::Value::Type::STRING != expected_value_container->type()) {
    ADD_FAILURE() << "Expected value is not a string!";
    return false;
  }

  std::string expected_value = expected_value_container->GetString();

  VLOG(1) << "Checking the field `" << xpath << "`.";
  ExpectElementPropertyEquals(frame, xpath.c_str(), "return target.value;",
                              expected_value);
  return true;
}

bool TestRecipeReplayer::ExecuteValidateNoSavePasswordPromptAction(
    const base::DictionaryValue& action) {
  VLOG(1) << "Verify that the page hasn't shown a save password prompt.";
  EXPECT_FALSE(feature_action_executor()->HasChromeShownSavePasswordPrompt());
  return true;
}

bool TestRecipeReplayer::ExecuteValidateSaveFallbackAction(
    const base::DictionaryValue& action) {
  VLOG(1) << "Verify that Chrome shows the save fallback icon in the omnibox.";
  EXPECT_TRUE(feature_action_executor()->WaitForSaveFallback());
  return true;
}

bool TestRecipeReplayer::ExecuteWaitForStateAction(
    const base::DictionaryValue& action) {
  // Extract the list of JavaScript assertions into a vector.
  std::vector<std::string> state_assertions;
  const base::Value* assertions_list_container = action.FindKey("assertions");
  if (!assertions_list_container) {
    ADD_FAILURE()
        << "Failed to extract assertions from the wait for state action!";
    return false;
  }

  if (base::Value::Type::LIST != assertions_list_container->type()) {
    ADD_FAILURE() << "Assertions is not a list!";
    return false;
  }

  const base::Value::ListStorage& assertions_list =
      assertions_list_container->GetList();
  for (const base::Value& assertion : assertions_list) {
    if (base::Value::Type::STRING != assertion.type()) {
      ADD_FAILURE() << "Assertion is not a string!";
      return false;
    }

    state_assertions.push_back(assertion.GetString());
  }

  content::RenderFrameHost* frame;
  if (!GetTargetFrameFromAction(action, &frame))
    return false;

  VLOG(1) << "Waiting for page to reach a state.";

  // Wait for all of the assertions to become true on the current page.
  return WaitForStateChange(frame, state_assertions, default_action_timeout);
}

bool TestRecipeReplayer::GetTargetHTMLElementXpathFromAction(
    const base::DictionaryValue& action,
    std::string* xpath) {
  xpath->clear();
  const base::Value* xpath_container = action.FindKey("selector");
  if (!xpath_container) {
    ADD_FAILURE() << "Failed to extract the xpath selector from action!";
    return false;
  }

  if (base::Value::Type::STRING != xpath_container->type()) {
    ADD_FAILURE() << "Xpath selector is not a string!";
    return false;
  }

  *xpath = xpath_container->GetString();
  return true;
}

bool TestRecipeReplayer::GetTargetHTMLElementVisibilityEnumFromAction(
    const base::DictionaryValue& action,
    int* visibility_enum_val) {
  const base::Value* visibility_container = action.FindKey("visibility");
  if (!visibility_container) {
    // By default, set the visibility to (visible | enabled | on_top), as
    // defined in
    // chrome/test/data/web_page_replay_go_helper_scripts/automation_helper.js
    *visibility_enum_val = 7;
    return true;
  }

  if (base::Value::Type::INTEGER != visibility_container->type()) {
    ADD_FAILURE() << "visibility property is not an integer!";
    return false;
  }

  *visibility_enum_val = visibility_container->GetInt();
  return true;
}

bool TestRecipeReplayer::GetTargetFrameFromAction(
    const base::DictionaryValue& action,
    content::RenderFrameHost** frame) {
  const base::Value* iframe_container = action.FindKey("context");
  if (!iframe_container) {
    ADD_FAILURE() << "Failed to extract the iframe context from action!";
    return false;
  }

  const base::DictionaryValue* iframe;
  if (!iframe_container->GetAsDictionary(&iframe)) {
    ADD_FAILURE() << "Failed to extract the iframe context object!";
    return false;
  }

  const base::Value* is_iframe_container = iframe->FindKey("isIframe");
  if (!is_iframe_container) {
    ADD_FAILURE()
        << "Failed to extract the isIframe field from the iframe context!";
    return false;
  }

  if (base::Value::Type::BOOLEAN != is_iframe_container->type()) {
    ADD_FAILURE() << "isIframe is not a boolean value!";
    return false;
  }

  if (!is_iframe_container->GetBool()) {
    *frame = GetWebContents()->GetMainFrame();
    return true;
  }

  const base::Value* frame_name_container =
      iframe->FindPath({"browserTest", "name"});
  const base::Value* frame_origin_container =
      iframe->FindPath({"browserTest", "origin"});
  const base::Value* frame_url_container =
      iframe->FindPath({"browserTest", "url"});
  IFrameWaiter iframe_waiter(GetWebContents());

  if (frame_name_container != nullptr &&
      base::Value::Type::STRING != frame_name_container->type()) {
    ADD_FAILURE() << "Iframe name is not a string!";
    return false;
  }

  if (frame_origin_container != nullptr &&
      base::Value::Type::STRING != frame_origin_container->type()) {
    ADD_FAILURE() << "Iframe origin is not a string!";
    return false;
  }

  if (frame_url_container != nullptr &&
      base::Value::Type::STRING != frame_url_container->type()) {
    ADD_FAILURE() << "Iframe url is not a string!";
    return false;
  }

  if (frame_name_container != nullptr) {
    std::string frame_name = frame_name_container->GetString();
    *frame = iframe_waiter.WaitForFrameMatchingName(frame_name);
  } else if (frame_origin_container != nullptr) {
    std::string frame_origin = frame_origin_container->GetString();
    *frame = iframe_waiter.WaitForFrameMatchingOrigin(GURL(frame_origin));
  } else if (frame_url_container != nullptr) {
    std::string frame_url = frame_url_container->GetString();
    *frame = iframe_waiter.WaitForFrameMatchingUrl(GURL(frame_url));
  } else {
    ADD_FAILURE() << "The recipe does not specify a way to find the iframe!";
  }

  if (frame == nullptr) {
    ADD_FAILURE() << "Failed to find iframe!";
    return false;
  }

  return true;
}

bool TestRecipeReplayer::GetIFramePathFromAction(
    const base::DictionaryValue& action,
    std::vector<std::string>* iframe_path) {
  *iframe_path = std::vector<std::string>();

  const base::Value* iframe_container = action.FindKey("context");
  if (!iframe_container) {
    ADD_FAILURE() << "Failed to extract the iframe context from action!";
    return false;
  }

  const base::DictionaryValue* iframe;
  if (!iframe_container->GetAsDictionary(&iframe)) {
    ADD_FAILURE() << "Failed to extract the iframe context object!";
    return false;
  }

  const base::Value* iframe_path_container = iframe->FindKey("path");
  if (!iframe_path_container) {
    // If the action does not have a path container, it would mean that:
    // 1. The target frame is the top level frame.
    // 2. The target frame is an iframe, but it is the top-level frame in its
    //    rendering process.
    return true;
  }

  if (base::Value::Type::LIST != iframe_path_container->type()) {
    ADD_FAILURE() << "The action's iframe path is not a list!";
    return false;
  }

  const base::Value::ListStorage& iframe_xpath_list =
      iframe_path_container->GetList();
  for (auto it_xpath = iframe_xpath_list.begin();
       it_xpath != iframe_xpath_list.end(); ++it_xpath) {
    std::string xpath;
    if (!it_xpath->GetAsString(&xpath)) {
      ADD_FAILURE() << "Failed to extract the iframe xpath from action!";
      return false;
    }
    iframe_path->push_back(xpath);
  }

  return true;
}

bool TestRecipeReplayer::GetIFrameOffsetFromIFramePath(
    content::RenderFrameHost* frame,
    const std::vector<std::string>& iframe_path,
    gfx::Vector2d* offset) {
  *offset = gfx::Vector2d(0, 0);

  for (auto it_xpath = iframe_path.begin(); it_xpath != iframe_path.end();
       it_xpath++) {
    content::RenderFrameHost* parent_frame = frame->GetParent();
    if (parent_frame == nullptr) {
      ADD_FAILURE() << "Trying to iterate past the top level frame!";
      return false;
    }

    gfx::Rect rect;
    if (!GetBoundingRectOfTargetElement(parent_frame, *it_xpath, &rect)) {
      ADD_FAILURE() << "Failed to extract position of iframe with xpath `"
                    << *it_xpath << "`!";
      return false;
    }

    *offset += rect.OffsetFromOrigin();
    frame = parent_frame;
  }

  return true;
}

bool TestRecipeReplayer::WaitForElementToBeReady(
    content::RenderFrameHost* frame,
    const std::string& xpath,
    const int visibility_enum_val) {
  std::vector<std::string> state_assertions;
  state_assertions.push_back(base::StringPrintf(
      "return automation_helper.isElementWithXpathReady(`%s`, %d);",
      xpath.c_str(), visibility_enum_val));
  return WaitForStateChange(frame, state_assertions, default_action_timeout);
}

bool TestRecipeReplayer::WaitForStateChange(
    content::RenderFrameHost* frame,
    const std::vector<std::string>& state_assertions,
    const base::TimeDelta& timeout) {
  const base::TimeTicks start_time = base::TimeTicks::Now();
  PageActivityObserver page_activity_observer(
      content::WebContents::FromRenderFrameHost(frame));
  while (!AllAssertionsPassed(frame, state_assertions)) {
    if (base::TimeTicks::Now() - start_time > timeout) {
      ADD_FAILURE() << "State change hasn't completed within timeout.";
      return false;
    }
    page_activity_observer.WaitTillPageIsIdle();
  }
  return true;
}

bool TestRecipeReplayer::AllAssertionsPassed(
    const content::ToRenderFrameHost& frame,
    const std::vector<std::string>& assertions) {
  for (const std::string& assertion : assertions) {
    bool assertion_passed = false;
    EXPECT_TRUE(ExecuteScriptAndExtractBool(
        frame,
        base::StringPrintf("window.domAutomationController.send("
                           "    (function() {"
                           "      try {"
                           "        %s"
                           "      } catch (ex) {}"
                           "      return false;"
                           "    })());",
                           assertion.c_str()),
        &assertion_passed));
    if (!assertion_passed) {
      VLOG(1) << "'" << assertion << "' failed!";
      return false;
    }
  }
  return true;
}

bool TestRecipeReplayer::ExecuteJavaScriptOnElementByXpath(
    const content::ToRenderFrameHost& frame,
    const std::string& element_xpath,
    const std::string& execute_function_body,
    const base::TimeDelta& time_to_wait_for_element) {
  std::string js(base::StringPrintf(
      "try {"
      "  var element = automation_helper.getElementByXpath(`%s`);"
      "  (function(target) { %s })(element);"
      "} catch(ex) {}",
      element_xpath.c_str(), execute_function_body.c_str()));
  return ExecuteScript(frame, js);
}

bool TestRecipeReplayer::GetElementProperty(
    const content::ToRenderFrameHost& frame,
    const std::string& element_xpath,
    const std::string& get_property_function_body,
    std::string* property) {
  return ExecuteScriptAndExtractString(
      frame,
      base::StringPrintf(
          "window.domAutomationController.send("
          "    (function() {"
          "      try {"
          "        var element = function() {"
          "          return automation_helper.getElementByXpath(`%s`);"
          "        }();"
          "        return function(target){%s}(element);"
          "      } catch (ex) {}"
          "      return 'Exception encountered';"
          "    })());",
          element_xpath.c_str(), get_property_function_body.c_str()),
      property);
}

bool TestRecipeReplayer::ExpectElementPropertyEquals(
    const content::ToRenderFrameHost& frame,
    const std::string& element_xpath,
    const std::string& get_property_function_body,
    const std::string& expected_value,
    bool ignoreCase) {
  std::string value;
  if (!GetElementProperty(frame, element_xpath, get_property_function_body,
                          &value)) {
    ADD_FAILURE() << "Failed to extract element property! " << element_xpath
                  << ", " << get_property_function_body;
    return false;
  }

  if (ignoreCase) {
    EXPECT_TRUE(base::EqualsCaseInsensitiveASCII(expected_value, value))
        << "Field xpath: `" << element_xpath << "`, "
        << "Expected: " << expected_value << ", actual: " << value;
  } else {
    EXPECT_EQ(expected_value, value)
        << "Field xpath: `" << element_xpath << "`, ";
  }
  return true;
}

bool TestRecipeReplayer::PlaceFocusOnElement(
    content::RenderFrameHost* frame,
    const std::string& element_xpath,
    const std::vector<std::string> iframe_path) {
  const std::string focus_on_target_field_js(base::StringPrintf(
      "try {"
      "  function onFocusHandler(event) {"
      "    event.target.removeEventListener(event.type, arguments.callee);"
      "    window.domAutomationController.send(true);"
      "  }"
      "  const element = automation_helper.getElementByXpath(`%s`);"
      "  element.scrollIntoView({"
      "    block: 'center', inline: 'center'});"
      "  if (document.activeElement === element) {"
      "    window.domAutomationController.send(true);"
      "  } else {"
      "    element.addEventListener('focus', onFocusHandler);"
      "    element.focus();"
      "  }"
      "  setTimeout(() => {"
      "    element.removeEventListener('focus', onFocusHandler);"
      "    window.domAutomationController.send(false);"
      "  }, 1000);"
      "} catch(ex) {"
      "  window.domAutomationController.send(false);"
      "}",
      element_xpath.c_str()));

  bool focused = false;
  if (!ExecuteScriptAndExtractBool(frame, focus_on_target_field_js, &focused)) {
    ADD_FAILURE() << "Failed to place focus on the element with JavaScript!";
    return false;
  }

  if (focused) {
    return true;
  } else {
    // Failing focusing on an element through script, use the less preferred
    // method of left mouse clicking the element.
    gfx::Rect rect;
    if (!GetBoundingRectOfTargetElement(frame, element_xpath, iframe_path,
                                        &rect))
      return false;

    return SimulateLeftMouseClickAt(frame, rect.CenterPoint());
  }
}

bool TestRecipeReplayer::GetBoundingRectOfTargetElement(
    content::RenderFrameHost* frame,
    const std::string& target_element_xpath,
    gfx::Rect* output_rect) {
  std::string rect_str;
  const std::string get_element_bounding_rect_js(base::StringPrintf(
      "window.domAutomationController.send("
      "    (function() {"
      "       try {"
      "         const element = automation_helper.getElementByXpath(`%s`);"
      "         const rect = element.getBoundingClientRect();"
      "         return Math.round(rect.left) + ',' + "
      "                Math.round(rect.top) + ',' + "
      "                Math.round(rect.width) + ',' + "
      "                Math.round(rect.height);"
      "       } catch(ex) {}"
      "       return '';"
      "    })());",
      target_element_xpath.c_str()));

  if (!content::ExecuteScriptAndExtractString(
          frame, get_element_bounding_rect_js, &rect_str)) {
    ADD_FAILURE()
        << "Failed to run script to extract target element's bounding rect!";
    return false;
  }

  if (rect_str.empty()) {
    ADD_FAILURE() << "Failed to extract target element's bounding rect!";
    return false;
  }

  // Parse the bounding rect string to extract the element coordinates.
  std::istringstream rect_stream(rect_str);
  std::string token;
  if (!std::getline(rect_stream, token, ',')) {
    ADD_FAILURE() << "Failed to extract target element's x coordinate from "
                  << "the string `" << rect_str << "`!";
    return false;
  }

  output_rect->set_x(std::stoi(token));

  if (!std::getline(rect_stream, token, ',')) {
    ADD_FAILURE() << "Failed to extract target element's y coordinate from "
                  << "the string `" << rect_str << "`!";
    return false;
  }

  output_rect->set_y(std::stoi(token));

  if (!std::getline(rect_stream, token, ',')) {
    ADD_FAILURE() << "Failed to extract target element's width from "
                  << "the string `" << rect_str << "`!";
    return false;
  }

  output_rect->set_width(std::stoi(token));

  if (!std::getline(rect_stream, token, ',')) {
    ADD_FAILURE() << "Failed to extract target element's height from "
                  << "the string `" << rect_str << "`!";
    return false;
  }

  output_rect->set_height(std::stoi(token));

  return true;
}

bool TestRecipeReplayer::GetBoundingRectOfTargetElement(
    content::RenderFrameHost* frame,
    const std::string& target_element_xpath,
    const std::vector<std::string> iframe_path,
    gfx::Rect* output_rect) {
  gfx::Vector2d offset;
  if (!GetIFrameOffsetFromIFramePath(frame, iframe_path, &offset))
    return false;
  if (!GetBoundingRectOfTargetElement(frame, target_element_xpath, output_rect))
    return false;

  *output_rect += offset;
  return true;
}

bool TestRecipeReplayer::SimulateLeftMouseClickAt(
    content::RenderFrameHost* render_frame_host,
    const gfx::Point& point) {
  content::RenderWidgetHostView* view = render_frame_host->GetView();
  if (!SimulateMouseHoverAt(render_frame_host, point))
    return false;

  blink::WebMouseEvent mouse_event(
      blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  mouse_event.button = blink::WebMouseEvent::Button::kLeft;
  mouse_event.SetPositionInWidget(point.x(), point.y());

  // Mac needs positionInScreen for events to plugins.
  gfx::Rect offset =
      content::WebContents::FromRenderFrameHost(render_frame_host)
          ->GetContainerBounds();
  mouse_event.SetPositionInScreen(point.x() + offset.x(),
                                  point.y() + offset.y());
  mouse_event.click_count = 1;
  content::RenderWidgetHost* widget = view->GetRenderWidgetHost();

  widget->ForwardMouseEvent(mouse_event);
  mouse_event.SetType(blink::WebInputEvent::kMouseUp);
  widget->ForwardMouseEvent(mouse_event);
  return true;
}

bool TestRecipeReplayer::SimulateMouseHoverAt(
    content::RenderFrameHost* render_frame_host,
    const gfx::Point& point) {
  gfx::Rect offset =
      content::WebContents::FromRenderFrameHost(render_frame_host)
          ->GetContainerBounds();
  gfx::Point reset_mouse =
      gfx::Point(offset.x() + point.x(), offset.y() + point.y());
  if (!ui_test_utils::SendMouseMoveSync(reset_mouse)) {
    ADD_FAILURE() << "Failed to position the mouse!";
    return false;
  }
  return true;
}

void TestRecipeReplayer::NavigateAwayAndDismissBeforeUnloadDialog() {
  content::PrepContentsForBeforeUnloadTest(GetWebContents());
  ui_test_utils::NavigateToURLWithDisposition(
      browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::CURRENT_TAB,
      ui_test_utils::BROWSER_TEST_NONE);
  app_modal::JavaScriptAppModalDialog* alert =
      ui_test_utils::WaitForAppModalDialog();
  alert->native_dialog()->AcceptAppModalDialog();
}

bool TestRecipeReplayer::HasChromeStoredCredential(
    const base::DictionaryValue& action,
    bool* stored_cred) {
  const base::Value* orgin_container = action.FindKey("origin");

  if (!orgin_container) {
    ADD_FAILURE() << "Failed to extract the origin from the action!";
    return false;
  }

  if (base::Value::Type::STRING != orgin_container->type()) {
    ADD_FAILURE() << "Origin is not a string!";
    return false;
  }

  const base::Value* user_name_container = action.FindKey("userName");

  if (!user_name_container) {
    ADD_FAILURE() << "Failed to extract the user name from the action!";
    return false;
  }

  if (base::Value::Type::STRING != user_name_container->type()) {
    ADD_FAILURE() << "User name is not a string!";
    return false;
  }

  const base::Value* password_container = action.FindKey("password");

  if (!password_container) {
    ADD_FAILURE() << "Failed to extract the password from the action!";
    return false;
  }

  if (base::Value::Type::STRING != password_container->type()) {
    ADD_FAILURE() << "Password is not a string!";
    return false;
  }

  *stored_cred = feature_action_executor()->HasChromeStoredCredential(
      orgin_container->GetString(), user_name_container->GetString(),
      password_container->GetString());

  return true;
}

bool TestRecipeReplayer::SetupSavedAutofillProfile(
    const base::Value& saved_autofill_profile_container) {
  if (base::Value::Type::LIST != saved_autofill_profile_container.type()) {
    ADD_FAILURE() << "Save Autofill Profile is not a list!";
    return false;
  }

  const base::Value::ListStorage& profile_entries_list =
      saved_autofill_profile_container.GetList();
  for (auto it_entry = profile_entries_list.begin();
       it_entry != profile_entries_list.end(); ++it_entry) {
    const base::DictionaryValue* entry;
    if (!it_entry->GetAsDictionary(&entry)) {
      ADD_FAILURE() << "Failed to extract an entry!";
      return false;
    }

    const base::Value* type_container = entry->FindKey("type");
    if (base::Value::Type::STRING != type_container->type()) {
      ADD_FAILURE() << "Type is not a string!";
      return false;
    }
    const std::string type = type_container->GetString();

    const base::Value* value_container = entry->FindKey("value");
    if (base::Value::Type::STRING != value_container->type()) {
      ADD_FAILURE() << "Value is not a string!";
      return false;
    }
    const std::string value = value_container->GetString();

    if (!feature_action_executor()->AddAutofillProfileInfo(type, value)) {
      return false;
    }
  }

  // Skip this step if autofill profile is empty.
  // Only Autofill Captured Sites test recipes will have non-empty autofill
  // profiles. Recipes for other captured sites tests will have empty autofill
  // profiles. This block prevents these other tests from failing because
  // the test feature action executor does not know how to setup the autofill
  // profile.
  if (profile_entries_list.size() == 0) {
    return true;
  }

  return feature_action_executor()->SetupAutofillProfile();
}

bool TestRecipeReplayer::SetupSavedPasswords(
    const base::Value& saved_password_list_container) {
  if (base::Value::Type::LIST != saved_password_list_container.type()) {
    ADD_FAILURE() << "Saved Password List is not a list!";
    return false;
  }

  const base::Value::ListStorage& saved_password_list =
      saved_password_list_container.GetList();
  for (auto it_password = saved_password_list.begin();
       it_password != saved_password_list.end(); ++it_password) {
    const base::DictionaryValue* cred;
    if (!it_password->GetAsDictionary(&cred)) {
      ADD_FAILURE() << "Failed to extract a saved password!";
      return false;
    }

    const base::Value* origin_container = cred->FindKey("website");
    if (base::Value::Type::STRING != origin_container->type()) {
      ADD_FAILURE() << "Website is not a string!";
      return false;
    }
    const std::string origin = origin_container->GetString();

    const base::Value* username_container = cred->FindKey("username");
    if (base::Value::Type::STRING != username_container->type()) {
      ADD_FAILURE() << "User name is not a string!";
      return false;
    }
    const std::string username = username_container->GetString();

    const base::Value* password_container = cred->FindKey("password");
    if (base::Value::Type::STRING != password_container->type()) {
      ADD_FAILURE() << "User name is not a string!";
      return false;
    }
    const std::string password = password_container->GetString();

    if (!feature_action_executor()->AddCredential(origin, username, password)) {
      return false;
    }
  }

  return true;
}

// TestRecipeReplayChromeFeatureActionExecutor --------------------------------
TestRecipeReplayChromeFeatureActionExecutor::
    TestRecipeReplayChromeFeatureActionExecutor() {}
TestRecipeReplayChromeFeatureActionExecutor::
    ~TestRecipeReplayChromeFeatureActionExecutor() {}

bool TestRecipeReplayChromeFeatureActionExecutor::AutofillForm(
    content::RenderFrameHost* frame,
    const std::string& focus_element_css_selector,
    const std::vector<std::string> iframe_path,
    const int attempts) {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor::AutofillForm "
                   "is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::AddAutofillProfileInfo(
    const std::string& field_type,
    const std::string& field_value) {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::AddAutofillProfileInfo is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::SetupAutofillProfile() {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::SetupAutofillProfile is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::AddCredential(
    const std::string& origin,
    const std::string& username,
    const std::string& password) {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor::AddCredential"
                   " is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::SavePassword() {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor::SavePassword"
                   " is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::UpdatePassword() {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::UpdatePassword is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::WaitForSaveFallback() {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::WaitForSaveFallback is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::
    HasChromeShownSavePasswordPrompt() {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::HasChromeShownSavePasswordPrompt is not implemented!";
  return false;
}

bool TestRecipeReplayChromeFeatureActionExecutor::HasChromeStoredCredential(
    const std::string& origin,
    const std::string& username,
    const std::string& password) {
  ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
                   "::HasChromeStoredCredential is not implemented!";
  return false;
}

}  // namespace captured_sites_test_utils
