1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
// Copyright 2017 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/web_request_hooks.h"
#include "base/logging.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"
#include "v8/include/v8-context.h"
#include "v8/include/v8-exception.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-object.h"
namespace extensions {
WebRequestHooks::WebRequestHooks() = default;
WebRequestHooks::~WebRequestHooks() = default;
bool WebRequestHooks::CreateCustomEvent(v8::Local<v8::Context> context,
const std::string& event_name,
v8::Local<v8::Value>* 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<v8::Object> internal_bindings;
{
ModuleSystem::NativesEnabledScope enable_natives(
script_context->module_system());
if (!script_context->module_system()
->Require("webRequestEvent")
.ToLocal(&internal_bindings)) {
// Even though this failed, we return true because a custom event was
// supposed to be created.
return true;
}
}
v8::Local<v8::Value> 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()) {
// In theory we should always be able to get the function from the
// internal bindings, however in practice the Get() call could fail if the
// worker is closing or if the custom bindings have been somehow modified.
// Since we have instances of this occurring, we just log an error here
// rather than crash. See crbug.com/40072548.
// TODO(tjudkins): We should handle the situations leading to this more
// gracefully.
LOG(ERROR) << "Unexpected error when creating custom webRequest event: "
<< "`createWebRequestEvent` not found on internal bindings.";
// Even though this failed, we return true because a custom event was
// supposed to be created.
return true;
}
}
// 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::Value::Dict* event_spec =
ExtensionAPI::GetSharedInstance()->GetSchema(event_name);
DCHECK(event_spec);
const base::Value::List* extra_params =
event_spec->FindList("extraParameters");
CHECK(extra_params);
v8::Local<v8::Value> extra_parameters_spec =
content::V8ValueConverter::Create()->ToV8Value(*extra_params, context);
v8::Local<v8::Function> get_event = get_event_value.As<v8::Function>();
v8::Local<v8::Value> 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<v8::Value> event;
if (!JSRunner::Get(context)
->RunJSFunctionSync(get_event, context, args)
.ToLocal(&event)) {
// In theory this should never happen, but log an error in case it does.
LOG(ERROR) << "Unexpected error when creating custom webRequest event: "
<< "`createWebRequestEvent` function did not successfully run.";
event = v8::Undefined(isolate);
}
*event_out = event;
return true;
}
} // namespace extensions
|