blob: 8833c9ded9b65cd8e7d10b5ba26e58fee6a7c1a9 [file] [log] [blame]
// 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 "third_party/blink/renderer/platform/bindings/callback_function_base.h"
#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
CallbackFunctionBase::CallbackFunctionBase(
v8::Local<v8::Object> callback_function) {
DCHECK(!callback_function.IsEmpty());
v8::Isolate* isolate = callback_function->GetIsolate();
callback_function_.Set(isolate, callback_function);
incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
// Set |callback_relevant_script_state_| iff the creation context and the
// incumbent context are the same origin-domain. Otherwise, leave it as
// nullptr.
v8::Local<v8::Context> creation_context =
callback_function->CreationContext();
if (BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
incumbent_script_state_->GetContext(), creation_context,
BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) {
callback_relevant_script_state_ = ScriptState::From(creation_context);
}
}
void CallbackFunctionBase::Trace(Visitor* visitor) {
visitor->Trace(callback_function_);
visitor->Trace(callback_relevant_script_state_);
visitor->Trace(incumbent_script_state_);
}
ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrReportError(
const char* interface,
const char* operation) {
if (callback_relevant_script_state_)
return callback_relevant_script_state_;
// Report a SecurityError due to a cross origin callback object.
ScriptState::Scope incumbent_scope(incumbent_script_state_);
v8::TryCatch try_catch(GetIsolate());
try_catch.SetVerbose(true);
ExceptionState exception_state(
GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
exception_state.ThrowSecurityError(
"An invocation of the provided callback failed due to cross origin "
"access.");
return nullptr;
}
ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrThrowException(
const char* interface,
const char* operation) {
if (callback_relevant_script_state_)
return callback_relevant_script_state_;
// Throw a SecurityError due to a cross origin callback object.
ScriptState::Scope incumbent_scope(incumbent_script_state_);
ExceptionState exception_state(
GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
exception_state.ThrowSecurityError(
"An invocation of the provided callback failed due to cross origin "
"access.");
return nullptr;
}
V8PersistentCallbackFunctionBase::V8PersistentCallbackFunctionBase(
CallbackFunctionBase* callback_function)
: callback_function_(callback_function) {
v8::Isolate* isolate = callback_function_->GetIsolate();
v8::HandleScope scope(isolate);
auto local = callback_function_->callback_function_.NewLocal(isolate);
v8_function_.Reset(isolate, local);
}
void V8PersistentCallbackFunctionBase::Trace(blink::Visitor* visitor) {
visitor->Trace(callback_function_);
}
} // namespace blink