// Copyright (c) 2009 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. package org.chromium.sdk.internal.v8native; import java.util.logging.Level; import java.util.logging.Logger; import org.chromium.sdk.DebugEventListener; import org.chromium.sdk.RelayOk; import org.chromium.sdk.SyncCallback; import org.chromium.sdk.internal.BaseCommandProcessor; import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException; import org.chromium.sdk.internal.v8native.protocol.input.CommandResponse; import org.chromium.sdk.internal.v8native.protocol.input.IncomingMessage; import org.chromium.sdk.internal.v8native.protocol.input.V8ProtocolParserAccess; import org.chromium.sdk.internal.v8native.protocol.output.DebuggerMessage; import org.json.simple.JSONObject; /** * Sends JSON commands to V8 VM and handles responses. Command is sent * via {@code V8CommandOutput}. Response is passed back to callback if it was provided. * Also all responses and events are dispatched to group of dedicated processors. */ public class V8CommandProcessor implements V8CommandSender<DebuggerMessage, RuntimeException> { /** * A callback to handle V8 debugger responses. */ public interface V8HandlerCallback extends BaseCommandProcessor.Callback<CommandResponse> { /** * This method is invoked when a debugger command result has become * available. * * @param response from the V8 debugger */ void messageReceived(CommandResponse response); /** * This method is invoked when a debugger command has failed. * * @param message containing the failure reason */ void failure(String message); /** A no-op callback implementation. */ V8HandlerCallback NULL_CALLBACK = new V8HandlerCallback() { public void failure(String message) { } public void messageReceived(CommandResponse response) { } }; } /** The class logger. */ private static final Logger LOGGER = Logger.getLogger(V8CommandProcessor.class.getName()); private final V8CommandOutput messageOutput; private final DefaultResponseHandler defaultResponseHandler; private final DebugSession debugSession; private final BaseCommandProcessor<Integer, DebuggerMessage, IncomingMessage, CommandResponse> baseCommandProcessor; public V8CommandProcessor(V8CommandOutput messageOutput, DefaultResponseHandler defaultResponseHandler, DebugSession debugSession) { this.messageOutput = messageOutput; this.defaultResponseHandler = defaultResponseHandler; this.debugSession = debugSession; this.baseCommandProcessor = new BaseCommandProcessor<Integer, DebuggerMessage, IncomingMessage, CommandResponse>( new HandlerImpl()); } @Override public RelayOk sendV8CommandAsync(DebuggerMessage message, boolean isImmediate, V8HandlerCallback v8HandlerCallback, SyncCallback syncCallback) { return baseCommandProcessor.send(message, isImmediate, v8HandlerCallback, syncCallback); } public RelayOk runInDispatchThread(final Runnable callback, final SyncCallback syncCallback) { Runnable innerRunnable = new Runnable() { @Override public void run() { RuntimeException exception = null; try { callback.run(); } catch (RuntimeException e) { exception = e; throw e; } finally { if (syncCallback != null) { syncCallback.callbackDone(exception); } } } }; messageOutput.runInDispatchThread(innerRunnable); return DISPATCH_THREAD_PROMISES_TO_CALL; } public void processIncomingJson(final JSONObject v8Json) { IncomingMessage response; try { response = V8ProtocolParserAccess.get().parseIncomingMessage(v8Json); } catch (JsonProtocolParseException e) { LOGGER.log(Level.SEVERE, "JSON message does not conform to the protocol", e); return; } baseCommandProcessor.processIncoming(response); } public void processEos() { baseCommandProcessor.processEos(); } private class HandlerImpl implements BaseCommandProcessor.Handler<Integer, DebuggerMessage, IncomingMessage, CommandResponse> { public Integer getUpdatedSeq(DebuggerMessage message) { return message.getSeq(); } public String getCommandName(DebuggerMessage message) { return message.getCommand(); } public void send(DebuggerMessage message, boolean isImmediate) { V8CommandProcessor.this.messageOutput.send(message, isImmediate); } public CommandResponse parseWithSeq(IncomingMessage incoming) { return incoming.asCommandResponse(); } public Integer getSeq(CommandResponse incomingWithSeq) { return (int) incomingWithSeq.requestSeq(); } public void acceptNonSeq(IncomingMessage incoming) { V8CommandProcessor.this.defaultResponseHandler.handleResponseWithHandler(incoming); } public void reportVmStatus(String currentRequest, int numberOfEnqueued) { DebugEventListener.VmStatusListener statusListener = V8CommandProcessor.this.debugSession.getDebugEventListener().getVmStatusListener(); if (statusListener == null) { return; } } } private static final RelayOk DISPATCH_THREAD_PROMISES_TO_CALL = new RelayOk() {}; }