/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/inspector/InspectorDOMDebuggerAgent.h"

#include "bindings/core/v8/ScriptEventListener.h"
#include "bindings/core/v8/V8EventTarget.h"
#include "core/dom/Element.h"
#include "core/dom/Node.h"
#include "core/events/Event.h"
#include "core/events/EventTarget.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/inspector/InspectorDOMAgent.h"
#include "core/inspector/V8InspectorString.h"

namespace {

enum DOMBreakpointType {
  SubtreeModified = 0,
  AttributeModified,
  NodeRemoved,
  DOMBreakpointTypesCount
};

static const char listenerEventCategoryType[] = "listener:";
static const char instrumentationEventCategoryType[] = "instrumentation:";

const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);
const int domBreakpointDerivedTypeShift = 16;

}  // namespace

namespace blink {

static const char webglErrorFiredEventName[] = "webglErrorFired";
static const char webglWarningFiredEventName[] = "webglWarningFired";
static const char webglErrorNameProperty[] = "webglErrorName";
static const char scriptBlockedByCSPEventName[] = "scriptBlockedByCSP";

namespace DOMDebuggerAgentState {
static const char eventListenerBreakpoints[] = "eventListenerBreakpoints";
static const char eventTargetAny[] = "*";
static const char pauseOnAllXHRs[] = "pauseOnAllXHRs";
static const char xhrBreakpoints[] = "xhrBreakpoints";
static const char enabled[] = "enabled";
}

static void removeEventListenerCallback(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Object> data = info.Data().As<v8::Object>();

  v8::Local<v8::Value> v8Target;
  if (!data->Get(context, v8String(isolate, "target")).ToLocal(&v8Target) ||
      !v8Target->IsObject())
    return;
  EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, v8Target);
  // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper
  // exists on prototype chain.
  if (!target)
    target = toDOMWindow(isolate, v8Target);
  if (!target || !target->getExecutionContext())
    return;

  v8::Local<v8::Value> v8Handler;
  if (!data->Get(context, v8String(isolate, "handler")).ToLocal(&v8Handler) ||
      !v8Handler->IsObject())
    return;
  v8::Local<v8::Value> v8Type;
  if (!data->Get(context, v8String(isolate, "type")).ToLocal(&v8Type) ||
      !v8Type->IsString())
    return;
  AtomicString type =
      AtomicString(toCoreString(v8::Local<v8::String>::Cast(v8Type)));
  v8::Local<v8::Value> v8UseCapture;
  if (!data->Get(context, v8String(isolate, "useCapture"))
           .ToLocal(&v8UseCapture) ||
      !v8UseCapture->IsBoolean())
    return;
  bool useCapture = v8::Local<v8::Boolean>::Cast(v8UseCapture)->Value();

  EventListener* eventListener = nullptr;
  EventListenerVector* listeners = target->getEventListeners(type);
  if (!listeners)
    return;
  for (size_t i = 0; i < listeners->size(); ++i) {
    if (listeners->at(i).capture() != useCapture)
      continue;
    V8AbstractEventListener* v8Listener =
        V8AbstractEventListener::cast(listeners->at(i).listener());
    if (!v8Listener)
      continue;
    if (!v8Listener->hasExistingListenerObject())
      continue;
    if (!v8Listener->getExistingListenerObject()
             ->Equals(context, v8Handler)
             .FromMaybe(false))
      continue;
    eventListener = v8Listener;
    break;
  }
  if (!eventListener)
    return;
  EventListenerOptions options;
  options.setCapture(useCapture);
  target->removeEventListener(type, eventListener, options);
}

static void returnDataCallback(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  info.GetReturnValue().Set(info.Data());
}

