// Copyright 2017 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/web_request_hooks.h" #include "base/cxx17_backports.h" #include "base/values.h" #include "content/public/renderer/v8_value_converter.h" #include "extensions/common/api/web_request.h" #include "extensions/common/extension_api.h" #include "extensions/renderer/bindings/api_binding_hooks.h" #include "extensions/renderer/bindings/js_runner.h" #include "extensions/renderer/get_script_context.h" #include "extensions/renderer/module_system.h" #include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context_set.h" #include "gin/converter.h" namespace extensions { WebRequestHooks::WebRequestHooks() {} WebRequestHooks::~WebRequestHooks() = default; bool WebRequestHooks::CreateCustomEvent( v8::Local context, const std::string& event_name, v8::Local* event_out) { // Don't create a custom event for the "onActionIgnored" event. if (event_name == api::web_request::OnActionIgnored::kEventName) return false; v8::Isolate* isolate = context->GetIsolate(); ScriptContext* script_context = GetScriptContextFromV8Context(context); v8::Local internal_bindings; { ModuleSystem::NativesEnabledScope enable_natives( script_context->module_system()); if (!script_context->module_system() ->Require("webRequestEvent") .ToLocal(&internal_bindings)) { return false; } } v8::Local get_event_value; { v8::TryCatch try_catch(isolate); if (!internal_bindings ->Get(context, gin::StringToSymbol(isolate, "createWebRequestEvent")) .ToLocal(&get_event_value) || !get_event_value->IsFunction()) { NOTREACHED(); return false; } } // The JS validates that the extra parameters passed to the web request event // match the expected schema. We need to initialize the event with that // schema. const base::DictionaryValue* event_spec = ExtensionAPI::GetSharedInstance()->GetSchema(event_name); DCHECK(event_spec); const base::ListValue* extra_params = nullptr; CHECK(event_spec->GetList("extraParameters", &extra_params)); v8::Local extra_parameters_spec = content::V8ValueConverter::Create()->ToV8Value(extra_params, context); v8::Local get_event = get_event_value.As(); v8::Local args[] = { gin::StringToSymbol(isolate, event_name), v8::Undefined(isolate), // opt_argSchemas are ignored. extra_parameters_spec, // opt_eventOptions and opt_webViewInstanceId are ignored. }; v8::TryCatch try_catch(isolate); v8::Local event; if (!JSRunner::Get(context) ->RunJSFunctionSync(get_event, context, base::size(args), args) .ToLocal(&event)) { // TODO(devlin): Do we care about the error? In theory, this should never // happen, so probably not. event = v8::Undefined(isolate); } *event_out = event; return true; } } // namespace extensions