void ActionsCommandHandler::ExecuteInternal(
    const IECommandExecutor& executor,
    const ParametersMap& command_parameters,
    Response* response) {
  BrowserHandle browser_wrapper;
  int status_code = executor.GetCurrentBrowser(&browser_wrapper);
  if (status_code != WD_SUCCESS) {
    response->SetErrorResponse(status_code, "Unable to get current browser");
    return;
  }
  ParametersMap::const_iterator actions_parameter_iterator = command_parameters.find("actions");
  if (actions_parameter_iterator == command_parameters.end()) {
    response->SetErrorResponse(ERROR_INVALID_ARGUMENT, "Missing parameter: actions");
    return;
  }
  if (!actions_parameter_iterator->second.isArray()) {
    response->SetErrorResponse(ERROR_INVALID_ARGUMENT, "Actions value is not an array");
    return;
  }
  std::string error_info = "";
  status_code = executor.input_manager()->PerformInputSequence(browser_wrapper,
                                                               actions_parameter_iterator->second,
                                                               &error_info);
  if (status_code != WD_SUCCESS) {
    if (status_code == EMOVETARGETOUTOFBOUNDS) {
      response->SetErrorResponse(status_code, error_info);
    } else {
      response->SetErrorResponse(status_code, "Unexpected error performing action sequence.");
    }
    return;
  }
  response->SetSuccessResponse(Json::Value::null);
}
void ClickElementCommandHandler::ExecuteInternal(const IECommandExecutor& executor,
                      const ParametersMap& command_parameters,
                      Response* response) {
  ParametersMap::const_iterator id_parameter_iterator = command_parameters.find("id");
  if (id_parameter_iterator == command_parameters.end()) {
    response->SetErrorResponse(ERROR_INVALID_ARGUMENT, "Missing parameter in URL: id");
    return;
  } else {
    int status_code = WD_SUCCESS;
    std::string element_id = id_parameter_iterator->second.asString();

    BrowserHandle browser_wrapper;
    status_code = executor.GetCurrentBrowser(&browser_wrapper);
    if (status_code != WD_SUCCESS) {
      response->SetErrorResponse(status_code, "Unable to get browser");
      return;
    }

    ElementHandle element_wrapper;
    status_code = this->GetElement(executor, element_id, &element_wrapper);
    if (status_code == WD_SUCCESS) {
      if (executor.input_manager()->enable_native_events()) {
        if (this->IsOptionElement(element_wrapper)) {
          std::string option_click_error = "";
          status_code = this->ExecuteAtom(this->GetClickAtom(),
                                          browser_wrapper,
                                          element_wrapper,
                                          &option_click_error);
          if (status_code != WD_SUCCESS) {
            response->SetErrorResponse(status_code, "Cannot click on option element. " + option_click_error);
            return;
          }
        } else {
          Json::Value move_action;
          move_action["type"] = "pointerMove";
          move_action["origin"] = element_wrapper->ConvertToJson();
          move_action["duration"] = 0;

          Json::Value down_action;
          down_action["type"] = "pointerDown";
          down_action["button"] = 0;
            
          Json::Value up_action;
          up_action["type"] = "pointerUp";
          up_action["button"] = 0;

          Json::Value action_array(Json::arrayValue);
          action_array.append(move_action);
          action_array.append(down_action);
          action_array.append(up_action);
            
          // Check to make sure we're not within the double-click time for this element
          // since the last click.
          int double_click_time = ::GetDoubleClickTime();

          Json::Value parameters_value;
          parameters_value["pointerType"] = "mouse";

          Json::Value value;
          value["type"] = "pointer";
          value["id"] = "click action mouse";
          value["parameters"] = parameters_value;
          value["actions"] = action_array;

          Json::Value actions(Json::arrayValue);
          actions.append(value);

          IECommandExecutor& mutable_executor = const_cast<IECommandExecutor&>(executor);
          status_code = mutable_executor.input_manager()->PerformInputSequence(browser_wrapper, actions);
          browser_wrapper->set_wait_required(true);
          ::Sleep(double_click_time + 10);
          if (status_code != WD_SUCCESS) {
            if (status_code == EELEMENTCLICKPOINTNOTSCROLLED) {
              // We hard-code the error code here to be "Element not visible"
              // to maintain compatibility with previous behavior.
              response->SetErrorResponse(ERROR_ELEMENT_NOT_INTERACTABLE, "The point at which the driver is attempting to click on the element was not scrolled into the viewport.");
            } else {
              response->SetErrorResponse(status_code, "Cannot click on element");
            }
            return;
          }
        }
      } else {
        bool displayed;
        status_code = element_wrapper->IsDisplayed(true, &displayed);
        if (status_code != WD_SUCCESS) {
          response->SetErrorResponse(status_code, "Unable to determine element is displayed");
          return;
        } 

        if (!displayed) {
          response->SetErrorResponse(ERROR_ELEMENT_NOT_INTERACTABLE, "Element is not displayed");
          return;
        }
        std::string synthetic_click_error = "";
        status_code = this->ExecuteAtom(this->GetSyntheticClickAtom(),
                                        browser_wrapper,
                                        element_wrapper,
                                        &synthetic_click_error);
        if (status_code != WD_SUCCESS) {
          // This is a hack. We should change this when we can get proper error
          // codes back from the atoms. We'll assume the script failed because
          // the element isn't visible.
          response->SetErrorResponse(ERROR_ELEMENT_NOT_INTERACTABLE,
              "Received a JavaScript error attempting to click on the element using synthetic events. We are assuming this is because the element isn't displayed, but it may be due to other problems with executing JavaScript.");
          return;
        }
        browser_wrapper->set_wait_required(true);
      }
    } else if (status_code == ENOSUCHELEMENT) {
      response->SetErrorResponse(ERROR_NO_SUCH_ELEMENT, "Invalid internal element ID requested: " + element_id);
      return;
    } else {
      response->SetErrorResponse(status_code, "Element is no longer valid");
      return;
    }

    response->SetSuccessResponse(Json::Value::null);
  }
}