static v8::MaybeLocal<v8::Function> createRemoveFunction(
    v8::Local<v8::Context> context,
    v8::Local<v8::Value> object,
    v8::Local<v8::Object> handler,
    AtomicString type,
    bool useCapture) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::Local<v8::Object> data = v8::Object::New(isolate);
  if (!data->Set(context, v8String(isolate, "target"), object).FromMaybe(false))
    return v8::MaybeLocal<v8::Function>();
  if (!data->Set(context, v8String(isolate, "handler"), handler)
           .FromMaybe(false))
    return v8::MaybeLocal<v8::Function>();
  if (!data->Set(context, v8String(isolate, "type"), v8String(isolate, type))
           .FromMaybe(false))
    return v8::MaybeLocal<v8::Function>();
  if (!data->Set(context, v8String(isolate, "useCapture"),
                 v8Boolean(useCapture, isolate))
           .FromMaybe(false))
    return v8::MaybeLocal<v8::Function>();
  v8::Local<v8::Function> removeFunction =
      v8::Function::New(context, removeEventListenerCallback, data, 0,
                        v8::ConstructorBehavior::kThrow)
          .ToLocalChecked();
  v8::Local<v8::Function> toStringFunction;
  if (v8::Function::New(
          context, returnDataCallback,
          v8String(isolate, "function remove() { [Command Line API] }"), 0,
          v8::ConstructorBehavior::kThrow)
          .ToLocal(&toStringFunction))
    removeFunction->Set(v8String(context->GetIsolate(), "toString"),
                        toStringFunction);
  return removeFunction;
}

void InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
    v8::Isolate* isolate,
    v8::Local<v8::Value> value,
    V8EventListenerInfoList& eventInformation) {
  EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, value);
  // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper
  // exists on prototype chain.
  if (!target)
    target = toDOMWindow(isolate, value);
  if (!target || !target->getExecutionContext())
    return;

  ExecutionContext* executionContext = target->getExecutionContext();

  // Nodes and their Listeners for the concerned event types (order is top to
  // bottom).
  Vector<AtomicString> eventTypes = target->eventTypes();
  for (size_t j = 0; j < eventTypes.size(); ++j) {
    AtomicString& type = eventTypes[j];
    EventListenerVector* listeners = target->getEventListeners(type);
    if (!listeners)
      continue;
    for (size_t k = 0; k < listeners->size(); ++k) {
      EventListener* eventListener = listeners->at(k).listener();
      if (eventListener->type() != EventListener::JSEventListenerType)
        continue;
      V8AbstractEventListener* v8Listener =
          static_cast<V8AbstractEventListener*>(eventListener);
      v8::Local<v8::Context> context =
          toV8Context(executionContext, v8Listener->world());
      // Hide listeners from other contexts.
      if (context != isolate->GetCurrentContext())
        continue;
      // getListenerObject() may cause JS in the event attribute to get
      // compiled, potentially unsuccessfully.  In that case, the function
      // returns the empty handle without an exception.
      v8::Local<v8::Object> handler =
          v8Listener->getListenerObject(executionContext);
      if (handler.IsEmpty())
        continue;
      bool useCapture = listeners->at(k).capture();
      eventInformation.append(V8EventListenerInfo(
          type, useCapture, listeners->at(k).passive(), handler,
          createRemoveFunction(context, value, handler, type, useCapture)));
    }
  }
}

InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent(
    v8::Isolate* isolate,
    InspectorDOMAgent* domAgent,
    v8_inspector::V8InspectorSession* v8Session)
    : m_isolate(isolate), m_domAgent(domAgent), m_v8Session(v8Session) {}

InspectorDOMDebuggerAgent::~InspectorDOMDebuggerAgent() {}

DEFINE_TRACE(InspectorDOMDebuggerAgent) {
  visitor->trace(m_domAgent);
  visitor->trace(m_domBreakpoints);
  InspectorBaseAgent::trace(visitor);
}

void InspectorDOMDebuggerAgent::disable(ErrorString*) {
  setEnabled(false);
  m_domBreakpoints.clear();
  m_state->remove(DOMDebuggerAgentState::eventListenerBreakpoints);
  m_state->remove(DOMDebuggerAgentState::xhrBreakpoints);
  m_state->remove(DOMDebuggerAgentState::pauseOnAllXHRs);
}

void InspectorDOMDebuggerAgent::restore() {
  if (m_state->booleanProperty(DOMDebuggerAgentState::enabled, false))
    m_instrumentingAgents->addInspectorDOMDebuggerAgent(this);
}

void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(
    ErrorString* error,
    const String& eventName,
    const Maybe<String>& targetName) {
  setBreakpoint(error, String(listenerEventCategoryType) + eventName,
                targetName.fromMaybe(String()));
}

