blob: 6856695e18bf9b9dc146f02f8ec741231b71d252 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/renderer/api/feedback_private_hooks_delegate.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/mojom/context_type.mojom.h"
#include "extensions/common/mojom/frame.mojom.h"
#include "extensions/renderer/bindings/api_binding_test_util.h"
#include "extensions/renderer/native_extension_bindings_system.h"
#include "extensions/renderer/native_extension_bindings_system_test_base.h"
#include "extensions/renderer/script_context.h"
namespace extensions {
using FeedbackPrivateHooksDelegateTest = NativeExtensionBindingsSystemUnittest;
// Tests that the result modifier used in the sendFeedback handle request hook
// results in callback-based calls getting a response with multiple arguments
// and promise-based calls getting a response with a single object.
// TODO(crbug.com/40243802): Disabled on ASAN due to bot failures caused by an
// underlying gin issue.
#if defined(ADDRESS_SANITIZER)
#define MAYBE_SendFeedback DISABLED_SendFeedback
#else
#define MAYBE_SendFeedback SendFeedback
#endif
TEST_F(FeedbackPrivateHooksDelegateTest, MAYBE_SendFeedback) {
// Initialize bindings system.
bindings_system()->api_system()->RegisterHooksDelegate(
"feedbackPrivate", std::make_unique<FeedbackPrivateHooksDelegate>());
// The feedbackPrivate API is restricted to allowlisted extensions and WebUI,
// so create a WebUI context to test on.
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = MainContext();
ScriptContext* script_context =
CreateScriptContext(context, nullptr, mojom::ContextType::kWebUi);
script_context->set_url(GURL("chrome://feedback"));
bindings_system()->UpdateBindingsForContext(script_context);
constexpr char kFakeAPIResponse[] =
R"([{"status": "success", "landingPageType": "normal"}])";
// Calling sendFeedback without a callback should return a promise that gets
// fulfilled with an object with the results as properties on it.
{
v8::Local<v8::Function> func = FunctionFromString(
context,
"(function() { return "
"chrome.feedbackPrivate.sendFeedback({description: 'foo'}); })");
v8::Local<v8::Value> result = RunFunction(func, context, 0, nullptr);
v8::Local<v8::Promise> promise;
ASSERT_TRUE(GetValueAs(result, &promise));
EXPECT_EQ(v8::Promise::kPending, promise->State());
bindings_system()->HandleResponse(last_params().request_id,
/*success=*/true,
ListValueFromString(kFakeAPIResponse),
/*error=*/std::string());
EXPECT_EQ(v8::Promise::kFulfilled, promise->State());
// Note: properties end up alphabetized here.
EXPECT_EQ(R"({"landingPageType":"normal","status":"success"})",
V8ToString(promise->Result(), context));
}
// Calling sendFeedback with a callback should end up with the callback being
// called with multiple parameters rather than a single object.
{
constexpr char kFunctionCall[] =
R"((function(api) {
let info = {description: 'foo'};
chrome.feedbackPrivate.sendFeedback(info, (...args) => {
this.callbackArguments = args;
});
}))";
v8::Local<v8::Function> func = FunctionFromString(context, kFunctionCall);
RunFunctionOnGlobal(func, context, 0, nullptr);
bindings_system()->HandleResponse(last_params().request_id,
/*success=*/true,
ListValueFromString(kFakeAPIResponse),
/*error=*/std::string());
EXPECT_EQ(R"(["success","normal"])",
GetStringPropertyFromObject(context->Global(), context,
"callbackArguments"));
}
}
} // namespace extensions