diff options
Diffstat (limited to 'WebCore/inspector/CodeGeneratorInspector.pm')
-rw-r--r-- | WebCore/inspector/CodeGeneratorInspector.pm | 267 |
1 files changed, 183 insertions, 84 deletions
diff --git a/WebCore/inspector/CodeGeneratorInspector.pm b/WebCore/inspector/CodeGeneratorInspector.pm index 5488dbd..9d0af53 100644 --- a/WebCore/inspector/CodeGeneratorInspector.pm +++ b/WebCore/inspector/CodeGeneratorInspector.pm @@ -14,9 +14,33 @@ $typeTransform{"InspectorClient"} = { "forward" => "InspectorClient", "header" => "InspectorClient.h", }; -$typeTransform{"InspectorBackend"} = { +$typeTransform{"Backend"} = { "forward" => "InspectorBackend", "header" => "InspectorBackend.h", + "handlerAccessor" => "m_inspectorController->inspectorBackend()", +}; +$typeTransform{"Controller"} = { + "forwardHeader" => "InspectorController.h", + "handlerAccessor" => "m_inspectorController", +}; +$typeTransform{"Debug"} = { + "forward" => "InspectorDebuggerAgent", + "header" => "InspectorDebuggerAgent.h", + "handlerAccessor" => "m_inspectorController->debuggerAgent()", +}; +$typeTransform{"DOM"} = { + "forward" => "InspectorDOMAgent", + "header" => "InspectorDOMAgent.h", + "handlerAccessor" => "m_inspectorController->domAgent()", +}; +$typeTransform{"ApplicationCache"} = { + "forward" => "InspectorApplicationCacheAgent", + "header" => "InspectorApplicationCacheAgent.h", + "handlerAccessor" => "m_inspectorController->applicationCacheAgent()", +}; +$typeTransform{"Frontend"} = { + "forward" => "RemoteInspectorFrontend", + "header" => "RemoteInspectorFrontend.h", }; $typeTransform{"PassRefPtr"} = { "forwardHeader" => "wtf/PassRefPtr.h", @@ -24,6 +48,8 @@ $typeTransform{"PassRefPtr"} = { $typeTransform{"Object"} = { "param" => "PassRefPtr<InspectorObject>", "retVal" => "PassRefPtr<InspectorObject>", + "variable" => "RefPtr<InspectorObject>", + "defaultValue" => "InspectorObject::create()", "forward" => "InspectorObject", "header" => "InspectorValues.h", "accessorSuffix" => "" @@ -31,6 +57,8 @@ $typeTransform{"Object"} = { $typeTransform{"Array"} = { "param" => "PassRefPtr<InspectorArray>", "retVal" => "PassRefPtr<InspectorArray>", + "variable" => "RefPtr<InspectorArray>", + "defaultValue" => "InspectorArray::create()", "forward" => "InspectorArray", "header" => "InspectorValues.h", "accessorSuffix" => "" @@ -38,41 +66,55 @@ $typeTransform{"Array"} = { $typeTransform{"Value"} = { "param" => "PassRefPtr<InspectorValue>", "retVal" => "PassRefPtr<InspectorValue>", + "variable" => "RefPtr<InspectorValue>", + "defaultValue" => "InspectorValue::null()", "forward" => "InspectorValue", "header" => "InspectorValues.h", "accessorSuffix" => "" }; $typeTransform{"String"} = { "param" => "const String&", - "retVal" => "String", - "forward" => "String", + "variable" => "String", + "forwardHeader" => "wtf/Forward.h", "header" => "PlatformString.h", "accessorSuffix" => "String" }; $typeTransform{"long"} = { "param" => "long", - "retVal" => "long", + "variable" => "long", + "defaultValue" => "0", "forward" => "", "header" => "", "accessorSuffix" => "Number" }; $typeTransform{"int"} = { "param" => "int", - "retVal" => "int", + "variable" => "int", + "defaultValue" => "0", "forward" => "", "header" => "", "accessorSuffix" => "Number", }; $typeTransform{"unsigned long"} = { "param" => "unsigned long", - "retVal" => "unsigned long", + "variable" => "unsigned long", + "defaultValue" => "0u", + "forward" => "", + "header" => "", + "accessorSuffix" => "Number" +}; +$typeTransform{"unsigned int"} = { + "param" => "unsigned int", + "variable" => "unsigned int", + "defaultValue" => "0u", "forward" => "", "header" => "", "accessorSuffix" => "Number" }; $typeTransform{"boolean"} = { "param" => "bool", - "retVal"=> "bool", + "variable"=> "bool", + "defaultValue" => "false", "forward" => "", "header" => "", "accessorSuffix" => "Bool" @@ -163,12 +205,14 @@ sub GenerateInterface $backendClassName = $className . "BackendDispatcher"; my @backendHead; - push(@backendHead, " ${backendClassName}(InspectorBackend* inspectorBackend) : m_inspectorBackend(inspectorBackend) { }"); + push(@backendHead, " ${backendClassName}(InspectorController* inspectorController) : m_inspectorController(inspectorController) { }"); + push(@backendHead, " void reportProtocolError(const long callId, const String& method, const String& errorText) const;"); push(@backendHead, " void dispatch(const String& message);"); push(@backendHead, "private:"); $backendConstructor = join("\n", @backendHead); - $backendFooter = " InspectorBackend* m_inspectorBackend;"; - $backendTypes{"InspectorBackend"} = 1; + $backendFooter = " InspectorController* m_inspectorController;"; + $backendTypes{"Controller"} = 1; + $backendTypes{"InspectorClient"} = 1; $backendTypes{"PassRefPtr"} = 1; $backendTypes{"Array"} = 1; @@ -185,20 +229,16 @@ sub generateFunctions generateBackendFunction($function); } push(@backendMethodsImpl, generateBackendDispatcher()); + push(@backendMethodsImpl, generateBackendReportProtocolError()); } sub generateFrontendFunction { my $function = shift; - my $functionName; my $notify = $function->signature->extendedAttributes->{"notify"}; - if ($notify) { - $functionName = $function->signature->name; - } else { - my $customResponse = $function->signature->extendedAttributes->{"customResponse"}; - $functionName = $customResponse ? $customResponse : "did" . ucfirst($function->signature->name); - } + return if !$notify; + my $functionName = $notify ? $function->signature->name : "did" . ucfirst($function->signature->name); my @argsFiltered = grep($_->direction eq "out", @{$function->parameters}); # just keep only out parameters for frontend interface. unshift(@argsFiltered, $callId) if !$notify; # Add callId as the first argument for all frontend did* methods. @@ -214,9 +254,10 @@ sub generateFrontendFunction push(@function, "void ${frontendClassName}::${functionName}(${arguments})"); push(@function, "{"); push(@function, " RefPtr<InspectorArray> arguments = InspectorArray::create();"); - push(@function, " arguments->pushString(\"$functionName\");"); + push(@function, " arguments->pushString(\"" . ($notify ? $functionName : "processResponse") . "\");"); push(@function, @pushArguments); push(@function, " m_inspectorClient->sendMessageToFrontend(arguments->toJSONString());"); + push(@function, "}"); push(@function, ""); push(@frontendMethodsImpl, @function); @@ -228,12 +269,12 @@ sub generateBackendPrivateFunctions my $privateFunctions = << "EOF"; static String formatWrongArgumentsCountMessage(unsigned expected, unsigned actual) { - return String::format(\"Wrong number of parameters: %d (expected: %d)\", actual, expected); + return String::format("Wrong number of parameters: %d (expected: %d)", actual, expected); } static String formatWrongArgumentTypeMessage(unsigned position, const char* name, const char* expectedType) { - return String::format(\"Failed to convert parameter %d (%s) to %s\", position, name, expectedType); + return String::format("Failed to convert parameter %d (%s) to %s", position, name, expectedType); } EOF push(@backendMethodsImpl, $privateFunctions); @@ -246,95 +287,153 @@ sub generateBackendFunction my $functionName = $function->signature->name; - my @argsFiltered = grep($_->direction eq "in", @{$function->parameters}); - map($backendTypes{$_->type} = 1, @argsFiltered); # register required types - my $arguments = join(", ", map($typeTransform{$_->type}->{"param"} . " " . $_->name, @argsFiltered)); + map($backendTypes{$_->type} = 1, @{$function->parameters}); # register required types + my @inArgs = grep($_->direction eq "in", @{$function->parameters}); + my @outArgs = grep($_->direction eq "out", @{$function->parameters}); - my $signature = " void ${functionName}(PassRefPtr<InspectorArray> args, String* exception);"; + my $signature = " void ${functionName}(PassRefPtr<InspectorArray> args);"; !$backendMethods{${signature}} || die "Duplicate function was detected for signature '$signature'."; $backendMethods{${signature}} = $functionName; my @function; - push(@function, "void ${backendClassName}::${functionName}(PassRefPtr<InspectorArray> args, String* exception)"); + push(@function, "void ${backendClassName}::${functionName}(PassRefPtr<InspectorArray> args)"); push(@function, "{"); - my $i = 1; # zero element is the method name. - my $expectedParametersCount = scalar(@argsFiltered); - my $expectedParametersCountWithMethodName = scalar(@argsFiltered) + 1; + push(@function, " DEFINE_STATIC_LOCAL(String, backendFunctionName, (\"$functionName\"));"); + push(@function, " long callId = 0;"); + push(@function, ""); + + my $expectedParametersCount = scalar(@inArgs); + my $expectedParametersCountWithMethodName = scalar(@inArgs) + 1; push(@function, " if (args->length() != $expectedParametersCountWithMethodName) {"); - push(@function, " *exception = formatWrongArgumentsCountMessage(args->length() - 1, $expectedParametersCount);"); push(@function, " ASSERT_NOT_REACHED();"); + push(@function, " reportProtocolError(callId, backendFunctionName, formatWrongArgumentsCountMessage(args->length() - 1, $expectedParametersCount));"); push(@function, " return;"); push(@function, " }"); + push(@function, ""); - foreach my $parameter (@argsFiltered) { - my $parameterType = $parameter->type; - push(@function, " " . $typeTransform{$parameterType}->{"retVal"} . " " . $parameter->name . ";"); - push(@function, " if (!args->get(" . $i . ")->as" . $typeTransform{$parameterType}->{"accessorSuffix"} . "(&" . $parameter->name . ")) {"); - push(@function, " *exception = formatWrongArgumentTypeMessage($i, \"" . $parameter->name . "\", \"$parameterType\");"); + my $i = 1; # zero element is the method name. + foreach my $parameter (@inArgs) { + my $type = $parameter->type; + my $argumentType = $typeTransform{$type}->{$typeTransform{$type}->{"retVal"} ? "retVal" : "variable"}; + push(@function, " $argumentType " . $parameter->name . ";") if !($parameter->name eq "callId"); + push(@function, " if (!args->get($i)->as" . $typeTransform{$type}->{"accessorSuffix"} . "(&" . $parameter->name . ")) {"); push(@function, " ASSERT_NOT_REACHED();"); + push(@function, " reportProtocolError(callId, backendFunctionName, formatWrongArgumentTypeMessage($i, \"" . $parameter->name . "\", \"$type\"));"); push(@function, " return;"); push(@function, " }"); + push(@function, ""); ++$i; } - push(@function, " m_inspectorBackend->$functionName(" . join(", ", map($_->name, @argsFiltered)) . ");"); + + my $handler = $function->signature->extendedAttributes->{"handler"} || "Controller"; + my $handlerAccessor = $typeTransform{$handler}->{"handlerAccessor"}; + $backendTypes{$handler} = 1; + push(@function, " if (!$handlerAccessor) {"); + push(@function, " reportProtocolError(callId, backendFunctionName, \"Error: $handler handler is not available.\");"); + push(@function, " return;"); + push(@function, " }"); + push(@function, ""); + + + foreach (@outArgs) { # declare local variables for out arguments. + my $initializer = $typeTransform{$_->type}->{"defaultValue"} ? " = " . $typeTransform{$_->type}->{"defaultValue"} : ""; + push(@function, " " . $typeTransform{$_->type}->{"variable"} . " " . $_->name . "$initializer;"); + } + + my $args = join(", ", (grep(!($_ eq "callId"), map($_->name, @inArgs)), map("&" . $_->name, @outArgs))); + push(@function, " $handlerAccessor->$functionName($args);"); + + # The results of function call should be transfered back to frontend. + if (scalar(grep($_->name eq "callId", @inArgs))) { + my @pushArguments = map(" arguments->push" . $typeTransform{$_->type}->{"accessorSuffix"} . "(" . $_->name . ");", @outArgs); + + push(@function, ""); + push(@function, " // use InspectorFrontend as a marker of WebInspector availability"); + push(@function, " if (m_inspectorController->hasFrontend()) {"); + push(@function, " RefPtr<InspectorArray> arguments = InspectorArray::create();"); + push(@function, " arguments->pushString(\"processResponse\");"); + push(@function, " arguments->pushNumber(callId);"); + push(@function, @pushArguments); + push(@function, " m_inspectorController->inspectorClient()->sendMessageToFrontend(arguments->toJSONString());"); + push(@function, " }"); + } push(@function, "}"); push(@function, ""); push(@backendMethodsImpl, @function); } +sub generateBackendReportProtocolError +{ + my $reportProtocolError = << "EOF"; + +void ${backendClassName}::reportProtocolError(const long callId, const String& method, const String& errorText) const +{ + RefPtr<InspectorArray> arguments = InspectorArray::create(); + arguments->pushString("reportProtocolError"); + arguments->pushNumber(callId); + arguments->pushString(method); + arguments->pushString(errorText); + m_inspectorController->inspectorClient()->sendMessageToFrontend(arguments->toJSONString()); +} +EOF + return split("\n", $reportProtocolError); +} + sub generateBackendDispatcher { my @body; my @methods = map($backendMethods{$_}, keys %backendMethods); - my @mapEntries = map("dispatchMap.add(\"$_\", &${backendClassName}::$_);", @methods); - - push(@body, "void ${backendClassName}::dispatch(const String& message)"); - push(@body, "{"); - push(@body, " String exception;"); - push(@body, " typedef void (${backendClassName}::*CallHandler)(PassRefPtr<InspectorArray> args, String* exception);"); - push(@body, " typedef HashMap<String, CallHandler> DispatchMap;"); - push(@body, " DEFINE_STATIC_LOCAL(DispatchMap, dispatchMap, );"); - push(@body, " if (dispatchMap.isEmpty()) {"); - push(@body, map(" $_", @mapEntries)); - push(@body, " }"); - push(@body, ""); - push(@body, " RefPtr<InspectorValue> parsedMessage = InspectorValue::parseJSON(message);"); - push(@body, " if (!parsedMessage) {"); - push(@body, " ASSERT_NOT_REACHED();"); - push(@body, " exception = \"Error: Invalid message format. Message should be in JSON format.\";"); - push(@body, " return;"); - push(@body, " }"); - push(@body, ""); - push(@body, " RefPtr<InspectorArray> messageArray = parsedMessage->asArray();"); - push(@body, " if (!messageArray) {"); - push(@body, " ASSERT_NOT_REACHED();"); - push(@body, " exception = \"Error: Invalid message format. The message should be a JSONified array of arguments.\";"); - push(@body, " return;"); - push(@body, " }"); - push(@body, ""); - push(@body, " if (!messageArray->length()) {"); - push(@body, " ASSERT_NOT_REACHED();"); - push(@body, " exception = \"Error: Invalid message format. Empty message was received.\";"); - push(@body, " return;"); - push(@body, " }"); - push(@body, ""); - push(@body, " String methodName;"); - push(@body, " if (!messageArray->get(0)->asString(&methodName)) {"); - push(@body, " ASSERT_NOT_REACHED();"); - push(@body, " exception = \"Error: Invalid message format. The first element of the message should be method name.\";"); - push(@body, " return;"); - push(@body, " }"); - push(@body, ""); - push(@body, " HashMap<String, CallHandler>::iterator it = dispatchMap.find(methodName);"); - push(@body, " if (it == dispatchMap.end()) {"); - push(@body, " ASSERT_NOT_REACHED();"); - push(@body, " exception = String::format(\"Error: Invalid method name. '%s' wasn't found.\", methodName.utf8().data());"); - push(@body, " return;"); - push(@body, " }"); - push(@body, ""); - push(@body, " ((*this).*it->second)(messageArray, &exception);"); - push(@body, "}"); - return @body; + my @mapEntries = map(" dispatchMap.add(\"$_\", &${backendClassName}::$_);", @methods); + my $mapEntries = join("\n", @mapEntries); + + my $backendDispatcherBody = << "EOF"; +void ${backendClassName}::dispatch(const String& message) +{ + typedef void (${backendClassName}::*CallHandler)(PassRefPtr<InspectorArray> args); + typedef HashMap<String, CallHandler> DispatchMap; + DEFINE_STATIC_LOCAL(DispatchMap, dispatchMap, ); + if (dispatchMap.isEmpty()) { +$mapEntries + } + + RefPtr<InspectorValue> parsedMessage = InspectorValue::parseJSON(message); + if (!parsedMessage) { + ASSERT_NOT_REACHED(); + reportProtocolError(0, "dispatch", "Error: Invalid message format. Message should be in JSON format."); + return; + } + + RefPtr<InspectorArray> messageArray = parsedMessage->asArray(); + if (!messageArray) { + ASSERT_NOT_REACHED(); + reportProtocolError(0, "dispatch", "Error: Invalid message format. The message should be a JSONified array of arguments."); + return; + } + + if (!messageArray->length()) { + ASSERT_NOT_REACHED(); + reportProtocolError(0, "dispatch", "Error: Invalid message format. Empty message was received."); + return; + } + + String methodName; + if (!messageArray->get(0)->asString(&methodName)) { + ASSERT_NOT_REACHED(); + reportProtocolError(0, "dispatch", "Error: Invalid message format. The first element of the message should be method name."); + return; + } + + HashMap<String, CallHandler>::iterator it = dispatchMap.find(methodName); + if (it == dispatchMap.end()) { + ASSERT_NOT_REACHED(); + reportProtocolError(0, "dispatch", String::format("Error: Invalid method name. '%s' wasn't found.", methodName.utf8().data())); + return; + } + + ((*this).*it->second)(messageArray); +} +EOF + return split("\n", $backendDispatcherBody); } sub generateHeader |