void InspectorDOMDebuggerAgent::setInstrumentationBreakpoint(
    ErrorString* error,
    const String& eventName) {
  setBreakpoint(error, String(instrumentationEventCategoryType) + eventName,
                String());
}

static protocol::DictionaryValue* ensurePropertyObject(
    protocol::DictionaryValue* object,
    const String& propertyName) {
  protocol::Value* value = object->get(propertyName);
  if (value)
    return protocol::DictionaryValue::cast(value);

  std::unique_ptr<protocol::DictionaryValue> newResult =
      protocol::DictionaryValue::create();
  protocol::DictionaryValue* result = newResult.get();
  object->setObject(propertyName, std::move(newResult));
  return result;
}

protocol::DictionaryValue*
InspectorDOMDebuggerAgent::eventListenerBreakpoints() {
  protocol::DictionaryValue* breakpoints =
      m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
  if (!breakpoints) {
    std::unique_ptr<protocol::DictionaryValue> newBreakpoints =
        protocol::DictionaryValue::create();
    breakpoints = newBreakpoints.get();
    m_state->setObject(DOMDebuggerAgentState::eventListenerBreakpoints,
                       std::move(newBreakpoints));
  }
  return breakpoints;
}

protocol::DictionaryValue* InspectorDOMDebuggerAgent::xhrBreakpoints() {
  protocol::DictionaryValue* breakpoints =
      m_state->getObject(DOMDebuggerAgentState::xhrBreakpoints);
  if (!breakpoints) {
    std::unique_ptr<protocol::DictionaryValue> newBreakpoints =
        protocol::DictionaryValue::create();
    breakpoints = newBreakpoints.get();
    m_state->setObject(DOMDebuggerAgentState::xhrBreakpoints,
                       std::move(newBreakpoints));
  }
  return breakpoints;
}

void InspectorDOMDebuggerAgent::setBreakpoint(ErrorString* error,
                                              const String& eventName,
                                              const String& targetName) {
  if (eventName.isEmpty()) {
    *error = "Event name is empty";
    return;
  }

  protocol::DictionaryValue* breakpointsByTarget =
      ensurePropertyObject(eventListenerBreakpoints(), eventName);
  if (targetName.isEmpty())
    breakpointsByTarget->setBoolean(DOMDebuggerAgentState::eventTargetAny,
                                    true);
  else
    breakpointsByTarget->setBoolean(targetName.lower(), true);
  didAddBreakpoint();
}

void InspectorDOMDebuggerAgent::removeEventListenerBreakpoint(
    ErrorString* error,
    const String& eventName,
    const Maybe<String>& targetName) {
  removeBreakpoint(error, String(listenerEventCategoryType) + eventName,
                   targetName.fromMaybe(String()));
}

void InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint(
    ErrorString* error,
    const String& eventName) {
  removeBreakpoint(error, String(instrumentationEventCategoryType) + eventName,
                   String());
}

void InspectorDOMDebuggerAgent::removeBreakpoint(ErrorString* error,
                                                 const String& eventName,
                                                 const String& targetName) {
  if (eventName.isEmpty()) {
    *error = "Event name is empty";
    return;
  }

  protocol::DictionaryValue* breakpointsByTarget =
      ensurePropertyObject(eventListenerBreakpoints(), eventName);
  if (targetName.isEmpty())
    breakpointsByTarget->remove(DOMDebuggerAgentState::eventTargetAny);
  else
    breakpointsByTarget->remove(targetName.lower());
  didRemoveBreakpoint();
}

void InspectorDOMDebuggerAgent::didInvalidateStyleAttr(Node* node) {
  if (hasBreakpoint(node, AttributeModified))
    breakProgramOnDOMEvent(node, AttributeModified, false);
}

void InspectorDOMDebuggerAgent::didInsertDOMNode(Node* node) {
  if (m_domBreakpoints.size()) {
    uint32_t mask =
        m_domBreakpoints.get(InspectorDOMAgent::innerParentNode(node));
    uint32_t inheritableTypesMask =
        (mask | (mask >> domBreakpointDerivedTypeShift)) &
        inheritableDOMBreakpointTypesMask;
    if (inheritableTypesMask)
      updateSubtreeBreakpoints(node, inheritableTypesMask, true);
  }
}

