void DebuggerAgentManager::onV8DebugMessage(const v8::Debug::Message& message) { v8::HandleScope scope; v8::String::Value value(message.GetJSON()); WTF::String out(reinterpret_cast<const UChar*>(*value), value.length()); // If callerData is not 0 the message is a response to a debugger command. if (v8::Debug::ClientData* callerData = message.GetClientData()) { CallerIdWrapper* wrapper = static_cast<CallerIdWrapper*>(callerData); if (wrapper->callerIsMananager()) { // Just ignore messages sent by this manager. return; } DebuggerAgentImpl* debuggerAgent = debuggerAgentForHostId(wrapper->callerId()); if (debuggerAgent) debuggerAgent->debuggerOutput(out); else if (!message.WillStartRunning()) { // Autocontinue execution if there is no handler. sendContinueCommandToV8(); } return; } // Otherwise it's an event message. ASSERT(message.IsEvent()); // Ignore unsupported event types. if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break && message.GetEvent() != v8::Exception) return; v8::Handle<v8::Context> context = message.GetEventContext(); // If the context is from one of the inpected tabs it should have its context // data. if (context.IsEmpty()) { // Unknown context, skip the event. return; } // If the context is from one of the inpected tabs or injected extension // scripts it must have hostId in the data field. int hostId = WebCore::V8Proxy::contextDebugId(context); if (hostId != -1) { DebuggerAgentImpl* agent = debuggerAgentForHostId(hostId); if (agent) { if (agent->autoContinueOnException() && message.GetEvent() == v8::Exception) { sendContinueCommandToV8(); return; } agent->debuggerOutput(out); return; } } if (!message.WillStartRunning()) { // Autocontinue execution on break and exception events if there is no // handler. sendContinueCommandToV8(); } }
void DebuggerAgentManager::debugDetach(DebuggerAgentImpl* debuggerAgent) { #if ENABLE(V8_SCRIPT_DEBUG_SERVER) if (!s_exposeV8DebuggerProtocol) return; #endif if (!s_attachedAgentsMap) { ASSERT_NOT_REACHED(); return; } int hostId = debuggerAgent->webdevtoolsAgent()->hostId(); ASSERT(s_attachedAgentsMap->get(hostId) == debuggerAgent); bool isOnBreakpoint = (findAgentForCurrentV8Context() == debuggerAgent); s_attachedAgentsMap->remove(hostId); if (s_attachedAgentsMap->isEmpty()) { delete s_attachedAgentsMap; s_attachedAgentsMap = 0; // Note that we do not empty handlers while in dispatch - we schedule // continue and do removal once we are out of the dispatch. Also there is // no need to send continue command in this case since removing message // handler will cause debugger unload and all breakpoints will be cleared. if (!s_inHostDispatchHandler) { v8::Debug::SetMessageHandler2(0); v8::Debug::SetHostDispatchHandler(0); } } else { // Remove all breakpoints set by the agent. String clearBreakpointGroupCmd = String::format( "{\"seq\":1,\"type\":\"request\",\"command\":\"clearbreakpointgroup\"," "\"arguments\":{\"groupId\":%d}}", hostId); sendCommandToV8(clearBreakpointGroupCmd, new CallerIdWrapper()); if (isOnBreakpoint) { // Force continue if detach happened in nessted message loop while // debugger was paused on a breakpoint(as long as there are other // attached agents v8 will wait for explicit'continue' message). sendContinueCommandToV8(); } } }