blob: d2d2253cb9d31ce432d44f4750b506c46d082957 [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.
#include "extensions/renderer/bindings/api_response_validator.h"
#include "extensions/renderer/bindings/api_binding_util.h"
#include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/bindings/api_type_reference_map.h"
namespace extensions {
namespace {
APIResponseValidator::TestHandler::HandlerMethod*
g_failure_handler_for_testing = nullptr;
} // namespace
APIResponseValidator::TestHandler::TestHandler(HandlerMethod method)
: method_(method) {
DCHECK(!g_failure_handler_for_testing)
<< "Only one TestHandler is allowed at a time.";
g_failure_handler_for_testing = &method_;
}
APIResponseValidator::TestHandler::~TestHandler() {
DCHECK_EQ(&method_, g_failure_handler_for_testing);
g_failure_handler_for_testing = nullptr;
}
APIResponseValidator::APIResponseValidator(const APITypeReferenceMap* type_refs)
: type_refs_(type_refs) {}
APIResponseValidator::~APIResponseValidator() = default;
void APIResponseValidator::ValidateResponse(
v8::Local<v8::Context> context,
const std::string& method_name,
const std::vector<v8::Local<v8::Value>> response_arguments,
const std::string& api_error,
CallbackType callback_type) {
DCHECK(binding::IsResponseValidationEnabled());
// If the callback is API-provided, the response can't be validated against
// the expected schema because the callback may modify the arguments.
if (callback_type == CallbackType::kAPIProvided)
return;
// If the call failed, there are no expected arguments.
if (!api_error.empty()) {
// TODO(devlin): It would be really nice to validate that
// |response_arguments| is empty here, but some functions both set an error
// and supply arguments.
return;
}
const APISignature* signature = type_refs_->GetCallbackSignature(method_name);
// If there's no corresponding signature, don't validate. This can
// legitimately happen with APIs that create custom requests.
if (!signature)
return;
std::string error;
if (signature->ValidateResponse(context, response_arguments, *type_refs_,
&error)) {
// Response was valid.
return;
}
// The response did not match the expected schema.
if (g_failure_handler_for_testing) {
g_failure_handler_for_testing->Run(method_name, error);
} else {
NOTREACHED() << "Error validating response to `" << method_name
<< "`: " << error;
}
}
} // namespace extensions