void InspectorDOMDebuggerAgent::didRemoveDOMNode(Node* node) {
  if (m_domBreakpoints.size()) {
    // Remove subtree breakpoints.
    m_domBreakpoints.remove(node);
    HeapVector<Member<Node>> stack(1, InspectorDOMAgent::innerFirstChild(node));
    do {
      Node* node = stack.last();
      stack.removeLast();
      if (!node)
        continue;
      m_domBreakpoints.remove(node);
      stack.append(InspectorDOMAgent::innerFirstChild(node));
      stack.append(InspectorDOMAgent::innerNextSibling(node));
    } while (!stack.isEmpty());
  }
}

static int domTypeForName(ErrorString* errorString, const String& typeString) {
  if (typeString == "subtree-modified")
    return SubtreeModified;
  if (typeString == "attribute-modified")
    return AttributeModified;
  if (typeString == "node-removed")
    return NodeRemoved;
  *errorString = String("Unknown DOM breakpoint type: " + typeString);
  return -1;
}

static String domTypeName(int type) {
  switch (type) {
    case SubtreeModified:
      return "subtree-modified";
    case AttributeModified:
      return "attribute-modified";
    case NodeRemoved:
      return "node-removed";
    default:
      break;
  }
  return "";
}

void InspectorDOMDebuggerAgent::setDOMBreakpoint(ErrorString* errorString,
                                                 int nodeId,
                                                 const String& typeString) {
  Node* node = m_domAgent->assertNode(errorString, nodeId);
  if (!node)
    return;

  int type = domTypeForName(errorString, typeString);
  if (type == -1)
    return;

  uint32_t rootBit = 1 << type;
  m_domBreakpoints.set(node, m_domBreakpoints.get(node) | rootBit);
  if (rootBit & inheritableDOMBreakpointTypesMask) {
    for (Node* child = InspectorDOMAgent::innerFirstChild(node); child;
         child = InspectorDOMAgent::innerNextSibling(child))
      updateSubtreeBreakpoints(child, rootBit, true);
  }
  didAddBreakpoint();
}

void InspectorDOMDebuggerAgent::removeDOMBreakpoint(ErrorString* errorString,
                                                    int nodeId,
                                                    const String& typeString) {
  Node* node = m_domAgent->assertNode(errorString, nodeId);
  if (!node)
    return;
  int type = domTypeForName(errorString, typeString);
  if (type == -1)
    return;

  uint32_t rootBit = 1 << type;
  uint32_t mask = m_domBreakpoints.get(node) & ~rootBit;
  if (mask)
    m_domBreakpoints.set(node, mask);
  else
    m_domBreakpoints.remove(node);

  if ((rootBit & inheritableDOMBreakpointTypesMask) &&
      !(mask & (rootBit << domBreakpointDerivedTypeShift))) {
    for (Node* child = InspectorDOMAgent::innerFirstChild(node); child;
         child = InspectorDOMAgent::innerNextSibling(child))
      updateSubtreeBreakpoints(child, rootBit, false);
  }
  didRemoveBreakpoint();
}

void InspectorDOMDebuggerAgent::getEventListeners(
    ErrorString* errorString,
    const String& objectId,
    std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>*
        listenersArray) {
  v8::HandleScope handles(m_isolate);
  v8::Local<v8::Value> object;
  v8::Local<v8::Context> context;
  std::unique_ptr<v8_inspector::StringBuffer> error;
  std::unique_ptr<v8_inspector::StringBuffer> objectGroup;
  if (!m_v8Session->unwrapObject(&error, toV8InspectorStringView(objectId),
                                 &object, &context, &objectGroup)) {
    *errorString = toCoreString(std::move(error));
    return;
  }
  v8::Context::Scope scope(context);
  *listenersArray =
      protocol::Array<protocol::DOMDebugger::EventListener>::create();
  V8EventListenerInfoList eventInformation;
  InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
      context->GetIsolate(), object, eventInformation);
  for (const auto& info : eventInformation) {
    if (!info.useCapture)
      continue;
    std::unique_ptr<protocol::DOMDebugger::EventListener> listenerObject =
        buildObjectForEventListener(context, info, objectGroup->string());
    if (listenerObject)
      (*listenersArray)->addItem(std::move(listenerObject));
  }
  for (const auto& info : eventInformation) {
    if (info.useCapture)
      continue;
    std::unique_ptr<protocol::DOMDebugger::EventListener> listenerObject =
        buildObjectForEventListener(context, info, objectGroup->string());
    if (listenerObject)
      (*listenersArray)->addItem(std::move(listenerObject));
  }
}

