File: callback_interface_base.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (89 lines) | stat: -rw-r--r-- 3,694 bytes parent folder | download | duplicates (6)
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
// 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 "third_party/blink/renderer/platform/bindings/callback_interface_base.h"

#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h"

namespace blink {

CallbackInterfaceBase::CallbackInterfaceBase(
    v8::Local<v8::Object> callback_object,
    SingleOperationOrNot single_op_or_not) {
  DCHECK(!callback_object.IsEmpty());

  v8::Isolate* isolate = callback_object->GetIsolate();
  callback_object_.Reset(isolate, callback_object);

  incumbent_script_state_ =
      ScriptState::From(isolate, isolate->GetIncumbentContext());
  is_callback_object_callable_ =
      (single_op_or_not == kSingleOperation) && callback_object->IsCallable();

  // Set |callback_relevant_script_state_| iff the creation context and the
  // incumbent context are the same origin-domain. Otherwise, leave it as
  // nullptr.
  if (is_callback_object_callable_) {
    // If the callback object is a function, it's guaranteed to be the same
    // origin at least, and very likely to be the same origin-domain. Even if
    // it's not the same origin-domain, it's already been possible for the
    // callsite to run arbitrary script in the context. No need to protect it.
    // This is an optimization faster than ShouldAllowAccessToV8Context below.
    callback_relevant_script_state_ =
        ScriptState::ForRelevantRealm(isolate, callback_object);
  } else {
    v8::MaybeLocal<v8::Context> creation_context =
        callback_object->GetCreationContext();
    if (BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
            incumbent_script_state_->GetContext(), creation_context)) {
      callback_relevant_script_state_ =
          ScriptState::From(isolate, creation_context.ToLocalChecked());
    }
  }
}

void CallbackInterfaceBase::Trace(Visitor* visitor) const {
  visitor->Trace(callback_object_);
  visitor->Trace(callback_relevant_script_state_);
  visitor->Trace(incumbent_script_state_);
}

ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrReportError(
    const char* interface_name,
    const char* operation_name) {
  if (callback_relevant_script_state_)
    return callback_relevant_script_state_.Get();

  // 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());
  exception_state.ThrowSecurityError(ExceptionMessages::FailedToExecute(
      operation_name, interface_name,
      "An invocation of the provided callback failed due to cross origin "
      "access."));
  return nullptr;
}

ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrThrowException(
    const char* interface_name,
    const char* operation_name) {
  if (callback_relevant_script_state_)
    return callback_relevant_script_state_.Get();

  // Throw a SecurityError due to a cross origin callback object.
  ScriptState::Scope incumbent_scope(incumbent_script_state_);
  ExceptionState exception_state(GetIsolate());
  exception_state.ThrowSecurityError(ExceptionMessages::FailedToExecute(
      operation_name, interface_name,
      "An invocation of the provided callback failed due to cross origin "
      "access."));
  return nullptr;
}

}  // namespace blink