std::unique_ptr<protocol::DOMDebugger::EventListener>
InspectorDOMDebuggerAgent::buildObjectForEventListener(
    v8::Local<v8::Context> context,
    const V8EventListenerInfo& info,
    const v8_inspector::StringView& objectGroupId) {
  if (info.handler.IsEmpty())
    return nullptr;

  v8::Isolate* isolate = context->GetIsolate();
  v8::Local<v8::Function> function =
      eventListenerEffectiveFunction(isolate, info.handler);
  if (function.IsEmpty())
    return nullptr;

  String scriptId;
  int lineNumber;
  int columnNumber;
  getFunctionLocation(function, scriptId, lineNumber, columnNumber);

  std::unique_ptr<protocol::DOMDebugger::EventListener> value =
      protocol::DOMDebugger::EventListener::create()
          .setType(info.eventType)
          .setUseCapture(info.useCapture)
          .setPassive(info.passive)
          .setScriptId(scriptId)
          .setLineNumber(lineNumber)
          .setColumnNumber(columnNumber)
          .build();
  if (objectGroupId.length()) {
    value->setHandler(
        m_v8Session->wrapObject(context, function, objectGroupId));
    value->setOriginalHandler(
        m_v8Session->wrapObject(context, info.handler, objectGroupId));
    v8::Local<v8::Function> removeFunction;
    if (info.removeFunction.ToLocal(&removeFunction))
      value->setRemoveFunction(
          m_v8Session->wrapObject(context, removeFunction, objectGroupId));
  }
  return value;
}

void InspectorDOMDebuggerAgent::allowNativeBreakpoint(
    const String& breakpointName,
    const String* targetName,
    bool sync) {
  pauseOnNativeEventIfNeeded(
      preparePauseOnNativeEventData(breakpointName, targetName), sync);
}

void InspectorDOMDebuggerAgent::willInsertDOMNode(Node* parent) {
  if (hasBreakpoint(parent, SubtreeModified))
    breakProgramOnDOMEvent(parent, SubtreeModified, true);
}

void InspectorDOMDebuggerAgent::willRemoveDOMNode(Node* node) {
  Node* parentNode = InspectorDOMAgent::innerParentNode(node);
  if (hasBreakpoint(node, NodeRemoved))
    breakProgramOnDOMEvent(node, NodeRemoved, false);
  else if (parentNode && hasBreakpoint(parentNode, SubtreeModified))
    breakProgramOnDOMEvent(node, SubtreeModified, false);
  didRemoveDOMNode(node);
}

void InspectorDOMDebuggerAgent::willModifyDOMAttr(Element* element,
                                                  const AtomicString&,
                                                  const AtomicString&) {
  if (hasBreakpoint(element, AttributeModified))
    breakProgramOnDOMEvent(element, AttributeModified, false);
}

void InspectorDOMDebuggerAgent::breakProgramOnDOMEvent(Node* target,
                                                       int breakpointType,
                                                       bool insertion) {
  DCHECK(hasBreakpoint(target, breakpointType));
  std::unique_ptr<protocol::DictionaryValue> description =
      protocol::DictionaryValue::create();

  Node* breakpointOwner = target;
  if ((1 << breakpointType) & inheritableDOMBreakpointTypesMask) {
    // For inheritable breakpoint types, target node isn't always the same as
    // the node that owns a breakpoint.  Target node may be unknown to frontend,
    // so we need to push it first.
    description->setInteger("targetNodeId",
                            m_domAgent->pushNodePathToFrontend(target));

    // Find breakpoint owner node.
    if (!insertion)
      breakpointOwner = InspectorDOMAgent::innerParentNode(target);
    ASSERT(breakpointOwner);
    while (!(m_domBreakpoints.get(breakpointOwner) & (1 << breakpointType))) {
      Node* parentNode = InspectorDOMAgent::innerParentNode(breakpointOwner);
      if (!parentNode)
        break;
      breakpointOwner = parentNode;
    }

    if (breakpointType == SubtreeModified)
      description->setBoolean("insertion", insertion);
  }

  int breakpointOwnerNodeId = m_domAgent->boundNodeId(breakpointOwner);
  ASSERT(breakpointOwnerNodeId);
  description->setInteger("nodeId", breakpointOwnerNodeId);
  description->setString("type", domTypeName(breakpointType));
  String json = description->toJSONString();
  m_v8Session->breakProgram(
      toV8InspectorStringView(
          v8_inspector::protocol::Debugger::API::Paused::ReasonEnum::DOM),
      toV8InspectorStringView(json));
}

bool InspectorDOMDebuggerAgent::hasBreakpoint(Node* node, int type) {
  if (!m_domAgent->enabled())
    return false;
  uint32_t rootBit = 1 << type;
  uint32_t derivedBit = rootBit << domBreakpointDerivedTypeShift;
  return m_domBreakpoints.get(node) & (rootBit | derivedBit);
}

void InspectorDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node,
                                                         uint32_t rootMask,
                                                         bool set) {
  uint32_t oldMask = m_domBreakpoints.get(node);
  uint32_t derivedMask = rootMask << domBreakpointDerivedTypeShift;
  uint32_t newMask = set ? oldMask | derivedMask : oldMask & ~derivedMask;
  if (newMask)
    m_domBreakpoints.set(node, newMask);
  else
    m_domBreakpoints.remove(node);

  uint32_t newRootMask = rootMask & ~newMask;
  if (!newRootMask)
    return;

  for (Node* child = InspectorDOMAgent::innerFirstChild(node); child;
       child = InspectorDOMAgent::innerNextSibling(child))
    updateSubtreeBreakpoints(child, newRootMask, set);
}

void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(
    std::unique_ptr<protocol::DictionaryValue> eventData,
    bool synchronous) {
  if (!eventData)
    return;
  String json = eventData->toJSONString();
  if (synchronous)
    m_v8Session->breakProgram(
        toV8InspectorStringView(v8_inspector::protocol::Debugger::API::Paused::
                                    ReasonEnum::EventListener),
        toV8InspectorStringView(json));
  else
    m_v8Session->schedulePauseOnNextStatement(
        toV8InspectorStringView(v8_inspector::protocol::Debugger::API::Paused::
                                    ReasonEnum::EventListener),
        toV8InspectorStringView(json));
}

std::unique_ptr<protocol::DictionaryValue>
InspectorDOMDebuggerAgent::preparePauseOnNativeEventData(
    const String& eventName,
    const String* targetName) {
  String fullEventName = (targetName ? listenerEventCategoryType
                                     : instrumentationEventCategoryType) +
                         eventName;
  protocol::DictionaryValue* breakpoints = eventListenerBreakpoints();
  protocol::Value* value = breakpoints->get(fullEventName);
  if (!value)
    return nullptr;
  bool match = false;
  protocol::DictionaryValue* breakpointsByTarget =
      protocol::DictionaryValue::cast(value);
  breakpointsByTarget->getBoolean(DOMDebuggerAgentState::eventTargetAny,
                                  &match);
  if (!match && targetName)
    breakpointsByTarget->getBoolean(targetName->lower(), &match);
  if (!match)
    return nullptr;

  std::unique_ptr<protocol::DictionaryValue> eventData =
      protocol::DictionaryValue::create();
  eventData->setString("eventName", fullEventName);
  if (targetName)
    eventData->setString("targetName", *targetName);
  return eventData;
}

void InspectorDOMDebuggerAgent::didFireWebGLError(const String& errorName) {
  std::unique_ptr<protocol::DictionaryValue> eventData =
      preparePauseOnNativeEventData(webglErrorFiredEventName, 0);
  if (!eventData)
    return;
  if (!errorName.isEmpty())
    eventData->setString(webglErrorNameProperty, errorName);
  pauseOnNativeEventIfNeeded(std::move(eventData), false);
}

void InspectorDOMDebuggerAgent::didFireWebGLWarning() {
  pauseOnNativeEventIfNeeded(
      preparePauseOnNativeEventData(webglWarningFiredEventName, 0), false);
}

void InspectorDOMDebuggerAgent::didFireWebGLErrorOrWarning(
    const String& message) {
  if (message.findIgnoringCase("error") != WTF::kNotFound)
    didFireWebGLError(String());
  else
    didFireWebGLWarning();
}

void InspectorDOMDebuggerAgent::cancelNativeBreakpoint() {
  m_v8Session->cancelPauseOnNextStatement();
}

void InspectorDOMDebuggerAgent::scriptExecutionBlockedByCSP(
    const String& directiveText) {
  std::unique_ptr<protocol::DictionaryValue> eventData =
      preparePauseOnNativeEventData(scriptBlockedByCSPEventName, 0);
  if (!eventData)
    return;
  eventData->setString("directiveText", directiveText);
  pauseOnNativeEventIfNeeded(std::move(eventData), true);
}

void InspectorDOMDebuggerAgent::setXHRBreakpoint(ErrorString* errorString,
                                                 const String& url) {
  if (url.isEmpty())
    m_state->setBoolean(DOMDebuggerAgentState::pauseOnAllXHRs, true);
  else
    xhrBreakpoints()->setBoolean(url, true);
  didAddBreakpoint();
}

void InspectorDOMDebuggerAgent::removeXHRBreakpoint(ErrorString* errorString,
                                                    const String& url) {
  if (url.isEmpty())
    m_state->setBoolean(DOMDebuggerAgentState::pauseOnAllXHRs, false);
  else
    xhrBreakpoints()->remove(url);
  didRemoveBreakpoint();
}

void InspectorDOMDebuggerAgent::willSendXMLHttpOrFetchNetworkRequest(
    const String& url) {
  String breakpointURL;
  if (m_state->booleanProperty(DOMDebuggerAgentState::pauseOnAllXHRs, false))
    breakpointURL = "";
  else {
    protocol::DictionaryValue* breakpoints = xhrBreakpoints();
    for (size_t i = 0; i < breakpoints->size(); ++i) {
      auto breakpoint = breakpoints->at(i);
      if (url.contains(breakpoint.first)) {
        breakpointURL = breakpoint.first;
        break;
      }
    }
  }

  if (breakpointURL.isNull())
    return;

  std::unique_ptr<protocol::DictionaryValue> eventData =
      protocol::DictionaryValue::create();
  eventData->setString("breakpointURL", breakpointURL);
  eventData->setString("url", url);
  String json = eventData->toJSONString();
  m_v8Session->breakProgram(
      toV8InspectorStringView(
          v8_inspector::protocol::Debugger::API::Paused::ReasonEnum::XHR),
      toV8InspectorStringView(json));
}

void InspectorDOMDebuggerAgent::didAddBreakpoint() {
  if (m_state->booleanProperty(DOMDebuggerAgentState::enabled, false))
    return;
  setEnabled(true);
}

void InspectorDOMDebuggerAgent::didRemoveBreakpoint() {
  if (!m_domBreakpoints.isEmpty())
    return;
  if (eventListenerBreakpoints()->size())
    return;
  if (xhrBreakpoints()->size())
    return;
  if (m_state->booleanProperty(DOMDebuggerAgentState::pauseOnAllXHRs, false))
    return;
  setEnabled(false);
}

void InspectorDOMDebuggerAgent::setEnabled(bool enabled) {
  if (enabled) {
    m_instrumentingAgents->addInspectorDOMDebuggerAgent(this);
    m_state->setBoolean(DOMDebuggerAgentState::enabled, true);
  } else {
    m_state->remove(DOMDebuggerAgentState::enabled);
    m_instrumentingAgents->removeInspectorDOMDebuggerAgent(this);
  }
}

void InspectorDOMDebuggerAgent::didCommitLoadForLocalFrame(LocalFrame*) {
  m_domBreakpoints.clear();
}

}  // namespace blink
