summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/inspector
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-24 11:24:40 +0100
committerBen Murdoch <benm@google.com>2011-06-02 09:53:15 +0100
commit81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch)
tree7a9e5ed86ff429fd347a25153107221543909b19 /Source/WebCore/inspector
parent94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff)
downloadexternal_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/WebCore/inspector')
-rw-r--r--Source/WebCore/inspector/CodeGeneratorInspector.pm427
-rw-r--r--Source/WebCore/inspector/ConsoleMessage.cpp6
-rw-r--r--Source/WebCore/inspector/ConsoleMessage.h5
-rw-r--r--Source/WebCore/inspector/InjectedScript.cpp108
-rw-r--r--Source/WebCore/inspector/InjectedScript.h21
-rw-r--r--Source/WebCore/inspector/InjectedScriptHost.cpp77
-rw-r--r--Source/WebCore/inspector/InjectedScriptHost.h26
-rw-r--r--Source/WebCore/inspector/InjectedScriptHost.idl17
-rw-r--r--Source/WebCore/inspector/InjectedScriptSource.js199
-rw-r--r--Source/WebCore/inspector/Inspector.idl170
-rw-r--r--Source/WebCore/inspector/InspectorAgent.cpp505
-rw-r--r--Source/WebCore/inspector/InspectorAgent.h100
-rw-r--r--Source/WebCore/inspector/InspectorApplicationCacheAgent.cpp38
-rw-r--r--Source/WebCore/inspector/InspectorApplicationCacheAgent.h18
-rw-r--r--Source/WebCore/inspector/InspectorBrowserDebuggerAgent.cpp102
-rw-r--r--Source/WebCore/inspector/InspectorBrowserDebuggerAgent.h43
-rw-r--r--Source/WebCore/inspector/InspectorCSSAgent.cpp66
-rw-r--r--Source/WebCore/inspector/InspectorCSSAgent.h32
-rw-r--r--Source/WebCore/inspector/InspectorConsoleAgent.cpp47
-rw-r--r--Source/WebCore/inspector/InspectorConsoleAgent.h21
-rw-r--r--Source/WebCore/inspector/InspectorController.cpp70
-rw-r--r--Source/WebCore/inspector/InspectorDOMAgent.cpp278
-rw-r--r--Source/WebCore/inspector/InspectorDOMAgent.h75
-rw-r--r--Source/WebCore/inspector/InspectorDOMStorageAgent.cpp89
-rw-r--r--Source/WebCore/inspector/InspectorDOMStorageAgent.h34
-rw-r--r--Source/WebCore/inspector/InspectorDOMStorageResource.cpp6
-rw-r--r--Source/WebCore/inspector/InspectorDOMStorageResource.h7
-rw-r--r--Source/WebCore/inspector/InspectorDatabaseAgent.cpp78
-rw-r--r--Source/WebCore/inspector/InspectorDatabaseAgent.h31
-rw-r--r--Source/WebCore/inspector/InspectorDatabaseResource.cpp4
-rw-r--r--Source/WebCore/inspector/InspectorDatabaseResource.h6
-rw-r--r--Source/WebCore/inspector/InspectorDebuggerAgent.cpp172
-rw-r--r--Source/WebCore/inspector/InspectorDebuggerAgent.h72
-rw-r--r--Source/WebCore/inspector/InspectorInstrumentation.cpp99
-rw-r--r--Source/WebCore/inspector/InspectorInstrumentation.h21
-rw-r--r--Source/WebCore/inspector/InspectorProfilerAgent.cpp48
-rw-r--r--Source/WebCore/inspector/InspectorProfilerAgent.h31
-rw-r--r--Source/WebCore/inspector/InspectorResourceAgent.cpp52
-rw-r--r--Source/WebCore/inspector/InspectorResourceAgent.h26
-rw-r--r--Source/WebCore/inspector/InspectorRuntimeAgent.cpp23
-rw-r--r--Source/WebCore/inspector/InspectorRuntimeAgent.h13
-rw-r--r--Source/WebCore/inspector/InspectorState.cpp17
-rw-r--r--Source/WebCore/inspector/InspectorState.h4
-rw-r--r--Source/WebCore/inspector/InspectorStyleSheet.cpp14
-rw-r--r--Source/WebCore/inspector/InspectorStyleSheet.h1
-rw-r--r--Source/WebCore/inspector/InspectorTimelineAgent.cpp88
-rw-r--r--Source/WebCore/inspector/InspectorTimelineAgent.h28
-rw-r--r--Source/WebCore/inspector/InstrumentingAgents.h146
-rw-r--r--Source/WebCore/inspector/front-end/AuditRules.js84
-rw-r--r--Source/WebCore/inspector/front-end/AuditsPanel.js2
-rw-r--r--Source/WebCore/inspector/front-end/BreakpointManager.js60
-rw-r--r--Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js14
-rw-r--r--Source/WebCore/inspector/front-end/CSSStyleModel.js28
-rw-r--r--Source/WebCore/inspector/front-end/CallStackSidebarPane.js43
-rw-r--r--Source/WebCore/inspector/front-end/ConsoleView.js43
-rw-r--r--Source/WebCore/inspector/front-end/CookieItemsView.js2
-rw-r--r--Source/WebCore/inspector/front-end/DOMAgent.js134
-rw-r--r--Source/WebCore/inspector/front-end/DOMStorage.js17
-rw-r--r--Source/WebCore/inspector/front-end/DataGrid.js4
-rw-r--r--Source/WebCore/inspector/front-end/Database.js12
-rw-r--r--Source/WebCore/inspector/front-end/DebuggerModel.js45
-rw-r--r--Source/WebCore/inspector/front-end/DebuggerPresentationModel.js131
-rw-r--r--Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js707
-rw-r--r--Source/WebCore/inspector/front-end/DetailedHeapshotView.js859
-rw-r--r--Source/WebCore/inspector/front-end/ElementsPanel.js32
-rw-r--r--Source/WebCore/inspector/front-end/ElementsTreeOutline.js74
-rw-r--r--Source/WebCore/inspector/front-end/ExtensionPanel.js2
-rw-r--r--Source/WebCore/inspector/front-end/ExtensionServer.js49
-rw-r--r--Source/WebCore/inspector/front-end/FontView.js69
-rw-r--r--Source/WebCore/inspector/front-end/HAREntry.js6
-rw-r--r--Source/WebCore/inspector/front-end/HeapSnapshot.js73
-rw-r--r--Source/WebCore/inspector/front-end/HeapSnapshotView.js2
-rw-r--r--Source/WebCore/inspector/front-end/Images/helpButtonGlyph.pngbin0 -> 271 bytes
-rw-r--r--Source/WebCore/inspector/front-end/MetricsSidebarPane.js2
-rw-r--r--Source/WebCore/inspector/front-end/NetworkManager.js8
-rw-r--r--Source/WebCore/inspector/front-end/NetworkPanel.js95
-rw-r--r--Source/WebCore/inspector/front-end/Panel.js34
-rw-r--r--Source/WebCore/inspector/front-end/PleaseWaitMessage.js2
-rw-r--r--Source/WebCore/inspector/front-end/Popover.js8
-rw-r--r--Source/WebCore/inspector/front-end/ProfileView.js6
-rw-r--r--Source/WebCore/inspector/front-end/ProfilesPanel.js95
-rw-r--r--Source/WebCore/inspector/front-end/PropertiesSidebarPane.js30
-rw-r--r--Source/WebCore/inspector/front-end/RemoteObject.js16
-rw-r--r--Source/WebCore/inspector/front-end/ResourceHeadersView.js2
-rw-r--r--Source/WebCore/inspector/front-end/ResourceView.js27
-rw-r--r--Source/WebCore/inspector/front-end/ResourcesPanel.js8
-rw-r--r--Source/WebCore/inspector/front-end/Script.js2
-rw-r--r--Source/WebCore/inspector/front-end/ScriptFormatter.js101
-rw-r--r--Source/WebCore/inspector/front-end/ScriptsPanel.js670
-rwxr-xr-xSource/WebCore/inspector/front-end/SearchController.js269
-rw-r--r--Source/WebCore/inspector/front-end/SourceFrame.js341
-rw-r--r--Source/WebCore/inspector/front-end/SourceFrameContent.js127
-rw-r--r--Source/WebCore/inspector/front-end/SourceTokenizer.js5
-rw-r--r--Source/WebCore/inspector/front-end/StylesSidebarPane.js29
-rw-r--r--Source/WebCore/inspector/front-end/TestController.js33
-rw-r--r--Source/WebCore/inspector/front-end/TextEditorHighlighter.js102
-rw-r--r--Source/WebCore/inspector/front-end/TextViewer.js790
-rw-r--r--Source/WebCore/inspector/front-end/TimelinePanel.js5
-rwxr-xr-xSource/WebCore/inspector/front-end/Toolbar.js220
-rw-r--r--Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js2
-rw-r--r--Source/WebCore/inspector/front-end/WebKit.qrc4
-rw-r--r--Source/WebCore/inspector/front-end/WorkersSidebarPane.js4
-rw-r--r--Source/WebCore/inspector/front-end/heapProfiler.css105
-rw-r--r--Source/WebCore/inspector/front-end/inspector.css169
-rw-r--r--Source/WebCore/inspector/front-end/inspector.html14
-rw-r--r--Source/WebCore/inspector/front-end/inspector.js379
-rw-r--r--Source/WebCore/inspector/front-end/networkPanel.css36
-rw-r--r--Source/WebCore/inspector/front-end/textViewer.css14
-rw-r--r--Source/WebCore/inspector/front-end/utilities.js119
109 files changed, 6897 insertions, 3029 deletions
diff --git a/Source/WebCore/inspector/CodeGeneratorInspector.pm b/Source/WebCore/inspector/CodeGeneratorInspector.pm
index e4e19b0..70eb61d 100644
--- a/Source/WebCore/inspector/CodeGeneratorInspector.pm
+++ b/Source/WebCore/inspector/CodeGeneratorInspector.pm
@@ -55,10 +55,6 @@ $typeTransform{"FileSystem"} = {
"header" => "InspectorFileSystemAgent.h",
"domainAccessor" => "m_inspectorAgent->fileSystemAgent()",
};
-$typeTransform{"InjectedScript"} = {
- "forwardHeader" => "InjectedScriptHost.h",
- "domainAccessor" => "m_inspectorAgent->injectedScriptAgent()",
-};
$typeTransform{"Inspector"} = {
"forwardHeader" => "InspectorAgent.h",
"domainAccessor" => "m_inspectorAgent",
@@ -78,6 +74,11 @@ $typeTransform{"Runtime"} = {
"header" => "InspectorRuntimeAgent.h",
"domainAccessor" => "m_inspectorAgent->runtimeAgent()",
};
+$typeTransform{"Timeline"} = {
+ "forward" => "InspectorTimelineAgent",
+ "header" => "InspectorTimelineAgent.h",
+ "domainAccessor" => "m_inspectorAgent->timelineAgent()",
+};
$typeTransform{"Frontend"} = {
"forward" => "InspectorFrontend",
@@ -97,7 +98,8 @@ $typeTransform{"Object"} = {
"forward" => "InspectorObject",
"header" => "InspectorValues.h",
"JSONType" => "Object",
- "JSType" => "object"
+ "JSType" => "object",
+ "DocType" => "%s"
};
$typeTransform{"Array"} = {
"param" => "PassRefPtr<InspectorArray>",
@@ -106,7 +108,8 @@ $typeTransform{"Array"} = {
"forward" => "InspectorArray",
"header" => "InspectorValues.h",
"JSONType" => "Array",
- "JSType" => "object"
+ "JSType" => "object",
+ "DocType" => "array of %s"
};
$typeTransform{"Value"} = {
"param" => "PassRefPtr<InspectorValue>",
@@ -115,7 +118,8 @@ $typeTransform{"Value"} = {
"forward" => "InspectorValue",
"header" => "InspectorValues.h",
"JSONType" => "Value",
- "JSType" => ""
+ "JSType" => "",
+ "DocType" => "value"
};
$typeTransform{"String"} = {
"param" => "const String&",
@@ -217,12 +221,16 @@ my @backendJSStubs;
my $frontendClassName;
my %frontendTypes;
my @frontendMethods;
+my @frontendAgentFields;
my @frontendMethodsImpl;
my %frontendMethodSignatures;
my $frontendConstructor;
my @frontendConstantDeclarations;
my @frontendConstantDefinitions;
-my $frontendFooter;
+my @frontendFooter;
+
+my @documentationToc;
+my @documentationLines;
# Default constructor
sub new
@@ -250,20 +258,11 @@ sub GenerateModule
$namespace = $dataNode->module;
$namespace =~ s/core/WebCore/;
-}
-
-# Params: 'idlDocument' struct
-sub GenerateInterface
-{
- my $object = shift;
- my $interface = shift;
- my $defines = shift;
-
- my $className = $interface->name;
$frontendClassName = "InspectorFrontend";
- $frontendConstructor = " ${frontendClassName}(InspectorClient* inspectorClient) : m_inspectorClient(inspectorClient) { }";
- $frontendFooter = " private:\n InspectorClient* m_inspectorClient;";
+ $frontendConstructor = " ${frontendClassName}(InspectorClient*);";
+ push(@frontendFooter, "private:");
+ push(@frontendFooter, " InspectorClient* m_inspectorClient;");
$frontendTypes{"String"} = 1;
$frontendTypes{"InspectorClient"} = 1;
$frontendTypes{"PassRefPtr"} = 1;
@@ -281,22 +280,87 @@ sub GenerateInterface
$backendTypes{"InspectorClient"} = 1;
$backendTypes{"PassRefPtr"} = 1;
$backendTypes{"Object"} = 1;
+}
+
+# Params: 'idlDocument' struct
+sub GenerateInterface
+{
+ my $object = shift;
+ my $interface = shift;
+ my $defines = shift;
- generateFunctions($interface);
+ my %agent = (
+ methodDeclarations => [],
+ methodSignatures => {}
+ );
+ generateFunctions($interface, \%agent);
+ if (@{$agent{methodDeclarations}}) {
+ generateAgentDeclaration($interface, \%agent);
+ }
+}
+
+sub generateAgentDeclaration
+{
+ my $interface = shift;
+ my $agent = shift;
+ my $agentName = $interface->name;
+ push(@frontendMethods, " class ${agentName} {");
+ push(@frontendMethods, " public:");
+ push(@frontendMethods, " ${agentName}(InspectorClient* inspectorClient) : m_inspectorClient(inspectorClient) { }");
+ push(@frontendMethods, @{$agent->{methodDeclarations}});
+ push(@frontendMethods, " private:");
+ push(@frontendMethods, " InspectorClient* m_inspectorClient;");
+ push(@frontendMethods, " };");
+ push(@frontendMethods, "");
+
+ my $getterName = lc($agentName);
+ push(@frontendMethods, " ${agentName}* ${getterName}() { return &m_${getterName}; }");
+ push(@frontendMethods, "");
+
+ push(@frontendFooter, " ${agentName} m_${getterName};");
+
+ push(@frontendAgentFields, "m_${getterName}");
+}
+
+sub generateFrontendConstructorImpl
+{
+ my @frontendConstructorImpl;
+ push(@frontendConstructorImpl, "${frontendClassName}::${frontendClassName}(InspectorClient* inspectorClient)");
+ push(@frontendConstructorImpl, " : m_inspectorClient(inspectorClient)");
+ foreach my $agentField (@frontendAgentFields) {
+ push(@frontendConstructorImpl, " , ${agentField}(inspectorClient)");
+ }
+ push(@frontendConstructorImpl, "{");
+ push(@frontendConstructorImpl, "}");
+ return @frontendConstructorImpl;
}
sub generateFunctions
{
my $interface = shift;
+ my $agent = shift;
foreach my $function (@{$interface->functions}) {
- if ($function->signature->extendedAttributes->{"notify"}) {
- generateFrontendFunction($interface, $function);
+ if ($function->signature->extendedAttributes->{"event"}) {
+ generateFrontendFunction($interface, $function, $agent);
} else {
generateBackendFunction($interface, $function);
}
}
+ push(@documentationToc, "<li><a href='#" . $interface->name . "'>" . $interface->name . "</a></li>");
+ push(@documentationLines, "<h2 id='" . $interface->name . "'><a name=" . $interface->name . "></a>" . $interface->name . "</h2>");
+
+ push(@documentationLines, "<h3>Events</h3>");
+ foreach my $function (grep($_->signature->extendedAttributes->{"event"}, @{$interface->functions}) ) {
+ generateDocumentationEvent($interface, $function);
+ }
+
+ push(@documentationLines, "<h3>Commands</h3>");
+ foreach my $function (grep(!$_->signature->extendedAttributes->{"event"}, @{$interface->functions})) {
+ generateDocumentationCommand($interface, $function);
+ }
+
collectBackendJSStubFunctions($interface);
}
@@ -304,37 +368,76 @@ sub generateFrontendFunction
{
my $interface = shift;
my $function = shift;
+ my $agent = shift;
my $functionName = $function->signature->name;
my $domain = $interface->name;
my @argsFiltered = grep($_->direction eq "out", @{$function->parameters}); # just keep only out parameters for frontend interface.
map($frontendTypes{$_->type} = 1, @argsFiltered); # register required types.
- my $arguments = join(", ", map($typeTransform{$_->type}->{"param"} . " " . $_->name, @argsFiltered)); # prepare arguments for function signature.
+ my $arguments = join(", ", map(typeTraits($_->type, "param") . " " . $_->name, @argsFiltered)); # prepare arguments for function signature.
- my $signature = " void ${functionName}(${arguments});";
- !$frontendMethodSignatures{${signature}} || die "Duplicate frontend function was detected for signature '$signature'.";
- $frontendMethodSignatures{${signature}} = 1;
- push(@frontendMethods, $signature);
+ my $signature = " void ${functionName}(${arguments});";
+ !$agent->{methodSignatures}->{$signature} || die "Duplicate frontend function was detected for signature '$signature'.";
+ $agent->{methodSignatures}->{$signature} = 1;
+ push(@{$agent->{methodDeclarations}}, $signature);
my @function;
- push(@function, "void ${frontendClassName}::${functionName}(${arguments})");
+ push(@function, "void ${frontendClassName}::${domain}::${functionName}(${arguments})");
push(@function, "{");
push(@function, " RefPtr<InspectorObject> ${functionName}Message = InspectorObject::create();");
push(@function, " ${functionName}Message->setString(\"type\", \"event\");");
push(@function, " ${functionName}Message->setString(\"domain\", \"$domain\");");
push(@function, " ${functionName}Message->setString(\"event\", \"$functionName\");");
- push(@function, " RefPtr<InspectorObject> payloadDataObject = InspectorObject::create();");
- my @pushArguments = map(" payloadDataObject->set" . $typeTransform{$_->type}->{"JSONType"} . "(\"" . $_->name . "\", " . $_->name . ");", @argsFiltered);
+ push(@function, " RefPtr<InspectorObject> bodyObject = InspectorObject::create();");
+ my @pushArguments = map(" bodyObject->set" . typeTraits($_->type, "JSONType") . "(\"" . $_->name . "\", " . $_->name . ");", @argsFiltered);
push(@function, @pushArguments);
- push(@function, " ${functionName}Message->setObject(\"data\", payloadDataObject);");
+ push(@function, " ${functionName}Message->setObject(\"body\", bodyObject);");
push(@function, " m_inspectorClient->sendMessageToFrontend(${functionName}Message->toJSONString());");
-
push(@function, "}");
push(@function, "");
push(@frontendMethodsImpl, @function);
}
+sub generateDocumentationEvent
+{
+ my $interface = shift;
+ my $function = shift;
+
+ my $functionName = $function->signature->name;
+ my $domain = $interface->name;
+
+ my @argsFiltered = grep($_->direction eq "out", @{$function->parameters});
+
+ my @lines;
+ push(@lines, "<h4>" . $interface->name . "." . ${functionName} . "</h4>");
+ my $doc = $function->signature->extendedAttributes->{"doc"};
+ if ($doc) {
+ push(@lines, $doc);
+ }
+
+ push(@lines, "<pre style='background: lightGrey; padding: 10px'>");
+ push(@lines, "{");
+ push(@lines, " seq: &lt;number&gt;,");
+ push(@lines, " type: \"event\",");
+ push(@lines, " domain: \"$domain\",");
+ if (scalar(@argsFiltered)) {
+ push(@lines, " event: \"${functionName}\",");
+ push(@lines, " data: {");
+ my @parameters;
+ foreach my $parameter (@argsFiltered) {
+ push(@parameters, " " . parameterDocLine($parameter));
+ }
+ push(@lines, join(",\n", @parameters));
+ push(@lines, " }");
+ } else {
+ push(@lines, " event: \"${functionName}\"");
+ }
+ push(@lines, "}");
+ push(@lines, "</pre>");
+ push(@documentationLines, @lines);
+}
+
sub camelCase
{
my $value = shift;
@@ -352,12 +455,12 @@ sub generateBackendFunction
my $fullQualifiedFunctionName = $interface->name . "_" . $function->signature->name;
push(@backendConstantDeclarations, " static const char* ${fullQualifiedFunctionName}Cmd;");
- push(@backendConstantDefinitions, "const char* ${backendClassName}::${fullQualifiedFunctionName}Cmd = \"${functionName}\";");
+ push(@backendConstantDefinitions, "const char* ${backendClassName}::${fullQualifiedFunctionName}Cmd = \"${fullQualifiedFunctionName}\";");
map($backendTypes{$_->type} = 1, @{$function->parameters}); # register required types
my @inArgs = grep($_->direction eq "in" && !($_->name eq "callId") , @{$function->parameters});
my @outArgs = grep($_->direction eq "out", @{$function->parameters});
-
+
my $signature = " void ${fullQualifiedFunctionName}(long callId, InspectorObject* requestMessageObject);";
!$backendMethodSignatures{${signature}} || die "Duplicate function was detected for signature '$signature'.";
$backendMethodSignatures{${signature}} = "$fullQualifiedFunctionName";
@@ -371,14 +474,14 @@ sub generateBackendFunction
push(@function, "");
my $domain = $interface->name;
- my $domainAccessor = $typeTransform{$domain}->{"domainAccessor"};
+ my $domainAccessor = typeTraits($domain, "domainAccessor");
$backendTypes{$domain} = 1;
push(@function, " if (!$domainAccessor)");
push(@function, " protocolErrors->pushString(\"Protocol Error: $domain handler is not available.\");");
push(@function, "");
# declare local variables for out arguments.
- push(@function, map(" " . $typeTransform{$_->type}->{"variable"} . " " . $_->name . " = " . $typeTransform{$_->type}->{"defaultValue"} . ";", @outArgs));
+ push(@function, map(" " . typeTraits($_->type, "variable") . " " . $_->name . " = " . typeTraits($_->type, "defaultValue") . ";", @outArgs));
my $indent = "";
if (scalar(@inArgs)) {
@@ -388,15 +491,18 @@ sub generateBackendFunction
my $name = $parameter->name;
my $type = $parameter->type;
my $typeString = camelCase($parameter->type);
- push(@function, " " . $typeTransform{$type}->{"variable"} . " $name = get$typeString(argumentsContainer.get(), \"$name\", protocolErrors.get());");
+ push(@function, " " . typeTraits($type, "variable") . " $name = get$typeString(argumentsContainer.get(), \"$name\", protocolErrors.get());");
}
push(@function, "");
$indent = " ";
}
- my $args = join(", ", (map($_->name, @inArgs), map("&" . $_->name, @outArgs)));
+ push(@function, "$indent ErrorString error;");
+ my $args = join(", ", ("&error", map($_->name, @inArgs), map("&" . $_->name, @outArgs)));
push(@function, "$indent if (!protocolErrors->length())");
push(@function, "$indent $domainAccessor->$functionName($args);");
+ push(@function, "$indent if (error.length())");
+ push(@function, "$indent protocolErrors->pushString(error);");
if (scalar(@inArgs)) {
push(@function, " } else {");
push(@function, " protocolErrors->pushString(\"Protocol Error: 'arguments' property with type 'object' was not found.\");");
@@ -407,16 +513,14 @@ sub generateBackendFunction
push(@function, " if ((callId || protocolErrors->length()) && m_inspectorAgent->hasFrontend()) {");
push(@function, " RefPtr<InspectorObject> responseMessage = InspectorObject::create();");
push(@function, " responseMessage->setNumber(\"seq\", callId);");
- push(@function, " responseMessage->setString(\"domain\", \"$domain\");");
- push(@function, " responseMessage->setBoolean(\"success\", !protocolErrors->length());");
push(@function, "");
push(@function, " if (protocolErrors->length())");
push(@function, " responseMessage->setArray(\"errors\", protocolErrors);");
if (scalar(@outArgs)) {
push(@function, " else {");
- push(@function, " RefPtr<InspectorObject> responseData = InspectorObject::create();");
- push(@function, map(" responseData->set" . $typeTransform{$_->type}->{"JSONType"} . "(\"" . $_->name . "\", " . $_->name . ");", @outArgs));
- push(@function, " responseMessage->setObject(\"data\", responseData);");
+ push(@function, " RefPtr<InspectorObject> responseBody = InspectorObject::create();");
+ push(@function, map(" responseBody->set" . typeTraits($_->type, "JSONType") . "(\"" . $_->name . "\", " . $_->name . ");", @outArgs));
+ push(@function, " responseMessage->setObject(\"body\", responseBody);");
push(@function, " }");
}
push(@function, " m_inspectorAgent->inspectorClient()->sendMessageToFrontend(responseMessage->toJSONString());");
@@ -428,6 +532,64 @@ sub generateBackendFunction
push(@backendMethodsImpl, @function);
}
+sub generateDocumentationCommand
+{
+ my $interface = shift;
+ my $function = shift;
+
+ my $functionName = $function->signature->name;
+ my $domain = $interface->name;
+
+ my @lines;
+
+ push(@lines, "<h4>" . $interface->name . "." . ${functionName} . "</h4>");
+ my $doc = $function->signature->extendedAttributes->{"doc"};
+ if ($doc) {
+ push(@lines, $doc);
+ }
+
+ my @inArgs = grep($_->direction eq "in" && !($_->name eq "callId") , @{$function->parameters});
+ push(@lines, "<pre style='background: lightGrey; padding: 10px'>");
+ push(@lines, "request: {");
+ push(@lines, " seq: &lt;number&gt;,");
+ push(@lines, " type: \"request\",");
+ push(@lines, " domain: \"" . $interface->name . "\",");
+ if (scalar(@inArgs)) {
+ push(@lines, " command: \"${functionName}\",");
+ push(@lines, " arguments: {");
+ my @parameters;
+ foreach my $parameter (@inArgs) {
+ push(@parameters, " " . parameterDocLine($parameter));
+ }
+ push(@lines, join(",\n", @parameters));
+ push(@lines, " }");
+ } else {
+ push(@lines, " command: \"${functionName}\"");
+ }
+ push(@lines, "}");
+
+ my @outArgs = grep($_->direction eq "out", @{$function->parameters});
+ push(@lines, "");
+ push(@lines, "response: {");
+ push(@lines, " seq: &lt;number&gt;,");
+ if (scalar(@outArgs)) {
+ push(@lines, " type: \"response\",");
+ push(@lines, " body: {");
+ my @parameters;
+ foreach my $parameter (@outArgs) {
+ push(@parameters, " " . parameterDocLine($parameter));
+ }
+ push(@lines, join(",\n", @parameters));
+ push(@lines, " }");
+ } else {
+ push(@lines, " type: \"response\"");
+ }
+ push(@lines, "}");
+ push(@lines, "</pre>");
+
+ push(@documentationLines, @lines);
+}
+
sub generateBackendReportProtocolError
{
my $reportProtocolError = << "EOF";
@@ -436,7 +598,6 @@ void ${backendClassName}::reportProtocolError(const long callId, const String& e
{
RefPtr<InspectorObject> message = InspectorObject::create();
message->setNumber("seq", callId);
- message->setBoolean("success", false);
RefPtr<InspectorArray> errors = InspectorArray::create();
errors->pushString(errorText);
message->setArray("errors", errors);
@@ -449,10 +610,10 @@ EOF
sub generateArgumentGetters
{
my $type = shift;
- my $json = $typeTransform{$type}{"JSONType"};
- my $variable = $typeTransform{$type}{"variable"};
- my $defaultValue = $typeTransform{$type}{"defaultValue"};
- my $return = $typeTransform{$type}{"return"} ? $typeTransform{$type}{"return"} : $typeTransform{$type}{"param"};
+ my $json = typeTraits($type, "JSONType");
+ my $variable = typeTraits($type, "variable");
+ my $defaultValue = typeTraits($type, "defaultValue");
+ my $return = typeTraits($type, "return") ? typeTraits($type, "return") : typeTraits($type, "param");
my $typeString = camelCase($type);
push(@backendConstantDeclarations, " $return get$typeString(InspectorObject* object, const String& name, InspectorArray* protocolErrors);");
@@ -487,6 +648,11 @@ sub generateBackendDispatcher
my $mapEntries = join("\n", @mapEntries);
my $backendDispatcherBody = << "EOF";
+static String commandName(const String& domain, const String& command)
+{
+ return makeString(domain, "_", command);
+}
+
void ${backendClassName}::dispatch(const String& message)
{
typedef void (${backendClassName}::*CallHandler)(long callId, InspectorObject* messageObject);
@@ -522,6 +688,18 @@ $mapEntries
return;
}
+ RefPtr<InspectorValue> domainValue = messageObject->get("domain");
+ if (!domainValue) {
+ reportProtocolError(callId, "Protocol Error: Invalid message format. 'domain' property wasn't found.");
+ return;
+ }
+
+ String domain;
+ if (!domainValue->asString(&domain)) {
+ reportProtocolError(callId, "Protocol Error: Invalid message format. The type of 'domain' property should be string.");
+ return;
+ }
+
RefPtr<InspectorValue> callIdValue = messageObject->get("seq");
if (!callIdValue) {
reportProtocolError(callId, "Protocol Error: Invalid message format. 'seq' property was not found in the request.");
@@ -533,9 +711,9 @@ $mapEntries
return;
}
- HashMap<String, CallHandler>::iterator it = dispatchMap.find(command);
+ HashMap<String, CallHandler>::iterator it = dispatchMap.find(commandName(domain, command));
if (it == dispatchMap.end()) {
- reportProtocolError(callId, makeString("Protocol Error: Invalid command was received. '", command, "' wasn't found."));
+ reportProtocolError(callId, makeString("Protocol Error: Invalid command was received. '", command, "' wasn't found in domain ", domain, "."));
return;
}
@@ -558,11 +736,16 @@ bool ${backendClassName}::getCommandName(const String& message, String* result)
if (!object)
return false;
- RefPtr<InspectorValue> commandValue = object->get("command");
- if (!commandValue)
+ String domain;
+ if (!object->getString("domain", &domain))
return false;
- return commandValue->asString(result);
+ String command;
+ if (!object->getString("command", &command))
+ return false;
+
+ *result = commandName(domain, command);
+ return true;
}
EOF
return split("\n", $messageParserBody);
@@ -571,12 +754,12 @@ EOF
sub collectBackendJSStubFunctions
{
my $interface = shift;
- my @functions = grep(!$_->signature->extendedAttributes->{"notify"}, @{$interface->functions});
+ my @functions = grep(!$_->signature->extendedAttributes->{"event"}, @{$interface->functions});
my $domain = $interface->name;
foreach my $function (@functions) {
my $name = $function->signature->name;
- my $argumentNames = join(",", map("\"" . $_->name . "\": \"" . $typeTransform{$_->type}->{"JSType"} . "\"", grep($_->direction eq "in", @{$function->parameters})));
+ my $argumentNames = join(",", map("\"" . $_->name . "\": \"" . typeTraits($_->type, "JSType") . "\"", grep($_->direction eq "in", @{$function->parameters})));
push(@backendJSStubs, " this._registerDelegate('{" .
"\"seq\": 0, " .
"\"domain\": \"$domain\", " .
@@ -595,6 +778,7 @@ $licenseTemplate
InspectorBackendStub = function()
{
this._lastCallbackId = 1;
+ this._pendingResponsesCount = 0;
this._callbacks = {};
this._domainDispatchers = {};
$JSStubs
@@ -608,22 +792,13 @@ InspectorBackendStub.prototype = {
return callbackId;
},
- _processResponse: function(callbackId, args)
- {
- var callback = this._callbacks[callbackId];
- callback.apply(null, args);
- delete this._callbacks[callbackId];
- },
-
- _removeResponseCallbackEntry: function(callbackId)
- {
- delete this._callbacks[callbackId];
- },
-
_registerDelegate: function(commandInfo)
{
var commandObject = JSON.parse(commandInfo);
- this[commandObject.command] = this.sendMessageToBackend.bind(this, commandInfo);
+ var agentName = commandObject.domain + "Agent";
+ if (!window[agentName])
+ window[agentName] = {};
+ window[agentName][commandObject.command] = this.sendMessageToBackend.bind(this, commandInfo);
},
sendMessageToBackend: function()
@@ -633,29 +808,33 @@ InspectorBackendStub.prototype = {
for (var key in request.arguments) {
if (args.length === 0) {
- console.error("Protocol Error: Invalid number of arguments for 'InspectorBackend.%s' call. It should have the next arguments '%s'.", request.command, JSON.stringify(request.arguments));
+ console.error("Protocol Error: Invalid number of arguments for '" + request.domain + "Agent." + request.command + "' call. It should have the next arguments '" + JSON.stringify(request.arguments) + "'.");
return;
}
var value = args.shift();
if (request.arguments[key] && typeof value !== request.arguments[key]) {
- console.error("Protocol Error: Invalid type of argument '%s' for 'InspectorBackend.%s' call. It should be '%s' but it is '%s'.", key, request.command, request.arguments[key], typeof value);
+ console.error("Protocol Error: Invalid type of argument '" + key + "' for '" + request.domain + "Agent." + request.command + "' call. It should be '" + request.arguments[key] + "' but it is '" + typeof value + "'.");
return;
}
request.arguments[key] = value;
}
+ var callback;
if (args.length === 1) {
if (typeof args[0] !== "function" && typeof args[0] !== "undefined") {
- console.error("Protocol Error: Optional callback argument for 'InspectorBackend.%s' call should be a function but its type is '%s'.", request.command, typeof args[0]);
+ console.error("Protocol Error: Optional callback argument for '" + request.domain + "Agent." + request.command + "' call should be a function but its type is '" + typeof args[0] + "'.");
return;
}
- request.seq = this._wrap(args[0]);
+ callback = args[0];
}
+ request.seq = this._wrap(callback || function() {});
if (window.dumpInspectorProtocolMessages)
console.log("frontend: " + JSON.stringify(request));
var message = JSON.stringify(request);
+
+ ++this._pendingResponsesCount;
InspectorFrontendHost.sendMessageToBackend(message);
},
@@ -672,28 +851,33 @@ InspectorBackendStub.prototype = {
var messageObject = (typeof message === "string") ? JSON.parse(message) : message;
var arguments = [];
- if (messageObject.data)
- for (var key in messageObject.data)
- arguments.push(messageObject.data[key]);
+ if (messageObject.body)
+ for (var key in messageObject.body)
+ arguments.push(messageObject.body[key]);
if ("seq" in messageObject) { // just a response for some request
- if (messageObject.success)
- this._processResponse(messageObject.seq, arguments);
- else {
- this._removeResponseCallbackEntry(messageObject.seq)
+ if (!messageObject.errors)
+ this._callbacks[messageObject.seq].apply(null, arguments);
+ else
this.reportProtocolError(messageObject);
- }
+
+ --this._pendingResponsesCount;
+ delete this._callbacks[messageObject.seq];
+
+ if (this._scripts && !this._pendingResponsesCount)
+ this.runAfterPendingDispatches();
+
return;
}
if (messageObject.type === "event") {
if (!(messageObject.domain in this._domainDispatchers)) {
- console.error("Protocol Error: the message is for non-existing domain '%s'", messageObject.domain);
+ console.error("Protocol Error: the message is for non-existing domain '" + messageObject.domain + "'");
return;
}
var dispatcher = this._domainDispatchers[messageObject.domain];
if (!(messageObject.event in dispatcher)) {
- console.error("Protocol Error: Attempted to dispatch an unimplemented method '%s.%s'", messageObject.domain, messageObject.event);
+ console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.domain + "." + messageObject.event + "'");
return;
}
dispatcher[messageObject.event].apply(dispatcher, arguments);
@@ -702,10 +886,25 @@ InspectorBackendStub.prototype = {
reportProtocolError: function(messageObject)
{
- console.error("Protocol Error: InspectorBackend request with seq = %d failed.", messageObject.seq);
+ console.error("Protocol Error: InspectorBackend request with seq = " + messageObject.seq + " failed.");
for (var i = 0; i < messageObject.errors.length; ++i)
console.error(" " + messageObject.errors[i]);
- this._removeResponseCallbackEntry(messageObject.seq);
+ },
+
+ runAfterPendingDispatches: function(script)
+ {
+ if (!this._scripts)
+ this._scripts = [];
+
+ if (script)
+ this._scripts.push(script);
+
+ if (!this._pendingResponsesCount) {
+ var scripts = this._scripts;
+ this._scripts = []
+ for (var id = 0; id < scripts.length; ++id)
+ scripts[id].call(this);
+ }
}
}
@@ -724,8 +923,8 @@ sub generateHeader
my $methods = shift;
my $footer = shift;
- my $forwardHeaders = join("\n", sort(map("#include <" . $typeTransform{$_}->{"forwardHeader"} . ">", grep($typeTransform{$_}->{"forwardHeader"}, keys %{$types}))));
- my $forwardDeclarations = join("\n", sort(map("class " . $typeTransform{$_}->{"forward"} . ";", grep($typeTransform{$_}->{"forward"}, keys %{$types}))));
+ my $forwardHeaders = join("\n", sort(map("#include <" . typeTraits($_, "forwardHeader") . ">", grep(typeTraits($_, "forwardHeader"), keys %{$types}))));
+ my $forwardDeclarations = join("\n", sort(map("class " . typeTraits($_, "forward") . ";", grep(typeTraits($_, "forward"), keys %{$types}))));
my $constantDeclarations = join("\n", @{$constants});
my $methodsDeclarations = join("\n", @{$methods});
@@ -742,6 +941,8 @@ namespace $namespace {
$forwardDeclarations
+typedef String ErrorString;
+
class $className {
public:
$constructor
@@ -777,7 +978,7 @@ sub generateSource
my %headers;
foreach my $type (keys %{$types}) {
- $headers{"#include \"" . $typeTransform{$type}->{"header"} . "\""} = 1 if !$typeTransform{$type}->{"header"} eq "";
+ $headers{"#include \"" . typeTraits($type, "header") . "\""} = 1 if !typeTraits($type, "header") eq "";
}
push(@sourceContent, sort keys %headers);
push(@sourceContent, "");
@@ -794,12 +995,50 @@ sub generateSource
return @sourceContent;
}
+sub typeTraits
+{
+ my $type = shift;
+ my $trait = shift;
+ return $typeTransform{$type}->{$trait};
+}
+
+sub parameterDocType
+{
+ my $parameter = shift;
+ my $subtype = $parameter->extendedAttributes->{"type"};
+ if ($subtype) {
+ my $pattern = typeTraits($parameter->type, "DocType");
+ return sprintf($pattern, "&lt;$subtype&gt;");
+ }
+
+ my $subtypeRef = $parameter->extendedAttributes->{"typeRef"};
+ if ($subtypeRef) {
+ my $pattern = typeTraits($parameter->type, "DocType");
+ return sprintf($pattern, "&lt;<a href='#$subtypeRef'>" . $subtypeRef . "</a>&gt;");
+ }
+
+ return "&lt;" . typeTraits($parameter->type, "JSType") . "&gt;";
+}
+
+sub parameterDocLine
+{
+ my $parameter = shift;
+
+ my $result = $parameter->name . ": " . parameterDocType($parameter);
+ my $doc = $parameter->extendedAttributes->{"doc"};
+ if ($doc) {
+ $result = $result . " // " . $doc;
+ }
+ return $result;
+}
+
sub finish
{
my $object = shift;
push(@backendMethodsImpl, generateBackendDispatcher());
push(@backendMethodsImpl, generateBackendReportProtocolError());
+ unshift(@frontendMethodsImpl, generateFrontendConstructorImpl(), "");
open(my $SOURCE, ">$outputDir/$frontendClassName.cpp") || die "Couldn't open file $outputDir/$frontendClassName.cpp";
print $SOURCE join("\n", generateSource($frontendClassName, \%frontendTypes, \@frontendConstantDefinitions, \@frontendMethodsImpl));
@@ -807,7 +1046,7 @@ sub finish
undef($SOURCE);
open(my $HEADER, ">$outputHeadersDir/$frontendClassName.h") || die "Couldn't open file $outputHeadersDir/$frontendClassName.h";
- print $HEADER generateHeader($frontendClassName, \%frontendTypes, $frontendConstructor, \@frontendConstantDeclarations, \@frontendMethods, $frontendFooter);
+ print $HEADER generateHeader($frontendClassName, \%frontendTypes, $frontendConstructor, \@frontendConstantDeclarations, \@frontendMethods, join("\n", @frontendFooter));
close($HEADER);
undef($HEADER);
@@ -816,7 +1055,7 @@ sub finish
push(@backendConstantDeclarations, "private:");
foreach my $type (keys %backendTypes) {
- if ($typeTransform{$type}{"JSONType"}) {
+ if (typeTraits($type, "JSONType")) {
push(@backendMethodsImpl, generateArgumentGetters($type));
}
}
@@ -840,6 +1079,14 @@ sub finish
print $JS_STUB join("\n", generateBackendStubJS());
close($JS_STUB);
undef($JS_STUB);
+
+ open(my $DOCS, ">$outputDir/WebInspectorProtocol.html") || die "Couldn't open file $outputDir/WebInspectorProtocol.html";
+ print $DOCS "<ol class='toc' style='list-style: none; padding: 0'>";
+ print $DOCS join("\n", @documentationToc);
+ print $DOCS "</ol>";
+ print $DOCS join("\n", @documentationLines);
+ close($DOCS);
+ undef($DOCS);
}
1;
diff --git a/Source/WebCore/inspector/ConsoleMessage.cpp b/Source/WebCore/inspector/ConsoleMessage.cpp
index 8d56a5a..63fb020 100644
--- a/Source/WebCore/inspector/ConsoleMessage.cpp
+++ b/Source/WebCore/inspector/ConsoleMessage.cpp
@@ -86,7 +86,7 @@ ConsoleMessage::~ConsoleMessage()
{
}
-void ConsoleMessage::addToFrontend(InspectorFrontend* frontend, InjectedScriptHost* injectedScriptHost)
+void ConsoleMessage::addToFrontend(InspectorFrontend::Console* frontend, InjectedScriptHost* injectedScriptHost)
{
RefPtr<InspectorObject> jsonObj = InspectorObject::create();
jsonObj->setNumber("source", static_cast<int>(m_source));
@@ -103,7 +103,7 @@ void ConsoleMessage::addToFrontend(InspectorFrontend* frontend, InjectedScriptHo
if (!injectedScript.hasNoValue()) {
RefPtr<InspectorArray> jsonArgs = InspectorArray::create();
for (unsigned i = 0; i < m_arguments->argumentCount(); ++i) {
- RefPtr<InspectorValue> inspectorValue = injectedScript.wrapForConsole(m_arguments->argumentAt(i));
+ RefPtr<InspectorValue> inspectorValue = injectedScript.wrapObject(m_arguments->argumentAt(i), "console");
if (!inspectorValue) {
ASSERT_NOT_REACHED();
return;
@@ -118,7 +118,7 @@ void ConsoleMessage::addToFrontend(InspectorFrontend* frontend, InjectedScriptHo
frontend->addConsoleMessage(jsonObj);
}
-void ConsoleMessage::updateRepeatCountInConsole(InspectorFrontend* frontend)
+void ConsoleMessage::updateRepeatCountInConsole(InspectorFrontend::Console* frontend)
{
frontend->updateConsoleMessageRepeatCount(m_repeatCount);
}
diff --git a/Source/WebCore/inspector/ConsoleMessage.h b/Source/WebCore/inspector/ConsoleMessage.h
index 7c3348b..26e5675 100644
--- a/Source/WebCore/inspector/ConsoleMessage.h
+++ b/Source/WebCore/inspector/ConsoleMessage.h
@@ -32,6 +32,7 @@
#define ConsoleMessage_h
#include "Console.h"
+#include "InspectorFrontend.h"
#include "ScriptState.h"
#include <wtf/Forward.h>
@@ -54,8 +55,8 @@ public:
ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& m, const String& responseUrl, unsigned long identifier);
~ConsoleMessage();
- void addToFrontend(InspectorFrontend*, InjectedScriptHost*);
- void updateRepeatCountInConsole(InspectorFrontend* frontend);
+ void addToFrontend(InspectorFrontend::Console*, InjectedScriptHost*);
+ void updateRepeatCountInConsole(InspectorFrontend::Console*);
void incrementCount() { ++m_repeatCount; }
bool isEqual(ConsoleMessage* msg) const;
diff --git a/Source/WebCore/inspector/InjectedScript.cpp b/Source/WebCore/inspector/InjectedScript.cpp
index 9fd606b..6c115d0 100644
--- a/Source/WebCore/inspector/InjectedScript.cpp
+++ b/Source/WebCore/inspector/InjectedScript.cpp
@@ -33,7 +33,10 @@
#if ENABLE(INSPECTOR)
+#include "Frame.h"
+#include "InjectedScriptHost.h"
#include "InspectorValues.h"
+#include "Node.h"
#include "PlatformString.h"
#include "ScriptFunctionCall.h"
@@ -53,37 +56,20 @@ void InjectedScript::evaluate(const String& expression, const String& objectGrou
makeCall(function, result);
}
-void InjectedScript::evaluateOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
-{
- ScriptFunctionCall function(m_injectedScriptObject, "evaluateOnCallFrame");
- function.appendArgument(callFrameId->toJSONString());
- function.appendArgument(expression);
- function.appendArgument(objectGroup);
- function.appendArgument(includeCommandLineAPI);
- makeCall(function, result);
-}
-
-void InjectedScript::evaluateOnSelf(const String& functionBody, PassRefPtr<InspectorArray> argumentsArray, RefPtr<InspectorValue>* result)
-{
- ScriptFunctionCall function(m_injectedScriptObject, "evaluateOnSelf");
- function.appendArgument(functionBody);
- function.appendArgument(argumentsArray->toJSONString());
- makeCall(function, result);
-}
-
-void InjectedScript::getCompletions(const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
+void InjectedScript::evaluateOn(PassRefPtr<InspectorObject> objectId, const String& expression, RefPtr<InspectorValue>* result)
{
- ScriptFunctionCall function(m_injectedScriptObject, "getCompletions");
+ ScriptFunctionCall function(m_injectedScriptObject, "evaluateOn");
+ function.appendArgument(objectId->toJSONString());
function.appendArgument(expression);
- function.appendArgument(includeCommandLineAPI);
makeCall(function, result);
}
-void InjectedScript::getCompletionsOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
+void InjectedScript::evaluateOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
{
- ScriptFunctionCall function(m_injectedScriptObject, "getCompletionsOnCallFrame");
+ ScriptFunctionCall function(m_injectedScriptObject, "evaluateOnCallFrame");
function.appendArgument(callFrameId->toJSONString());
function.appendArgument(expression);
+ function.appendArgument(objectGroup);
function.appendArgument(includeCommandLineAPI);
makeCall(function, result);
}
@@ -98,44 +84,45 @@ void InjectedScript::getProperties(PassRefPtr<InspectorObject> objectId, bool ig
makeCall(function, result);
}
-void InjectedScript::pushNodeToFrontend(PassRefPtr<InspectorObject> objectId, RefPtr<InspectorValue>* result)
+Node* InjectedScript::nodeForObjectId(PassRefPtr<InspectorObject> objectId)
{
- ScriptFunctionCall function(m_injectedScriptObject, "pushNodeToFrontend");
+ if (hasNoValue() || !canAccessInspectedWindow())
+ return 0;
+
+ ScriptFunctionCall function(m_injectedScriptObject, "nodeForObjectId");
function.appendArgument(objectId->toJSONString());
- makeCall(function, result);
-}
-void InjectedScript::resolveNode(long nodeId, RefPtr<InspectorValue>* result)
-{
- ScriptFunctionCall function(m_injectedScriptObject, "resolveNode");
- function.appendArgument(nodeId);
- makeCall(function, result);
-}
+ bool hadException = false;
+ ScriptValue resultValue = function.call(hadException);
+ ASSERT(!hadException);
-void InjectedScript::getNodeProperties(long nodeId, PassRefPtr<InspectorArray> propertiesArray, RefPtr<InspectorValue>* result)
-{
- ScriptFunctionCall function(m_injectedScriptObject, "getNodeProperties");
- function.appendArgument(nodeId);
- function.appendArgument(propertiesArray->toJSONString());
- makeCall(function, result);
+ return InjectedScriptHost::scriptValueAsNode(resultValue);
}
-void InjectedScript::getNodePrototypes(long nodeId, RefPtr<InspectorValue>* result)
+void InjectedScript::resolveNode(long nodeId, RefPtr<InspectorValue>* result)
{
- ScriptFunctionCall function(m_injectedScriptObject, "getNodePrototypes");
+ ScriptFunctionCall function(m_injectedScriptObject, "resolveNode");
function.appendArgument(nodeId);
makeCall(function, result);
}
void InjectedScript::setPropertyValue(PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result)
{
- ScriptFunctionCall function(m_injectedScriptObject, "getNodeProperties");
+ ScriptFunctionCall function(m_injectedScriptObject, "setPropertyValue");
function.appendArgument(objectId->toJSONString());
function.appendArgument(propertyName);
function.appendArgument(expression);
makeCall(function, result);
}
+void InjectedScript::releaseObject(PassRefPtr<InspectorObject> objectId)
+{
+ ScriptFunctionCall function(m_injectedScriptObject, "releaseObject");
+ function.appendArgument(objectId->toJSONString());
+ RefPtr<InspectorValue> result;
+ makeCall(function, &result);
+}
+
#if ENABLE(JAVASCRIPT_DEBUGGER)
PassRefPtr<InspectorValue> InjectedScript::callFrames()
{
@@ -146,23 +133,41 @@ PassRefPtr<InspectorValue> InjectedScript::callFrames()
}
#endif
-PassRefPtr<InspectorValue> InjectedScript::wrapForConsole(ScriptValue value)
+PassRefPtr<InspectorObject> InjectedScript::wrapObject(ScriptValue value, const String& groupName)
{
ASSERT(!hasNoValue());
- ScriptFunctionCall wrapFunction(m_injectedScriptObject, "wrapObjectForConsole");
+ ScriptFunctionCall wrapFunction(m_injectedScriptObject, "wrapObject");
wrapFunction.appendArgument(value);
+ wrapFunction.appendArgument(groupName);
wrapFunction.appendArgument(canAccessInspectedWindow());
bool hadException = false;
ScriptValue r = wrapFunction.call(hadException);
- if (hadException)
- return InspectorString::create("<exception>");
- return r.toInspectorValue(m_injectedScriptObject.scriptState());
+ if (hadException) {
+ RefPtr<InspectorObject> result = InspectorObject::create();
+ result->setString("description", "<exception>");
+ return result;
+ }
+ return r.toInspectorValue(m_injectedScriptObject.scriptState())->asObject();
+}
+
+PassRefPtr<InspectorObject> InjectedScript::wrapNode(Node* node, const String& groupName)
+{
+ return wrapObject(nodeAsScriptValue(node), groupName);
+}
+
+void InjectedScript::inspectNode(Node* node)
+{
+ ASSERT(!hasNoValue());
+ ScriptFunctionCall function(m_injectedScriptObject, "inspectNode");
+ function.appendArgument(nodeAsScriptValue(node));
+ RefPtr<InspectorValue> result;
+ makeCall(function, &result);
}
-void InjectedScript::releaseWrapperObjectGroup(const String& objectGroup)
+void InjectedScript::releaseObjectGroup(const String& objectGroup)
{
ASSERT(!hasNoValue());
- ScriptFunctionCall releaseFunction(m_injectedScriptObject, "releaseWrapperObjectGroup");
+ ScriptFunctionCall releaseFunction(m_injectedScriptObject, "releaseObjectGroup");
releaseFunction.appendArgument(objectGroup);
releaseFunction.call();
}
@@ -189,6 +194,11 @@ void InjectedScript::makeCall(ScriptFunctionCall& function, RefPtr<InspectorValu
*result = InspectorValue::null();
}
+ScriptValue InjectedScript::nodeAsScriptValue(Node* node)
+{
+ return InjectedScriptHost::nodeAsScriptValue(m_injectedScriptObject.scriptState(), node);
+}
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/inspector/InjectedScript.h b/Source/WebCore/inspector/InjectedScript.h
index 0dd41ae..33d5411 100644
--- a/Source/WebCore/inspector/InjectedScript.h
+++ b/Source/WebCore/inspector/InjectedScript.h
@@ -41,6 +41,7 @@
namespace WebCore {
class InspectorValue;
+class Node;
class ScriptFunctionCall;
class InjectedScript {
@@ -51,31 +52,31 @@ public:
bool hasNoValue() const { return m_injectedScriptObject.hasNoValue(); }
void evaluate(const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
+ void evaluateOn(PassRefPtr<InspectorObject> objectId, const String& expression, RefPtr<InspectorValue>* result);
void evaluateOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
- void evaluateOnSelf(const String& functionBody, PassRefPtr<InspectorArray> argumentsArray, RefPtr<InspectorValue>* result);
- void getCompletions(const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
- void getCompletionsOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
void getProperties(PassRefPtr<InspectorObject> objectId, bool ignoreHasOwnProperty, bool abbreviate, RefPtr<InspectorValue>* result);
- void pushNodeToFrontend(PassRefPtr<InspectorObject> objectId, RefPtr<InspectorValue>* result);
+ Node* nodeForObjectId(PassRefPtr<InspectorObject> objectId);
void resolveNode(long nodeId, RefPtr<InspectorValue>* result);
- void getNodeProperties(long nodeId, PassRefPtr<InspectorArray> propertiesArray, RefPtr<InspectorValue>* result);
- void getNodePrototypes(long nodeId, RefPtr<InspectorValue>* result);
void setPropertyValue(PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result);
-
+ void releaseObject(PassRefPtr<InspectorObject> objectId);
+
#if ENABLE(JAVASCRIPT_DEBUGGER)
PassRefPtr<InspectorValue> callFrames();
#endif
- PassRefPtr<InspectorValue> wrapForConsole(ScriptValue);
- void releaseWrapperObjectGroup(const String&);
+ PassRefPtr<InspectorObject> wrapObject(ScriptValue, const String& groupName);
+ PassRefPtr<InspectorObject> wrapNode(Node*, const String& groupName);
+ void inspectNode(Node*);
+ void releaseObjectGroup(const String&);
ScriptState* scriptState() const { return m_injectedScriptObject.scriptState(); }
private:
friend InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState*);
explicit InjectedScript(ScriptObject);
- bool canAccessInspectedWindow();
+ bool canAccessInspectedWindow();
void makeCall(ScriptFunctionCall&, RefPtr<InspectorValue>* result);
+ ScriptValue nodeAsScriptValue(Node*);
ScriptObject m_injectedScriptObject;
};
diff --git a/Source/WebCore/inspector/InjectedScriptHost.cpp b/Source/WebCore/inspector/InjectedScriptHost.cpp
index fbb4dbf..ad4df45 100644
--- a/Source/WebCore/inspector/InjectedScriptHost.cpp
+++ b/Source/WebCore/inspector/InjectedScriptHost.cpp
@@ -42,10 +42,10 @@
#include "InspectorAgent.h"
#include "InspectorClient.h"
#include "InspectorConsoleAgent.h"
-#include "InspectorDOMAgent.h"
#include "InspectorDOMStorageAgent.h"
#include "InspectorDatabaseAgent.h"
#include "InspectorFrontend.h"
+#include "InspectorValues.h"
#include "Pasteboard.h"
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -80,73 +80,59 @@ InjectedScriptHost::~InjectedScriptHost()
{
}
-void InjectedScriptHost::evaluateOnSelf(const String& functionBody, PassRefPtr<InspectorArray> argumentsArray, RefPtr<InspectorValue>* result)
+void InjectedScriptHost::inspectImpl(PassRefPtr<InspectorValue> objectId, PassRefPtr<InspectorValue> hints)
{
- InjectedScript injectedScript = injectedScriptForMainFrame();
- if (!injectedScript.hasNoValue())
- injectedScript.evaluateOnSelf(functionBody, argumentsArray, result);
+ if (InspectorFrontend* fe = frontend())
+ fe->inspector()->inspect(objectId->asObject(), hints->asObject());
}
void InjectedScriptHost::clearConsoleMessages()
{
- if (m_inspectorAgent)
- m_inspectorAgent->consoleAgent()->clearConsoleMessages();
+ if (m_inspectorAgent) {
+ ErrorString error;
+ m_inspectorAgent->consoleAgent()->clearConsoleMessages(&error);
+ }
}
-void InjectedScriptHost::copyText(const String& text)
+void InjectedScriptHost::addInspectedNode(Node* node)
{
- Pasteboard::generalPasteboard()->writePlainText(text);
+ m_inspectedNodes.prepend(node);
+ while (m_inspectedNodes.size() > 5)
+ m_inspectedNodes.removeLast();
}
-Node* InjectedScriptHost::nodeForId(long nodeId)
+void InjectedScriptHost::clearInspectedNodes()
{
- if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
- return domAgent->nodeForId(nodeId);
- return 0;
+ m_inspectedNodes.clear();
}
-long InjectedScriptHost::pushNodePathToFrontend(Node* node, bool withChildren, bool selectInUI)
+void InjectedScriptHost::copyText(const String& text)
{
- InspectorDOMAgent* domAgent = inspectorDOMAgent();
- if (!domAgent || !frontend())
- return 0;
- long id = domAgent->pushNodePathToFrontend(node);
- if (withChildren)
- domAgent->pushChildNodesToFrontend(id);
- if (selectInUI)
- frontend()->updateFocusedNode(id);
- return id;
+ Pasteboard::generalPasteboard()->writePlainText(text);
}
-long InjectedScriptHost::inspectedNode(unsigned long num)
+Node* InjectedScriptHost::inspectedNode(unsigned long num)
{
- InspectorDOMAgent* domAgent = inspectorDOMAgent();
- if (!domAgent)
- return 0;
-
- return domAgent->inspectedNode(num);
+ if (num < m_inspectedNodes.size())
+ return m_inspectedNodes[num].get();
+ return 0;
}
#if ENABLE(DATABASE)
-Database* InjectedScriptHost::databaseForId(long databaseId)
+long InjectedScriptHost::databaseIdImpl(Database* database)
{
if (m_inspectorAgent && m_inspectorAgent->databaseAgent())
- return m_inspectorAgent->databaseAgent()->databaseForId(databaseId);
+ return m_inspectorAgent->databaseAgent()->databaseId(database);
return 0;
}
-
-void InjectedScriptHost::selectDatabase(Database* database)
-{
- if (m_inspectorAgent && m_inspectorAgent->databaseAgent())
- m_inspectorAgent->databaseAgent()->selectDatabase(database);
-}
#endif
#if ENABLE(DOM_STORAGE)
-void InjectedScriptHost::selectDOMStorage(Storage* storage)
+long InjectedScriptHost::storageIdImpl(Storage* storage)
{
if (m_inspectorAgent && m_inspectorAgent->domStorageAgent())
- m_inspectorAgent->domStorageAgent()->selectDOMStorage(storage);
+ return m_inspectorAgent->domStorageAgent()->storageId(storage);
+ return 0;
}
#endif
@@ -177,26 +163,19 @@ void InjectedScriptHost::discardInjectedScripts()
m_idToInjectedScript.clear();
}
-void InjectedScriptHost::releaseWrapperObjectGroup(long injectedScriptId, const String& objectGroup)
+void InjectedScriptHost::releaseObjectGroup(long injectedScriptId, const String& objectGroup)
{
if (injectedScriptId) {
InjectedScript injectedScript = m_idToInjectedScript.get(injectedScriptId);
if (!injectedScript.hasNoValue())
- injectedScript.releaseWrapperObjectGroup(objectGroup);
+ injectedScript.releaseObjectGroup(objectGroup);
} else {
// Iterate over all injected scripts if injectedScriptId is not specified.
for (IdToInjectedScriptMap::iterator it = m_idToInjectedScript.begin(); it != m_idToInjectedScript.end(); ++it)
- it->second.releaseWrapperObjectGroup(objectGroup);
+ it->second.releaseObjectGroup(objectGroup);
}
}
-InspectorDOMAgent* InjectedScriptHost::inspectorDOMAgent()
-{
- if (!m_inspectorAgent)
- return 0;
- return m_inspectorAgent->domAgent();
-}
-
InspectorFrontend* InjectedScriptHost::frontend()
{
if (!m_inspectorAgent)
diff --git a/Source/WebCore/inspector/InjectedScriptHost.h b/Source/WebCore/inspector/InjectedScriptHost.h
index f51f8da..cdb1e64 100644
--- a/Source/WebCore/inspector/InjectedScriptHost.h
+++ b/Source/WebCore/inspector/InjectedScriptHost.h
@@ -37,16 +37,17 @@
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
namespace WebCore {
class Database;
class InjectedScript;
-class InspectorDOMAgent;
class InspectorFrontend;
class InspectorObject;
class Node;
class ScriptObject;
+class ScriptValue;
class Storage;
class InjectedScriptHost : public RefCounted<InjectedScriptHost>
@@ -57,27 +58,28 @@ public:
return adoptRef(new InjectedScriptHost(inspectorAgent));
}
- ~InjectedScriptHost();
+ static Node* scriptValueAsNode(ScriptValue);
+ static ScriptValue nodeAsScriptValue(ScriptState*, Node*);
- // Part of the protocol.
- void evaluateOnSelf(const String& functionBody, PassRefPtr<InspectorArray> argumentsArray, RefPtr<InspectorValue>* result);
+ ~InjectedScriptHost();
InspectorAgent* inspectorAgent() { return m_inspectorAgent; }
void disconnectController() { m_inspectorAgent = 0; }
+ void inspectImpl(PassRefPtr<InspectorValue> objectId, PassRefPtr<InspectorValue> hints);
void clearConsoleMessages();
+ void addInspectedNode(Node*);
+ void clearInspectedNodes();
+
void copyText(const String& text);
- Node* nodeForId(long nodeId);
- long pushNodePathToFrontend(Node* node, bool withChildren, bool selectInUI);
- long inspectedNode(unsigned long num);
+ Node* inspectedNode(unsigned long num);
#if ENABLE(DATABASE)
- Database* databaseForId(long databaseId);
- void selectDatabase(Database* database);
+ long databaseIdImpl(Database*);
#endif
#if ENABLE(DOM_STORAGE)
- void selectDOMStorage(Storage* storage);
+ long storageIdImpl(Storage*);
#endif
#if ENABLE(WORKERS)
long nextWorkerId();
@@ -91,13 +93,12 @@ public:
InjectedScript injectedScriptForObjectId(InspectorObject* objectId);
InjectedScript injectedScriptForMainFrame();
void discardInjectedScripts();
- void releaseWrapperObjectGroup(long injectedScriptId, const String& objectGroup);
+ void releaseObjectGroup(long injectedScriptId, const String& objectGroup);
static bool canAccessInspectedWindow(ScriptState*);
private:
InjectedScriptHost(InspectorAgent*);
- InspectorDOMAgent* inspectorDOMAgent();
InspectorFrontend* frontend();
String injectedScriptSource();
ScriptObject createInjectedScript(const String& source, ScriptState* scriptState, long id);
@@ -108,6 +109,7 @@ private:
long m_lastWorkerId;
typedef HashMap<long, InjectedScript> IdToInjectedScriptMap;
IdToInjectedScriptMap m_idToInjectedScript;
+ Vector<RefPtr<Node> > m_inspectedNodes;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InjectedScriptHost.idl b/Source/WebCore/inspector/InjectedScriptHost.idl
index 5fb57b4..0d5c500 100644
--- a/Source/WebCore/inspector/InjectedScriptHost.idl
+++ b/Source/WebCore/inspector/InjectedScriptHost.idl
@@ -35,22 +35,13 @@ module core {
void clearConsoleMessages();
void copyText(in DOMString text);
- [Custom] DOMObject nodeForId(in long nodeId);
- [Custom] int pushNodePathToFrontend(in DOMObject node, in boolean withChildren, in boolean selectInUI);
- long inspectedNode(in unsigned long num);
+ [Custom] void inspect(in DOMObject objectId, in DOMObject hints);
+ [Custom] DOMObject inspectedNode(in unsigned long num);
[Custom] DOMObject internalConstructorName(in DOMObject object);
-#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
[Custom] DOMObject currentCallFrame();
-#endif
-
-#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
- [Custom] void selectDatabase(in DOMObject database);
-#endif
-
-#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE
- [Custom] void selectDOMStorage(in DOMObject storage);
-#endif
+ [Custom] long databaseId(in DOMObject database);
+ [Custom] long storageId(in DOMObject storage);
#if defined(ENABLE_WORKERS) && ENABLE_WORKERS
void didCreateWorker(in long id, in DOMString url, in boolean isFakeWorker);
diff --git a/Source/WebCore/inspector/InjectedScriptSource.js b/Source/WebCore/inspector/InjectedScriptSource.js
index c88e8e4..9c662e8 100644
--- a/Source/WebCore/inspector/InjectedScriptSource.js
+++ b/Source/WebCore/inspector/InjectedScriptSource.js
@@ -50,33 +50,62 @@ var InjectedScript = function()
}
InjectedScript.prototype = {
- wrapObjectForConsole: function(object, canAccessInspectedWindow)
+ wrapObject: function(object, groupName, canAccessInspectedWindow)
{
if (canAccessInspectedWindow)
- return this._wrapObject(object, "console");
+ return this._wrapObject(object, groupName);
var result = {};
result.type = typeof object;
result.description = this._toString(object);
return result;
},
+ inspectNode: function(object)
+ {
+ this._inspect(object);
+ },
+
+ _inspect: function(object)
+ {
+ if (arguments.length === 0)
+ return;
+
+ var objectId = this._wrapObject(object, "", false);
+ var hints = {};
+
+ switch (injectedScript._describe(object)) {
+ case "Database":
+ var databaseId = InjectedScriptHost.databaseId(object)
+ if (databaseId)
+ hints.databaseId = databaseId;
+ break;
+ case "Storage":
+ var storageId = InjectedScriptHost.storageId(object)
+ if (storageId)
+ hints.domStorageId = storageId;
+ break;
+ }
+ InjectedScriptHost.inspect(objectId, hints);
+ return object;
+ },
+
_wrapObject: function(object, objectGroupName, abbreviate)
{
try {
- var objectId;
if (typeof object === "object" || typeof object === "function" || this._isHTMLAllCollection(object)) {
var id = this._lastBoundObjectId++;
this._idToWrappedObject[id] = object;
+ var objectId = { injectedScriptId: injectedScriptId, id: id };
- var group = this._objectGroups[objectGroupName];
- if (!group) {
- group = [];
- this._objectGroups[objectGroupName] = group;
+ if (objectGroupName) {
+ var group = this._objectGroups[objectGroupName];
+ if (!group) {
+ group = [];
+ this._objectGroups[objectGroupName] = group;
+ }
+ group.push(id);
+ objectId.groupName = objectGroupName;
}
- group.push(id);
- objectId = { injectedScriptId: injectedScriptId,
- id: id,
- groupName: objectGroupName };
}
return InjectedScript.RemoteObject.fromObject(object, objectId, abbreviate);
} catch (e) {
@@ -89,7 +118,7 @@ InjectedScript.prototype = {
return eval("(" + objectId + ")");
},
- releaseWrapperObjectGroup: function(objectGroupName)
+ releaseObjectGroup: function(objectGroupName)
{
var group = this._objectGroups[objectGroupName];
if (!group)
@@ -181,6 +210,12 @@ InjectedScript.prototype = {
}
},
+ releaseObject: function(objectId)
+ {
+ var parsedObjectId = this._parseObjectId(objectId);
+ delete this._idToWrappedObject[parsedObjectId.id];
+ },
+
_populatePropertyNames: function(object, resultSet)
{
for (var o = object; o; o = o.__proto__) {
@@ -200,57 +235,23 @@ InjectedScript.prototype = {
return Object.keys(propertyNameSet);
},
- getCompletions: function(expression, includeCommandLineAPI)
+ evaluate: function(expression, objectGroup, injectCommandLineAPI)
{
- var props = {};
- try {
- if (!expression)
- expression = "this";
- var expressionResult = this._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false, false);
-
- if (typeof expressionResult === "object")
- this._populatePropertyNames(expressionResult, props);
-
- if (includeCommandLineAPI) {
- for (var prop in CommandLineAPI.members_)
- props[CommandLineAPI.members_[prop]] = true;
- }
- } catch(e) {
- }
- return props;
+ return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup, false, injectCommandLineAPI);
},
- getCompletionsOnCallFrame: function(callFrameId, expression, includeCommandLineAPI)
+ evaluateOn: function(objectId, expression)
{
- var props = {};
+ var parsedObjectId = this._parseObjectId(objectId);
+ var object = this._objectForId(parsedObjectId);
+ if (!object)
+ return false;
try {
- var callFrame = this._callFrameForId(callFrameId);
- if (!callFrame)
- return props;
-
- if (expression) {
- var expressionResult = this._evaluateOn(callFrame.evaluate, callFrame, expression, true, false);
- if (typeof expressionResult === "object")
- this._populatePropertyNames(expressionResult, props);
- } else {
- // Evaluate into properties in scope of the selected call frame.
- var scopeChain = callFrame.scopeChain;
- for (var i = 0; i < scopeChain.length; ++i)
- this._populatePropertyNames(scopeChain[i], props);
- }
-
- if (includeCommandLineAPI) {
- for (var prop in CommandLineAPI.members_)
- props[CommandLineAPI.members_[prop]] = true;
- }
- } catch(e) {
+ inspectedWindow.console._objectToEvaluateOn = object;
+ return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, "(function() {" + expression + "}).call(window.console._objectToEvaluateOn)", parsedObjectId.objectGroup, false, false);
+ } finally {
+ delete inspectedWindow.console._objectToEvaluateOn;
}
- return props;
- },
-
- evaluate: function(expression, objectGroup, injectCommandLineAPI)
- {
- return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup, false, injectCommandLineAPI);
},
_evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI)
@@ -287,18 +288,13 @@ InjectedScript.prototype = {
}
},
- getNodeId: function(node)
- {
- return InjectedScriptHost.pushNodePathToFrontend(node, false, false);
- },
-
callFrames: function()
{
var callFrame = InjectedScriptHost.currentCallFrame();
if (!callFrame)
return false;
- injectedScript.releaseWrapperObjectGroup("backtrace");
+ injectedScript.releaseObjectGroup("backtrace");
var result = [];
var depth = 0;
do {
@@ -326,68 +322,23 @@ InjectedScript.prototype = {
return callFrame;
},
- _nodeForId: function(nodeId)
- {
- if (!nodeId)
- return null;
- return InjectedScriptHost.nodeForId(nodeId);
- },
-
_objectForId: function(objectId)
{
return this._idToWrappedObject[objectId.id];
},
- resolveNode: function(nodeId)
- {
- var node = this._nodeForId(nodeId);
- if (!node)
- return false;
- // FIXME: receive the object group from client.
- return this._wrapObject(node, "prototype");
- },
-
- getNodeProperties: function(nodeId, properties)
- {
- var node = this._nodeForId(nodeId);
- if (!node)
- return false;
- properties = eval("(" + properties + ")");
- var result = {};
- for (var i = 0; i < properties.length; ++i)
- result[properties[i]] = node[properties[i]];
- return result;
- },
-
- getNodePrototypes: function(nodeId)
- {
- this.releaseWrapperObjectGroup("prototypes");
- var node = this._nodeForId(nodeId);
- if (!node)
- return false;
-
- var result = [];
- var prototype = node;
- do {
- result.push(this._wrapObject(prototype, "prototypes"));
- prototype = prototype.__proto__;
- } while (prototype)
- return result;
- },
-
- pushNodeToFrontend: function(objectId)
+ nodeForObjectId: function(objectId)
{
var parsedObjectId = this._parseObjectId(objectId);
var object = this._objectForId(parsedObjectId);
if (!object || this._type(object) !== "node")
- return false;
- return InjectedScriptHost.pushNodePathToFrontend(object, false, false);
+ return null;
+ return object;
},
- evaluateOnSelf: function(funcBody, args)
+ resolveNode: function(node)
{
- var func = eval("(" + funcBody + ")");
- return func.apply(this, eval("(" + args + ")") || []);
+ return this._wrapObject(node);
},
_isDefined: function(object)
@@ -510,7 +461,7 @@ InjectedScript.RemoteObject.fromObject = function(object, objectId, abbreviate)
{
var type = injectedScript._type(object);
var rawType = typeof object;
- var hasChildren = (rawType === "object" && object !== null && (Object.getOwnPropertyNames(object).length || !!object.__proto__)) || rawType === "function";
+ var hasChildren = (rawType === "object" && object !== null && (!!Object.getOwnPropertyNames(object).length || !!object.__proto__)) || rawType === "function";
var description = "";
try {
var description = injectedScript._describe(object, abbreviate);
@@ -697,22 +648,7 @@ CommandLineAPIImpl.prototype = {
inspect: function(object)
{
- if (arguments.length === 0)
- return;
-
- inspectedWindow.console.log(object);
- if (injectedScript._type(object) === "node")
- InjectedScriptHost.pushNodePathToFrontend(object, false, true);
- else {
- switch (injectedScript._describe(object)) {
- case "Database":
- InjectedScriptHost.selectDatabase(object);
- break;
- case "Storage":
- InjectedScriptHost.selectDOMStorage(object);
- break;
- }
- }
+ return injectedScript._inspect(object);
},
copy: function(object)
@@ -729,8 +665,7 @@ CommandLineAPIImpl.prototype = {
_inspectedNode: function(num)
{
- var nodeId = InjectedScriptHost.inspectedNode(num);
- return injectedScript._nodeForId(nodeId);
+ return InjectedScriptHost.inspectedNode(num);
},
_normalizeEventTypes: function(types)
diff --git a/Source/WebCore/inspector/Inspector.idl b/Source/WebCore/inspector/Inspector.idl
index 80c24db..216d4b1 100644
--- a/Source/WebCore/inspector/Inspector.idl
+++ b/Source/WebCore/inspector/Inspector.idl
@@ -38,37 +38,32 @@ module core {
void openInInspectedWindow(in String url);
void setSearchingForNode(in boolean enabled, out boolean newState);
- [notify] void frontendReused();
- [notify] void addNodesToSearchResult(out Array nodeIds);
- [notify] void bringToFront();
- [notify] void disconnectFromBackend();
- [notify] void inspectedURLChanged(out String url);
- [notify] void domContentEventFired(out double time);
- [notify] void loadEventFired(out double time);
- [notify] void reset();
- [notify] void showPanel(out String panel);
-
- [notify] void evaluateForTestInFrontend(out long testCallId, out String script);
+ [event] void frontendReused();
+ [event] void bringToFront();
+ [event] void disconnectFromBackend();
+ [event] void inspectedURLChanged(out String url);
+ [event] void domContentEventFired(out double time);
+ [event] void loadEventFired(out double time);
+ [event] void reset();
+ [event] void showPanel(out String panel);
+
+ [event] void evaluateForTestInFrontend(out long testCallId, out String script);
void didEvaluateForTestInFrontend(in long testCallId, in String jsonResult);
void highlightDOMNode(in long nodeId);
void hideDOMNodeHighlight();
void highlightFrame(in unsigned long frameId);
void hideFrameHighlight();
- [notify] void updateFocusedNode(out long nodeId);
void setUserAgentOverride(in String userAgent);
void getCookies(out Array cookies, out String cookiesString);
void deleteCookie(in String cookieName, in String domain);
- // FIXME: dispatch on agents.
- void startTimelineProfiler();
- void stopTimelineProfiler();
+ [event] void inspect(out Object objectId, out Object hints);
+ // FIXME: dispatch on agents.
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
- void enableDebugger();
- void disableDebugger();
void enableProfiler();
void disableProfiler();
void startProfiling();
@@ -78,46 +73,44 @@ module core {
interface [Conditional=INSPECTOR] Runtime {
void evaluate(in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
- void getCompletions(in String expression, in boolean includeCommandLineAPI, out Value result);
+ void evaluateOn(in Object objectId, in String expression, out Value result);
void getProperties(in Object objectId, in boolean ignoreHasOwnProperty, in boolean abbreviate, out Value result);
void setPropertyValue(in Object objectId, in String propertyName, in String expression, out Value result);
- void releaseWrapperObjectGroup(in long injectedScriptId, in String objectGroup);
- };
-
- interface [Conditional=INSPECTOR] InjectedScript {
- void evaluateOnSelf(in String functionBody, in Array argumentsArray, out Value result);
+ void releaseObject(in Object objectId);
+ void releaseObjectGroup(in long injectedScriptId, in String objectGroup);
};
interface [Conditional=INSPECTOR] Console {
void setConsoleMessagesEnabled(in boolean enabled, out boolean newState);
- [notify] void addConsoleMessage(out Object messageObj);
- [notify] void updateConsoleMessageExpiredCount(out unsigned long count);
- [notify] void updateConsoleMessageRepeatCount(out unsigned long count);
+ [event] void addConsoleMessage(out Object messageObj);
+ [event] void updateConsoleMessageExpiredCount(out unsigned long count);
+ [event] void updateConsoleMessageRepeatCount(out unsigned long count);
void clearConsoleMessages();
- [notify] void consoleMessagesCleared();
+ [event] void consoleMessagesCleared();
void setMonitoringXHREnabled(in boolean enabled);
};
interface [Conditional=INSPECTOR] Network {
- void cachedResources(out Object resources);
+ void enable(out Object resources);
+ void disable();
void resourceContent(in unsigned long frameId, in String url, in boolean base64Encode, out boolean success, out String content);
void setExtraHeaders(in Object headers);
- [notify] void frameDetachedFromParent(out unsigned long frameId);
- [notify] void identifierForInitialRequest(out long identifier, out String url, out Object loader, out Value callStack);
- [notify] void willSendRequest(out long identifier, out double time, out Object request, out Object redirectResponse);
- [notify] void markResourceAsCached(out long identifier);
- [notify] void didReceiveResponse(out long identifier, out double time, out String resourceType, out Object response);
- [notify] void didReceiveContentLength(out long identifier, out double time, out long lengthReceived);
- [notify] void didFinishLoading(out long identifier, out double finishTime);
- [notify] void didFailLoading(out long identifier, out double time, out String localizedDescription);
- [notify] void didLoadResourceFromMemoryCache(out double time, out Object resource);
- [notify] void setInitialContent(out long identifier, out String sourceString, out String type);
- [notify] void didCommitLoadForFrame(out Object frame, out Object loader);
- [notify] void didCreateWebSocket(out unsigned long identifier, out String requestURL);
- [notify] void willSendWebSocketHandshakeRequest(out unsigned long identifier, out double time, out Object request);
- [notify] void didReceiveWebSocketHandshakeResponse(out unsigned long identifier, out double time, out Object response);
- [notify] void didCloseWebSocket(out unsigned long identifier, out double time);
+ [event] void frameDetachedFromParent(out unsigned long frameId);
+ [event] void identifierForInitialRequest(out long identifier, out String url, out Object loader, out Value callStack);
+ [event] void willSendRequest(out long identifier, out double time, out Object request, out Object redirectResponse);
+ [event] void markResourceAsCached(out long identifier);
+ [event] void didReceiveResponse(out long identifier, out double time, out String resourceType, out Object response);
+ [event] void didReceiveContentLength(out long identifier, out double time, out long lengthReceived);
+ [event] void didFinishLoading(out long identifier, out double finishTime);
+ [event] void didFailLoading(out long identifier, out double time, out String localizedDescription);
+ [event] void didLoadResourceFromMemoryCache(out double time, out Object resource);
+ [event] void setInitialContent(out long identifier, out String sourceString, out String type);
+ [event] void didCommitLoadForFrame(out Object frame, out Object loader);
+ [event] void didCreateWebSocket(out unsigned long identifier, out String requestURL);
+ [event] void willSendWebSocketHandshakeRequest(out unsigned long identifier, out double time, out Object request);
+ [event] void didReceiveWebSocketHandshakeResponse(out unsigned long identifier, out double time, out Object response);
+ [event] void didCloseWebSocket(out unsigned long identifier, out double time);
};
#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
@@ -125,10 +118,9 @@ module core {
void getDatabaseTableNames(in long databaseId, out Array tableNames);
void executeSQL(in long databaseId, in String query, out boolean success, out long transactionId);
- [notify] void addDatabase(out Object database);
- [notify] void selectDatabase(out int databaseId);
- [notify] void sqlTransactionSucceeded(out long transactionId, out Value columnNames, out Value values);
- [notify] void sqlTransactionFailed(out long transactionId, out Value sqlError);
+ [event] void addDatabase(out Object database);
+ [event] void sqlTransactionSucceeded(out long transactionId, out Value columnNames, out Value values);
+ [event] void sqlTransactionFailed(out long transactionId, out Value sqlError);
};
#endif
@@ -137,22 +129,24 @@ module core {
void getDOMStorageEntries(in long storageId, out Array entries);
void setDOMStorageItem(in long storageId, in String key, in String value, out boolean success);
void removeDOMStorageItem(in long storageId, in String key, out boolean success);
- [notify] void addDOMStorage(out Object storage);
- [notify] void updateDOMStorage(out int storageId);
- [notify] void selectDOMStorage(out int storageId);
+ [event] void addDOMStorage(out Object storage);
+ [event] void updateDOMStorage(out int storageId);
};
#endif
#if defined(ENABLE_OFFLINE_WEB_APPLICATIONS) && ENABLE_OFFLINE_WEB_APPLICATIONS
interface [Conditional=INSPECTOR] ApplicationCache {
void getApplicationCaches(out Value applicationCaches);
- [notify] void updateApplicationCacheStatus(out int status);
- [notify] void updateNetworkState(out boolean isNowOnline);
+ [event] void updateApplicationCacheStatus(out int status);
+ [event] void updateNetworkState(out boolean isNowOnline);
};
#endif
interface [Conditional=INSPECTOR] DOM {
+ void getDocument(out Object root);
void getChildNodes(in long nodeId);
+ void querySelector(in long nodeId, in String selectors, in boolean documentWide, out long elementId);
+ void querySelectorAll(in long nodeId, in String selectors, in boolean documentWide, out Array result);
void setAttribute(in long elementId, in String name, in String value, out boolean success);
void removeAttribute(in long elementId, in String name, out boolean success);
void setTextNodeValue(in long nodeId, in String value, out boolean success);
@@ -166,19 +160,18 @@ module core {
void performSearch(in String query, in boolean runSynchronously);
void searchCanceled();
void pushNodeByPathToFrontend(in String path, out long nodeId);
- void resolveNode(in long nodeId, out Value result);
- void getNodeProperties(in long nodeId, in Array propertiesArray, out Value result);
- void getNodePrototypes(in long nodeId, out Value result);
- void pushNodeToFrontend(in Object objectId, out Value result);
-
- [notify] void setDocument(out Value root); // FIXME: should be requested from the front-end as getDocument.
- [notify] void attributesUpdated(out long id, out Array attributes);
- [notify] void characterDataModified(out long id, out String newValue);
- [notify] void setChildNodes(out long parentId, out Array nodes);
- [notify] void setDetachedRoot(out Object root);
- [notify] void childNodeCountUpdated(out long id, out int newValue);
- [notify] void childNodeInserted(out long parentId, out long prevId, out Object node);
- [notify] void childNodeRemoved(out long parentId, out long id);
+ void resolveNode(in long nodeId, in String objectGroup, out Value result);
+ void pushNodeToFrontend(in Object objectId, out long nodeId);
+
+ [event] void addNodesToSearchResult(out Array nodeIds);
+ [event] void documentUpdated();
+ [event] void setChildNodes(out long parentId, out Array nodes);
+ [event] void attributesUpdated(out long id, out Array attributes);
+ [event] void characterDataModified(out long id, out String newValue);
+ [event] void setDetachedRoot(out Object root);
+ [event] void childNodeCountUpdated(out long id, out int newValue);
+ [event] void childNodeInserted(out long parentId, out long prevId, out Object node);
+ [event] void childNodeRemoved(out long parentId, out long id);
};
interface [Conditional=INSPECTOR] CSS {
@@ -194,22 +187,25 @@ module core {
void setRuleSelector(in Object ruleId, in String selector, out Value rule);
void addRule(in long contextNodeId, in String selector, out Value rule);
void getSupportedCSSProperties(out Array cssProperties);
- void querySelectorAll(in long documentId, in String selector, out Array result);
};
interface [Conditional=INSPECTOR] Timeline {
- [notify] void timelineProfilerWasStarted();
- [notify] void timelineProfilerWasStopped();
- [notify] void addRecordToTimeline(out Object record);
+ void start();
+ void stop();
+ [event] void timelineProfilerWasStarted();
+ [event] void timelineProfilerWasStopped();
+ [event] void addRecordToTimeline(out Object record);
};
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
interface [Conditional=INSPECTOR] Debugger {
- [notify] void debuggerWasEnabled();
- [notify] void debuggerWasDisabled();
+ void enable();
+ void disable();
+ [event] void debuggerWasEnabled();
+ [event] void debuggerWasDisabled();
- [notify] void parsedScriptSource(out String sourceID, out String url, out int lineOffset, out int columnOffset, out int length, out int scriptWorldType);
- [notify] void failedToParseScriptSource(out String url, out String data, out int firstLine, out int errorLine, out String errorMessage);
+ [event] void parsedScriptSource(out String sourceID, out String url, out int lineOffset, out int columnOffset, out int length, out int scriptWorldType);
+ [event] void failedToParseScriptSource(out String url, out String data, out int firstLine, out int errorLine, out String errorMessage);
void activateBreakpoints();
void deactivateBreakpoints();
@@ -217,16 +213,16 @@ module core {
void setJavaScriptBreakpoint(in String url, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out Array locations);
void setJavaScriptBreakpointBySourceId(in String sourceId, in int lineNumber, in int columnNumber, in String condition, in boolean enabled, out String breakpointId, out int actualLineNumber, out int actualColumnNumber);
void removeJavaScriptBreakpoint(in String breakpointId);
- [notify] void breakpointResolved(out String breakpointId, out String sourceId, out int lineNumber, out int columnNumber);
+ [event] void breakpointResolved(out String breakpointId, out String sourceId, out int lineNumber, out int columnNumber);
void continueToLocation(in String sourceId, in int lineNumber, in int columnNumber);
void stepOver();
void stepInto();
void stepOut();
void pause();
- [notify] void pausedScript(out Object details);
+ [event] void pausedScript(out Object details);
void resume();
- [notify] void resumedScript(); // FIXME: Make this out parameter of resume if possible.
+ [event] void resumedScript(); // FIXME: Make this out parameter of resume if possible.
void editScriptSource(in String sourceID, in String newContent, out boolean success, out String result, out Value newCallFrames);
void getScriptSource(in String sourceID, out String scriptSource);
@@ -234,11 +230,10 @@ module core {
void setPauseOnExceptionsState(in long pauseOnExceptionsState, out long newState);
void evaluateOnCallFrame(in Object callFrameId, in String expression, in String objectGroup, in boolean includeCommandLineAPI, out Value result);
- void getCompletionsOnCallFrame(in Object callFrameId, in String expression, in boolean includeCommandLineAPI, out Value result);
#if defined(ENABLE_WORKERS) && ENABLE_WORKERS
- [notify] void didCreateWorker(out long id, out String url, out boolean isShared);
- [notify] void didDestroyWorker(out long id);
+ [event] void didCreateWorker(out long id, out String url, out boolean isShared);
+ [event] void didDestroyWorker(out long id);
#endif // ENABLE_WORKERS
};
@@ -258,8 +253,8 @@ module core {
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
interface [Conditional=INSPECTOR] Profiler {
- [notify] void profilerWasEnabled();
- [notify] void profilerWasDisabled();
+ [event] void profilerWasEnabled();
+ [event] void profilerWasDisabled();
void getProfileHeaders(out Array headers);
void getProfile(in String type, in unsigned long uid, out Object profile);
@@ -268,12 +263,13 @@ module core {
// FIXME: split into Profiler and HeapProfiler.
void takeHeapSnapshot(in boolean detailed);
- [notify] void addProfileHeader(out Object header);
- [notify] void addHeapSnapshotChunk(out unsigned long uid, out String chunk);
- [notify] void finishHeapSnapshot(out unsigned long uid);
- [notify] void setRecordingProfile(out boolean isProfiling);
- [notify] void resetProfiles();
- [notify] void reportHeapSnapshotProgress(out int done, out int total);
+ void getExactHeapSnapshotNodeRetainedSize(in unsigned long uid, in unsigned long nodeId, out long size);
+ [event] void addProfileHeader(out Object header);
+ [event] void addHeapSnapshotChunk(out unsigned long uid, out String chunk);
+ [event] void finishHeapSnapshot(out unsigned long uid);
+ [event] void setRecordingProfile(out boolean isProfiling);
+ [event] void resetProfiles();
+ [event] void reportHeapSnapshotProgress(out int done, out int total);
};
#endif // ENABLE_JAVASCRIPT_DEBUGGER
}
diff --git a/Source/WebCore/inspector/InspectorAgent.cpp b/Source/WebCore/inspector/InspectorAgent.cpp
index 9559099..15ceba0 100644
--- a/Source/WebCore/inspector/InspectorAgent.cpp
+++ b/Source/WebCore/inspector/InspectorAgent.cpp
@@ -62,8 +62,6 @@
#include "InspectorConsoleAgent.h"
#include "InspectorController.h"
#include "InspectorDOMAgent.h"
-#include "InspectorDOMStorageResource.h"
-#include "InspectorDatabaseResource.h"
#include "InspectorDebuggerAgent.h"
#include "InspectorFrontend.h"
#include "InspectorFrontendClient.h"
@@ -75,6 +73,7 @@
#include "InspectorTimelineAgent.h"
#include "InspectorValues.h"
#include "InspectorWorkerResource.h"
+#include "InstrumentingAgents.h"
#include "IntRect.h"
#include "Page.h"
#include "ProgressTracker.h"
@@ -106,14 +105,11 @@
#include <wtf/text/StringConcatenate.h>
#if ENABLE(DATABASE)
-#include "Database.h"
#include "InspectorDatabaseAgent.h"
#endif
#if ENABLE(DOM_STORAGE)
#include "InspectorDOMStorageAgent.h"
-#include "Storage.h"
-#include "StorageArea.h"
#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
@@ -140,13 +136,29 @@ InspectorAgent::InspectorAgent(Page* page, InspectorClient* client)
: m_inspectedPage(page)
, m_client(client)
, m_frontend(0)
- , m_cssAgent(new InspectorCSSAgent())
- , m_state(new InspectorState(client))
+ , m_instrumentingAgents(new InstrumentingAgents())
, m_injectedScriptHost(InjectedScriptHost::create(this))
- , m_consoleAgent(new InspectorConsoleAgent(this))
+ , m_state(new InspectorState(client))
+ , m_domAgent(InspectorDOMAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptHost.get()))
+ , m_cssAgent(new InspectorCSSAgent(m_instrumentingAgents.get(), m_domAgent.get()))
+#if ENABLE(DATABASE)
+ , m_databaseAgent(InspectorDatabaseAgent::create(m_instrumentingAgents.get()))
+#endif
+#if ENABLE(DOM_STORAGE)
+ , m_domStorageAgent(InspectorDOMStorageAgent::create(m_instrumentingAgents.get()))
+#endif
+ , m_timelineAgent(InspectorTimelineAgent::create(m_instrumentingAgents.get(), m_state.get()))
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ , m_applicationCacheAgent(new InspectorApplicationCacheAgent(m_instrumentingAgents.get(), page))
+#endif
+ , m_resourceAgent(InspectorResourceAgent::create(m_instrumentingAgents.get(), page, m_state.get()))
+ , m_consoleAgent(new InspectorConsoleAgent(m_instrumentingAgents.get(), this, m_state.get(), m_injectedScriptHost.get(), m_domAgent.get()))
#if ENABLE(JAVASCRIPT_DEBUGGER)
- , m_profilerAgent(InspectorProfilerAgent::create(this))
+ , m_debuggerAgent(InspectorDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), page, m_injectedScriptHost.get()))
+ , m_browserDebuggerAgent(InspectorBrowserDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent.get(), m_debuggerAgent.get(), this))
+ , m_profilerAgent(InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), page))
#endif
+ , m_canIssueEvaluateForTestInFrontend(false)
{
ASSERT_ARG(page, page);
ASSERT_ARG(client, client);
@@ -163,14 +175,17 @@ InspectorAgent::~InspectorAgent()
void InspectorAgent::inspectedPageDestroyed()
{
- if (m_frontend)
- m_frontend->disconnectFromBackend();
+ if (m_frontend) {
+ m_frontend->inspector()->disconnectFromBackend();
+ disconnectFrontend();
+ }
- hideHighlight();
+ ErrorString error;
+ hideHighlight(&error);
#if ENABLE(JAVASCRIPT_DEBUGGER)
- m_debuggerAgent.clear();
m_browserDebuggerAgent.clear();
+ m_debuggerAgent.clear();
#endif
ASSERT(m_inspectedPage);
@@ -191,17 +206,17 @@ bool InspectorAgent::searchingForNodeInPage() const
void InspectorAgent::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
{
- m_state = new InspectorState(m_client, inspectorStateCookie);
+ m_state->loadFromCookie(inspectorStateCookie);
- m_frontend->frontendReused();
- m_frontend->inspectedURLChanged(inspectedURL().string());
+ m_frontend->inspector()->frontendReused();
+ m_frontend->inspector()->inspectedURLChanged(inspectedURL().string());
pushDataCollectedOffline();
- m_resourceAgent = InspectorResourceAgent::restore(m_inspectedPage, m_state.get(), m_frontend);
- m_timelineAgent = InspectorTimelineAgent::restore(m_state.get(), m_frontend);
+ m_resourceAgent->restore();
+ m_timelineAgent->restore();
#if ENABLE(JAVASCRIPT_DEBUGGER)
- restoreDebugger(false);
+ m_debuggerAgent->restore();
restoreProfiler(ProfilerRestoreResetAgent);
if (m_state->getBoolean(InspectorAgentState::userInitiatedProfiling))
startUserInitiatedProfiling();
@@ -228,12 +243,24 @@ void InspectorAgent::focusNode()
ASSERT(m_frontend);
ASSERT(m_nodeToFocus);
- long id = m_domAgent->pushNodePathToFrontend(m_nodeToFocus.get());
- m_frontend->updateFocusedNode(id);
+ RefPtr<Node> node = m_nodeToFocus.get();
m_nodeToFocus = 0;
+
+ Document* document = node->ownerDocument();
+ if (!document)
+ return;
+ Frame* frame = document->frame();
+ if (!frame)
+ return;
+
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptFor(mainWorldScriptState(frame));
+ if (injectedScript.hasNoValue())
+ return;
+
+ injectedScript.inspectNode(node.get());
}
-void InspectorAgent::highlight(Node* node)
+void InspectorAgent::highlight(ErrorString*, Node* node)
{
if (!enabled())
return;
@@ -242,25 +269,25 @@ void InspectorAgent::highlight(Node* node)
m_client->highlight(node);
}
-void InspectorAgent::highlightDOMNode(long nodeId)
+void InspectorAgent::highlightDOMNode(ErrorString* error, long nodeId)
{
Node* node = 0;
if (m_domAgent && (node = m_domAgent->nodeForId(nodeId)))
- highlight(node);
+ highlight(error, node);
}
-void InspectorAgent::highlightFrame(unsigned long frameId)
+void InspectorAgent::highlightFrame(ErrorString* error, unsigned long frameId)
{
Frame* mainFrame = m_inspectedPage->mainFrame();
for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext(mainFrame)) {
if (reinterpret_cast<uintptr_t>(frame) == frameId && frame->ownerElement()) {
- highlight(frame->ownerElement());
+ highlight(error, frame->ownerElement());
return;
}
}
}
-void InspectorAgent::hideHighlight()
+void InspectorAgent::hideHighlight(ErrorString*)
{
if (!enabled())
return;
@@ -276,8 +303,10 @@ void InspectorAgent::mouseDidMoveOverElement(const HitTestResult& result, unsign
Node* node = result.innerNode();
while (node && node->nodeType() == Node::TEXT_NODE)
node = node->parentNode();
- if (node)
- highlight(node);
+ if (node) {
+ ErrorString error;
+ highlight(&error, node);
+ }
}
bool InspectorAgent::handleMousePress()
@@ -320,11 +349,13 @@ void InspectorAgent::setSearchingForNode(bool enabled)
if (searchingForNodeInPage() == enabled)
return;
m_state->setBoolean(InspectorAgentState::searchingForNode, enabled);
- if (!enabled)
- hideHighlight();
+ if (!enabled) {
+ ErrorString error;
+ hideHighlight(&error);
+ }
}
-void InspectorAgent::setSearchingForNode(bool enabled, bool* newState)
+void InspectorAgent::setSearchingForNode(ErrorString*, bool enabled, bool* newState)
{
*newState = enabled;
setSearchingForNode(enabled);
@@ -332,14 +363,31 @@ void InspectorAgent::setSearchingForNode(bool enabled, bool* newState)
void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
{
+ // We can reconnect to existing front-end -> unmute state.
+ m_state->unmute();
+
m_frontend = inspectorFrontend;
createFrontendLifetimeAgents();
- m_cssAgent->setDOMAgent(m_domAgent.get());
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ m_applicationCacheAgent->setFrontend(m_frontend);
+#endif
+ m_domAgent->setFrontend(m_frontend);
m_consoleAgent->setFrontend(m_frontend);
-
+ m_timelineAgent->setFrontend(m_frontend);
+ m_resourceAgent->setFrontend(m_frontend);
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ m_debuggerAgent->setFrontend(m_frontend);
+ m_browserDebuggerAgent->setFrontend(m_frontend);
+#endif
+#if ENABLE(DATABASE)
+ m_databaseAgent->setFrontend(m_frontend);
+#endif
+#if ENABLE(DOM_STORAGE)
+ m_domStorageAgent->setFrontend(m_frontend);
+#endif
// Initialize Web Inspector title.
- m_frontend->inspectedURLChanged(inspectedURL().string());
+ m_frontend->inspector()->inspectedURLChanged(inspectedURL().string());
}
void InspectorAgent::disconnectFrontend()
@@ -347,82 +395,58 @@ void InspectorAgent::disconnectFrontend()
if (!m_frontend)
return;
+ m_canIssueEvaluateForTestInFrontend = false;
+ m_pendingEvaluateTestCommands.clear();
+
// Destroying agents would change the state, but we don't want that.
// Pre-disconnect state will be used to restore inspector agents.
m_state->mute();
m_frontend = 0;
+ ErrorString error;
#if ENABLE(JAVASCRIPT_DEBUGGER)
- // If the window is being closed with the debugger enabled,
- // remember this state to re-enable debugger on the next window
- // opening.
- disableDebugger();
+ m_debuggerAgent->clearFrontend();
+ m_browserDebuggerAgent->clearFrontend();
#endif
setSearchingForNode(false);
- hideHighlight();
+ hideHighlight(&error);
#if ENABLE(JAVASCRIPT_DEBUGGER)
- m_profilerAgent->setFrontend(0);
+ m_profilerAgent->clearFrontend();
m_profilerAgent->stopUserInitiatedProfiling(true);
#endif
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ m_applicationCacheAgent->clearFrontend();
+#endif
- m_consoleAgent->setFrontend(0);
+ m_consoleAgent->clearFrontend();
+ m_domAgent->clearFrontend();
+ m_timelineAgent->clearFrontend();
+ m_resourceAgent->clearFrontend();
+#if ENABLE(DATABASE)
+ m_databaseAgent->clearFrontend();
+#endif
+#if ENABLE(DOM_STORAGE)
+ m_domStorageAgent->clearFrontend();
+#endif
releaseFrontendLifetimeAgents();
m_userAgentOverride = "";
}
-InspectorResourceAgent* InspectorAgent::resourceAgent()
-{
- if (!m_resourceAgent && m_frontend)
- m_resourceAgent = InspectorResourceAgent::create(m_inspectedPage, m_state.get(), m_frontend);
- return m_resourceAgent.get();
-}
-
void InspectorAgent::createFrontendLifetimeAgents()
{
- m_domAgent = InspectorDOMAgent::create(m_injectedScriptHost.get(), m_frontend);
m_runtimeAgent = InspectorRuntimeAgent::create(m_injectedScriptHost.get());
-
-#if ENABLE(DATABASE)
- m_databaseAgent = InspectorDatabaseAgent::create(&m_databaseResources, m_frontend);
-#endif
-
-#if ENABLE(DOM_STORAGE)
- m_domStorageAgent = InspectorDOMStorageAgent::create(&m_domStorageResources, m_frontend);
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- m_applicationCacheAgent = new InspectorApplicationCacheAgent(m_inspectedPage->mainFrame()->loader()->documentLoader(), m_frontend);
-#endif
}
void InspectorAgent::releaseFrontendLifetimeAgents()
{
- m_resourceAgent.clear();
m_runtimeAgent.clear();
- m_timelineAgent.clear();
-
-#if ENABLE(DATABASE)
- m_databaseAgent.clear();
-#endif
-
-#if ENABLE(DOM_STORAGE)
- m_domStorageAgent.clear();
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- m_applicationCacheAgent.clear();
-#endif
-
- // This should be invoked prior to m_domAgent destruction.
- m_cssAgent->setDOMAgent(0);
- m_domAgent.clear();
}
-void InspectorAgent::populateScriptObjects()
+void InspectorAgent::populateScriptObjects(ErrorString*)
{
ASSERT(m_frontend);
if (!m_frontend)
@@ -430,7 +454,7 @@ void InspectorAgent::populateScriptObjects()
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (m_profilerAgent->enabled())
- m_frontend->profilerWasEnabled();
+ m_frontend->profiler()->profilerWasEnabled();
#endif
pushDataCollectedOffline();
@@ -438,59 +462,42 @@ void InspectorAgent::populateScriptObjects()
if (m_nodeToFocus)
focusNode();
- if (!m_requiredPanel.isEmpty()) {
- m_frontend->showPanel(m_requiredPanel);
- m_requiredPanel = "";
+ if (!m_showPanelAfterVisible.isEmpty()) {
+ m_frontend->inspector()->showPanel(m_showPanelAfterVisible);
+ m_showPanelAfterVisible = "";
}
- restoreDebugger(true);
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ m_debuggerAgent->enableDebuggerAfterShown();
+#endif
restoreProfiler(ProfilerRestoreNoAction);
// Dispatch pending frontend commands
- for (Vector<pair<long, String> >::iterator it = m_pendingEvaluateTestCommands.begin(); it != m_pendingEvaluateTestCommands.end(); ++it)
- m_frontend->evaluateForTestInFrontend((*it).first, (*it).second);
- m_pendingEvaluateTestCommands.clear();
+ issueEvaluateForTestCommands();
}
void InspectorAgent::pushDataCollectedOffline()
{
m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
-#if ENABLE(DATABASE)
- DatabaseResourcesMap::iterator databasesEnd = m_databaseResources.end();
- for (DatabaseResourcesMap::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it)
- it->second->bind(m_frontend);
-#endif
-#if ENABLE(DOM_STORAGE)
- DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources.end();
- for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it)
- it->second->bind(m_frontend);
-#endif
#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
WorkersMap::iterator workersEnd = m_workers.end();
for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) {
InspectorWorkerResource* worker = it->second.get();
- m_frontend->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
+ m_frontend->debugger()->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
}
#endif
}
-void InspectorAgent::restoreDebugger(bool eraseStickyBreakpoints)
-{
- ASSERT(m_frontend);
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (m_state->getBoolean(InspectorAgentState::debuggerEnabled))
- enableDebugger(eraseStickyBreakpoints);
-#endif
-}
-
void InspectorAgent::restoreProfiler(ProfilerRestoreAction action)
{
ASSERT(m_frontend);
#if ENABLE(JAVASCRIPT_DEBUGGER)
m_profilerAgent->setFrontend(m_frontend);
- if (m_state->getBoolean(InspectorAgentState::profilerEnabled))
- enableProfiler();
+ if (m_state->getBoolean(InspectorAgentState::profilerEnabled)) {
+ ErrorString error;
+ enableProfiler(&error);
+ }
if (action == ProfilerRestoreResetAgent)
m_profilerAgent->resetFrontendProfiles();
#endif
@@ -498,61 +505,14 @@ void InspectorAgent::restoreProfiler(ProfilerRestoreAction action)
void InspectorAgent::didCommitLoad(DocumentLoader* loader)
{
- if (!enabled())
- return;
-
- if (m_resourceAgent)
- m_resourceAgent->didCommitLoad(loader);
-
- ASSERT(m_inspectedPage);
-
- if (loader->frame() == m_inspectedPage->mainFrame()) {
- if (m_frontend)
- m_frontend->inspectedURLChanged(loader->url().string());
-
- m_injectedScriptHost->discardInjectedScripts();
- m_consoleAgent->reset();
-
- if (m_timelineAgent)
- m_timelineAgent->didCommitLoad();
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (m_applicationCacheAgent)
- m_applicationCacheAgent->didCommitLoad(loader);
-#endif
-
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (m_debuggerAgent) {
- KURL url = inspectedURLWithoutFragment();
- m_debuggerAgent->inspectedURLChanged(url);
- if (m_browserDebuggerAgent)
- m_browserDebuggerAgent->inspectedURLChanged(url);
- }
-#endif
-
-#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
- m_profilerAgent->stopUserInitiatedProfiling(true);
- m_profilerAgent->resetState();
-#endif
-
- if (m_frontend) {
- m_frontend->reset();
- m_domAgent->reset();
- m_cssAgent->reset();
- }
+ if (m_frontend) {
+ m_frontend->inspector()->inspectedURLChanged(loader->url().string());
+ m_frontend->inspector()->reset();
+ }
+ m_injectedScriptHost->discardInjectedScripts();
#if ENABLE(WORKERS)
- m_workers.clear();
-#endif
-#if ENABLE(DATABASE)
- m_databaseResources.clear();
-#endif
-#if ENABLE(DOM_STORAGE)
- m_domStorageResources.clear();
+ m_workers.clear();
#endif
-
- if (m_frontend)
- m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
- }
}
void InspectorAgent::domContentLoadedEventFired(DocumentLoader* loader, const KURL& url)
@@ -560,12 +520,12 @@ void InspectorAgent::domContentLoadedEventFired(DocumentLoader* loader, const KU
if (!enabled() || !isMainResourceLoader(loader, url))
return;
- if (m_domAgent)
- m_domAgent->mainFrameDOMContentLoaded();
- if (m_timelineAgent)
- m_timelineAgent->didMarkDOMContentEvent();
+ if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
+ domAgent->mainFrameDOMContentLoaded();
+ if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+ timelineAgent->didMarkDOMContentEvent();
if (m_frontend)
- m_frontend->domContentEventFired(currentTime());
+ m_frontend->inspector()->domContentEventFired(currentTime());
}
void InspectorAgent::loadEventFired(DocumentLoader* loader, const KURL& url)
@@ -573,16 +533,16 @@ void InspectorAgent::loadEventFired(DocumentLoader* loader, const KURL& url)
if (!enabled())
return;
- if (m_domAgent)
- m_domAgent->loadEventFired(loader->frame()->document());
+ if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
+ domAgent->loadEventFired(loader->frame()->document());
if (!isMainResourceLoader(loader, url))
return;
- if (m_timelineAgent)
- m_timelineAgent->didMarkLoadEvent();
+ if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+ timelineAgent->didMarkLoadEvent();
if (m_frontend)
- m_frontend->loadEventFired(currentTime());
+ m_frontend->inspector()->loadEventFired(currentTime());
}
bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
@@ -590,7 +550,7 @@ bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& re
return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
}
-void InspectorAgent::setUserAgentOverride(const String& userAgent)
+void InspectorAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
{
m_userAgentOverride = userAgent;
}
@@ -601,19 +561,6 @@ void InspectorAgent::applyUserAgentOverride(String* userAgent) const
*userAgent = m_userAgentOverride;
}
-void InspectorAgent::startTimelineProfiler()
-{
- if (m_timelineAgent || !enabled() || !m_frontend)
- return;
-
- m_timelineAgent = InspectorTimelineAgent::create(m_state.get(), m_frontend);
-}
-
-void InspectorAgent::stopTimelineProfiler()
-{
- m_timelineAgent.clear();
-}
-
#if ENABLE(WORKERS)
class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task {
public:
@@ -649,10 +596,10 @@ void InspectorAgent::postWorkerNotificationToFrontend(const InspectorWorkerResou
#if ENABLE(JAVASCRIPT_DEBUGGER)
switch (action) {
case InspectorAgent::WorkerCreated:
- m_frontend->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
+ m_frontend->debugger()->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
break;
case InspectorAgent::WorkerDestroyed:
- m_frontend->didDestroyWorker(worker.id());
+ m_frontend->debugger()->didDestroyWorker(worker.id());
break;
}
#endif
@@ -683,23 +630,7 @@ void InspectorAgent::didDestroyWorker(intptr_t id)
}
#endif // ENABLE(WORKERS)
-#if ENABLE(DATABASE)
-void InspectorAgent::didOpenDatabase(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
-{
- if (!enabled())
- return;
-
- RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
-
- m_databaseResources.set(resource->id(), resource);
-
- // Resources are only bound while visible.
- if (m_frontend)
- resource->bind(m_frontend);
-}
-#endif
-
-void InspectorAgent::getCookies(RefPtr<InspectorArray>* cookies, WTF::String* cookiesString)
+void InspectorAgent::getCookies(ErrorString*, RefPtr<InspectorArray>* cookies, WTF::String* cookiesString)
{
// If we can get raw cookies.
ListHashSet<Cookie> rawCookiesList;
@@ -770,7 +701,7 @@ PassRefPtr<InspectorObject> InspectorAgent::buildObjectForCookie(const Cookie& c
return value;
}
-void InspectorAgent::deleteCookie(const String& cookieName, const String& domain)
+void InspectorAgent::deleteCookie(ErrorString*, const String& cookieName, const String& domain)
{
for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
Document* document = frame->document();
@@ -783,59 +714,6 @@ void InspectorAgent::deleteCookie(const String& cookieName, const String& domain
}
}
-#if ENABLE(DOM_STORAGE)
-void InspectorAgent::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
-{
- if (!enabled())
- return;
-
- DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources.end();
- for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it)
- if (it->second->isSameHostAndType(frame, isLocalStorage))
- return;
-
- RefPtr<Storage> domStorage = Storage::create(frame, storageArea);
- RefPtr<InspectorDOMStorageResource> resource = InspectorDOMStorageResource::create(domStorage.get(), isLocalStorage, frame);
-
- m_domStorageResources.set(resource->id(), resource);
-
- // Resources are only bound while visible.
- if (m_frontend)
- resource->bind(m_frontend);
-}
-#endif
-
-#if ENABLE(WEB_SOCKETS)
-void InspectorAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
-{
- if (!enabled())
- return;
- ASSERT(m_inspectedPage);
-
- if (m_resourceAgent)
- m_resourceAgent->didCreateWebSocket(identifier, requestURL);
- UNUSED_PARAM(documentURL);
-}
-
-void InspectorAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
-{
- if (m_resourceAgent)
- m_resourceAgent->willSendWebSocketHandshakeRequest(identifier, request);
-}
-
-void InspectorAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
-{
- if (m_resourceAgent)
- m_resourceAgent->didReceiveWebSocketHandshakeResponse(identifier, response);
-}
-
-void InspectorAgent::didCloseWebSocket(unsigned long identifier)
-{
- if (m_resourceAgent)
- m_resourceAgent->didCloseWebSocket(identifier);
-}
-#endif // ENABLE(WEB_SOCKETS)
-
#if ENABLE(JAVASCRIPT_DEBUGGER)
bool InspectorAgent::isRecordingUserInitiatedProfile() const
{
@@ -852,8 +730,6 @@ void InspectorAgent::startUserInitiatedProfiling()
void InspectorAgent::stopUserInitiatedProfiling()
{
- if (!enabled())
- return;
m_profilerAgent->stopUserInitiatedProfiling();
m_state->setBoolean(InspectorAgentState::userInitiatedProfiling, false);
showPanel(profilesPanelName);
@@ -864,7 +740,7 @@ bool InspectorAgent::profilerEnabled() const
return enabled() && m_profilerAgent->enabled();
}
-void InspectorAgent::enableProfiler()
+void InspectorAgent::enableProfiler(ErrorString*)
{
if (profilerEnabled())
return;
@@ -872,7 +748,7 @@ void InspectorAgent::enableProfiler()
m_profilerAgent->enable(false);
}
-void InspectorAgent::disableProfiler()
+void InspectorAgent::disableProfiler(ErrorString*)
{
m_state->setBoolean(InspectorAgentState::profilerEnabled, false);
m_profilerAgent->disable();
@@ -880,64 +756,20 @@ void InspectorAgent::disableProfiler()
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
-void InspectorAgent::showAndEnableDebugger()
-{
- if (!enabled())
- return;
-
- if (debuggerEnabled())
- return;
-
- if (!m_frontend) {
- m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
- showPanel(scriptsPanelName);
- } else
- enableDebugger(true);
-}
-
-void InspectorAgent::enableDebugger(bool eraseStickyBreakpoints)
-{
- if (debuggerEnabled())
- return;
- m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
- ASSERT(m_inspectedPage);
-
- m_debuggerAgent = InspectorDebuggerAgent::create(this, m_frontend, eraseStickyBreakpoints);
- m_browserDebuggerAgent = InspectorBrowserDebuggerAgent::create(this, eraseStickyBreakpoints);
-
- m_frontend->debuggerWasEnabled();
-}
-
-void InspectorAgent::disableDebugger()
+void InspectorAgent::showScriptsPanel()
{
- if (!enabled())
- return;
- ASSERT(m_inspectedPage);
- m_debuggerAgent.clear();
- m_browserDebuggerAgent.clear();
-
- if (m_frontend) {
- m_frontend->debuggerWasDisabled();
- m_state->setBoolean(InspectorAgentState::debuggerEnabled, false);
- }
-}
-
-void InspectorAgent::resume()
-{
- if (m_debuggerAgent)
- m_debuggerAgent->resume();
+ showPanel(scriptsPanelName);
}
#endif
void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
{
- if (m_frontend)
- m_frontend->evaluateForTestInFrontend(callId, script);
- else
- m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
+ m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
+ if (m_canIssueEvaluateForTestInFrontend)
+ issueEvaluateForTestCommands();
}
-void InspectorAgent::didEvaluateForTestInFrontend(long callId, const String& jsonResult)
+void InspectorAgent::didEvaluateForTestInFrontend(ErrorString*, long callId, const String& jsonResult)
{
ScriptState* scriptState = scriptStateFromPage(debuggerWorld(), m_inspectedPage);
ScriptObject window;
@@ -1043,7 +875,7 @@ void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
IntRect boundingBox = renderer->absoluteBoundingBoxRect(true);
boundingBox.move(mainFrameOffset);
- IntRect titleReferenceBox = boundingBox;
+ IntRect titleAnchorBox = boundingBox;
ASSERT(m_inspectedPage);
@@ -1072,9 +904,6 @@ void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
IntRect marginBox(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
borderBox.width() + renderBox->marginLeft() + renderBox->marginRight(), borderBox.height() + renderBox->marginTop() + renderBox->marginBottom());
- titleReferenceBox = marginBox;
- titleReferenceBox.move(mainFrameOffset);
- titleReferenceBox.move(boundingBox.x(), boundingBox.y());
FloatQuad absContentQuad = renderBox->localToAbsoluteQuad(FloatRect(contentBox));
FloatQuad absPaddingQuad = renderBox->localToAbsoluteQuad(FloatRect(paddingBox));
@@ -1086,6 +915,8 @@ void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
absBorderQuad.move(mainFrameOffset);
absMarginQuad.move(mainFrameOffset);
+ titleAnchorBox = absMarginQuad.enclosingBoundingBox();
+
drawHighlightForBox(context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
} else if (renderer->isRenderInline() || isSVGRenderer) {
// FIXME: We should show margins/padding/border for inlines.
@@ -1103,10 +934,10 @@ void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
return;
WebCore::Settings* settings = containingFrame->settings();
- drawElementTitle(context, titleReferenceBox, overlayRect, settings);
+ drawElementTitle(context, boundingBox, titleAnchorBox, overlayRect, settings);
}
-void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& boundingBox, const FloatRect& overlayRect, WebCore::Settings* settings) const
+void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& boundingBox, const IntRect& anchorBox, const FloatRect& overlayRect, WebCore::Settings* settings) const
{
static const int rectInflatePx = 4;
static const int fontHeightPx = 12;
@@ -1139,11 +970,10 @@ void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& b
}
}
- Element* highlightedElement = m_highlightedNode->isElementNode() ? static_cast<Element*>(m_highlightedNode.get()) : 0;
nodeTitle += " [";
- nodeTitle += String::number(highlightedElement ? highlightedElement->offsetWidth() : boundingBox.width());
+ nodeTitle += String::number(boundingBox.width());
nodeTitle.append(static_cast<UChar>(0x00D7)); // &times;
- nodeTitle += String::number(highlightedElement ? highlightedElement->offsetHeight() : boundingBox.height());
+ nodeTitle += String::number(boundingBox.height());
nodeTitle += "]";
FontDescription desc;
@@ -1155,7 +985,7 @@ void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& b
font.update(0);
TextRun nodeTitleRun(nodeTitle);
- IntPoint titleBasePoint = IntPoint(boundingBox.x(), boundingBox.maxY() - 1);
+ IntPoint titleBasePoint = IntPoint(anchorBox.x(), anchorBox.maxY() - 1);
titleBasePoint.move(rectInflatePx, rectInflatePx);
IntRect titleRect = enclosingIntRect(font.selectionRectForText(nodeTitleRun, titleBasePoint, fontHeightPx));
titleRect.inflate(rectInflatePx);
@@ -1174,7 +1004,7 @@ void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& b
// If the tip sticks beyond the bottom of overlayRect, show the tip at top of bounding box.
if (titleRect.maxY() > overlayRect.maxY()) {
- dy = boundingBox.y() - titleRect.maxY() - borderWidthPx;
+ dy = anchorBox.y() - titleRect.maxY() - borderWidthPx;
// If the tip still sticks beyond the bottom of overlayRect, bottom-align the tip with the said boundary.
if (titleRect.maxY() + dy > overlayRect.maxY())
dy = overlayRect.maxY() - titleRect.maxY();
@@ -1193,7 +1023,7 @@ void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& b
context.drawText(font, nodeTitleRun, IntPoint(titleRect.x() + rectInflatePx, titleRect.y() + font.fontMetrics().height()));
}
-void InspectorAgent::openInInspectedWindow(const String& url)
+void InspectorAgent::openInInspectedWindow(ErrorString*, const String& url)
{
Frame* mainFrame = m_inspectedPage->mainFrame();
@@ -1211,12 +1041,12 @@ void InspectorAgent::openInInspectedWindow(const String& url)
newFrame->loader()->changeLocation(mainFrame->document()->securityOrigin(), newFrame->loader()->completeURL(url), "", false, false);
}
-void InspectorAgent::addScriptToEvaluateOnLoad(const String& source)
+void InspectorAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source)
{
m_scriptsToEvaluateOnLoad.append(source);
}
-void InspectorAgent::removeAllScriptsToEvaluateOnLoad()
+void InspectorAgent::removeAllScriptsToEvaluateOnLoad(ErrorString*)
{
m_scriptsToEvaluateOnLoad.clear();
}
@@ -1238,7 +1068,7 @@ KURL InspectorAgent::inspectedURLWithoutFragment() const
return url;
}
-void InspectorAgent::reloadPage(bool ignoreCache)
+void InspectorAgent::reloadPage(ErrorString*, bool ignoreCache)
{
m_inspectedPage->mainFrame()->loader()->reload(ignoreCache);
}
@@ -1258,10 +1088,21 @@ void InspectorAgent::showConsole()
void InspectorAgent::showPanel(const String& panel)
{
if (!m_frontend) {
- m_requiredPanel = panel;
+ m_showPanelAfterVisible = panel;
return;
}
- m_frontend->showPanel(panel);
+ m_frontend->inspector()->showPanel(panel);
+}
+
+void InspectorAgent::issueEvaluateForTestCommands()
+{
+ if (m_frontend) {
+ Vector<pair<long, String> > copy = m_pendingEvaluateTestCommands;
+ m_pendingEvaluateTestCommands.clear();
+ for (Vector<pair<long, String> >::iterator it = copy.begin(); m_frontend && it != copy.end(); ++it)
+ m_frontend->inspector()->evaluateForTestInFrontend((*it).first, (*it).second);
+ m_canIssueEvaluateForTestInFrontend = true;
+ }
}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorAgent.h b/Source/WebCore/inspector/InspectorAgent.h
index 1f14dd9..151dba5 100644
--- a/Source/WebCore/inspector/InspectorAgent.h
+++ b/Source/WebCore/inspector/InspectorAgent.h
@@ -62,7 +62,6 @@ class InspectorConsoleAgent;
class InspectorCSSAgent;
class InspectorDOMAgent;
class InspectorDOMStorageAgent;
-class InspectorDOMStorageResource;
class InspectorDatabaseAgent;
class InspectorDatabaseResource;
class InspectorDebuggerAgent;
@@ -77,6 +76,7 @@ class InspectorStorageAgent;
class InspectorTimelineAgent;
class InspectorValue;
class InspectorWorkerResource;
+class InstrumentingAgents;
class IntRect;
class KURL;
class Node;
@@ -94,10 +94,7 @@ class StorageArea;
class InspectorApplicationCacheAgent;
#endif
-#if ENABLE(WEB_SOCKETS)
-class WebSocketHandshakeRequest;
-class WebSocketHandshakeResponse;
-#endif
+typedef String ErrorString;
class InspectorAgent {
WTF_MAKE_NONCOPYABLE(InspectorAgent);
@@ -116,33 +113,33 @@ public:
Page* inspectedPage() const { return m_inspectedPage; }
KURL inspectedURL() const;
KURL inspectedURLWithoutFragment() const;
- void reloadPage(bool ignoreCache);
+ void reloadPage(ErrorString* error, bool ignoreCache);
void showConsole();
void restoreInspectorStateFromCookie(const String& inspectorCookie);
- void highlight(Node*);
- void hideHighlight();
+ void highlight(ErrorString* error, Node*);
+ void hideHighlight(ErrorString* error);
void inspect(Node*);
- void highlightDOMNode(long nodeId);
- void hideDOMNodeHighlight() { hideHighlight(); }
+ void highlightDOMNode(ErrorString* error, long nodeId);
+ void hideDOMNodeHighlight(ErrorString* error) { hideHighlight(error); }
- void highlightFrame(unsigned long frameId);
- void hideFrameHighlight() { hideHighlight(); }
+ void highlightFrame(ErrorString* error, unsigned long frameId);
+ void hideFrameHighlight(ErrorString* error) { hideHighlight(error); }
void setFrontend(InspectorFrontend*);
InspectorFrontend* frontend() const { return m_frontend; }
void disconnectFrontend();
- InspectorResourceAgent* resourceAgent();
+ InstrumentingAgents* instrumentingAgents() const { return m_instrumentingAgents.get(); }
InspectorAgent* inspectorAgent() { return this; }
InspectorConsoleAgent* consoleAgent() { return m_consoleAgent.get(); }
InspectorCSSAgent* cssAgent() { return m_cssAgent.get(); }
InspectorDOMAgent* domAgent() { return m_domAgent.get(); }
- InjectedScriptHost* injectedScriptAgent() { return m_injectedScriptHost.get(); }
InspectorRuntimeAgent* runtimeAgent() { return m_runtimeAgent.get(); }
InspectorTimelineAgent* timelineAgent() { return m_timelineAgent.get(); }
+ InspectorResourceAgent* resourceAgent() { return m_resourceAgent.get(); }
#if ENABLE(DATABASE)
InspectorDatabaseAgent* databaseAgent() { return m_databaseAgent.get(); }
#endif
@@ -166,11 +163,8 @@ public:
void didCommitLoad(DocumentLoader*);
- void startTimelineProfiler();
- void stopTimelineProfiler();
-
- void getCookies(RefPtr<InspectorArray>* cookies, WTF::String* cookiesString);
- void deleteCookie(const String& cookieName, const String& domain);
+ void getCookies(ErrorString* error, RefPtr<InspectorArray>* cookies, WTF::String* cookiesString);
+ void deleteCookie(ErrorString* error, const String& cookieName, const String& domain);
void domContentLoadedEventFired(DocumentLoader*, const KURL&);
void loadEventFired(DocumentLoader*, const KURL&);
@@ -183,50 +177,30 @@ public:
void didDestroyWorker(intptr_t);
#endif
-#if ENABLE(DATABASE)
- void didOpenDatabase(PassRefPtr<Database>, const String& domain, const String& name, const String& version);
-#endif
-
-#if ENABLE(DOM_STORAGE)
- void didUseDOMStorage(StorageArea*, bool isLocalStorage, Frame*);
-#endif
-
-#if ENABLE(WEB_SOCKETS)
- void didCreateWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL);
- void willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest&);
- void didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse&);
- void didCloseWebSocket(unsigned long identifier);
-#endif
-
bool hasFrontend() const { return m_frontend; }
void drawNodeHighlight(GraphicsContext&) const;
- void openInInspectedWindow(const String& url);
- void drawElementTitle(GraphicsContext&, const IntRect& boundingBox, const FloatRect& overlayRect, WebCore::Settings*) const;
+ void openInInspectedWindow(ErrorString* error, const String& url);
+ void drawElementTitle(GraphicsContext&, const IntRect& boundingBox, const IntRect& anchorBox, const FloatRect& overlayRect, WebCore::Settings*) const;
#if ENABLE(JAVASCRIPT_DEBUGGER)
bool isRecordingUserInitiatedProfile() const;
- void startProfiling() { startUserInitiatedProfiling(); }
+ void startProfiling(ErrorString*) { startUserInitiatedProfiling(); }
void startUserInitiatedProfiling();
- void stopProfiling() { stopUserInitiatedProfiling(); }
+ void stopProfiling(ErrorString*) { stopUserInitiatedProfiling(); }
void stopUserInitiatedProfiling();
- void enableProfiler();
- void disableProfiler();
+ void enableProfiler(ErrorString* error);
+ void disableProfiler(ErrorString* error);
bool profilerEnabled() const;
- void showAndEnableDebugger();
- void enableDebugger() { enableDebugger(false); }
- void enableDebugger(bool eraseStickyBreakpoints);
- void disableDebugger();
- bool debuggerEnabled() const { return m_debuggerAgent; }
- void resume();
+ void showScriptsPanel();
#endif
// Generic code called from custom implementations.
void evaluateForTestInFrontend(long testCallId, const String& script);
- void addScriptToEvaluateOnLoad(const String& source);
- void removeAllScriptsToEvaluateOnLoad();
+ void addScriptToEvaluateOnLoad(ErrorString* error, const String& source);
+ void removeAllScriptsToEvaluateOnLoad(ErrorString* error);
void setInspectorExtensionAPI(const String& source);
InspectorState* state() { return m_state.get(); }
@@ -234,18 +208,17 @@ public:
// InspectorAgent API
void getInspectorState(RefPtr<InspectorObject>* state);
void setMonitoringXHREnabled(bool enabled, bool* newState);
- void populateScriptObjects();
+ void populateScriptObjects(ErrorString* error);
// Following are used from InspectorBackend and internally.
- void setSearchingForNode(bool enabled, bool* newState);
- void didEvaluateForTestInFrontend(long callId, const String& jsonResult);
+ void setSearchingForNode(ErrorString* error, bool enabled, bool* newState);
+ void didEvaluateForTestInFrontend(ErrorString* error, long callId, const String& jsonResult);
- void setUserAgentOverride(const String& userAgent);
+ void setUserAgentOverride(ErrorString* error, const String& userAgent);
void applyUserAgentOverride(String* userAgent) const;
private:
void showPanel(const String& panel);
void pushDataCollectedOffline();
- void restoreDebugger(bool eraseStickyBreakpoints);
enum ProfilerRestoreAction {
ProfilerRestoreNoAction = 0,
ProfilerRestoreResetAgent = 1
@@ -266,12 +239,16 @@ private:
void focusNode();
bool isMainResourceLoader(DocumentLoader*, const KURL& requestUrl);
+ void issueEvaluateForTestCommands();
Page* m_inspectedPage;
InspectorClient* m_client;
InspectorFrontend* m_frontend;
- OwnPtr<InspectorCSSAgent> m_cssAgent;
+ OwnPtr<InstrumentingAgents> m_instrumentingAgents;
+ RefPtr<InjectedScriptHost> m_injectedScriptHost;
+ OwnPtr<InspectorState> m_state;
OwnPtr<InspectorDOMAgent> m_domAgent;
+ OwnPtr<InspectorCSSAgent> m_cssAgent;
#if ENABLE(DATABASE)
OwnPtr<InspectorDatabaseAgent> m_databaseAgent;
@@ -282,7 +259,6 @@ private:
#endif
OwnPtr<InspectorTimelineAgent> m_timelineAgent;
- OwnPtr<InspectorState> m_state;
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
OwnPtr<InspectorApplicationCacheAgent> m_applicationCacheAgent;
@@ -293,20 +269,10 @@ private:
RefPtr<InspectorResourceAgent> m_resourceAgent;
OwnPtr<InspectorRuntimeAgent> m_runtimeAgent;
-#if ENABLE(DATABASE)
- typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
- DatabaseResourcesMap m_databaseResources;
-#endif
-#if ENABLE(DOM_STORAGE)
- typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
- DOMStorageResourcesMap m_domStorageResources;
-#endif
-
- RefPtr<InjectedScriptHost> m_injectedScriptHost;
OwnPtr<InspectorConsoleAgent> m_consoleAgent;
Vector<pair<long, String> > m_pendingEvaluateTestCommands;
- String m_requiredPanel;
+ String m_showPanelAfterVisible;
Vector<String> m_scriptsToEvaluateOnLoad;
String m_inspectorExtensionAPI;
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -317,9 +283,9 @@ private:
String m_userAgentOverride;
#if ENABLE(WORKERS)
typedef HashMap<intptr_t, RefPtr<InspectorWorkerResource> > WorkersMap;
-
WorkersMap m_workers;
#endif
+ bool m_canIssueEvaluateForTestInFrontend;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorApplicationCacheAgent.cpp b/Source/WebCore/inspector/InspectorApplicationCacheAgent.cpp
index b38bb83..625f53d 100644
--- a/Source/WebCore/inspector/InspectorApplicationCacheAgent.cpp
+++ b/Source/WebCore/inspector/InspectorApplicationCacheAgent.cpp
@@ -35,21 +35,30 @@
#include "InspectorAgent.h"
#include "InspectorFrontend.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "NetworkStateNotifier.h"
#include "Page.h"
#include "ResourceResponse.h"
namespace WebCore {
-InspectorApplicationCacheAgent::InspectorApplicationCacheAgent(DocumentLoader* documentLoader, InspectorFrontend* frontend)
- : m_documentLoader(documentLoader)
- , m_frontend(frontend)
+InspectorApplicationCacheAgent::InspectorApplicationCacheAgent(InstrumentingAgents* instrumentingAgents, Page* inspectedPage)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_inspectedPage(inspectedPage)
+ , m_frontend(0)
{
}
-void InspectorApplicationCacheAgent::didCommitLoad(DocumentLoader* documentLoader)
+void InspectorApplicationCacheAgent::setFrontend(InspectorFrontend* frontend)
{
- m_documentLoader = documentLoader;
+ m_frontend = frontend->applicationcache();
+ m_instrumentingAgents->setInspectorApplicationCacheAgent(this);
+}
+
+void InspectorApplicationCacheAgent::clearFrontend()
+{
+ m_instrumentingAgents->setInspectorApplicationCacheAgent(0);
+ m_frontend = 0;
}
void InspectorApplicationCacheAgent::updateApplicationCacheStatus(Frame* frame)
@@ -64,16 +73,17 @@ void InspectorApplicationCacheAgent::networkStateChanged()
m_frontend->updateNetworkState(isNowOnline);
}
-void InspectorApplicationCacheAgent::getApplicationCaches(RefPtr<InspectorValue>* applicationCaches)
+void InspectorApplicationCacheAgent::getApplicationCaches(ErrorString*, RefPtr<InspectorValue>* applicationCaches)
{
- if (m_documentLoader) {
- ApplicationCacheHost* host = m_documentLoader->applicationCacheHost();
- ApplicationCacheHost::CacheInfo info = host->applicationCacheInfo();
-
- ApplicationCacheHost::ResourceInfoList resources;
- host->fillResourceList(&resources);
- *applicationCaches = buildObjectForApplicationCache(resources, info);
- }
+ DocumentLoader* documentLoader = m_inspectedPage->mainFrame()->loader()->documentLoader();
+ if (!documentLoader)
+ return;
+ ApplicationCacheHost* host = documentLoader->applicationCacheHost();
+ ApplicationCacheHost::CacheInfo info = host->applicationCacheInfo();
+
+ ApplicationCacheHost::ResourceInfoList resources;
+ host->fillResourceList(&resources);
+ *applicationCaches = buildObjectForApplicationCache(resources, info);
}
PassRefPtr<InspectorObject> InspectorApplicationCacheAgent::buildObjectForApplicationCache(const ApplicationCacheHost::ResourceInfoList& applicationCacheResources, const ApplicationCacheHost::CacheInfo& applicationCacheInfo)
diff --git a/Source/WebCore/inspector/InspectorApplicationCacheAgent.h b/Source/WebCore/inspector/InspectorApplicationCacheAgent.h
index 33cee59..34abf81 100644
--- a/Source/WebCore/inspector/InspectorApplicationCacheAgent.h
+++ b/Source/WebCore/inspector/InspectorApplicationCacheAgent.h
@@ -28,42 +28,48 @@
#if ENABLE(INSPECTOR) && ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCacheHost.h"
+#include "InspectorFrontend.h"
#include <wtf/Noncopyable.h>
#include <wtf/PassRefPtr.h>
namespace WebCore {
-class DocumentLoader;
class Frame;
class InspectorArray;
class InspectorAgent;
class InspectorFrontend;
class InspectorObject;
class InspectorValue;
+class InstrumentingAgents;
+class Page;
class ResourceResponse;
+typedef String ErrorString;
+
class InspectorApplicationCacheAgent {
WTF_MAKE_NONCOPYABLE(InspectorApplicationCacheAgent); WTF_MAKE_FAST_ALLOCATED;
public:
- InspectorApplicationCacheAgent(DocumentLoader*, InspectorFrontend*);
+ InspectorApplicationCacheAgent(InstrumentingAgents*, Page*);
~InspectorApplicationCacheAgent() { }
- void didCommitLoad(DocumentLoader*);
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
// Backend to Frontend
void updateApplicationCacheStatus(Frame*);
void networkStateChanged();
// From Frontend
- void getApplicationCaches(RefPtr<InspectorValue>* applicationCaches);
+ void getApplicationCaches(ErrorString* error, RefPtr<InspectorValue>* applicationCaches);
private:
PassRefPtr<InspectorObject> buildObjectForApplicationCache(const ApplicationCacheHost::ResourceInfoList&, const ApplicationCacheHost::CacheInfo&);
PassRefPtr<InspectorArray> buildArrayForApplicationCacheResources(const ApplicationCacheHost::ResourceInfoList&);
PassRefPtr<InspectorObject> buildObjectForApplicationCacheResource(const ApplicationCacheHost::ResourceInfo&);
- DocumentLoader* m_documentLoader;
- InspectorFrontend* m_frontend;
+ InstrumentingAgents* m_instrumentingAgents;
+ Page* m_inspectedPage;
+ InspectorFrontend::ApplicationCache* m_frontend;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.cpp b/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.cpp
index 5fe9937..0cba775 100644
--- a/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.cpp
+++ b/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.cpp
@@ -35,10 +35,11 @@
#if ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
#include "HTMLElement.h"
-#include "InspectorAgent.h"
#include "InspectorDOMAgent.h"
#include "InspectorDebuggerAgent.h"
#include "InspectorState.h"
+#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include <wtf/text/CString.h>
namespace {
@@ -65,26 +66,61 @@ namespace BrowserDebuggerAgentState {
static const char browserBreakpoints[] = "browserBreakpoints";
}
-PassOwnPtr<InspectorBrowserDebuggerAgent> InspectorBrowserDebuggerAgent::create(InspectorAgent* inspectorAgent, bool eraseStickyBreakpoints)
+PassOwnPtr<InspectorBrowserDebuggerAgent> InspectorBrowserDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, InspectorDOMAgent* domAgent, InspectorDebuggerAgent* debuggerAgent, InspectorAgent* inspectorAgent)
{
- return adoptPtr(new InspectorBrowserDebuggerAgent(inspectorAgent, eraseStickyBreakpoints));
+ return adoptPtr(new InspectorBrowserDebuggerAgent(instrumentingAgents, inspectorState, domAgent, debuggerAgent, inspectorAgent));
}
-InspectorBrowserDebuggerAgent::InspectorBrowserDebuggerAgent(InspectorAgent* inspectorAgent, bool eraseStickyBreakpoints)
- : m_inspectorAgent(inspectorAgent)
+InspectorBrowserDebuggerAgent::InspectorBrowserDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, InspectorDOMAgent* domAgent, InspectorDebuggerAgent* debuggerAgent, InspectorAgent* inspectorAgent)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_inspectorState(inspectorState)
+ , m_domAgent(domAgent)
+ , m_debuggerAgent(debuggerAgent)
+ , m_inspectorAgent(inspectorAgent)
, m_hasXHRBreakpointWithEmptyURL(false)
{
- if (eraseStickyBreakpoints)
- inspectorAgent->state()->setObject(BrowserDebuggerAgentState::browserBreakpoints, InspectorObject::create());
+ m_debuggerAgent->setListener(this);
}
InspectorBrowserDebuggerAgent::~InspectorBrowserDebuggerAgent()
{
+ m_debuggerAgent->setListener(0);
+ ASSERT(!m_instrumentingAgents->inspectorBrowserDebuggerAgent());
}
-void InspectorBrowserDebuggerAgent::setAllBrowserBreakpoints(PassRefPtr<InspectorObject> breakpoints)
+// Browser debugger agent enabled only when JS debugger is enabled.
+void InspectorBrowserDebuggerAgent::debuggerWasEnabled()
{
- m_inspectorAgent->state()->setObject(BrowserDebuggerAgentState::browserBreakpoints, breakpoints);
+ m_instrumentingAgents->setInspectorBrowserDebuggerAgent(this);
+}
+
+void InspectorBrowserDebuggerAgent::debuggerWasDisabled()
+{
+ disable();
+}
+
+void InspectorBrowserDebuggerAgent::disable()
+{
+ m_instrumentingAgents->setInspectorBrowserDebuggerAgent(0);
+ clear();
+}
+
+void InspectorBrowserDebuggerAgent::setFrontend(InspectorFrontend*)
+{
+ // Erase sticky breakpoints. If we are restoring from a cookie setFrontend msut be called
+ // before the state is loaded from the cookie.
+ m_inspectorState->setObject(BrowserDebuggerAgentState::browserBreakpoints, InspectorObject::create());
+}
+
+void InspectorBrowserDebuggerAgent::clearFrontend()
+{
+ disable();
+}
+
+void InspectorBrowserDebuggerAgent::setAllBrowserBreakpoints(ErrorString*, PassRefPtr<InspectorObject> breakpoints)
+{
+ m_inspectorState->setObject(BrowserDebuggerAgentState::browserBreakpoints, breakpoints);
+ // FIXME: remove this call to inspector agent and dependency on the inspector agent.
inspectedURLChanged(m_inspectorAgent->inspectedURLWithoutFragment());
}
@@ -94,7 +130,7 @@ void InspectorBrowserDebuggerAgent::inspectedURLChanged(const String& url)
m_XHRBreakpoints.clear();
m_hasXHRBreakpointWithEmptyURL = false;
- RefPtr<InspectorObject> allBreakpoints = m_inspectorAgent->state()->getObject(BrowserDebuggerAgentState::browserBreakpoints);
+ RefPtr<InspectorObject> allBreakpoints = m_inspectorState->getObject(BrowserDebuggerAgentState::browserBreakpoints);
RefPtr<InspectorArray> breakpoints = allBreakpoints->getArray(url);
if (!breakpoints)
return;
@@ -116,20 +152,21 @@ void InspectorBrowserDebuggerAgent::restoreStickyBreakpoint(PassRefPtr<Inspector
if (!condition)
return;
+ ErrorString error;
if (type == eventListenerNativeBreakpointType) {
if (!enabled)
return;
String eventName;
if (!condition->getString("eventName", &eventName))
return;
- setEventListenerBreakpoint(eventName);
+ setEventListenerBreakpoint(&error, eventName);
} else if (type == xhrNativeBreakpointType) {
if (!enabled)
return;
String url;
if (!condition->getString("url", &url))
return;
- setXHRBreakpoint(url);
+ setXHRBreakpoint(&error, url);
}
}
@@ -138,12 +175,12 @@ void InspectorBrowserDebuggerAgent::discardBindings()
m_domBreakpoints.clear();
}
-void InspectorBrowserDebuggerAgent::setEventListenerBreakpoint(const String& eventName)
+void InspectorBrowserDebuggerAgent::setEventListenerBreakpoint(ErrorString*, const String& eventName)
{
m_eventListenerBreakpoints.add(eventName);
}
-void InspectorBrowserDebuggerAgent::removeEventListenerBreakpoint(const String& eventName)
+void InspectorBrowserDebuggerAgent::removeEventListenerBreakpoint(ErrorString*, const String& eventName)
{
m_eventListenerBreakpoints.remove(eventName);
}
@@ -176,9 +213,9 @@ void InspectorBrowserDebuggerAgent::didRemoveDOMNode(Node* node)
}
}
-void InspectorBrowserDebuggerAgent::setDOMBreakpoint(long nodeId, long type)
+void InspectorBrowserDebuggerAgent::setDOMBreakpoint(ErrorString*, long nodeId, long type)
{
- Node* node = m_inspectorAgent->domAgent()->nodeForId(nodeId);
+ Node* node = m_domAgent->nodeForId(nodeId);
if (!node)
return;
@@ -190,9 +227,9 @@ void InspectorBrowserDebuggerAgent::setDOMBreakpoint(long nodeId, long type)
}
}
-void InspectorBrowserDebuggerAgent::removeDOMBreakpoint(long nodeId, long type)
+void InspectorBrowserDebuggerAgent::removeDOMBreakpoint(ErrorString*, long nodeId, long type)
{
- Node* node = m_inspectorAgent->domAgent()->nodeForId(nodeId);
+ Node* node = m_domAgent->nodeForId(nodeId);
if (!node)
return;
@@ -211,7 +248,7 @@ void InspectorBrowserDebuggerAgent::removeDOMBreakpoint(long nodeId, long type)
void InspectorBrowserDebuggerAgent::willInsertDOMNode(Node*, Node* parent)
{
- InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent();
+ InspectorDebuggerAgent* debuggerAgent = m_debuggerAgent;
if (!debuggerAgent)
return;
@@ -225,7 +262,7 @@ void InspectorBrowserDebuggerAgent::willInsertDOMNode(Node*, Node* parent)
void InspectorBrowserDebuggerAgent::willRemoveDOMNode(Node* node)
{
- InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent();
+ InspectorDebuggerAgent* debuggerAgent = m_debuggerAgent;
if (!debuggerAgent)
return;
@@ -244,7 +281,7 @@ void InspectorBrowserDebuggerAgent::willRemoveDOMNode(Node* node)
void InspectorBrowserDebuggerAgent::willModifyDOMAttr(Element* element)
{
- InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent();
+ InspectorDebuggerAgent* debuggerAgent = m_debuggerAgent;
if (!debuggerAgent)
return;
@@ -264,9 +301,8 @@ void InspectorBrowserDebuggerAgent::descriptionForDOMEvent(Node* target, long br
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.
- long targetNodeId = m_inspectorAgent->domAgent()->pushNodePathToFrontend(target);
- ASSERT(targetNodeId);
- description->setNumber("targetNodeId", targetNodeId);
+ RefPtr<InspectorObject> targetNodeObject = m_domAgent->resolveNode(target, "");
+ description->setObject("targetNode", targetNodeObject);
// Find breakpoint owner node.
if (!insertion)
@@ -281,7 +317,7 @@ void InspectorBrowserDebuggerAgent::descriptionForDOMEvent(Node* target, long br
description->setBoolean("insertion", insertion);
}
- long breakpointOwnerNodeId = m_inspectorAgent->domAgent()->pushNodePathToFrontend(breakpointOwner);
+ long breakpointOwnerNodeId = m_domAgent->boundNodeId(breakpointOwner);
ASSERT(breakpointOwnerNodeId);
description->setNumber("nodeId", breakpointOwnerNodeId);
description->setNumber("type", breakpointType);
@@ -314,7 +350,7 @@ void InspectorBrowserDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_
void InspectorBrowserDebuggerAgent::pauseOnNativeEventIfNeeded(const String& categoryType, const String& eventName, bool synchronous)
{
- InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent();
+ InspectorDebuggerAgent* debuggerAgent = m_debuggerAgent;
if (!debuggerAgent)
return;
@@ -331,7 +367,7 @@ void InspectorBrowserDebuggerAgent::pauseOnNativeEventIfNeeded(const String& cat
debuggerAgent->schedulePauseOnNextStatement(NativeBreakpointDebuggerEventType, eventData.release());
}
-void InspectorBrowserDebuggerAgent::setXHRBreakpoint(const String& url)
+void InspectorBrowserDebuggerAgent::setXHRBreakpoint(ErrorString*, const String& url)
{
if (url.isEmpty())
m_hasXHRBreakpointWithEmptyURL = true;
@@ -339,7 +375,7 @@ void InspectorBrowserDebuggerAgent::setXHRBreakpoint(const String& url)
m_XHRBreakpoints.add(url);
}
-void InspectorBrowserDebuggerAgent::removeXHRBreakpoint(const String& url)
+void InspectorBrowserDebuggerAgent::removeXHRBreakpoint(ErrorString*, const String& url)
{
if (url.isEmpty())
m_hasXHRBreakpointWithEmptyURL = false;
@@ -349,7 +385,7 @@ void InspectorBrowserDebuggerAgent::removeXHRBreakpoint(const String& url)
void InspectorBrowserDebuggerAgent::willSendXMLHttpRequest(const String& url)
{
- InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent();
+ InspectorDebuggerAgent* debuggerAgent = m_debuggerAgent;
if (!debuggerAgent)
return;
@@ -375,6 +411,14 @@ void InspectorBrowserDebuggerAgent::willSendXMLHttpRequest(const String& url)
debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData.release());
}
+void InspectorBrowserDebuggerAgent::clear()
+{
+ m_domBreakpoints.clear();
+ m_eventListenerBreakpoints.clear();
+ m_XHRBreakpoints.clear();
+ m_hasXHRBreakpointWithEmptyURL = false;
+}
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
diff --git a/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.h b/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.h
index fac54bb..7c0bc8d 100644
--- a/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.h
+++ b/Source/WebCore/inspector/InspectorBrowserDebuggerAgent.h
@@ -33,8 +33,8 @@
#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
+#include "InspectorDebuggerAgent.h"
#include "PlatformString.h"
-
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/PassOwnPtr.h>
@@ -45,26 +45,36 @@ namespace WebCore {
class Element;
class InspectorAgent;
+class InspectorDOMAgent;
+class InspectorDebuggerAgent;
+class InspectorFrontend;
class InspectorObject;
+class InspectorState;
+class InstrumentingAgents;
class Node;
-class InspectorBrowserDebuggerAgent {
+typedef String ErrorString;
+
+class InspectorBrowserDebuggerAgent : public InspectorDebuggerAgent::Listener {
WTF_MAKE_NONCOPYABLE(InspectorBrowserDebuggerAgent);
public:
- static PassOwnPtr<InspectorBrowserDebuggerAgent> create(InspectorAgent*, bool eraseStickyBreakpoints);
+ static PassOwnPtr<InspectorBrowserDebuggerAgent> create(InstrumentingAgents*, InspectorState*, InspectorDOMAgent*, InspectorDebuggerAgent*, InspectorAgent*);
virtual ~InspectorBrowserDebuggerAgent();
- void setAllBrowserBreakpoints(PassRefPtr<InspectorObject>);
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
+
+ void setAllBrowserBreakpoints(ErrorString* error, PassRefPtr<InspectorObject>);
void inspectedURLChanged(const String& url);
// BrowserDebugger API for InspectorFrontend
- void setXHRBreakpoint(const String& url);
- void removeXHRBreakpoint(const String& url);
- void setEventListenerBreakpoint(const String& eventName);
- void removeEventListenerBreakpoint(const String& eventName);
- void setDOMBreakpoint(long nodeId, long type);
- void removeDOMBreakpoint(long nodeId, long type);
+ void setXHRBreakpoint(ErrorString* error, const String& url);
+ void removeXHRBreakpoint(ErrorString* error, const String& url);
+ void setEventListenerBreakpoint(ErrorString* error, const String& eventName);
+ void removeEventListenerBreakpoint(ErrorString* error, const String& eventName);
+ void setDOMBreakpoint(ErrorString* error, long nodeId, long type);
+ void removeDOMBreakpoint(ErrorString* error, long nodeId, long type);
// InspectorInstrumentation API
void willInsertDOMNode(Node*, Node* parent);
@@ -76,7 +86,12 @@ public:
void pauseOnNativeEventIfNeeded(const String& categoryType, const String& eventName, bool synchronous);
private:
- InspectorBrowserDebuggerAgent(InspectorAgent*, bool eraseStickyBreakpoints);
+ InspectorBrowserDebuggerAgent(InstrumentingAgents*, InspectorState*, InspectorDOMAgent*, InspectorDebuggerAgent*, InspectorAgent*);
+
+ // InspectorDebuggerAgent::Listener implementation.
+ virtual void debuggerWasEnabled();
+ virtual void debuggerWasDisabled();
+ void disable();
void restoreStickyBreakpoint(PassRefPtr<InspectorObject> breakpoint);
@@ -85,6 +100,12 @@ private:
bool hasBreakpoint(Node*, long type);
void discardBindings();
+ void clear();
+
+ InstrumentingAgents* m_instrumentingAgents;
+ InspectorState* m_inspectorState;
+ InspectorDOMAgent* m_domAgent;
+ InspectorDebuggerAgent* m_debuggerAgent;
InspectorAgent* m_inspectorAgent;
HashMap<Node*, uint32_t> m_domBreakpoints;
HashSet<String> m_eventListenerBreakpoints;
diff --git a/Source/WebCore/inspector/InspectorCSSAgent.cpp b/Source/WebCore/inspector/InspectorCSSAgent.cpp
index f49f89c..b96071d 100644
--- a/Source/WebCore/inspector/InspectorCSSAgent.cpp
+++ b/Source/WebCore/inspector/InspectorCSSAgent.cpp
@@ -39,8 +39,8 @@
#include "DOMWindow.h"
#include "HTMLHeadElement.h"
#include "InspectorDOMAgent.h"
-#include "InspectorFrontend.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "Node.h"
#include "NodeList.h"
#include "StyleSheetList.h"
@@ -143,28 +143,26 @@ CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(StyleBase* styleBase)
return static_cast<CSSStyleRule*>(rule);
}
-InspectorCSSAgent::InspectorCSSAgent()
- : m_domAgent(0)
+InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorDOMAgent* domAgent)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_domAgent(domAgent)
, m_lastStyleSheetId(1)
, m_lastRuleId(1)
, m_lastStyleId(1)
{
+ m_domAgent->setDOMListener(this);
+ m_instrumentingAgents->setInspectorCSSAgent(this);
}
InspectorCSSAgent::~InspectorCSSAgent()
{
+ m_instrumentingAgents->setInspectorCSSAgent(0);
+ // DOM agent should be destroyed after CSS agent.
+ m_domAgent->setDOMListener(0);
+ m_domAgent = 0;
reset();
}
-void InspectorCSSAgent::setDOMAgent(InspectorDOMAgent* domAgent)
-{
- if (m_domAgent)
- m_domAgent->setDOMListener(0);
- m_domAgent = domAgent;
- if (m_domAgent)
- m_domAgent->setDOMListener(this);
-}
-
void InspectorCSSAgent::reset()
{
m_idToInspectorStyleSheet.clear();
@@ -173,7 +171,7 @@ void InspectorCSSAgent::reset()
m_documentToInspectorStyleSheet.clear();
}
-void InspectorCSSAgent::getStylesForNode(long nodeId, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::getStylesForNode(ErrorString*, long nodeId, RefPtr<InspectorValue>* result)
{
Element* element = elementForId(nodeId);
if (!element)
@@ -228,7 +226,7 @@ void InspectorCSSAgent::getStylesForNode(long nodeId, RefPtr<InspectorValue>* re
*result = resultObject.release();
}
-void InspectorCSSAgent::getInlineStyleForNode(long nodeId, RefPtr<InspectorValue>* style)
+void InspectorCSSAgent::getInlineStyleForNode(ErrorString*, long nodeId, RefPtr<InspectorValue>* style)
{
Element* element = elementForId(nodeId);
if (!element)
@@ -241,7 +239,7 @@ void InspectorCSSAgent::getInlineStyleForNode(long nodeId, RefPtr<InspectorValue
*style = styleSheet->buildObjectForStyle(element->style());
}
-void InspectorCSSAgent::getComputedStyleForNode(long nodeId, RefPtr<InspectorValue>* style)
+void InspectorCSSAgent::getComputedStyleForNode(ErrorString*, long nodeId, RefPtr<InspectorValue>* style)
{
Element* element = elementForId(nodeId);
if (!element)
@@ -252,7 +250,7 @@ void InspectorCSSAgent::getComputedStyleForNode(long nodeId, RefPtr<InspectorVal
*style = inspectorStyle->buildObjectForStyle();
}
-void InspectorCSSAgent::getAllStyles(RefPtr<InspectorArray>* styles)
+void InspectorCSSAgent::getAllStyles(ErrorString*, RefPtr<InspectorArray>* styles)
{
Vector<Document*> documents = m_domAgent->documents();
for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
@@ -267,7 +265,7 @@ void InspectorCSSAgent::getAllStyles(RefPtr<InspectorArray>* styles)
}
}
-void InspectorCSSAgent::getStyleSheet(const String& styleSheetId, RefPtr<InspectorValue>* styleSheetObject)
+void InspectorCSSAgent::getStyleSheet(ErrorString*, const String& styleSheetId, RefPtr<InspectorValue>* styleSheetObject)
{
InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(styleSheetId);
if (!inspectorStyleSheet)
@@ -276,7 +274,7 @@ void InspectorCSSAgent::getStyleSheet(const String& styleSheetId, RefPtr<Inspect
*styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
}
-void InspectorCSSAgent::getStyleSheetText(const String& styleSheetId, String* url, String* result)
+void InspectorCSSAgent::getStyleSheetText(ErrorString*, const String& styleSheetId, String* url, String* result)
{
InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(styleSheetId);
if (!inspectorStyleSheet)
@@ -285,7 +283,7 @@ void InspectorCSSAgent::getStyleSheetText(const String& styleSheetId, String* ur
inspectorStyleSheet->text(result);
}
-void InspectorCSSAgent::setStyleSheetText(const String& styleSheetId, const String& text, bool* success)
+void InspectorCSSAgent::setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text, bool* success)
{
InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(styleSheetId);
if (!inspectorStyleSheet) {
@@ -298,7 +296,7 @@ void InspectorCSSAgent::setStyleSheetText(const String& styleSheetId, const Stri
inspectorStyleSheet->reparseStyleSheet(text);
}
-void InspectorCSSAgent::setPropertyText(const RefPtr<InspectorObject>& fullStyleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::setPropertyText(ErrorString*, const RefPtr<InspectorObject>& fullStyleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result)
{
InspectorCSSId compoundId(fullStyleId);
ASSERT(!compoundId.isEmpty());
@@ -312,7 +310,7 @@ void InspectorCSSAgent::setPropertyText(const RefPtr<InspectorObject>& fullStyle
*result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
}
-void InspectorCSSAgent::toggleProperty(const RefPtr<InspectorObject>& fullStyleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::toggleProperty(ErrorString*, const RefPtr<InspectorObject>& fullStyleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result)
{
InspectorCSSId compoundId(fullStyleId);
ASSERT(!compoundId.isEmpty());
@@ -326,7 +324,7 @@ void InspectorCSSAgent::toggleProperty(const RefPtr<InspectorObject>& fullStyleI
*result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
}
-void InspectorCSSAgent::setRuleSelector(const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::setRuleSelector(ErrorString*, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<InspectorValue>* result)
{
InspectorCSSId compoundId(fullRuleId);
ASSERT(!compoundId.isEmpty());
@@ -342,7 +340,7 @@ void InspectorCSSAgent::setRuleSelector(const RefPtr<InspectorObject>& fullRuleI
*result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
}
-void InspectorCSSAgent::addRule(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::addRule(ErrorString*, const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result)
{
Node* node = m_domAgent->nodeForId(contextNodeId);
if (!node)
@@ -358,7 +356,7 @@ void InspectorCSSAgent::addRule(const long contextNodeId, const String& selector
*result = inspectorStyleSheet->buildObjectForRule(newRule);
}
-void InspectorCSSAgent::getSupportedCSSProperties(RefPtr<InspectorArray>* cssProperties)
+void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<InspectorArray>* cssProperties)
{
RefPtr<InspectorArray> properties = InspectorArray::create();
for (int i = 0; i < numCSSProperties; ++i)
@@ -367,26 +365,6 @@ void InspectorCSSAgent::getSupportedCSSProperties(RefPtr<InspectorArray>* cssPro
*cssProperties = properties.release();
}
-void InspectorCSSAgent::querySelectorAll(const long nodeId, const String& selector, RefPtr<InspectorArray>* result)
-{
- Node* node = m_domAgent->nodeForId(nodeId);
- if (!node)
- return;
- if (!node->isDocumentNode())
- node = node->ownerDocument();
- if (!node)
- return;
- ExceptionCode ec = 0;
- RefPtr<NodeList> nodes = static_cast<Document*>(node)->querySelectorAll(selector, ec);
- if (ec)
- return;
- for (unsigned i = 0; i < nodes->length(); ++i) {
- Node* affectedNode = nodes->item(i);
- long id = m_domAgent->pushNodePathToFrontend(affectedNode);
- (*result)->pushNumber(id);
- }
-}
-
// static
Element* InspectorCSSAgent::inlineStyleElement(CSSStyleDeclaration* style)
{
diff --git a/Source/WebCore/inspector/InspectorCSSAgent.h b/Source/WebCore/inspector/InspectorCSSAgent.h
index 12b3f9b..4e3f57a 100644
--- a/Source/WebCore/inspector/InspectorCSSAgent.h
+++ b/Source/WebCore/inspector/InspectorCSSAgent.h
@@ -44,6 +44,7 @@ class CSSStyleSheet;
class Document;
class Element;
class InspectorFrontend;
+class InstrumentingAgents;
class NameNodeMap;
class Node;
class StyleBase;
@@ -51,29 +52,27 @@ class StyleBase;
#if ENABLE(INSPECTOR)
class InspectorCSSAgent : public InspectorDOMAgent::DOMListener {
+ WTF_MAKE_NONCOPYABLE(InspectorCSSAgent);
public:
static CSSStyleSheet* parentStyleSheet(StyleBase*);
static CSSStyleRule* asCSSStyleRule(StyleBase*);
- InspectorCSSAgent();
+ InspectorCSSAgent(InstrumentingAgents*, InspectorDOMAgent*);
~InspectorCSSAgent();
- void setDOMAgent(InspectorDOMAgent* domAgent);
-
void reset();
- void getStylesForNode(long nodeId, RefPtr<InspectorValue>* result);
- void getInlineStyleForNode(long nodeId, RefPtr<InspectorValue>* style);
- void getComputedStyleForNode(long nodeId, RefPtr<InspectorValue>* style);
- void getAllStyles(RefPtr<InspectorArray>* styles);
- void getStyleSheet(const String& styleSheetId, RefPtr<InspectorValue>* result);
- void getStyleSheetText(const String& styleSheetId, String* url, String* result);
- void setStyleSheetText(const String& styleSheetId, const String& text, bool* success);
- void setPropertyText(const RefPtr<InspectorObject>& styleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result);
- void toggleProperty(const RefPtr<InspectorObject>& styleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result);
- void setRuleSelector(const RefPtr<InspectorObject>& ruleId, const String& selector, RefPtr<InspectorValue>* result);
- void addRule(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result);
- void getSupportedCSSProperties(RefPtr<InspectorArray>* result);
- void querySelectorAll(const long nodeId, const String& selector, RefPtr<InspectorArray>* result);
+ void getStylesForNode(ErrorString* error, long nodeId, RefPtr<InspectorValue>* result);
+ void getInlineStyleForNode(ErrorString* error, long nodeId, RefPtr<InspectorValue>* style);
+ void getComputedStyleForNode(ErrorString* error, long nodeId, RefPtr<InspectorValue>* style);
+ void getAllStyles(ErrorString* error, RefPtr<InspectorArray>* styles);
+ void getStyleSheet(ErrorString* error, const String& styleSheetId, RefPtr<InspectorValue>* result);
+ void getStyleSheetText(ErrorString* error, const String& styleSheetId, String* url, String* result);
+ void setStyleSheetText(ErrorString* error, const String& styleSheetId, const String& text, bool* success);
+ void setPropertyText(ErrorString* error, const RefPtr<InspectorObject>& styleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result);
+ void toggleProperty(ErrorString* error, const RefPtr<InspectorObject>& styleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result);
+ void setRuleSelector(ErrorString* error, const RefPtr<InspectorObject>& ruleId, const String& selector, RefPtr<InspectorValue>* result);
+ void addRule(ErrorString* error, const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result);
+ void getSupportedCSSProperties(ErrorString* error, RefPtr<InspectorArray>* result);
private:
typedef HashMap<String, RefPtr<InspectorStyleSheet> > IdToInspectorStyleSheet;
@@ -99,6 +98,7 @@ private:
virtual void didRemoveDOMNode(Node*);
virtual void didModifyDOMAttr(Element*);
+ InstrumentingAgents* m_instrumentingAgents;
InspectorDOMAgent* m_domAgent;
IdToInspectorStyleSheet m_idToInspectorStyleSheet;
diff --git a/Source/WebCore/inspector/InspectorConsoleAgent.cpp b/Source/WebCore/inspector/InspectorConsoleAgent.cpp
index 7d11a7a..0379590 100644
--- a/Source/WebCore/inspector/InspectorConsoleAgent.cpp
+++ b/Source/WebCore/inspector/InspectorConsoleAgent.cpp
@@ -27,6 +27,7 @@
#include "InspectorConsoleAgent.h"
#if ENABLE(INSPECTOR)
+#include "InstrumentingAgents.h"
#include "Console.h"
#include "ConsoleMessage.h"
#include "InjectedScriptHost.h"
@@ -54,31 +55,41 @@ static const char monitoringXHR[] = "monitoringXHR";
static const char consoleMessagesEnabled[] = "consoleMessagesEnabled";
}
-InspectorConsoleAgent::InspectorConsoleAgent(InspectorAgent* inspectorAgent)
- : m_inspectorAgent(inspectorAgent)
+InspectorConsoleAgent::InspectorConsoleAgent(InstrumentingAgents* instrumentingAgents, InspectorAgent* inspectorAgent, InspectorState* state, InjectedScriptHost* injectedScriptHost, InspectorDOMAgent* domAgent)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_inspectorAgent(inspectorAgent)
+ , m_inspectorState(state)
+ , m_injectedScriptHost(injectedScriptHost)
+ , m_inspectorDOMAgent(domAgent)
, m_frontend(0)
, m_previousMessage(0)
, m_expiredConsoleMessageCount(0)
{
+ m_instrumentingAgents->setInspectorConsoleAgent(this);
}
InspectorConsoleAgent::~InspectorConsoleAgent()
{
+ m_instrumentingAgents->setInspectorConsoleAgent(0);
+ m_instrumentingAgents = 0;
m_inspectorAgent = 0;
+ m_inspectorState = 0;
+ m_injectedScriptHost = 0;
+ m_inspectorDOMAgent = 0;
}
-void InspectorConsoleAgent::setConsoleMessagesEnabled(bool enabled, bool* newState)
+void InspectorConsoleAgent::setConsoleMessagesEnabled(ErrorString*, bool enabled, bool* newState)
{
*newState = enabled;
setConsoleMessagesEnabled(enabled);
}
-void InspectorConsoleAgent::clearConsoleMessages()
+void InspectorConsoleAgent::clearConsoleMessages(ErrorString*)
{
m_consoleMessages.clear();
m_expiredConsoleMessageCount = 0;
m_previousMessage = 0;
- m_inspectorAgent->injectedScriptHost()->releaseWrapperObjectGroup(0 /* release the group in all scripts */, "console");
+ m_injectedScriptHost->releaseObjectGroup(0 /* release the group in all scripts */, "console");
if (InspectorDOMAgent* domAgent = m_inspectorAgent->domAgent())
domAgent->releaseDanglingNodes();
if (m_frontend)
@@ -87,14 +98,20 @@ void InspectorConsoleAgent::clearConsoleMessages()
void InspectorConsoleAgent::reset()
{
- clearConsoleMessages();
+ ErrorString error;
+ clearConsoleMessages(&error);
m_times.clear();
m_counts.clear();
}
void InspectorConsoleAgent::setFrontend(InspectorFrontend* frontend)
{
- m_frontend = frontend;
+ m_frontend = frontend->console();
+}
+
+void InspectorConsoleAgent::clearFrontend()
+{
+ m_frontend = 0;
}
void InspectorConsoleAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
@@ -169,7 +186,7 @@ void InspectorConsoleAgent::resourceRetrievedByXMLHttpRequest(const String& url,
{
if (!m_inspectorAgent->enabled())
return;
- if (m_inspectorAgent->state()->getBoolean(ConsoleAgentState::monitoringXHR))
+ if (m_inspectorState->getBoolean(ConsoleAgentState::monitoringXHR))
addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, "XHR finished loading: \"" + url + "\".", sendLineNumber, sendURL);
}
@@ -195,14 +212,14 @@ void InspectorConsoleAgent::didFailLoading(unsigned long identifier, const Resou
addConsoleMessage(new ConsoleMessage(OtherMessageSource, NetworkErrorMessageType, ErrorMessageLevel, message, error.failingURL(), identifier));
}
-void InspectorConsoleAgent::setMonitoringXHREnabled(bool enabled)
+void InspectorConsoleAgent::setMonitoringXHREnabled(ErrorString*, bool enabled)
{
- m_inspectorAgent->state()->setBoolean(ConsoleAgentState::monitoringXHR, enabled);
+ m_inspectorState->setBoolean(ConsoleAgentState::monitoringXHR, enabled);
}
void InspectorConsoleAgent::setConsoleMessagesEnabled(bool enabled)
{
- m_inspectorAgent->state()->setBoolean(ConsoleAgentState::consoleMessagesEnabled, enabled);
+ m_inspectorState->setBoolean(ConsoleAgentState::consoleMessagesEnabled, enabled);
if (!enabled || !m_frontend)
return;
@@ -210,7 +227,7 @@ void InspectorConsoleAgent::setConsoleMessagesEnabled(bool enabled)
m_frontend->updateConsoleMessageExpiredCount(m_expiredConsoleMessageCount);
unsigned messageCount = m_consoleMessages.size();
for (unsigned i = 0; i < messageCount; ++i)
- m_consoleMessages[i]->addToFrontend(m_frontend, m_inspectorAgent->injectedScriptHost());
+ m_consoleMessages[i]->addToFrontend(m_frontend, m_injectedScriptHost);
}
void InspectorConsoleAgent::addConsoleMessage(PassOwnPtr<ConsoleMessage> consoleMessage)
@@ -220,13 +237,13 @@ void InspectorConsoleAgent::addConsoleMessage(PassOwnPtr<ConsoleMessage> console
if (m_previousMessage && m_previousMessage->isEqual(consoleMessage.get())) {
m_previousMessage->incrementCount();
- if (m_inspectorAgent->state()->getBoolean(ConsoleAgentState::consoleMessagesEnabled) && m_frontend)
+ if (m_inspectorState->getBoolean(ConsoleAgentState::consoleMessagesEnabled) && m_frontend)
m_previousMessage->updateRepeatCountInConsole(m_frontend);
} else {
m_previousMessage = consoleMessage.get();
m_consoleMessages.append(consoleMessage);
- if (m_inspectorAgent->state()->getBoolean(ConsoleAgentState::consoleMessagesEnabled) && m_frontend)
- m_previousMessage->addToFrontend(m_frontend, m_inspectorAgent->injectedScriptHost());
+ if (m_inspectorState->getBoolean(ConsoleAgentState::consoleMessagesEnabled) && m_frontend)
+ m_previousMessage->addToFrontend(m_frontend, m_injectedScriptHost);
}
if (!m_frontend && m_consoleMessages.size() >= maximumConsoleMessages) {
diff --git a/Source/WebCore/inspector/InspectorConsoleAgent.h b/Source/WebCore/inspector/InspectorConsoleAgent.h
index 10ffb02..8d3a570 100644
--- a/Source/WebCore/inspector/InspectorConsoleAgent.h
+++ b/Source/WebCore/inspector/InspectorConsoleAgent.h
@@ -26,6 +26,7 @@
#define InspectorConsoleAgent_h
#include "Console.h"
+#include "InspectorFrontend.h"
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
@@ -38,24 +39,30 @@ namespace WebCore {
class ConsoleMessage;
class InspectorAgent;
+class InspectorDOMAgent;
class InspectorFrontend;
class InspectorState;
+class InjectedScriptHost;
+class InstrumentingAgents;
class ResourceError;
class ResourceResponse;
class ScriptArguments;
class ScriptCallStack;
class ScriptProfile;
+typedef String ErrorString;
+
class InspectorConsoleAgent {
WTF_MAKE_NONCOPYABLE(InspectorConsoleAgent);
public:
- InspectorConsoleAgent(InspectorAgent*);
+ InspectorConsoleAgent(InstrumentingAgents*, InspectorAgent*, InspectorState*, InjectedScriptHost*, InspectorDOMAgent*);
~InspectorConsoleAgent();
- void setConsoleMessagesEnabled(bool enabled, bool* newState);
- void clearConsoleMessages();
+ void setConsoleMessagesEnabled(ErrorString* error, bool enabled, bool* newState);
+ void clearConsoleMessages(ErrorString* error);
void reset();
void setFrontend(InspectorFrontend*);
+ void clearFrontend();
void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack>);
void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
@@ -71,14 +78,18 @@ public:
void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
#endif
- void setMonitoringXHREnabled(bool enabled);
+ void setMonitoringXHREnabled(ErrorString* error, bool enabled);
private:
void setConsoleMessagesEnabled(bool);
void addConsoleMessage(PassOwnPtr<ConsoleMessage>);
+ InstrumentingAgents* m_instrumentingAgents;
InspectorAgent* m_inspectorAgent;
- InspectorFrontend* m_frontend;
+ InspectorState* m_inspectorState;
+ InjectedScriptHost* m_injectedScriptHost;
+ InspectorDOMAgent* m_inspectorDOMAgent;
+ InspectorFrontend::Console* m_frontend;
ConsoleMessage* m_previousMessage;
Vector<OwnPtr<ConsoleMessage> > m_consoleMessages;
unsigned m_expiredConsoleMessageCount;
diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp
index 426e5f3..2f1bea2 100644
--- a/Source/WebCore/inspector/InspectorController.cpp
+++ b/Source/WebCore/inspector/InspectorController.cpp
@@ -38,11 +38,13 @@
#include "InjectedScriptHost.h"
#include "InspectorAgent.h"
#include "InspectorBackendDispatcher.h"
+#include "InspectorBrowserDebuggerAgent.h"
#include "InspectorDebuggerAgent.h"
#include "InspectorClient.h"
#include "InspectorFrontend.h"
#include "InspectorFrontendClient.h"
#include "InspectorInstrumentation.h"
+#include "InspectorTimelineAgent.h"
#include "Page.h"
#include "ScriptObject.h"
#include "Settings.h"
@@ -84,12 +86,14 @@ void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWo
void InspectorController::startTimelineProfiler()
{
- m_inspectorAgent->startTimelineProfiler();
+ ErrorString error;
+ m_inspectorAgent->timelineAgent()->start(&error);
}
void InspectorController::stopTimelineProfiler()
{
- m_inspectorAgent->stopTimelineProfiler();
+ ErrorString error;
+ m_inspectorAgent->timelineAgent()->stop(&error);
}
void InspectorController::connectFrontend()
@@ -127,7 +131,7 @@ void InspectorController::show()
return;
if (m_inspectorFrontend)
- m_inspectorFrontend->bringToFront();
+ m_inspectorFrontend->inspector()->bringToFront();
else {
m_openingFrontend = true;
m_inspectorClient->openInspectorFrontend(this);
@@ -138,7 +142,7 @@ void InspectorController::close()
{
if (!m_inspectorFrontend)
return;
- m_inspectorFrontend->disconnectFromBackend();
+ m_inspectorFrontend->inspector()->disconnectFromBackend();
disconnectFrontend();
}
@@ -189,18 +193,36 @@ Page* InspectorController::inspectedPage() const
bool InspectorController::timelineProfilerEnabled()
{
- return m_inspectorAgent->timelineAgent();
+ return m_inspectorAgent->timelineAgent()->started();
+}
+
+void InspectorController::setInspectorExtensionAPI(const String& source)
+{
+ m_inspectorAgent->setInspectorExtensionAPI(source);
+}
+
+void InspectorController::dispatchMessageFromFrontend(const String& message)
+{
+ m_inspectorBackendDispatcher->dispatch(message);
+}
+
+void InspectorController::hideHighlight()
+{
+ ErrorString error;
+ m_inspectorAgent->hideHighlight(&error);
}
#if ENABLE(JAVASCRIPT_DEBUGGER)
void InspectorController::enableProfiler()
{
- m_inspectorAgent->enableProfiler();
+ ErrorString error;
+ m_inspectorAgent->enableProfiler(&error);
}
void InspectorController::disableProfiler()
{
- m_inspectorAgent->disableProfiler();
+ ErrorString error;
+ m_inspectorAgent->disableProfiler(&error);
}
bool InspectorController::profilerEnabled()
@@ -210,17 +232,21 @@ bool InspectorController::profilerEnabled()
bool InspectorController::debuggerEnabled()
{
- return m_inspectorAgent->debuggerEnabled();
+ return m_inspectorAgent->debuggerAgent()->enabled();
}
void InspectorController::showAndEnableDebugger()
{
- m_inspectorAgent->showAndEnableDebugger();
+ if (!enabled())
+ return;
+ show();
+ m_inspectorAgent->showScriptsPanel();
+ m_inspectorAgent->debuggerAgent()->startUserInitiatedDebugging();
}
void InspectorController::disableDebugger()
{
- m_inspectorAgent->disableDebugger();
+ m_inspectorAgent->debuggerAgent()->disable();
}
void InspectorController::startUserInitiatedProfiling()
@@ -230,6 +256,9 @@ void InspectorController::startUserInitiatedProfiling()
void InspectorController::stopUserInitiatedProfiling()
{
+ if (!enabled())
+ return;
+ show();
m_inspectorAgent->stopUserInitiatedProfiling();
}
@@ -238,25 +267,12 @@ bool InspectorController::isRecordingUserInitiatedProfile() const
return m_inspectorAgent->isRecordingUserInitiatedProfile();
}
-void InspectorController::setInspectorExtensionAPI(const String& source)
-{
- m_inspectorAgent->setInspectorExtensionAPI(source);
-}
-
void InspectorController::resume()
{
- if (InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent())
- debuggerAgent->resume();
-}
-
-void InspectorController::hideHighlight()
-{
- m_inspectorAgent->hideHighlight();
-}
-
-void InspectorController::dispatchMessageFromFrontend(const String& message)
-{
- m_inspectorBackendDispatcher->dispatch(message);
+ if (InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent()) {
+ ErrorString error;
+ debuggerAgent->resume(&error);
+ }
}
#endif
diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp
index e222edb..3edd72c 100644
--- a/Source/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp
@@ -61,6 +61,8 @@
#include "HTMLFrameOwnerElement.h"
#include "InjectedScriptHost.h"
#include "InspectorFrontend.h"
+#include "InspectorState.h"
+#include "InstrumentingAgents.h"
#include "MutationEvent.h"
#include "Node.h"
#include "NodeList.h"
@@ -88,6 +90,10 @@
namespace WebCore {
+namespace DOMAgentState {
+static const char documentRequested[] = "documentRequested";
+};
+
class MatchJob {
public:
virtual void match(ListHashSet<Node*>& resultCollector) = 0;
@@ -108,6 +114,19 @@ protected:
String m_query;
};
+class RevalidateStyleAttributeTask {
+public:
+ RevalidateStyleAttributeTask(InspectorDOMAgent*);
+ void scheduleFor(Element*);
+ void reset() { m_timer.stop(); }
+ void onTimer(Timer<RevalidateStyleAttributeTask>*);
+
+private:
+ InspectorDOMAgent* m_domAgent;
+ Timer<RevalidateStyleAttributeTask> m_timer;
+ HashSet<RefPtr<Element> > m_elements;
+};
+
namespace {
class MatchExactIdJob : public WebCore::MatchJob {
@@ -207,9 +226,33 @@ public:
}
-InspectorDOMAgent::InspectorDOMAgent(InjectedScriptHost* injectedScriptHost, InspectorFrontend* frontend)
- : m_injectedScriptHost(injectedScriptHost)
- , m_frontend(frontend)
+RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
+ : m_domAgent(domAgent)
+ , m_timer(this, &RevalidateStyleAttributeTask::onTimer)
+{
+}
+
+void RevalidateStyleAttributeTask::scheduleFor(Element* element)
+{
+ m_elements.add(element);
+ if (!m_timer.isActive())
+ m_timer.startOneShot(0);
+}
+
+void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
+{
+ // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
+ for (HashSet<RefPtr<Element> >::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
+ m_domAgent->didModifyDOMAttr(it->get());
+
+ m_elements.clear();
+}
+
+InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, InjectedScriptHost* injectedScriptHost)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_inspectorState(inspectorState)
+ , m_injectedScriptHost(injectedScriptHost)
+ , m_frontend(0)
, m_domListener(0)
, m_lastNodeId(1)
, m_matchJobsTimer(this, &InspectorDOMAgent::onMatchJobsTimer)
@@ -221,6 +264,22 @@ InspectorDOMAgent::~InspectorDOMAgent()
reset();
}
+void InspectorDOMAgent::setFrontend(InspectorFrontend* frontend)
+{
+ ASSERT(!m_frontend);
+ m_frontend = frontend->dom();
+ m_instrumentingAgents->setInspectorDOMAgent(this);
+}
+
+void InspectorDOMAgent::clearFrontend()
+{
+ ASSERT(m_frontend);
+ m_frontend = 0;
+ m_instrumentingAgents->setInspectorDOMAgent(0);
+ m_inspectorState->setBoolean(DOMAgentState::documentRequested, false);
+ reset();
+}
+
Vector<Document*> InspectorDOMAgent::documents()
{
Vector<Document*> result;
@@ -235,8 +294,12 @@ Vector<Document*> InspectorDOMAgent::documents()
void InspectorDOMAgent::reset()
{
- searchCanceled();
+ ErrorString error;
+ searchCanceled(&error);
discardBindings();
+ if (m_revalidateStyleAttrTask)
+ m_revalidateStyleAttrTask->reset();
+ m_document = 0;
}
void InspectorDOMAgent::setDOMListener(DOMListener* listener)
@@ -253,11 +316,8 @@ void InspectorDOMAgent::setDocument(Document* doc)
m_document = doc;
- if (doc) {
- if (doc->documentElement())
- pushDocumentToFrontend();
- } else
- m_frontend->setDocument(InspectorValue::null());
+ if (!doc && m_inspectorState->getBoolean(DOMAgentState::documentRequested))
+ m_frontend->documentUpdated();
}
void InspectorDOMAgent::releaseDanglingNodes()
@@ -303,13 +363,35 @@ void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
}
}
-bool InspectorDOMAgent::pushDocumentToFrontend()
+Node* InspectorDOMAgent::nodeToSelectOn(long nodeId, bool documentWide)
{
+ Node* node;
+ if (!nodeId)
+ node = m_document.get();
+ else
+ node = nodeForId(nodeId);
+ if (!node)
+ return 0;
+
+ if (documentWide && nodeId)
+ node = node->ownerDocument();
+ return node;
+}
+
+void InspectorDOMAgent::getDocument(ErrorString*, RefPtr<InspectorObject>* root)
+{
+ m_inspectorState->setBoolean(DOMAgentState::documentRequested, true);
+
if (!m_document)
- return false;
+ return;
+
+ // Reset backend state.
+ RefPtr<Document> doc = m_document;
+ reset();
+ m_document = doc;
+
if (!m_documentNodeToIdMap.contains(m_document))
- m_frontend->setDocument(buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap));
- return true;
+ *root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
}
void InspectorDOMAgent::pushChildNodesToFrontend(long nodeId)
@@ -326,20 +408,13 @@ void InspectorDOMAgent::pushChildNodesToFrontend(long nodeId)
m_frontend->setChildNodes(nodeId, children.release());
}
-long InspectorDOMAgent::inspectedNode(unsigned long num)
-{
- if (num < m_inspectedNodes.size())
- return m_inspectedNodes[num];
- return 0;
-}
-
void InspectorDOMAgent::discardBindings()
{
m_documentNodeToIdMap.clear();
m_idToNode.clear();
releaseDanglingNodes();
m_childrenRequested.clear();
- m_inspectedNodes.clear();
+ m_injectedScriptHost->clearInspectedNodes();
}
Node* InspectorDOMAgent::nodeForId(long id)
@@ -353,17 +428,49 @@ Node* InspectorDOMAgent::nodeForId(long id)
return 0;
}
-void InspectorDOMAgent::getChildNodes(long nodeId)
+void InspectorDOMAgent::getChildNodes(ErrorString*, long nodeId)
{
pushChildNodesToFrontend(nodeId);
}
+void InspectorDOMAgent::querySelector(ErrorString*, long nodeId, const String& selectors, bool documentWide, long* elementId)
+{
+ *elementId = 0;
+ Node* node = nodeToSelectOn(nodeId, documentWide);
+ if (!node)
+ return;
+
+ ExceptionCode ec = 0;
+ RefPtr<Element> element = node->querySelector(selectors, ec);
+ if (ec)
+ return;
+
+ if (element)
+ *elementId = pushNodePathToFrontend(element.get());
+}
+
+void InspectorDOMAgent::querySelectorAll(ErrorString*, long nodeId, const String& selectors, bool documentWide, RefPtr<InspectorArray>* result)
+{
+ Node* node = nodeToSelectOn(nodeId, documentWide);
+ if (!node)
+ return;
+
+ ExceptionCode ec = 0;
+ RefPtr<NodeList> nodes = node->querySelectorAll(selectors, ec);
+ if (ec)
+ return;
+
+ for (unsigned i = 0; i < nodes->length(); ++i)
+ (*result)->pushNumber(pushNodePathToFrontend(nodes->item(i)));
+}
+
long InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
{
ASSERT(nodeToPush); // Invalid input
- // If we are sending information to the client that is currently being created. Send root node first.
- if (!pushDocumentToFrontend())
+ if (!m_document)
+ return 0;
+ if (!m_documentNodeToIdMap.contains(m_document))
return 0;
// Return id in case the node is known.
@@ -374,13 +481,16 @@ long InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
Node* node = nodeToPush;
Vector<Node*> path;
NodeToIdMap* danglingMap = 0;
+
while (true) {
Node* parent = innerParentNode(node);
if (!parent) {
// Node being pushed is detached -> push subtree root.
danglingMap = new NodeToIdMap();
m_danglingNodeToIdMaps.append(danglingMap);
- m_frontend->setDetachedRoot(buildObjectForNode(node, 0, danglingMap));
+ RefPtr<InspectorArray> children = InspectorArray::create();
+ children->pushObject(buildObjectForNode(node, 0, danglingMap));
+ m_frontend->setChildNodes(0, children);
break;
} else {
path.append(parent);
@@ -400,7 +510,12 @@ long InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
return map->get(nodeToPush);
}
-void InspectorDOMAgent::setAttribute(long elementId, const String& name, const String& value, bool* success)
+long InspectorDOMAgent::boundNodeId(Node* node)
+{
+ return m_documentNodeToIdMap.get(node);
+}
+
+void InspectorDOMAgent::setAttribute(ErrorString*, long elementId, const String& name, const String& value, bool* success)
{
Node* node = nodeForId(elementId);
if (node && (node->nodeType() == Node::ELEMENT_NODE)) {
@@ -411,7 +526,7 @@ void InspectorDOMAgent::setAttribute(long elementId, const String& name, const S
}
}
-void InspectorDOMAgent::removeAttribute(long elementId, const String& name, bool* success)
+void InspectorDOMAgent::removeAttribute(ErrorString*, long elementId, const String& name, bool* success)
{
Node* node = nodeForId(elementId);
if (node && (node->nodeType() == Node::ELEMENT_NODE)) {
@@ -422,7 +537,7 @@ void InspectorDOMAgent::removeAttribute(long elementId, const String& name, bool
}
}
-void InspectorDOMAgent::removeNode(long nodeId, long* outNodeId)
+void InspectorDOMAgent::removeNode(ErrorString*, long nodeId, long* outNodeId)
{
Node* node = nodeForId(nodeId);
if (!node)
@@ -440,7 +555,7 @@ void InspectorDOMAgent::removeNode(long nodeId, long* outNodeId)
*outNodeId = nodeId;
}
-void InspectorDOMAgent::changeTagName(long nodeId, const String& tagName, long* newId)
+void InspectorDOMAgent::changeTagName(ErrorString*, long nodeId, const String& tagName, long* newId)
{
Node* oldNode = nodeForId(nodeId);
if (!oldNode || !oldNode->isElementNode())
@@ -475,7 +590,7 @@ void InspectorDOMAgent::changeTagName(long nodeId, const String& tagName, long*
pushChildNodesToFrontend(*newId);
}
-void InspectorDOMAgent::getOuterHTML(long nodeId, WTF::String* outerHTML)
+void InspectorDOMAgent::getOuterHTML(ErrorString*, long nodeId, WTF::String* outerHTML)
{
Node* node = nodeForId(nodeId);
if (!node || !node->isHTMLElement())
@@ -484,7 +599,7 @@ void InspectorDOMAgent::getOuterHTML(long nodeId, WTF::String* outerHTML)
*outerHTML = toHTMLElement(node)->outerHTML();
}
-void InspectorDOMAgent::setOuterHTML(long nodeId, const String& outerHTML, long* newId)
+void InspectorDOMAgent::setOuterHTML(ErrorString*, long nodeId, const String& outerHTML, long* newId)
{
Node* node = nodeForId(nodeId);
if (!node || !node->isHTMLElement())
@@ -522,7 +637,7 @@ void InspectorDOMAgent::setOuterHTML(long nodeId, const String& outerHTML, long*
pushChildNodesToFrontend(*newId);
}
-void InspectorDOMAgent::setTextNodeValue(long nodeId, const String& value, bool* success)
+void InspectorDOMAgent::setTextNodeValue(ErrorString*, long nodeId, const String& value, bool* success)
{
Node* node = nodeForId(nodeId);
if (node && (node->nodeType() == Node::TEXT_NODE)) {
@@ -533,7 +648,7 @@ void InspectorDOMAgent::setTextNodeValue(long nodeId, const String& value, bool*
}
}
-void InspectorDOMAgent::getEventListenersForNode(long nodeId, long* outNodeId, RefPtr<InspectorArray>* listenersArray)
+void InspectorDOMAgent::getEventListenersForNode(ErrorString*, long nodeId, long* outNodeId, RefPtr<InspectorArray>* listenersArray)
{
Node* node = nodeForId(nodeId);
*outNodeId = nodeId;
@@ -600,14 +715,15 @@ void InspectorDOMAgent::getEventListenersForNode(long nodeId, long* outNodeId, R
}
}
-void InspectorDOMAgent::addInspectedNode(long nodeId)
+void InspectorDOMAgent::addInspectedNode(ErrorString*, long nodeId)
{
- m_inspectedNodes.prepend(nodeId);
- while (m_inspectedNodes.size() > 5)
- m_inspectedNodes.removeLast();
+ Node* node = nodeForId(nodeId);
+ if (!node)
+ return;
+ m_injectedScriptHost->addInspectedNode(node);
}
-void InspectorDOMAgent::performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously)
+void InspectorDOMAgent::performSearch(ErrorString* error, const String& whitespaceTrimmedQuery, bool runSynchronously)
{
// FIXME: Few things are missing here:
// 1) Search works with node granularity - number of matches within node is not calculated.
@@ -634,7 +750,7 @@ void InspectorDOMAgent::performSearch(const String& whitespaceTrimmedQuery, bool
escapedTagNameQuery.replace("'", "\\'");
// Clear pending jobs.
- searchCanceled();
+ searchCanceled(error);
// Find all frames, iframes and object elements to search their documents.
Vector<Document*> docs = documents();
@@ -688,13 +804,13 @@ void InspectorDOMAgent::performSearch(const String& whitespaceTrimmedQuery, bool
for (Deque<MatchJob*>::iterator it = m_pendingMatchJobs.begin(); it != m_pendingMatchJobs.end(); ++it)
(*it)->match(resultCollector);
reportNodesAsSearchResults(resultCollector);
- searchCanceled();
+ searchCanceled(error);
return;
}
m_matchJobsTimer.startOneShot(0);
}
-void InspectorDOMAgent::searchCanceled()
+void InspectorDOMAgent::searchCanceled(ErrorString*)
{
if (m_matchJobsTimer.isActive())
m_matchJobsTimer.stop();
@@ -703,32 +819,24 @@ void InspectorDOMAgent::searchCanceled()
m_searchResults.clear();
}
-void InspectorDOMAgent::resolveNode(long nodeId, RefPtr<InspectorValue>* result)
-{
- InjectedScript injectedScript = injectedScriptForNodeId(nodeId);
- if (!injectedScript.hasNoValue())
- injectedScript.resolveNode(nodeId, result);
-}
-
-void InspectorDOMAgent::getNodeProperties(long nodeId, PassRefPtr<InspectorArray> propertiesArray, RefPtr<InspectorValue>* result)
-{
- InjectedScript injectedScript = injectedScriptForNodeId(nodeId);
- if (!injectedScript.hasNoValue())
- injectedScript.getNodeProperties(nodeId, propertiesArray, result);
-}
-
-void InspectorDOMAgent::getNodePrototypes(long nodeId, RefPtr<InspectorValue>* result)
+void InspectorDOMAgent::resolveNode(ErrorString* error, long nodeId, const String& objectGroup, RefPtr<InspectorValue>* result)
{
- InjectedScript injectedScript = injectedScriptForNodeId(nodeId);
- if (!injectedScript.hasNoValue())
- injectedScript.getNodePrototypes(nodeId, result);
+ Node* node = nodeForId(nodeId);
+ if (!node) {
+ *error = "No node with given id found.";
+ return;
+ }
+ *result = resolveNode(node, objectGroup);
}
-void InspectorDOMAgent::pushNodeToFrontend(PassRefPtr<InspectorObject> objectId, RefPtr<InspectorValue>* result)
+void InspectorDOMAgent::pushNodeToFrontend(ErrorString*, PassRefPtr<InspectorObject> objectId, long* nodeId)
{
InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(objectId.get());
- if (!injectedScript.hasNoValue())
- injectedScript.pushNodeToFrontend(objectId, result);
+ Node* node = injectedScript.nodeForObjectId(objectId);
+ if (node)
+ *nodeId = pushNodePathToFrontend(node);
+ else
+ *nodeId = 0;
}
String InspectorDOMAgent::documentURLString(Document* document) const
@@ -918,7 +1026,8 @@ void InspectorDOMAgent::mainFrameDOMContentLoaded()
{
// Re-push document once it is loaded.
discardBindings();
- pushDocumentToFrontend();
+ if (m_inspectorState->getBoolean(DOMAgentState::documentRequested))
+ m_frontend->documentUpdated();
}
void InspectorDOMAgent::loadEventFired(Document* document)
@@ -1017,6 +1126,18 @@ void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
m_frontend->characterDataModified(id, characterData->data());
}
+void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
+{
+ long id = m_documentNodeToIdMap.get(node);
+ // If node is not mapped yet -> ignore the event.
+ if (!id)
+ return;
+
+ if (!m_revalidateStyleAttrTask)
+ m_revalidateStyleAttrTask = new RevalidateStyleAttributeTask(this);
+ m_revalidateStyleAttrTask->scheduleFor(static_cast<Element*>(node));
+}
+
Node* InspectorDOMAgent::nodeForPath(const String& path)
{
// The path is of form "1,HTML,2,BODY,1,DIV"
@@ -1059,7 +1180,8 @@ PassRefPtr<InspectorArray> InspectorDOMAgent::toArray(const Vector<String>& data
void InspectorDOMAgent::onMatchJobsTimer(Timer<InspectorDOMAgent>*)
{
if (!m_pendingMatchJobs.size()) {
- searchCanceled();
+ ErrorString error;
+ searchCanceled(&error);
return;
}
@@ -1085,7 +1207,7 @@ void InspectorDOMAgent::reportNodesAsSearchResults(ListHashSet<Node*>& resultCol
m_frontend->addNodesToSearchResult(nodeIds.release());
}
-void InspectorDOMAgent::copyNode(long nodeId)
+void InspectorDOMAgent::copyNode(ErrorString*, long nodeId)
{
Node* node = nodeForId(nodeId);
if (!node)
@@ -1094,32 +1216,26 @@ void InspectorDOMAgent::copyNode(long nodeId)
Pasteboard::generalPasteboard()->writePlainText(markup);
}
-void InspectorDOMAgent::pushNodeByPathToFrontend(const String& path, long* nodeId)
+void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString*, const String& path, long* nodeId)
{
if (Node* node = nodeForPath(path))
*nodeId = pushNodePathToFrontend(node);
}
-InjectedScript InspectorDOMAgent::injectedScriptForNodeId(long nodeId)
+PassRefPtr<InspectorObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
{
- Frame* frame = 0;
- if (nodeId) {
- Node* node = nodeForId(nodeId);
- if (node) {
- Document* document = node->ownerDocument();
- if (document)
- frame = document->frame();
- }
- } else
- frame = m_document->frame();
+ Document* document = node->ownerDocument();
+ Frame* frame = document ? document->frame() : 0;
+ if (!frame)
+ return 0;
- if (frame)
- return m_injectedScriptHost->injectedScriptFor(mainWorldScriptState(frame));
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptFor(mainWorldScriptState(frame));
+ if (injectedScript.hasNoValue())
+ return 0;
- return InjectedScript();
+ return injectedScript.wrapNode(node, objectGroup);
}
-
} // namespace WebCore
#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/inspector/InspectorDOMAgent.h b/Source/WebCore/inspector/InspectorDOMAgent.h
index 4e603da..0368880 100644
--- a/Source/WebCore/inspector/InspectorDOMAgent.h
+++ b/Source/WebCore/inspector/InspectorDOMAgent.h
@@ -32,6 +32,7 @@
#include "InjectedScript.h"
#include "InjectedScriptHost.h"
+#include "InspectorFrontend.h"
#include "InspectorValues.h"
#include "Timer.h"
@@ -39,6 +40,7 @@
#include <wtf/ListHashSet.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
@@ -53,9 +55,15 @@ class Event;
class InspectorDOMAgent;
class InspectorFrontend;
class MatchJob;
+class InspectorState;
+class InstrumentingAgents;
class NameNodeMap;
class Node;
class Page;
+class RevalidateStyleAttributeTask;
+class ScriptValue;
+
+typedef String ErrorString;
#if ENABLE(INSPECTOR)
@@ -83,34 +91,38 @@ public:
virtual void didModifyDOMAttr(Element*) = 0;
};
- static PassOwnPtr<InspectorDOMAgent> create(InjectedScriptHost* injectedScriptHost, InspectorFrontend* frontend)
+ static PassOwnPtr<InspectorDOMAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, InjectedScriptHost* injectedScriptHost)
{
- return adoptPtr(new InspectorDOMAgent(injectedScriptHost, frontend));
+ return adoptPtr(new InspectorDOMAgent(instrumentingAgents, inspectorState, injectedScriptHost));
}
- InspectorDOMAgent(InjectedScriptHost*, InspectorFrontend*);
~InspectorDOMAgent();
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
+
Vector<Document*> documents();
void reset();
// Methods called from the frontend for DOM nodes inspection.
- void getChildNodes(long nodeId);
- void setAttribute(long elementId, const String& name, const String& value, bool* success);
- void removeAttribute(long elementId, const String& name, bool* success);
- void removeNode(long nodeId, long* outNodeId);
- void changeTagName(long nodeId, const String& tagName, long* newId);
- void getOuterHTML(long nodeId, WTF::String* outerHTML);
- void setOuterHTML(long nodeId, const String& outerHTML, long* newId);
- void setTextNodeValue(long nodeId, const String& value, bool* success);
- void getEventListenersForNode(long nodeId, long* outNodeId, RefPtr<InspectorArray>* listenersArray);
- void addInspectedNode(long nodeId);
- void performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously);
- void searchCanceled();
- void resolveNode(long nodeId, RefPtr<InspectorValue>* result);
- void getNodeProperties(long nodeId, PassRefPtr<InspectorArray> propertiesArray, RefPtr<InspectorValue>* result);
- void getNodePrototypes(long nodeId, RefPtr<InspectorValue>* result);
- void pushNodeToFrontend(PassRefPtr<InspectorObject> objectId, RefPtr<InspectorValue>* result);
+ void querySelector(ErrorString*, long nodeId, const String& selectors, bool documentWide, long* elementId);
+ void querySelectorAll(ErrorString*, long nodeId, const String& selectors, bool documentWide, RefPtr<InspectorArray>* result);
+ void getDocument(ErrorString*, RefPtr<InspectorObject>* root);
+ void getChildNodes(ErrorString*, long nodeId);
+ void setAttribute(ErrorString*, long elementId, const String& name, const String& value, bool* success);
+ void removeAttribute(ErrorString*, long elementId, const String& name, bool* success);
+ void removeNode(ErrorString*, long nodeId, long* outNodeId);
+ void changeTagName(ErrorString*, long nodeId, const String& tagName, long* newId);
+ void getOuterHTML(ErrorString*, long nodeId, WTF::String* outerHTML);
+ void setOuterHTML(ErrorString*, long nodeId, const String& outerHTML, long* newId);
+ void setTextNodeValue(ErrorString*, long nodeId, const String& value, bool* success);
+ void getEventListenersForNode(ErrorString*, long nodeId, long* outNodeId, RefPtr<InspectorArray>* listenersArray);
+ void addInspectedNode(ErrorString*, long nodeId);
+ void performSearch(ErrorString*, const String& whitespaceTrimmedQuery, bool runSynchronously);
+ void searchCanceled(ErrorString*);
+ void resolveNode(ErrorString*, long nodeId, const String& objectGroup, RefPtr<InspectorValue>* result);
+ void pushNodeToFrontend(ErrorString*, PassRefPtr<InspectorObject> objectId, long* nodeId);
+ void pushNodeByPathToFrontend(ErrorString*, const String& path, long* nodeId);
// Methods called from the InspectorInstrumentation.
void setDocument(Document*);
@@ -123,17 +135,17 @@ public:
void didRemoveDOMNode(Node*);
void didModifyDOMAttr(Element*);
void characterDataModified(CharacterData*);
+ void didInvalidateStyleAttr(Node*);
Node* nodeForId(long nodeId);
- long pushNodePathToFrontend(Node*);
- void pushChildNodesToFrontend(long nodeId);
- void pushNodeByPathToFrontend(const String& path, long* nodeId);
- long inspectedNode(unsigned long num);
- void copyNode(long nodeId);
+ long boundNodeId(Node*);
+ void copyNode(ErrorString*, long nodeId);
void setDOMListener(DOMListener*);
String documentURLString(Document*) const;
+ PassRefPtr<InspectorObject> resolveNode(Node*, const String& objectGroup);
+
// We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
// We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
static Node* innerFirstChild(Node*);
@@ -144,12 +156,17 @@ public:
static bool isWhitespace(Node*);
private:
+ InspectorDOMAgent(InstrumentingAgents*, InspectorState*, InjectedScriptHost*);
+
// Node-related methods.
typedef HashMap<RefPtr<Node>, long> NodeToIdMap;
long bind(Node*, NodeToIdMap*);
void unbind(Node*, NodeToIdMap*);
- bool pushDocumentToFrontend();
+ Node* nodeToSelectOn(long nodeId, bool documentWide);
+
+ long pushNodePathToFrontend(Node*);
+ void pushChildNodesToFrontend(long nodeId);
bool hasBreakpoint(Node*, long type);
void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);
@@ -168,10 +185,10 @@ private:
void discardBindings();
- InjectedScript injectedScriptForNodeId(long nodeId);
-
+ InstrumentingAgents* m_instrumentingAgents;
+ InspectorState* m_inspectorState;
InjectedScriptHost* m_injectedScriptHost;
- InspectorFrontend* m_frontend;
+ InspectorFrontend::DOM* m_frontend;
DOMListener* m_domListener;
NodeToIdMap m_documentNodeToIdMap;
// Owns node mappings for dangling nodes.
@@ -184,7 +201,7 @@ private:
Deque<MatchJob*> m_pendingMatchJobs;
Timer<InspectorDOMAgent> m_matchJobsTimer;
HashSet<RefPtr<Node> > m_searchResults;
- Vector<long> m_inspectedNodes;
+ OwnPtr<RevalidateStyleAttributeTask> m_revalidateStyleAttrTask;
};
#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/inspector/InspectorDOMStorageAgent.cpp b/Source/WebCore/inspector/InspectorDOMStorageAgent.cpp
index 0919b64..6ea72f6 100644
--- a/Source/WebCore/inspector/InspectorDOMStorageAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDOMStorageAgent.cpp
@@ -39,21 +39,47 @@
#include "InspectorDOMStorageResource.h"
#include "InspectorFrontend.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "Storage.h"
+#include "StorageArea.h"
#include "VoidCallback.h"
#include <wtf/Vector.h>
namespace WebCore {
+typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
+
+InspectorDOMStorageAgent::InspectorDOMStorageAgent(InstrumentingAgents* instrumentingAgents)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_frontend(0)
+{
+ m_instrumentingAgents->setInspectorDOMStorageAgent(this);
+}
+
InspectorDOMStorageAgent::~InspectorDOMStorageAgent()
{
- DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources->end();
- for (DOMStorageResourcesMap::iterator it = m_domStorageResources->begin(); it != domStorageEnd; ++it)
+ m_instrumentingAgents->setInspectorDOMStorageAgent(0);
+ m_instrumentingAgents = 0;
+}
+
+void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend)
+{
+ m_frontend = frontend;
+ DOMStorageResourcesMap::iterator resourcesEnd = m_resources.end();
+ for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
+ it->second->bind(m_frontend);
+}
+
+void InspectorDOMStorageAgent::clearFrontend()
+{
+ DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
+ for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it)
it->second->unbind();
+ m_frontend = 0;
}
-void InspectorDOMStorageAgent::getDOMStorageEntries(long storageId, RefPtr<InspectorArray>* entries)
+void InspectorDOMStorageAgent::getDOMStorageEntries(ErrorString*, long storageId, RefPtr<InspectorArray>* entries)
{
InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
if (storageResource) {
@@ -70,7 +96,7 @@ void InspectorDOMStorageAgent::getDOMStorageEntries(long storageId, RefPtr<Inspe
}
}
-void InspectorDOMStorageAgent::setDOMStorageItem(long storageId, const String& key, const String& value, bool* success)
+void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString*, long storageId, const String& key, const String& value, bool* success)
{
InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
if (storageResource) {
@@ -80,7 +106,7 @@ void InspectorDOMStorageAgent::setDOMStorageItem(long storageId, const String& k
}
}
-void InspectorDOMStorageAgent::removeDOMStorageItem(long storageId, const String& key, bool* success)
+void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString*, long storageId, const String& key, bool* success)
{
InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
if (storageResource) {
@@ -89,41 +115,52 @@ void InspectorDOMStorageAgent::removeDOMStorageItem(long storageId, const String
}
}
-void InspectorDOMStorageAgent::selectDOMStorage(Storage* storage)
+long InspectorDOMStorageAgent::storageId(Storage* storage)
{
ASSERT(storage);
- if (!m_frontend)
- return;
-
Frame* frame = storage->frame();
ExceptionCode ec = 0;
bool isLocalStorage = (frame->domWindow()->localStorage(ec) == storage && !ec);
- long storageResourceId = 0;
- DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources->end();
- for (DOMStorageResourcesMap::iterator it = m_domStorageResources->begin(); it != domStorageEnd; ++it) {
- if (it->second->isSameHostAndType(frame, isLocalStorage)) {
- storageResourceId = it->first;
- break;
- }
+ DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
+ for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
+ if (it->second->isSameHostAndType(frame, isLocalStorage))
+ return it->first;
}
- if (storageResourceId)
- m_frontend->selectDOMStorage(storageResourceId);
-}
-
-InspectorDOMStorageAgent::InspectorDOMStorageAgent(DOMStorageResourcesMap* domStorageResources, InspectorFrontend* frontend)
- : m_domStorageResources(domStorageResources)
- , m_frontend(frontend)
-{
+ return 0;
}
InspectorDOMStorageResource* InspectorDOMStorageAgent::getDOMStorageResourceForId(long storageId)
{
- DOMStorageResourcesMap::iterator it = m_domStorageResources->find(storageId);
- if (it == m_domStorageResources->end())
+ DOMStorageResourcesMap::iterator it = m_resources.find(storageId);
+ if (it == m_resources.end())
return 0;
return it->second.get();
}
+void InspectorDOMStorageAgent::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
+{
+ DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
+ for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
+ if (it->second->isSameHostAndType(frame, isLocalStorage))
+ return;
+ }
+
+ RefPtr<Storage> domStorage = Storage::create(frame, storageArea);
+ RefPtr<InspectorDOMStorageResource> resource = InspectorDOMStorageResource::create(domStorage.get(), isLocalStorage, frame);
+
+ m_resources.set(resource->id(), resource);
+
+ // Resources are only bound while visible.
+ if (m_frontend)
+ resource->bind(m_frontend);
+}
+
+void InspectorDOMStorageAgent::clearResources()
+{
+ m_resources.clear();
+}
+
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR) && ENABLE(DOM_STORE)
diff --git a/Source/WebCore/inspector/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/InspectorDOMStorageAgent.h
index 987c530..adae9b2 100644
--- a/Source/WebCore/inspector/InspectorDOMStorageAgent.h
+++ b/Source/WebCore/inspector/InspectorDOMStorageAgent.h
@@ -35,36 +35,48 @@
namespace WebCore {
+class Frame;
class InspectorArray;
class InspectorDOMStorageResource;
class InspectorFrontend;
+class InstrumentingAgents;
class Storage;
+class StorageArea;
+
+typedef String ErrorString;
class InspectorDOMStorageAgent {
public:
- typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
-
- static PassOwnPtr<InspectorDOMStorageAgent> create(DOMStorageResourcesMap* domStorageResources, InspectorFrontend* frontend)
+ static PassOwnPtr<InspectorDOMStorageAgent> create(InstrumentingAgents* instrumentingAgents)
{
- return adoptPtr(new InspectorDOMStorageAgent(domStorageResources, frontend));
+ return adoptPtr(new InspectorDOMStorageAgent(instrumentingAgents));
}
+ ~InspectorDOMStorageAgent();
- virtual ~InspectorDOMStorageAgent();
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
+
+ void clearResources();
// Called from the front-end.
- void getDOMStorageEntries(long storageId, RefPtr<InspectorArray>* entries);
- void setDOMStorageItem(long storageId, const String& key, const String& value, bool* success);
- void removeDOMStorageItem(long storageId, const String& key, bool* success);
+ void getDOMStorageEntries(ErrorString*, long storageId, RefPtr<InspectorArray>* entries);
+ void setDOMStorageItem(ErrorString*, long storageId, const String& key, const String& value, bool* success);
+ void removeDOMStorageItem(ErrorString*, long storageId, const String& key, bool* success);
// Called from the injected script.
- void selectDOMStorage(Storage* storage);
+ long storageId(Storage*);
+
+ // Called from InspectorInstrumentation
+ void didUseDOMStorage(StorageArea*, bool isLocalStorage, Frame*);
private:
- InspectorDOMStorageAgent(DOMStorageResourcesMap*, InspectorFrontend*);
+ explicit InspectorDOMStorageAgent(InstrumentingAgents*);
InspectorDOMStorageResource* getDOMStorageResourceForId(long storageId);
- DOMStorageResourcesMap* m_domStorageResources;
+ InstrumentingAgents* m_instrumentingAgents;
+ typedef HashMap<long, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
+ DOMStorageResourcesMap m_resources;
InspectorFrontend* m_frontend;
};
diff --git a/Source/WebCore/inspector/InspectorDOMStorageResource.cpp b/Source/WebCore/inspector/InspectorDOMStorageResource.cpp
index cfd5f9f..6ff6418 100644
--- a/Source/WebCore/inspector/InspectorDOMStorageResource.cpp
+++ b/Source/WebCore/inspector/InspectorDOMStorageResource.cpp
@@ -46,7 +46,7 @@ using namespace JSC;
namespace WebCore {
-int InspectorDOMStorageResource::s_nextUnusedId = 1;
+long InspectorDOMStorageResource::s_nextUnusedId = 1;
InspectorDOMStorageResource::InspectorDOMStorageResource(Storage* domStorage, bool isLocalStorage, Frame* frame)
: EventListener(InspectorDOMStorageResourceType)
@@ -67,13 +67,13 @@ bool InspectorDOMStorageResource::isSameHostAndType(Frame* frame, bool isLocalSt
void InspectorDOMStorageResource::bind(InspectorFrontend* frontend)
{
ASSERT(!m_frontend);
- m_frontend = frontend;
+ m_frontend = frontend->domstorage();
RefPtr<InspectorObject> jsonObject = InspectorObject::create();
jsonObject->setString("host", m_frame->document()->securityOrigin()->host());
jsonObject->setBoolean("isLocalStorage", m_isLocalStorage);
jsonObject->setNumber("id", m_id);
- frontend->addDOMStorage(jsonObject);
+ m_frontend->addDOMStorage(jsonObject);
}
void InspectorDOMStorageResource::unbind()
diff --git a/Source/WebCore/inspector/InspectorDOMStorageResource.h b/Source/WebCore/inspector/InspectorDOMStorageResource.h
index f0975ba..9ad5b91 100644
--- a/Source/WebCore/inspector/InspectorDOMStorageResource.h
+++ b/Source/WebCore/inspector/InspectorDOMStorageResource.h
@@ -34,6 +34,7 @@
#if ENABLE(DOM_STORAGE)
#include "EventListener.h"
+#include "InspectorFrontend.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -75,11 +76,11 @@ namespace WebCore {
RefPtr<Storage> m_domStorage;
bool m_isLocalStorage;
RefPtr<Frame> m_frame;
- InspectorFrontend* m_frontend;
- int m_id;
+ InspectorFrontend::DOMStorage* m_frontend;
+ long m_id;
bool m_reportingChangesToFrontend;
- static int s_nextUnusedId;
+ static long s_nextUnusedId;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorDatabaseAgent.cpp b/Source/WebCore/inspector/InspectorDatabaseAgent.cpp
index 221bdf2..45ec42a 100644
--- a/Source/WebCore/inspector/InspectorDatabaseAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDatabaseAgent.cpp
@@ -34,10 +34,10 @@
#include "Database.h"
#include "ExceptionCode.h"
-#include "InspectorAgent.h"
#include "InspectorDatabaseResource.h"
#include "InspectorFrontend.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "SQLError.h"
#include "SQLStatementCallback.h"
#include "SQLStatementErrorCallback.h"
@@ -61,18 +61,18 @@ public:
virtual ~FrontendProvider() { }
- InspectorFrontend* frontend() { return m_inspectorFrontend; }
+ InspectorFrontend::Database* frontend() { return m_inspectorFrontend; }
void clearFrontend() { m_inspectorFrontend = 0; }
private:
- FrontendProvider(InspectorFrontend* inspectorFrontend) : m_inspectorFrontend(inspectorFrontend) { }
- InspectorFrontend* m_inspectorFrontend;
+ FrontendProvider(InspectorFrontend* inspectorFrontend) : m_inspectorFrontend(inspectorFrontend->database()) { }
+ InspectorFrontend::Database* m_inspectorFrontend;
};
namespace {
long lastTransactionId = 0;
-void reportTransactionFailed(InspectorFrontend* frontend, long transactionId, SQLError* error)
+void reportTransactionFailed(InspectorFrontend::Database* frontend, long transactionId, SQLError* error)
{
if (!frontend)
return;
@@ -218,12 +218,46 @@ private:
} // namespace
+void InspectorDatabaseAgent::didOpenDatabase(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+{
+ RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
+ m_resources.set(resource->id(), resource);
+ // Resources are only bound while visible.
+ if (m_frontendProvider)
+ resource->bind(m_frontendProvider->frontend());
+}
+
+void InspectorDatabaseAgent::clearResources()
+{
+ m_resources.clear();
+}
+
+InspectorDatabaseAgent::InspectorDatabaseAgent(InstrumentingAgents* instrumentingAgents)
+ : m_instrumentingAgents(instrumentingAgents)
+{
+ m_instrumentingAgents->setInspectorDatabaseAgent(this);
+}
+
InspectorDatabaseAgent::~InspectorDatabaseAgent()
{
+ m_instrumentingAgents->setInspectorDatabaseAgent(0);
+}
+
+void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend)
+{
+ m_frontendProvider = FrontendProvider::create(frontend);
+ DatabaseResourcesMap::iterator databasesEnd = m_resources.end();
+ for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != databasesEnd; ++it)
+ it->second->bind(m_frontendProvider->frontend());
+}
+
+void InspectorDatabaseAgent::clearFrontend()
+{
m_frontendProvider->clearFrontend();
+ m_frontendProvider.clear();
}
-void InspectorDatabaseAgent::getDatabaseTableNames(long databaseId, RefPtr<InspectorArray>* names)
+void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString*, long databaseId, RefPtr<InspectorArray>* names)
{
Database* database = databaseForId(databaseId);
if (database) {
@@ -234,7 +268,7 @@ void InspectorDatabaseAgent::getDatabaseTableNames(long databaseId, RefPtr<Inspe
}
}
-void InspectorDatabaseAgent::executeSQL(long databaseId, const String& query, bool* success, long* transactionId)
+void InspectorDatabaseAgent::executeSQL(ErrorString*, long databaseId, const String& query, bool* success, long* transactionId)
{
Database* database = databaseForId(databaseId);
if (!database) {
@@ -250,31 +284,21 @@ void InspectorDatabaseAgent::executeSQL(long databaseId, const String& query, bo
*success = true;
}
-Database* InspectorDatabaseAgent::databaseForId(long databaseId)
-{
- DatabaseResourcesMap::iterator it = m_databaseResources->find(databaseId);
- if (it == m_databaseResources->end())
- return 0;
- return it->second->database();
-}
-
-void InspectorDatabaseAgent::selectDatabase(Database* database)
+long InspectorDatabaseAgent::databaseId(Database* database)
{
- if (!m_frontendProvider->frontend())
- return;
-
- for (DatabaseResourcesMap::iterator it = m_databaseResources->begin(); it != m_databaseResources->end(); ++it) {
- if (it->second->database() == database) {
- m_frontendProvider->frontend()->selectDatabase(it->first);
- break;
- }
+ for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
+ if (it->second->database() == database)
+ return it->first;
}
+ return 0;
}
-InspectorDatabaseAgent::InspectorDatabaseAgent(DatabaseResourcesMap* databaseResources, InspectorFrontend* frontend)
- : m_databaseResources(databaseResources)
- , m_frontendProvider(FrontendProvider::create(frontend))
+Database* InspectorDatabaseAgent::databaseForId(long databaseId)
{
+ DatabaseResourcesMap::iterator it = m_resources.find(databaseId);
+ if (it == m_resources.end())
+ return 0;
+ return it->second->database();
}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorDatabaseAgent.h b/Source/WebCore/inspector/InspectorDatabaseAgent.h
index 4ad3e62..7e42211 100644
--- a/Source/WebCore/inspector/InspectorDatabaseAgent.h
+++ b/Source/WebCore/inspector/InspectorDatabaseAgent.h
@@ -39,32 +39,41 @@ class Database;
class InspectorArray;
class InspectorDatabaseResource;
class InspectorFrontend;
+class InstrumentingAgents;
+
+typedef String ErrorString;
class InspectorDatabaseAgent {
public:
class FrontendProvider;
- typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
-
- static PassOwnPtr<InspectorDatabaseAgent> create(DatabaseResourcesMap* databaseResources, InspectorFrontend* frontend)
+ static PassOwnPtr<InspectorDatabaseAgent> create(InstrumentingAgents* instrumentingAgents)
{
- return adoptPtr(new InspectorDatabaseAgent(databaseResources, frontend));
+ return adoptPtr(new InspectorDatabaseAgent(instrumentingAgents));
}
+ ~InspectorDatabaseAgent();
+
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
- virtual ~InspectorDatabaseAgent();
+ void clearResources();
// Called from the front-end.
- void getDatabaseTableNames(long databaseId, RefPtr<InspectorArray>* names);
- void executeSQL(long databaseId, const String& query, bool* success, long* transactionId);
+ void getDatabaseTableNames(ErrorString* error, long databaseId, RefPtr<InspectorArray>* names);
+ void executeSQL(ErrorString* error, long databaseId, const String& query, bool* success, long* transactionId);
// Called from the injected script.
- Database* databaseForId(long databaseId);
- void selectDatabase(Database* database);
+ long databaseId(Database*);
+ void didOpenDatabase(PassRefPtr<Database>, const String& domain, const String& name, const String& version);
private:
- InspectorDatabaseAgent(DatabaseResourcesMap*, InspectorFrontend*);
+ explicit InspectorDatabaseAgent(InstrumentingAgents*);
+
+ Database* databaseForId(long databaseId);
- DatabaseResourcesMap* m_databaseResources;
+ InstrumentingAgents* m_instrumentingAgents;
+ typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
+ DatabaseResourcesMap m_resources;
RefPtr<FrontendProvider> m_frontendProvider;
};
diff --git a/Source/WebCore/inspector/InspectorDatabaseResource.cpp b/Source/WebCore/inspector/InspectorDatabaseResource.cpp
index e2d2f81..41342a4 100644
--- a/Source/WebCore/inspector/InspectorDatabaseResource.cpp
+++ b/Source/WebCore/inspector/InspectorDatabaseResource.cpp
@@ -38,7 +38,7 @@
namespace WebCore {
-static int nextUnusedId = 1;
+static long nextUnusedId = 1;
PassRefPtr<InspectorDatabaseResource> InspectorDatabaseResource::create(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
{
@@ -54,7 +54,7 @@ InspectorDatabaseResource::InspectorDatabaseResource(PassRefPtr<Database> databa
{
}
-void InspectorDatabaseResource::bind(InspectorFrontend* frontend)
+void InspectorDatabaseResource::bind(InspectorFrontend::Database* frontend)
{
RefPtr<InspectorObject> jsonObject = InspectorObject::create();
jsonObject->setNumber("id", m_id);
diff --git a/Source/WebCore/inspector/InspectorDatabaseResource.h b/Source/WebCore/inspector/InspectorDatabaseResource.h
index 24d4f1c..550fcd8 100644
--- a/Source/WebCore/inspector/InspectorDatabaseResource.h
+++ b/Source/WebCore/inspector/InspectorDatabaseResource.h
@@ -32,6 +32,7 @@
#define InspectorDatabaseResource_h
#if ENABLE(DATABASE)
+#include "InspectorFrontend.h"
#include "PlatformString.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -45,14 +46,15 @@ class InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> {
public:
static PassRefPtr<InspectorDatabaseResource> create(PassRefPtr<Database> database, const String& domain, const String& name, const String& version);
- void bind(InspectorFrontend* frontend);
+ void bind(InspectorFrontend::Database*);
Database* database() { return m_database.get(); }
long id() const { return m_id; }
+
private:
InspectorDatabaseResource(PassRefPtr<Database>, const String& domain, const String& name, const String& version);
RefPtr<Database> m_database;
- int m_id;
+ long m_id;
String m_domain;
String m_name;
String m_version;
diff --git a/Source/WebCore/inspector/InspectorDebuggerAgent.cpp b/Source/WebCore/inspector/InspectorDebuggerAgent.cpp
index e8b4ad5..0cdc2b0 100644
--- a/Source/WebCore/inspector/InspectorDebuggerAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDebuggerAgent.cpp
@@ -36,6 +36,7 @@
#include "InspectorFrontend.h"
#include "InspectorState.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "PlatformString.h"
#include "ScriptDebugServer.h"
#include <wtf/text/StringConcatenate.h>
@@ -43,41 +44,121 @@
namespace WebCore {
namespace DebuggerAgentState {
+static const char debuggerEnabled[] = "debuggerEnabled";
+static const char enableWhenShown[] = "debuggerEnableWhenShown";
static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
};
-PassOwnPtr<InspectorDebuggerAgent> InspectorDebuggerAgent::create(InspectorAgent* inspectorAgent, InspectorFrontend* frontend, bool eraseStickyBreakpoints)
+PassOwnPtr<InspectorDebuggerAgent> InspectorDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, Page* inspectedPage, InjectedScriptHost* injectedScriptHost)
{
- OwnPtr<InspectorDebuggerAgent> agent = adoptPtr(new InspectorDebuggerAgent(inspectorAgent, frontend, eraseStickyBreakpoints));
- ScriptDebugServer::shared().clearBreakpoints();
- // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
- ScriptDebugServer::shared().setBreakpointsActivated(true);
- ScriptDebugServer::shared().addListener(agent.get(), inspectorAgent->inspectedPage());
- return agent.release();
+ return adoptPtr(new InspectorDebuggerAgent(instrumentingAgents, inspectorState, inspectedPage, injectedScriptHost));
}
-InspectorDebuggerAgent::InspectorDebuggerAgent(InspectorAgent* inspectorAgent, InspectorFrontend* frontend, bool eraseStickyBreakpoints)
- : m_inspectorAgent(inspectorAgent)
- , m_frontend(frontend)
+InspectorDebuggerAgent::InspectorDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, Page* inspectedPage, InjectedScriptHost* injectedScriptHost)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_inspectorState(inspectorState)
+ , m_inspectedPage(inspectedPage)
+ , m_injectedScriptHost(injectedScriptHost)
+ , m_frontend(0)
, m_pausedScriptState(0)
, m_javaScriptPauseScheduled(false)
+ , m_listener(0)
{
- if (eraseStickyBreakpoints)
- inspectorAgent->state()->setObject(DebuggerAgentState::javaScriptBreakpoints, InspectorObject::create());
}
InspectorDebuggerAgent::~InspectorDebuggerAgent()
{
- ScriptDebugServer::shared().removeListener(this, m_inspectorAgent->inspectedPage());
- m_pausedScriptState = 0;
+ ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
+}
+
+void InspectorDebuggerAgent::startUserInitiatedDebugging()
+{
+ if (m_frontend)
+ enable(false);
+ else
+ m_inspectorState->setBoolean(DebuggerAgentState::enableWhenShown, true);
+}
+
+void InspectorDebuggerAgent::enable(bool restoringFromState)
+{
+ ASSERT(m_frontend);
+ if (!restoringFromState && enabled())
+ return;
+ m_inspectorState->setBoolean(DebuggerAgentState::debuggerEnabled, true);
+ m_instrumentingAgents->setInspectorDebuggerAgent(this);
+
+ ScriptDebugServer::shared().clearBreakpoints();
+ // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
+ ScriptDebugServer::shared().setBreakpointsActivated(true);
+ ScriptDebugServer::shared().addListener(this, m_inspectedPage);
+
+ m_frontend->debuggerWasEnabled();
+ if (m_listener)
+ m_listener->debuggerWasEnabled();
}
-void InspectorDebuggerAgent::activateBreakpoints()
+void InspectorDebuggerAgent::disable()
+{
+ if (!enabled())
+ return;
+ m_inspectorState->setBoolean(DebuggerAgentState::debuggerEnabled, false);
+ m_instrumentingAgents->setInspectorDebuggerAgent(0);
+
+ ScriptDebugServer::shared().removeListener(this, m_inspectedPage);
+ clear();
+
+ if (m_frontend)
+ m_frontend->debuggerWasDisabled();
+ if (m_listener)
+ m_listener->debuggerWasDisabled();
+}
+
+bool InspectorDebuggerAgent::enabled()
+{
+ return m_inspectorState->getBoolean(DebuggerAgentState::debuggerEnabled);
+}
+
+void InspectorDebuggerAgent::restore()
+{
+ if (m_inspectorState->getBoolean(DebuggerAgentState::debuggerEnabled))
+ enable(true);
+}
+
+void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
+{
+ m_frontend = frontend->debugger();
+}
+
+void InspectorDebuggerAgent::enableDebuggerAfterShown()
+{
+ // Erase sticky breakpoints. If we are restoring from a cookie setFrontend msut be called
+ // before the state is loaded from the cookie.
+ m_inspectorState->setObject(DebuggerAgentState::javaScriptBreakpoints, InspectorObject::create());
+ if (m_inspectorState->getBoolean(DebuggerAgentState::enableWhenShown)) {
+ m_inspectorState->setBoolean(DebuggerAgentState::enableWhenShown, false);
+ enable(false);
+ }
+}
+
+void InspectorDebuggerAgent::clearFrontend()
+{
+ m_frontend = 0;
+
+ if (!enabled())
+ return;
+ // If the window is being closed with the debugger enabled,
+ // remember this state to re-enable debugger on the next window
+ // opening.
+ disable();
+ m_inspectorState->setBoolean(DebuggerAgentState::enableWhenShown, true);
+}
+
+void InspectorDebuggerAgent::activateBreakpoints(ErrorString*)
{
ScriptDebugServer::shared().activateBreakpoints();
}
-void InspectorDebuggerAgent::deactivateBreakpoints()
+void InspectorDebuggerAgent::deactivateBreakpoints(ErrorString*)
{
ScriptDebugServer::shared().deactivateBreakpoints();
}
@@ -88,10 +169,10 @@ void InspectorDebuggerAgent::inspectedURLChanged(const String&)
m_breakpointIdToDebugServerBreakpointIds.clear();
}
-void InspectorDebuggerAgent::setJavaScriptBreakpoint(const String& url, int lineNumber, int columnNumber, const String& condition, bool enabled, String* outBreakpointId, RefPtr<InspectorArray>* locations)
+void InspectorDebuggerAgent::setJavaScriptBreakpoint(ErrorString*, const String& url, int lineNumber, int columnNumber, const String& condition, bool enabled, String* outBreakpointId, RefPtr<InspectorArray>* locations)
{
String breakpointId = makeString(url, ":", String::number(lineNumber), ":", String::number(columnNumber));
- RefPtr<InspectorObject> breakpointsCookie = m_inspectorAgent->state()->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ RefPtr<InspectorObject> breakpointsCookie = m_inspectorState->getObject(DebuggerAgentState::javaScriptBreakpoints);
if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end())
return;
RefPtr<InspectorObject> breakpointObject = InspectorObject::create();
@@ -101,7 +182,7 @@ void InspectorDebuggerAgent::setJavaScriptBreakpoint(const String& url, int line
breakpointObject->setString("condition", condition);
breakpointObject->setBoolean("enabled", enabled);
breakpointsCookie->setObject(breakpointId, breakpointObject);
- m_inspectorAgent->state()->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
+ m_inspectorState->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, enabled);
for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
@@ -119,7 +200,7 @@ void InspectorDebuggerAgent::setJavaScriptBreakpoint(const String& url, int line
*outBreakpointId = breakpointId;
}
-void InspectorDebuggerAgent::setJavaScriptBreakpointBySourceId(const String& sourceId, int lineNumber, int columnNumber, const String& condition, bool enabled, String* outBreakpointId, int* actualLineNumber, int* actualColumnNumber)
+void InspectorDebuggerAgent::setJavaScriptBreakpointBySourceId(ErrorString*, const String& sourceId, int lineNumber, int columnNumber, const String& condition, bool enabled, String* outBreakpointId, int* actualLineNumber, int* actualColumnNumber)
{
String breakpointId = makeString(sourceId, ":", String::number(lineNumber), ":", String::number(columnNumber));
if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end())
@@ -130,11 +211,11 @@ void InspectorDebuggerAgent::setJavaScriptBreakpointBySourceId(const String& sou
*outBreakpointId = breakpointId;
}
-void InspectorDebuggerAgent::removeJavaScriptBreakpoint(const String& breakpointId)
+void InspectorDebuggerAgent::removeJavaScriptBreakpoint(ErrorString*, const String& breakpointId)
{
- RefPtr<InspectorObject> breakpointsCookie = m_inspectorAgent->state()->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ RefPtr<InspectorObject> breakpointsCookie = m_inspectorState->getObject(DebuggerAgentState::javaScriptBreakpoints);
breakpointsCookie->remove(breakpointId);
- m_inspectorAgent->state()->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
+ m_inspectorState->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
@@ -144,7 +225,7 @@ void InspectorDebuggerAgent::removeJavaScriptBreakpoint(const String& breakpoint
m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
}
-void InspectorDebuggerAgent::continueToLocation(const String& sourceId, int lineNumber, int columnNumber)
+void InspectorDebuggerAgent::continueToLocation(ErrorString* error, const String& sourceId, int lineNumber, int columnNumber)
{
if (!m_continueToLocationBreakpointId.isEmpty()) {
ScriptDebugServer::shared().removeBreakpoint(m_continueToLocationBreakpointId);
@@ -152,7 +233,7 @@ void InspectorDebuggerAgent::continueToLocation(const String& sourceId, int line
}
ScriptBreakpoint breakpoint(lineNumber, columnNumber, "", true);
m_continueToLocationBreakpointId = ScriptDebugServer::shared().setBreakpoint(sourceId, breakpoint, &lineNumber, &columnNumber);
- resume();
+ resume(error);
}
bool InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& sourceId, const ScriptBreakpoint& breakpoint, int* actualLineNumber, int* actualColumnNumber)
@@ -185,13 +266,13 @@ bool InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const
return true;
}
-void InspectorDebuggerAgent::editScriptSource(const String& sourceID, const String& newContent, bool* success, String* result, RefPtr<InspectorValue>* newCallFrames)
+void InspectorDebuggerAgent::editScriptSource(ErrorString*, const String& sourceID, const String& newContent, bool* success, String* result, RefPtr<InspectorValue>* newCallFrames)
{
if ((*success = ScriptDebugServer::shared().editScriptSource(sourceID, newContent, *result)))
*newCallFrames = currentCallFrames();
}
-void InspectorDebuggerAgent::getScriptSource(const String& sourceID, String* scriptSource)
+void InspectorDebuggerAgent::getScriptSource(ErrorString*, const String& sourceID, String* scriptSource)
{
*scriptSource = m_scripts.get(sourceID).data;
}
@@ -214,57 +295,50 @@ void InspectorDebuggerAgent::cancelPauseOnNextStatement()
ScriptDebugServer::shared().setPauseOnNextStatement(false);
}
-void InspectorDebuggerAgent::pause()
+void InspectorDebuggerAgent::pause(ErrorString*)
{
schedulePauseOnNextStatement(JavaScriptPauseEventType, InspectorObject::create());
m_javaScriptPauseScheduled = true;
}
-void InspectorDebuggerAgent::resume()
+void InspectorDebuggerAgent::resume(ErrorString*)
{
ScriptDebugServer::shared().continueProgram();
}
-void InspectorDebuggerAgent::stepOver()
+void InspectorDebuggerAgent::stepOver(ErrorString*)
{
ScriptDebugServer::shared().stepOverStatement();
}
-void InspectorDebuggerAgent::stepInto()
+void InspectorDebuggerAgent::stepInto(ErrorString*)
{
ScriptDebugServer::shared().stepIntoStatement();
}
-void InspectorDebuggerAgent::stepOut()
+void InspectorDebuggerAgent::stepOut(ErrorString*)
{
ScriptDebugServer::shared().stepOutOfFunction();
}
-void InspectorDebuggerAgent::setPauseOnExceptionsState(long pauseState, long* newState)
+void InspectorDebuggerAgent::setPauseOnExceptionsState(ErrorString*, long pauseState, long* newState)
{
ScriptDebugServer::shared().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
*newState = ScriptDebugServer::shared().pauseOnExceptionsState();
}
-void InspectorDebuggerAgent::evaluateOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
+void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString*, PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
{
- InjectedScript injectedScript = m_inspectorAgent->injectedScriptHost()->injectedScriptForObjectId(callFrameId.get());
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(callFrameId.get());
if (!injectedScript.hasNoValue())
injectedScript.evaluateOnCallFrame(callFrameId, expression, objectGroup, includeCommandLineAPI, result);
}
-void InspectorDebuggerAgent::getCompletionsOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
-{
- InjectedScript injectedScript = m_inspectorAgent->injectedScriptHost()->injectedScriptForObjectId(callFrameId.get());
- if (!injectedScript.hasNoValue())
- injectedScript.getCompletionsOnCallFrame(callFrameId, expression, includeCommandLineAPI, result);
-}
-
PassRefPtr<InspectorValue> InspectorDebuggerAgent::currentCallFrames()
{
if (!m_pausedScriptState)
return InspectorValue::null();
- InjectedScript injectedScript = m_inspectorAgent->injectedScriptHost()->injectedScriptFor(m_pausedScriptState);
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptFor(m_pausedScriptState);
if (injectedScript.hasNoValue()) {
ASSERT_NOT_REACHED();
return InspectorValue::null();
@@ -284,7 +358,7 @@ void InspectorDebuggerAgent::didParseSource(const String& sourceID, const String
if (url.isEmpty())
return;
- RefPtr<InspectorObject> breakpointsCookie = m_inspectorAgent->state()->getObject(DebuggerAgentState::javaScriptBreakpoints);
+ RefPtr<InspectorObject> breakpointsCookie = m_inspectorState->getObject(DebuggerAgentState::javaScriptBreakpoints);
for (InspectorObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
RefPtr<InspectorObject> breakpointObject = it->second->asObject();
String breakpointURL;
@@ -340,6 +414,16 @@ void InspectorDebuggerAgent::breakProgram(DebuggerEventType type, PassRefPtr<Ins
ScriptDebugServer::shared().breakProgram();
}
+void InspectorDebuggerAgent::clear()
+{
+ m_pausedScriptState = 0;
+ m_scripts.clear();
+ m_breakpointIdToDebugServerBreakpointIds.clear();
+ m_continueToLocationBreakpointId = String();
+ m_breakProgramDetails.clear();
+ m_javaScriptPauseScheduled = false;
+}
+
} // namespace WebCore
#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
diff --git a/Source/WebCore/inspector/InspectorDebuggerAgent.h b/Source/WebCore/inspector/InspectorDebuggerAgent.h
index 644557f..394034a 100644
--- a/Source/WebCore/inspector/InspectorDebuggerAgent.h
+++ b/Source/WebCore/inspector/InspectorDebuggerAgent.h
@@ -32,6 +32,7 @@
#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
#include "InjectedScript.h"
+#include "InspectorFrontend.h"
#include "ScriptBreakpoint.h"
#include "ScriptDebugListener.h"
#include "ScriptState.h"
@@ -42,11 +43,16 @@
#include <wtf/text/StringHash.h>
namespace WebCore {
+
class InjectedScriptHost;
-class InspectorAgent;
class InspectorFrontend;
class InspectorObject;
+class InspectorState;
class InspectorValue;
+class InstrumentingAgents;
+class Page;
+
+typedef String ErrorString;
enum DebuggerEventType {
JavaScriptPauseEventType,
@@ -57,36 +63,55 @@ enum DebuggerEventType {
class InspectorDebuggerAgent : public ScriptDebugListener {
WTF_MAKE_NONCOPYABLE(InspectorDebuggerAgent); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<InspectorDebuggerAgent> create(InspectorAgent*, InspectorFrontend*, bool eraseStickyBreakpoints);
+ static PassOwnPtr<InspectorDebuggerAgent> create(InstrumentingAgents*, InspectorState*, Page*, InjectedScriptHost*);
virtual ~InspectorDebuggerAgent();
+ void startUserInitiatedDebugging();
+ void enable(ErrorString*) { enable(false); }
+ void disable(ErrorString*) { disable(); }
+ void disable();
+ bool enabled();
+ void restore();
+ void setFrontend(InspectorFrontend*);
+ void enableDebuggerAfterShown();
+ void clearFrontend();
+
void inspectedURLChanged(const String& url);
// Part of the protocol.
- void activateBreakpoints();
- void deactivateBreakpoints();
+ void activateBreakpoints(ErrorString* error);
+ void deactivateBreakpoints(ErrorString* error);
- void setJavaScriptBreakpoint(const String& url, int lineNumber, int columnNumber, const String& condition, bool enabled, String* breakpointId, RefPtr<InspectorArray>* locations);
- void setJavaScriptBreakpointBySourceId(const String& sourceId, int lineNumber, int columnNumber, const String& condition, bool enabled, String* breakpointId, int* actualLineNumber, int* actualColumnNumber);
- void removeJavaScriptBreakpoint(const String& breakpointId);
- void continueToLocation(const String& sourceId, int lineNumber, int columnNumber);
+ void setJavaScriptBreakpoint(ErrorString* error, const String& url, int lineNumber, int columnNumber, const String& condition, bool enabled, String* breakpointId, RefPtr<InspectorArray>* locations);
+ void setJavaScriptBreakpointBySourceId(ErrorString* error, const String& sourceId, int lineNumber, int columnNumber, const String& condition, bool enabled, String* breakpointId, int* actualLineNumber, int* actualColumnNumber);
+ void removeJavaScriptBreakpoint(ErrorString* error, const String& breakpointId);
+ void continueToLocation(ErrorString* error, const String& sourceId, int lineNumber, int columnNumber);
- void editScriptSource(const String& sourceID, const String& newContent, bool* success, String* result, RefPtr<InspectorValue>* newCallFrames);
- void getScriptSource(const String& sourceID, String* scriptSource);
+ void editScriptSource(ErrorString* error, const String& sourceID, const String& newContent, bool* success, String* result, RefPtr<InspectorValue>* newCallFrames);
+ void getScriptSource(ErrorString* error, const String& sourceID, String* scriptSource);
void schedulePauseOnNextStatement(DebuggerEventType type, PassRefPtr<InspectorValue> data);
void cancelPauseOnNextStatement();
void breakProgram(DebuggerEventType type, PassRefPtr<InspectorValue> data);
- void pause();
- void resume();
- void stepOver();
- void stepInto();
- void stepOut();
- void setPauseOnExceptionsState(long pauseState, long* newState);
- void evaluateOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
- void getCompletionsOnCallFrame(PassRefPtr<InspectorObject> callFrameId, const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
+ void pause(ErrorString* error);
+ void resume(ErrorString* error);
+ void stepOver(ErrorString* error);
+ void stepInto(ErrorString* error);
+ void stepOut(ErrorString* error);
+ void setPauseOnExceptionsState(ErrorString* error, long pauseState, long* newState);
+ void evaluateOnCallFrame(ErrorString* error, PassRefPtr<InspectorObject> callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
+
+ class Listener {
+ public:
+ virtual ~Listener() { }
+ virtual void debuggerWasEnabled() = 0;
+ virtual void debuggerWasDisabled() = 0;
+ };
+ void setListener(Listener* listener) { m_listener = listener; }
private:
- InspectorDebuggerAgent(InspectorAgent*, InspectorFrontend*, bool eraseStickyBreakpoints);
+ InspectorDebuggerAgent(InstrumentingAgents*, InspectorState*, Page*, InjectedScriptHost*);
+
+ void enable(bool restoringFromState);
PassRefPtr<InspectorValue> currentCallFrames();
@@ -96,6 +121,7 @@ private:
virtual void didContinue();
bool resolveBreakpoint(const String& breakpointId, const String& sourceId, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber);
+ void clear();
class Script {
public:
@@ -125,14 +151,18 @@ private:
typedef HashMap<String, Script> ScriptsMap;
typedef HashMap<String, Vector<String> > BreakpointIdToDebugServerBreakpointIdsMap;
- InspectorAgent* m_inspectorAgent;
- InspectorFrontend* m_frontend;
+ InstrumentingAgents* m_instrumentingAgents;
+ InspectorState* m_inspectorState;
+ Page* m_inspectedPage;
+ InjectedScriptHost* m_injectedScriptHost;
+ InspectorFrontend::Debugger* m_frontend;
ScriptState* m_pausedScriptState;
ScriptsMap m_scripts;
BreakpointIdToDebugServerBreakpointIdsMap m_breakpointIdToDebugServerBreakpointIds;
String m_continueToLocationBreakpointId;
RefPtr<InspectorObject> m_breakProgramDetails;
bool m_javaScriptPauseScheduled;
+ Listener* m_listener;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp
index e7bb1eb..dfe1c28 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp
@@ -41,12 +41,16 @@
#include "InspectorAgent.h"
#include "InspectorApplicationCacheAgent.h"
#include "InspectorBrowserDebuggerAgent.h"
+#include "InspectorCSSAgent.h"
#include "InspectorConsoleAgent.h"
+#include "InspectorDatabaseAgent.h"
#include "InspectorDOMAgent.h"
+#include "InspectorDOMStorageAgent.h"
#include "InspectorDebuggerAgent.h"
#include "InspectorProfilerAgent.h"
#include "InspectorResourceAgent.h"
#include "InspectorTimelineAgent.h"
+#include "InstrumentingAgents.h"
#include "ScriptArguments.h"
#include "ScriptCallStack.h"
#include "XMLHttpRequest.h"
@@ -99,7 +103,7 @@ void InspectorInstrumentation::inspectedPageDestroyedImpl(InspectorAgent* inspec
void InspectorInstrumentation::willInsertDOMNodeImpl(InspectorAgent* inspectorAgent, Node* node, Node* parent)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->willInsertDOMNode(node, parent);
#endif
}
@@ -109,7 +113,7 @@ void InspectorInstrumentation::didInsertDOMNodeImpl(InspectorAgent* inspectorAge
if (InspectorDOMAgent* domAgent = inspectorAgent->domAgent())
domAgent->didInsertDOMNode(node);
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->didInsertDOMNode(node);
#endif
}
@@ -117,7 +121,7 @@ void InspectorInstrumentation::didInsertDOMNodeImpl(InspectorAgent* inspectorAge
void InspectorInstrumentation::willRemoveDOMNodeImpl(InspectorAgent* inspectorAgent, Node* node)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->willRemoveDOMNode(node);
#endif
}
@@ -125,7 +129,7 @@ void InspectorInstrumentation::willRemoveDOMNodeImpl(InspectorAgent* inspectorAg
void InspectorInstrumentation::didRemoveDOMNodeImpl(InspectorAgent* inspectorAgent, Node* node)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->didRemoveDOMNode(node);
#endif
if (InspectorDOMAgent* domAgent = inspectorAgent->domAgent())
@@ -135,7 +139,7 @@ void InspectorInstrumentation::didRemoveDOMNodeImpl(InspectorAgent* inspectorAge
void InspectorInstrumentation::willModifyDOMAttrImpl(InspectorAgent* inspectorAgent, Element* element)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->willModifyDOMAttr(element);
#endif
}
@@ -146,6 +150,12 @@ void InspectorInstrumentation::didModifyDOMAttrImpl(InspectorAgent* inspectorAge
domAgent->didModifyDOMAttr(element);
}
+void InspectorInstrumentation::didInvalidateStyleAttrImpl(InspectorAgent* inspectorAgent, Node* node)
+{
+ if (InspectorDOMAgent* domAgent = inspectorAgent->domAgent())
+ domAgent->didInvalidateStyleAttr(node);
+}
+
void InspectorInstrumentation::mouseDidMoveOverElementImpl(InspectorAgent* inspectorAgent, const HitTestResult& result, unsigned modifierFlags)
{
inspectorAgent->mouseDidMoveOverElement(result, modifierFlags);
@@ -165,7 +175,7 @@ void InspectorInstrumentation::characterDataModifiedImpl(InspectorAgent* inspect
void InspectorInstrumentation::willSendXMLHttpRequestImpl(InspectorAgent* inspectorAgent, const String& url)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->willSendXMLHttpRequest(url);
#endif
}
@@ -498,8 +508,47 @@ void InspectorInstrumentation::frameDetachedFromParentImpl(InspectorAgent* inspe
resourceAgent->frameDetachedFromParent(frame);
}
-void InspectorInstrumentation::didCommitLoadImpl(InspectorAgent* inspectorAgent, DocumentLoader* loader)
+void InspectorInstrumentation::didCommitLoadImpl(Page* page, InspectorAgent* inspectorAgent, DocumentLoader* loader)
{
+ if (!inspectorAgent->enabled())
+ return;
+
+ InstrumentingAgents* instrumentingAgents = inspectorAgent->instrumentingAgents();
+ if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+ resourceAgent->didCommitLoad(loader);
+
+ Frame* mainFrame = page->mainFrame();
+ if (loader->frame() != mainFrame)
+ return;
+
+ if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+ consoleAgent->reset();
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent()) {
+ KURL url = inspectorAgent->inspectedURLWithoutFragment();
+ debuggerAgent->inspectedURLChanged(url);
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = instrumentingAgents->inspectorBrowserDebuggerAgent())
+ browserDebuggerAgent->inspectedURLChanged(url);
+ }
+#endif
+#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
+ if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent()) {
+ profilerAgent->stopUserInitiatedProfiling(true);
+ profilerAgent->resetState();
+ }
+#endif
+ if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+ cssAgent->reset();
+#if ENABLE(DATABASE)
+ if (InspectorDatabaseAgent* databaseAgent = instrumentingAgents->inspectorDatabaseAgent())
+ databaseAgent->clearResources();
+#endif
+#if ENABLE(DOM_STORAGE)
+ if (InspectorDOMStorageAgent* domStorageAgent = instrumentingAgents->inspectorDOMStorageAgent())
+ domStorageAgent->clearResources();
+#endif
+ if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+ domAgent->setDocument(mainFrame->document());
inspectorAgent->didCommitLoad(loader);
}
@@ -585,14 +634,20 @@ bool InspectorInstrumentation::profilerEnabledImpl(InspectorAgent* inspectorAgen
#if ENABLE(DATABASE)
void InspectorInstrumentation::didOpenDatabaseImpl(InspectorAgent* inspectorAgent, PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
{
- inspectorAgent->didOpenDatabase(database, domain, name, version);
+ if (!inspectorAgent->enabled())
+ return;
+ if (InspectorDatabaseAgent* dbAgent = inspectorAgent->instrumentingAgents()->inspectorDatabaseAgent())
+ dbAgent->didOpenDatabase(database, domain, name, version);
}
#endif
#if ENABLE(DOM_STORAGE)
void InspectorInstrumentation::didUseDOMStorageImpl(InspectorAgent* inspectorAgent, StorageArea* storageArea, bool isLocalStorage, Frame* frame)
{
- inspectorAgent->didUseDOMStorage(storageArea, isLocalStorage, frame);
+ if (!inspectorAgent->enabled())
+ return;
+ if (InspectorDOMStorageAgent* domStorageAgent = inspectorAgent->instrumentingAgents()->inspectorDOMStorageAgent())
+ domStorageAgent->didUseDOMStorage(storageArea, isLocalStorage, frame);
}
#endif
@@ -609,37 +664,43 @@ void InspectorInstrumentation::didDestroyWorkerImpl(InspectorAgent* inspectorAge
#endif
#if ENABLE(WEB_SOCKETS)
-void InspectorInstrumentation::didCreateWebSocketImpl(InspectorAgent* inspectorAgent, unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
+void InspectorInstrumentation::didCreateWebSocketImpl(InspectorAgent* inspectorAgent, unsigned long identifier, const KURL& requestURL, const KURL&)
{
- inspectorAgent->didCreateWebSocket(identifier, requestURL, documentURL);
+ if (!inspectorAgent->enabled())
+ return;
+ if (InspectorResourceAgent* resourceAgent = retrieveResourceAgent(inspectorAgent))
+ resourceAgent->didCreateWebSocket(identifier, requestURL);
}
void InspectorInstrumentation::willSendWebSocketHandshakeRequestImpl(InspectorAgent* inspectorAgent, unsigned long identifier, const WebSocketHandshakeRequest& request)
{
- inspectorAgent->willSendWebSocketHandshakeRequest(identifier, request);
+ if (InspectorResourceAgent* resourceAgent = retrieveResourceAgent(inspectorAgent))
+ resourceAgent->willSendWebSocketHandshakeRequest(identifier, request);
}
void InspectorInstrumentation::didReceiveWebSocketHandshakeResponseImpl(InspectorAgent* inspectorAgent, unsigned long identifier, const WebSocketHandshakeResponse& response)
{
- inspectorAgent->didReceiveWebSocketHandshakeResponse(identifier, response);
+ if (InspectorResourceAgent* resourceAgent = retrieveResourceAgent(inspectorAgent))
+ resourceAgent->didReceiveWebSocketHandshakeResponse(identifier, response);
}
void InspectorInstrumentation::didCloseWebSocketImpl(InspectorAgent* inspectorAgent, unsigned long identifier)
{
- inspectorAgent->didCloseWebSocket(identifier);
+ if (InspectorResourceAgent* resourceAgent = retrieveResourceAgent(inspectorAgent))
+ resourceAgent->didCloseWebSocket(identifier);
}
#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
void InspectorInstrumentation::networkStateChangedImpl(InspectorAgent* inspectorAgent)
{
- if (InspectorApplicationCacheAgent* applicationCacheAgent = inspectorAgent->applicationCacheAgent())
+ if (InspectorApplicationCacheAgent* applicationCacheAgent = inspectorAgent->instrumentingAgents()->inspectorApplicationCacheAgent())
applicationCacheAgent->networkStateChanged();
}
void InspectorInstrumentation::updateApplicationCacheStatusImpl(InspectorAgent* inspectorAgent, Frame* frame)
{
- if (InspectorApplicationCacheAgent* applicationCacheAgent = inspectorAgent->applicationCacheAgent())
+ if (InspectorApplicationCacheAgent* applicationCacheAgent = inspectorAgent->instrumentingAgents()->inspectorApplicationCacheAgent())
applicationCacheAgent->updateApplicationCacheStatus(frame);
}
#endif
@@ -652,7 +713,7 @@ bool InspectorInstrumentation::hasFrontend(InspectorAgent* inspectorAgent)
void InspectorInstrumentation::pauseOnNativeEventIfNeeded(InspectorAgent* inspectorAgent, const String& categoryType, const String& eventName, bool synchronous)
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->browserDebuggerAgent())
+ if (InspectorBrowserDebuggerAgent* browserDebuggerAgent = inspectorAgent->instrumentingAgents()->inspectorBrowserDebuggerAgent())
browserDebuggerAgent->pauseOnNativeEventIfNeeded(categoryType, eventName, synchronous);
#endif
}
@@ -667,7 +728,7 @@ void InspectorInstrumentation::cancelPauseOnNativeEvent(InspectorAgent* inspecto
InspectorTimelineAgent* InspectorInstrumentation::retrieveTimelineAgent(InspectorAgent* inspectorAgent)
{
- return inspectorAgent->timelineAgent();
+ return inspectorAgent->instrumentingAgents()->inspectorTimelineAgent();
}
InspectorTimelineAgent* InspectorInstrumentation::retrieveTimelineAgent(const InspectorInstrumentationCookie& cookie)
@@ -680,7 +741,7 @@ InspectorTimelineAgent* InspectorInstrumentation::retrieveTimelineAgent(const In
InspectorResourceAgent* InspectorInstrumentation::retrieveResourceAgent(InspectorAgent* inspectorAgent)
{
- return inspectorAgent->resourceAgent();
+ return inspectorAgent->instrumentingAgents()->inspectorResourceAgent();
}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h
index e406e40..2ea4e4f 100644
--- a/Source/WebCore/inspector/InspectorInstrumentation.h
+++ b/Source/WebCore/inspector/InspectorInstrumentation.h
@@ -78,6 +78,7 @@ public:
static void willModifyDOMAttr(Document*, Element*);
static void didModifyDOMAttr(Document*, Element*);
static void characterDataModified(Document*, CharacterData*);
+ static void didInvalidateStyleAttr(Document*, Node*);
static void mouseDidMoveOverElement(Page*, const HitTestResult&, unsigned modifierFlags);
static bool handleMousePress(Page*);
@@ -194,6 +195,7 @@ private:
static void willModifyDOMAttrImpl(InspectorAgent*, Element*);
static void didModifyDOMAttrImpl(InspectorAgent*, Element*);
static void characterDataModifiedImpl(InspectorAgent*, CharacterData*);
+ static void didInvalidateStyleAttrImpl(InspectorAgent*, Node*);
static void mouseDidMoveOverElementImpl(InspectorAgent*, const HitTestResult&, unsigned modifierFlags);
static bool handleMousePressImpl(InspectorAgent*);
@@ -241,7 +243,7 @@ private:
static void domContentLoadedEventFiredImpl(InspectorAgent*, Frame*, const KURL&);
static void loadEventFiredImpl(InspectorAgent*, Frame*, const KURL&);
static void frameDetachedFromParentImpl(InspectorAgent*, Frame*);
- static void didCommitLoadImpl(InspectorAgent*, DocumentLoader*);
+ static void didCommitLoadImpl(Page*, InspectorAgent*, DocumentLoader*);
static InspectorInstrumentationCookie willWriteHTMLImpl(InspectorAgent*, unsigned int length, unsigned int startLine);
static void didWriteHTMLImpl(const InspectorInstrumentationCookie&, unsigned int endLine);
@@ -363,6 +365,14 @@ inline void InspectorInstrumentation::didModifyDOMAttr(Document* document, Eleme
#endif
}
+inline void InspectorInstrumentation::didInvalidateStyleAttr(Document* document, Node* node)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorAgent* inspectorAgent = inspectorAgentWithFrontendForDocument(document))
+ didInvalidateStyleAttrImpl(inspectorAgent, node);
+#endif
+}
+
inline void InspectorInstrumentation::mouseDidMoveOverElement(Page* page, const HitTestResult& result, unsigned modifierFlags)
{
#if ENABLE(INSPECTOR)
@@ -733,8 +743,13 @@ inline void InspectorInstrumentation::frameDetachedFromParent(Frame* frame)
inline void InspectorInstrumentation::didCommitLoad(Frame* frame, DocumentLoader* loader)
{
#if ENABLE(INSPECTOR)
- if (InspectorAgent* inspectorAgent = inspectorAgentForFrame(frame))
- didCommitLoadImpl(inspectorAgent, loader);
+ if (!frame)
+ return;
+ Page* page = frame->page();
+ if (!page)
+ return;
+ if (InspectorAgent* inspectorAgent = inspectorAgentForPage(page))
+ didCommitLoadImpl(page, inspectorAgent, loader);
#endif
}
diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.cpp b/Source/WebCore/inspector/InspectorProfilerAgent.cpp
index 550febf..8867023 100644
--- a/Source/WebCore/inspector/InspectorProfilerAgent.cpp
+++ b/Source/WebCore/inspector/InspectorProfilerAgent.cpp
@@ -37,6 +37,7 @@
#include "InspectorConsoleAgent.h"
#include "InspectorFrontend.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "KURL.h"
#include "Page.h"
#include "ScriptDebugServer.h"
@@ -56,14 +57,15 @@ static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-in
static const char* const CPUProfileType = "CPU";
static const char* const HeapProfileType = "HEAP";
-PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InspectorAgent* inspectorAgent)
+PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage)
{
- OwnPtr<InspectorProfilerAgent> agent = adoptPtr(new InspectorProfilerAgent(inspectorAgent));
- return agent.release();
+ return adoptPtr(new InspectorProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage));
}
-InspectorProfilerAgent::InspectorProfilerAgent(InspectorAgent* inspectorAgent)
- : m_inspectorAgent(inspectorAgent)
+InspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_consoleAgent(consoleAgent)
+ , m_inspectedPage(inspectedPage)
, m_frontend(0)
, m_enabled(false)
, m_recordingUserInitiatedProfile(false)
@@ -71,10 +73,12 @@ InspectorProfilerAgent::InspectorProfilerAgent(InspectorAgent* inspectorAgent)
, m_nextUserInitiatedProfileNumber(1)
, m_nextUserInitiatedHeapSnapshotNumber(1)
{
+ m_instrumentingAgents->setInspectorProfilerAgent(this);
}
InspectorProfilerAgent::~InspectorProfilerAgent()
{
+ m_instrumentingAgents->setInspectorProfilerAgent(0);
}
void InspectorProfilerAgent::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
@@ -93,7 +97,7 @@ void InspectorProfilerAgent::addProfileFinishedMessageToConsole(PassRefPtr<Scrip
RefPtr<ScriptProfile> profile = prpProfile;
String title = profile->title();
String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), '#', String::number(profile->uid()), "\" finished.");
- m_inspectorAgent->consoleAgent()->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
+ m_consoleAgent->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
}
void InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
@@ -101,7 +105,7 @@ void InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& tit
if (!m_frontend)
return;
String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), "#0\" started.");
- m_inspectorAgent->consoleAgent()->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
+ m_consoleAgent->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
}
PassRefPtr<InspectorObject> InspectorProfilerAgent::createProfileHeader(const ScriptProfile& profile)
@@ -151,7 +155,17 @@ String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool increment
return makeString(UserInitiatedProfileName, '.', String::number(m_currentUserInitiatedProfileNumber));
}
-void InspectorProfilerAgent::getProfileHeaders(RefPtr<InspectorArray>* headers)
+void InspectorProfilerAgent::getExactHeapSnapshotNodeRetainedSize(ErrorString*, unsigned long uid, unsigned long nodeId, long* size)
+{
+ HeapSnapshotsMap::iterator it = m_snapshots.find(uid);
+ if (it != m_snapshots.end()) {
+ RefPtr<ScriptHeapSnapshot> snapshot = it->second;
+ *size = snapshot->exactRetainedSize(nodeId);
+ } else
+ *size = -1;
+}
+
+void InspectorProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<InspectorArray>* headers)
{
ProfilesMap::iterator profilesEnd = m_profiles.end();
for (ProfilesMap::iterator it = m_profiles.begin(); it != profilesEnd; ++it)
@@ -165,18 +179,18 @@ namespace {
class OutputStream : public ScriptHeapSnapshot::OutputStream {
public:
- OutputStream(InspectorFrontend* frontend, unsigned long uid)
+ OutputStream(InspectorFrontend::Profiler* frontend, unsigned long uid)
: m_frontend(frontend), m_uid(uid) { }
void Write(const String& chunk) { m_frontend->addHeapSnapshotChunk(m_uid, chunk); }
void Close() { m_frontend->finishHeapSnapshot(m_uid); }
private:
- InspectorFrontend* m_frontend;
+ InspectorFrontend::Profiler* m_frontend;
unsigned long m_uid;
};
} // namespace
-void InspectorProfilerAgent::getProfile(const String& type, unsigned uid, RefPtr<InspectorObject>* profileObject)
+void InspectorProfilerAgent::getProfile(ErrorString*, const String& type, unsigned uid, RefPtr<InspectorObject>* profileObject)
{
if (type == CPUProfileType) {
ProfilesMap::iterator it = m_profiles.find(uid);
@@ -197,7 +211,7 @@ void InspectorProfilerAgent::getProfile(const String& type, unsigned uid, RefPtr
}
}
-void InspectorProfilerAgent::removeProfile(const String& type, unsigned uid)
+void InspectorProfilerAgent::removeProfile(ErrorString*, const String& type, unsigned uid)
{
if (type == CPUProfileType) {
if (m_profiles.contains(uid))
@@ -237,7 +251,7 @@ void InspectorProfilerAgent::startUserInitiatedProfiling()
m_recordingUserInitiatedProfile = true;
String title = getCurrentUserInitiatedProfileName(true);
#if USE(JSC)
- JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorAgent->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
+ JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
#else
ScriptState* scriptState = 0;
#endif
@@ -253,7 +267,7 @@ void InspectorProfilerAgent::stopUserInitiatedProfiling(bool ignoreProfile)
m_recordingUserInitiatedProfile = false;
String title = getCurrentUserInitiatedProfileName();
#if USE(JSC)
- JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorAgent->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
+ JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
#else
// Use null script state to avoid filtering by context security token.
// All functions from all iframes should be visible from Inspector UI.
@@ -273,7 +287,7 @@ namespace {
class HeapSnapshotProgress: public ScriptProfiler::HeapSnapshotProgress {
public:
- explicit HeapSnapshotProgress(InspectorFrontend* frontend)
+ explicit HeapSnapshotProgress(InspectorFrontend::Profiler* frontend)
: m_frontend(frontend) { }
void Start(int totalWork)
{
@@ -287,13 +301,13 @@ public:
void Done() { }
bool isCanceled() { return false; }
private:
- InspectorFrontend* m_frontend;
+ InspectorFrontend::Profiler* m_frontend;
int m_totalWork;
};
};
-void InspectorProfilerAgent::takeHeapSnapshot(bool detailed)
+void InspectorProfilerAgent::takeHeapSnapshot(ErrorString*, bool detailed)
{
String title = makeString(UserInitiatedProfileName, '.', String::number(m_nextUserInitiatedHeapSnapshotNumber));
++m_nextUserInitiatedHeapSnapshotNumber;
diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.h b/Source/WebCore/inspector/InspectorProfilerAgent.h
index 93637f5..839d801 100644
--- a/Source/WebCore/inspector/InspectorProfilerAgent.h
+++ b/Source/WebCore/inspector/InspectorProfilerAgent.h
@@ -32,6 +32,7 @@
#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
+#include "InspectorFrontend.h"
#include "PlatformString.h"
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
@@ -41,48 +42,56 @@
namespace WebCore {
class InspectorArray;
-class InspectorAgent;
+class InspectorConsoleAgent;
class InspectorFrontend;
class InspectorObject;
+class InstrumentingAgents;
+class Page;
class ScriptHeapSnapshot;
class ScriptProfile;
+typedef String ErrorString;
+
class InspectorProfilerAgent {
WTF_MAKE_NONCOPYABLE(InspectorProfilerAgent); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<InspectorProfilerAgent> create(InspectorAgent*);
+ static PassOwnPtr<InspectorProfilerAgent> create(InstrumentingAgents*, InspectorConsoleAgent*, Page*);
virtual ~InspectorProfilerAgent();
void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL);
void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
- void clearProfiles() { resetState(); }
+ void clearProfiles(ErrorString*) { resetState(); }
void disable();
void enable(bool skipRecompile);
bool enabled() { return m_enabled; }
String getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false);
- void getProfileHeaders(RefPtr<InspectorArray>* headers);
- void getProfile(const String& type, unsigned uid, RefPtr<InspectorObject>* profileObject);
+ void getExactHeapSnapshotNodeRetainedSize(ErrorString*, unsigned long uid, unsigned long nodeId, long* size);
+ void getProfileHeaders(ErrorString* error, RefPtr<InspectorArray>* headers);
+ void getProfile(ErrorString* error, const String& type, unsigned uid, RefPtr<InspectorObject>* profileObject);
bool isRecordingUserInitiatedProfile() { return m_recordingUserInitiatedProfile; }
- void removeProfile(const String& type, unsigned uid);
+ void removeProfile(ErrorString* error, const String& type, unsigned uid);
void resetState();
void resetFrontendProfiles();
- void setFrontend(InspectorFrontend* frontend) { m_frontend = frontend; }
+ void setFrontend(InspectorFrontend* frontend) { m_frontend = frontend->profiler(); }
+ void clearFrontend() { m_frontend = 0; }
void startUserInitiatedProfiling();
void stopUserInitiatedProfiling(bool ignoreProfile = false);
- void takeHeapSnapshot(bool detailed);
+ void takeHeapSnapshot(ErrorString* error, bool detailed);
void toggleRecordButton(bool isProfiling);
private:
typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
typedef HashMap<unsigned int, RefPtr<ScriptHeapSnapshot> > HeapSnapshotsMap;
- InspectorProfilerAgent(InspectorAgent*);
+ InspectorProfilerAgent(InstrumentingAgents*, InspectorConsoleAgent*, Page*);
PassRefPtr<InspectorObject> createProfileHeader(const ScriptProfile& profile);
PassRefPtr<InspectorObject> createSnapshotHeader(const ScriptHeapSnapshot& snapshot);
- InspectorAgent* m_inspectorAgent;
- InspectorFrontend* m_frontend;
+ InstrumentingAgents* m_instrumentingAgents;
+ InspectorConsoleAgent* m_consoleAgent;
+ Page* m_inspectedPage;
+ InspectorFrontend::Profiler* m_frontend;
bool m_enabled;
bool m_recordingUserInitiatedProfile;
int m_currentUserInitiatedProfileNumber;
diff --git a/Source/WebCore/inspector/InspectorResourceAgent.cpp b/Source/WebCore/inspector/InspectorResourceAgent.cpp
index 38d9e32..db41640 100644
--- a/Source/WebCore/inspector/InspectorResourceAgent.cpp
+++ b/Source/WebCore/inspector/InspectorResourceAgent.cpp
@@ -47,6 +47,7 @@
#include "InspectorFrontend.h"
#include "InspectorState.h"
#include "InspectorValues.h"
+#include "InstrumentingAgents.h"
#include "KURL.h"
#include "Page.h"
#include "ProgressTracker.h"
@@ -72,11 +73,21 @@ static const char resourceAgentEnabled[] = "resourceAgentEnabled";
static const char extraRequestHeaders[] = "extraRequestHeaders";
}
-PassRefPtr<InspectorResourceAgent> InspectorResourceAgent::restore(Page* page, InspectorState* state, InspectorFrontend* frontend)
+void InspectorResourceAgent::setFrontend(InspectorFrontend* frontend)
{
- if (state->getBoolean(ResourceAgentState::resourceAgentEnabled))
- return create(page, state, frontend);
- return 0;
+ m_frontend = frontend->network();
+}
+
+void InspectorResourceAgent::clearFrontend()
+{
+ m_frontend = 0;
+ disable(0);
+}
+
+void InspectorResourceAgent::restore()
+{
+ if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
+ enable();
}
bool InspectorResourceAgent::resourceContent(Frame* frame, const KURL& url, String* result)
@@ -107,7 +118,7 @@ bool InspectorResourceAgent::resourceContentBase64(Frame* frame, const KURL& url
return false;
}
- *result = base64Encode(data->buffer());
+ *result = base64Encode(data->data(), data->size());
return true;
}
@@ -296,7 +307,7 @@ static void populateObjectWithFrameResources(Frame* frame, PassRefPtr<InspectorO
InspectorResourceAgent::~InspectorResourceAgent()
{
- m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
+ ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
}
void InspectorResourceAgent::identifierForInitialRequest(unsigned long identifier, const KURL& url, DocumentLoader* loader)
@@ -311,7 +322,7 @@ void InspectorResourceAgent::identifierForInitialRequest(unsigned long identifie
m_frontend->identifierForInitialRequest(identifier, url.string(), loaderObject, callStackValue);
}
-void InspectorResourceAgent::setExtraHeaders(PassRefPtr<InspectorObject> headers)
+void InspectorResourceAgent::setExtraHeaders(ErrorString*, PassRefPtr<InspectorObject> headers)
{
m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
}
@@ -498,12 +509,27 @@ Frame* InspectorResourceAgent::frameForId(unsigned long frameId)
return 0;
}
-void InspectorResourceAgent::cachedResources(RefPtr<InspectorObject>* object)
+void InspectorResourceAgent::enable(ErrorString*, RefPtr<InspectorObject>* object)
{
+ enable();
*object = buildObjectForFrameTree(m_page->mainFrame(), true);
}
-void InspectorResourceAgent::resourceContent(unsigned long frameId, const String& url, bool base64Encode, bool* success, String* content)
+void InspectorResourceAgent::enable()
+{
+ if (!m_frontend)
+ return;
+ m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
+ m_instrumentingAgents->setInspectorResourceAgent(this);
+}
+
+void InspectorResourceAgent::disable(ErrorString*)
+{
+ m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
+ m_instrumentingAgents->setInspectorResourceAgent(0);
+}
+
+void InspectorResourceAgent::resourceContent(ErrorString*, unsigned long frameId, const String& url, bool base64Encode, bool* success, String* content)
{
Frame* frame = frameForId(frameId);
if (!frame) {
@@ -516,12 +542,12 @@ void InspectorResourceAgent::resourceContent(unsigned long frameId, const String
*success = InspectorResourceAgent::resourceContent(frame, KURL(ParsedURLString, url), content);
}
-InspectorResourceAgent::InspectorResourceAgent(Page* page, InspectorState* state, InspectorFrontend* frontend)
- : m_page(page)
+InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, Page* page, InspectorState* state)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_page(page)
, m_state(state)
- , m_frontend(frontend)
+ , m_frontend(0)
{
- m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorResourceAgent.h b/Source/WebCore/inspector/InspectorResourceAgent.h
index fb24b70..f1b3d46 100644
--- a/Source/WebCore/inspector/InspectorResourceAgent.h
+++ b/Source/WebCore/inspector/InspectorResourceAgent.h
@@ -31,6 +31,7 @@
#ifndef InspectorResourceAgent_h
#define InspectorResourceAgent_h
+#include "InspectorFrontend.h"
#include "PlatformString.h"
#include <wtf/PassRefPtr.h>
@@ -52,6 +53,7 @@ class InspectorArray;
class InspectorFrontend;
class InspectorObject;
class InspectorState;
+class InstrumentingAgents;
class KURL;
class Page;
class ResourceError;
@@ -64,13 +66,19 @@ class WebSocketHandshakeRequest;
class WebSocketHandshakeResponse;
#endif
+typedef String ErrorString;
+
class InspectorResourceAgent : public RefCounted<InspectorResourceAgent> {
public:
- static PassRefPtr<InspectorResourceAgent> create(Page* page, InspectorState* state, InspectorFrontend* frontend)
+ static PassRefPtr<InspectorResourceAgent> create(InstrumentingAgents* instrumentingAgents, Page* page, InspectorState* state)
{
- return adoptRef(new InspectorResourceAgent(page, state, frontend));
+ return adoptRef(new InspectorResourceAgent(instrumentingAgents, page, state));
}
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
+ void restore();
+
static PassRefPtr<InspectorResourceAgent> restore(Page*, InspectorState*, InspectorFrontend*);
static bool resourceContent(Frame*, const KURL&, String* result);
@@ -102,16 +110,20 @@ public:
Frame* frameForId(unsigned long);
// Called from frontend
- void cachedResources(RefPtr<InspectorObject>*);
- void resourceContent(unsigned long frameId, const String& url, bool base64Encode, bool* resourceFound, String* content);
- void setExtraHeaders(PassRefPtr<InspectorObject>);
+ void enable(ErrorString*, RefPtr<InspectorObject>*);
+ void disable(ErrorString*);
+ void resourceContent(ErrorString*, unsigned long frameId, const String& url, bool base64Encode, bool* resourceFound, String* content);
+ void setExtraHeaders(ErrorString*, PassRefPtr<InspectorObject>);
private:
- InspectorResourceAgent(Page* page, InspectorState*, InspectorFrontend* frontend);
+ InspectorResourceAgent(InstrumentingAgents*, Page*, InspectorState*);
+
+ void enable();
+ InstrumentingAgents* m_instrumentingAgents;
Page* m_page;
InspectorState* m_state;
- InspectorFrontend* m_frontend;
+ InspectorFrontend::Network* m_frontend;
};
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorRuntimeAgent.cpp b/Source/WebCore/inspector/InspectorRuntimeAgent.cpp
index 7938afd..badd8e1 100644
--- a/Source/WebCore/inspector/InspectorRuntimeAgent.cpp
+++ b/Source/WebCore/inspector/InspectorRuntimeAgent.cpp
@@ -45,37 +45,44 @@ InspectorRuntimeAgent::InspectorRuntimeAgent(InjectedScriptHost* injectedScriptH
InspectorRuntimeAgent::~InspectorRuntimeAgent() { }
-void InspectorRuntimeAgent::evaluate(const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
+void InspectorRuntimeAgent::evaluate(ErrorString*, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
{
InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForMainFrame();
if (!injectedScript.hasNoValue())
injectedScript.evaluate(expression, objectGroup, includeCommandLineAPI, result);
}
-void InspectorRuntimeAgent::getCompletions(const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result)
+void InspectorRuntimeAgent::evaluateOn(ErrorString*, PassRefPtr<InspectorObject> objectId, const String& expression, RefPtr<InspectorValue>* result)
{
- InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForMainFrame();
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(objectId.get());
if (!injectedScript.hasNoValue())
- injectedScript.getCompletions(expression, includeCommandLineAPI, result);
+ injectedScript.evaluateOn(objectId, expression, result);
}
-void InspectorRuntimeAgent::getProperties(PassRefPtr<InspectorObject> objectId, bool ignoreHasOwnProperty, bool abbreviate, RefPtr<InspectorValue>* result)
+void InspectorRuntimeAgent::getProperties(ErrorString*, PassRefPtr<InspectorObject> objectId, bool ignoreHasOwnProperty, bool abbreviate, RefPtr<InspectorValue>* result)
{
InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(objectId.get());
if (!injectedScript.hasNoValue())
injectedScript.getProperties(objectId, ignoreHasOwnProperty, abbreviate, result);
}
-void InspectorRuntimeAgent::setPropertyValue(PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result)
+void InspectorRuntimeAgent::setPropertyValue(ErrorString*, PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result)
{
InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(objectId.get());
if (!injectedScript.hasNoValue())
injectedScript.setPropertyValue(objectId, propertyName, expression, result);
}
-void InspectorRuntimeAgent::releaseWrapperObjectGroup(long injectedScriptId, const String& objectGroup)
+void InspectorRuntimeAgent::releaseObject(ErrorString*, PassRefPtr<InspectorObject> objectId)
+{
+ InjectedScript injectedScript = m_injectedScriptHost->injectedScriptForObjectId(objectId.get());
+ if (!injectedScript.hasNoValue())
+ injectedScript.releaseObject(objectId);
+}
+
+void InspectorRuntimeAgent::releaseObjectGroup(ErrorString*, long injectedScriptId, const String& objectGroup)
{
- m_injectedScriptHost->releaseWrapperObjectGroup(injectedScriptId, objectGroup);
+ m_injectedScriptHost->releaseObjectGroup(injectedScriptId, objectGroup);
}
} // namespace WebCore
diff --git a/Source/WebCore/inspector/InspectorRuntimeAgent.h b/Source/WebCore/inspector/InspectorRuntimeAgent.h
index 9fb2716..4274eea 100644
--- a/Source/WebCore/inspector/InspectorRuntimeAgent.h
+++ b/Source/WebCore/inspector/InspectorRuntimeAgent.h
@@ -46,6 +46,8 @@ class InjectedScriptHost;
class InspectorObject;
class InspectorValue;
+typedef String ErrorString;
+
class InspectorRuntimeAgent {
WTF_MAKE_NONCOPYABLE(InspectorRuntimeAgent);
public:
@@ -57,11 +59,12 @@ public:
~InspectorRuntimeAgent();
// Part of the protocol.
- void evaluate(const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
- void getCompletions(const String& expression, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
- void getProperties(PassRefPtr<InspectorObject> objectId, bool ignoreHasOwnProperty, bool abbreviate, RefPtr<InspectorValue>* result);
- void setPropertyValue(PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result);
- void releaseWrapperObjectGroup(long injectedScriptId, const String& objectGroup);
+ void evaluate(ErrorString*, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorValue>* result);
+ void evaluateOn(ErrorString*, PassRefPtr<InspectorObject> objectId, const String& expression, RefPtr<InspectorValue>* result);
+ void releaseObject(ErrorString*, PassRefPtr<InspectorObject> objectId);
+ void getProperties(ErrorString*, PassRefPtr<InspectorObject> objectId, bool ignoreHasOwnProperty, bool abbreviate, RefPtr<InspectorValue>* result);
+ void setPropertyValue(ErrorString*, PassRefPtr<InspectorObject> objectId, const String& propertyName, const String& expression, RefPtr<InspectorValue>* result);
+ void releaseObjectGroup(ErrorString*, long injectedScriptId, const String& objectGroup);
private:
InspectorRuntimeAgent(InjectedScriptHost*);
diff --git a/Source/WebCore/inspector/InspectorState.cpp b/Source/WebCore/inspector/InspectorState.cpp
index 290ffc2..2988cf2 100644
--- a/Source/WebCore/inspector/InspectorState.cpp
+++ b/Source/WebCore/inspector/InspectorState.cpp
@@ -42,14 +42,12 @@ InspectorState::InspectorState(InspectorClient* client)
{
}
-InspectorState::InspectorState(InspectorClient* client, const String& json)
- : m_client(client)
- , m_properties(InspectorObject::create())
- , m_isOnMute(false)
+void InspectorState::loadFromCookie(const String& inspectorStateCookie)
{
- RefPtr<InspectorValue> jsonValue = InspectorValue::parseJSON(json);
- if (jsonValue)
- m_properties = jsonValue->asObject();
+ m_properties.clear();
+ RefPtr<InspectorValue> cookie = InspectorValue::parseJSON(inspectorStateCookie);
+ if (cookie)
+ m_properties = cookie->asObject();
if (!m_properties)
m_properties = InspectorObject::create();
}
@@ -59,6 +57,11 @@ void InspectorState::mute()
m_isOnMute = true;
}
+void InspectorState::unmute()
+{
+ m_isOnMute = false;
+}
+
void InspectorState::updateCookie()
{
if (!m_isOnMute)
diff --git a/Source/WebCore/inspector/InspectorState.h b/Source/WebCore/inspector/InspectorState.h
index 3a9c3ed..4407c40 100644
--- a/Source/WebCore/inspector/InspectorState.h
+++ b/Source/WebCore/inspector/InspectorState.h
@@ -46,10 +46,12 @@ class InspectorClient;
class InspectorState {
public:
InspectorState(InspectorClient*);
- InspectorState(InspectorClient*, const String& jsonString);
virtual ~InspectorState() {}
+ void loadFromCookie(const String& inspectorStateCookie);
+
void mute();
+ void unmute();
bool getBoolean(const String& propertyName);
String getString(const String& propertyName);
diff --git a/Source/WebCore/inspector/InspectorStyleSheet.cpp b/Source/WebCore/inspector/InspectorStyleSheet.cpp
index 4af0371..45e6e43 100644
--- a/Source/WebCore/inspector/InspectorStyleSheet.cpp
+++ b/Source/WebCore/inspector/InspectorStyleSheet.cpp
@@ -1131,7 +1131,7 @@ InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const Strin
void InspectorStyleSheetForInlineStyle::didModifyElementAttribute()
{
- String newStyleText = m_element->getAttribute("style");
+ String newStyleText = elementStyleText();
bool shouldDropSourceData = false;
if (m_element->isStyledElement() && m_element->style() != m_inspectorStyle->cssStyle()) {
m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id(), 0), inlineStyle(), this);
@@ -1168,6 +1168,13 @@ Document* InspectorStyleSheetForInlineStyle::ownerDocument() const
bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
{
+ // The "style" property value can get changed indirectly, e.g. via element.style.borderWidth = "2px".
+ const String& currentStyleText = elementStyleText();
+ if (m_styleText != currentStyleText) {
+ m_ruleSourceData.clear();
+ m_styleText = currentStyleText;
+ }
+
if (m_ruleSourceData)
return true;
@@ -1192,6 +1199,11 @@ CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
return m_element->style();
}
+const String& InspectorStyleSheetForInlineStyle::elementStyleText() const
+{
+ return m_element->getAttribute("style").string();
+}
+
bool InspectorStyleSheetForInlineStyle::getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result)
{
if (!m_element->isStyledElement())
diff --git a/Source/WebCore/inspector/InspectorStyleSheet.h b/Source/WebCore/inspector/InspectorStyleSheet.h
index 606d318..92318cb 100644
--- a/Source/WebCore/inspector/InspectorStyleSheet.h
+++ b/Source/WebCore/inspector/InspectorStyleSheet.h
@@ -243,6 +243,7 @@ protected:
private:
CSSStyleDeclaration* inlineStyle() const;
+ const String& elementStyleText() const;
bool getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result);
RefPtr<Element> m_element;
diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.cpp b/Source/WebCore/inspector/InspectorTimelineAgent.cpp
index dd0a119..d45a507 100644
--- a/Source/WebCore/inspector/InspectorTimelineAgent.cpp
+++ b/Source/WebCore/inspector/InspectorTimelineAgent.cpp
@@ -36,6 +36,7 @@
#include "Event.h"
#include "InspectorFrontend.h"
#include "InspectorState.h"
+#include "InstrumentingAgents.h"
#include "IntRect.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
@@ -49,15 +50,6 @@ namespace TimelineAgentState {
static const char timelineAgentEnabled[] = "timelineAgentEnabled";
}
-int InspectorTimelineAgent::s_id = 0;
-
-PassOwnPtr<InspectorTimelineAgent> InspectorTimelineAgent::restore(InspectorState* state, InspectorFrontend* frontend)
-{
- if (state->getBoolean(TimelineAgentState::timelineAgentEnabled))
- return create(state, frontend);
- return 0;
-}
-
void InspectorTimelineAgent::pushGCEventRecords()
{
if (!m_gcEvents.size())
@@ -80,11 +72,59 @@ void InspectorTimelineAgent::didGC(double startTime, double endTime, size_t coll
InspectorTimelineAgent::~InspectorTimelineAgent()
{
- m_frontend->timelineProfilerWasStopped();
+ clearFrontend();
+}
+
+void InspectorTimelineAgent::setFrontend(InspectorFrontend* frontend)
+{
+ m_frontend = frontend->timeline();
+}
+
+void InspectorTimelineAgent::clearFrontend()
+{
+ ErrorString error;
+ stop(&error);
+ m_frontend = 0;
+}
+
+void InspectorTimelineAgent::restore()
+{
+ if (m_state->getBoolean(TimelineAgentState::timelineAgentEnabled)) {
+ ErrorString error;
+ start(&error);
+ }
+}
+
+void InspectorTimelineAgent::start(ErrorString*)
+{
+ if (!m_frontend)
+ return;
+ m_instrumentingAgents->setInspectorTimelineAgent(this);
+ ScriptGCEvent::addEventListener(this);
+ m_frontend->timelineProfilerWasStarted();
+ m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, true);
+}
+
+void InspectorTimelineAgent::stop(ErrorString*)
+{
+ if (!started())
+ return;
+ m_instrumentingAgents->setInspectorTimelineAgent(0);
+ if (m_frontend)
+ m_frontend->timelineProfilerWasStopped();
ScriptGCEvent::removeEventListener(this);
+
+ clearRecordStack();
+ m_gcEvents.clear();
+
m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, false);
}
+bool InspectorTimelineAgent::started() const
+{
+ return m_state->getBoolean(TimelineAgentState::timelineAgentEnabled);
+}
+
void InspectorTimelineAgent::willCallFunction(const String& scriptName, int scriptLine)
{
pushCurrentRecord(TimelineRecordFactory::createFunctionCallData(scriptName, scriptLine), FunctionCallTimelineRecordType);
@@ -280,14 +320,7 @@ void InspectorTimelineAgent::didMarkLoadEvent()
void InspectorTimelineAgent::didCommitLoad()
{
- m_recordStack.clear();
-}
-
-void InspectorTimelineAgent::setFrontend(InspectorFrontend* frontend)
-{
- ASSERT(frontend);
- m_recordStack.clear();
- m_frontend = frontend;
+ clearRecordStack();
}
void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<InspectorObject> prpRecord, TimelineRecordType type)
@@ -329,14 +362,12 @@ void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type)
}
}
-InspectorTimelineAgent::InspectorTimelineAgent(InspectorState* state, InspectorFrontend* frontend)
- : m_state(state)
- , m_frontend(frontend)
- , m_id(++s_id)
+InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state)
+ : m_instrumentingAgents(instrumentingAgents)
+ , m_state(state)
+ , m_frontend(0)
+ , m_id(1)
{
- ScriptGCEvent::addEventListener(this);
- m_frontend->timelineProfilerWasStarted();
- m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, true);
}
void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data, TimelineRecordType type)
@@ -345,6 +376,13 @@ void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data,
RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(WTF::currentTimeMS());
m_recordStack.append(TimelineRecordEntry(record.release(), data, InspectorArray::create(), type));
}
+
+void InspectorTimelineAgent::clearRecordStack()
+{
+ m_recordStack.clear();
+ m_id++;
+}
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.h b/Source/WebCore/inspector/InspectorTimelineAgent.h
index 36c2df2..c4c0f3b 100644
--- a/Source/WebCore/inspector/InspectorTimelineAgent.h
+++ b/Source/WebCore/inspector/InspectorTimelineAgent.h
@@ -33,6 +33,7 @@
#if ENABLE(INSPECTOR)
+#include "InspectorFrontend.h"
#include "InspectorValues.h"
#include "ScriptGCEvent.h"
#include "ScriptGCEventListener.h"
@@ -43,10 +44,13 @@ namespace WebCore {
class Event;
class InspectorFrontend;
class InspectorState;
+class InstrumentingAgents;
class IntRect;
class ResourceRequest;
class ResourceResponse;
+typedef String ErrorString;
+
// Must be kept in sync with TimelineAgent.js
enum TimelineRecordType {
EventDispatchTimelineRecordType = 0,
@@ -75,19 +79,24 @@ enum TimelineRecordType {
class InspectorTimelineAgent : ScriptGCEventListener {
WTF_MAKE_NONCOPYABLE(InspectorTimelineAgent);
public:
- static PassOwnPtr<InspectorTimelineAgent> create(InspectorState* state, InspectorFrontend* frontend)
+ static PassOwnPtr<InspectorTimelineAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state)
{
- return adoptPtr(new InspectorTimelineAgent(state, frontend));
+ return adoptPtr(new InspectorTimelineAgent(instrumentingAgents, state));
}
- static PassOwnPtr<InspectorTimelineAgent> restore(InspectorState*, InspectorFrontend*);
-
~InspectorTimelineAgent();
+ void setFrontend(InspectorFrontend*);
+ void clearFrontend();
+ void restore();
+
+ void start(ErrorString* error);
+ void stop(ErrorString* error);
+ bool started() const;
+
int id() const { return m_id; }
void didCommitLoad();
- void setFrontend(InspectorFrontend*);
// Methods called from WebCore.
void willCallFunction(const String& scriptName, int scriptLine);
@@ -149,7 +158,7 @@ private:
TimelineRecordType type;
};
- InspectorTimelineAgent(InspectorState*, InspectorFrontend*);
+ InspectorTimelineAgent(InstrumentingAgents*, InspectorState*);
void pushCurrentRecord(PassRefPtr<InspectorObject>, TimelineRecordType);
void setHeapSizeStatistic(InspectorObject* record);
@@ -159,14 +168,15 @@ private:
void addRecordToTimeline(PassRefPtr<InspectorObject>, TimelineRecordType);
void pushGCEventRecords();
+ void clearRecordStack();
+ InstrumentingAgents* m_instrumentingAgents;
InspectorState* m_state;
- InspectorFrontend* m_frontend;
+ InspectorFrontend::Timeline* m_frontend;
Vector<TimelineRecordEntry> m_recordStack;
- static int s_id;
- const int m_id;
+ int m_id;
struct GCEvent {
GCEvent(double startTime, double endTime, size_t collectedBytes)
: startTime(startTime), endTime(endTime), collectedBytes(collectedBytes)
diff --git a/Source/WebCore/inspector/InstrumentingAgents.h b/Source/WebCore/inspector/InstrumentingAgents.h
new file mode 100644
index 0000000..c53ef00
--- /dev/null
+++ b/Source/WebCore/inspector/InstrumentingAgents.h
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#ifndef InstrumentingAgents_h
+#define InstrumentingAgents_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class InspectorApplicationCacheAgent;
+class InspectorBrowserDebuggerAgent;
+class InspectorCSSAgent;
+class InspectorConsoleAgent;
+class InspectorDOMAgent;
+class InspectorDOMStorageAgent;
+class InspectorDatabaseAgent;
+class InspectorDebuggerAgent;
+class InspectorProfilerAgent;
+class InspectorResourceAgent;
+class InspectorRuntimeAgent;
+class InspectorTimelineAgent;
+
+class InstrumentingAgents {
+ WTF_MAKE_NONCOPYABLE(InstrumentingAgents);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ InstrumentingAgents()
+ : m_inspectorCSSAgent(0)
+ , m_inspectorConsoleAgent(0)
+ , m_inspectorDOMAgent(0)
+ , m_inspectorResourceAgent(0)
+ , m_inspectorRuntimeAgent(0)
+ , m_inspectorTimelineAgent(0)
+#if ENABLE(DOM_STORAGE)
+ , m_inspectorDOMStorageAgent(0)
+#endif
+#if ENABLE(DATABASE)
+ , m_inspectorDatabaseAgent(0)
+#endif
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ , m_inspectorApplicationCacheAgent(0)
+#endif
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ , m_inspectorDebuggerAgent(0)
+ , m_inspectorBrowserDebuggerAgent(0)
+ , m_inspectorProfilerAgent(0)
+#endif
+ { }
+ ~InstrumentingAgents() { }
+
+ InspectorCSSAgent* inspectorCSSAgent() const { return m_inspectorCSSAgent; }
+ void setInspectorCSSAgent(InspectorCSSAgent* agent) { m_inspectorCSSAgent = agent; }
+
+ InspectorConsoleAgent* inspectorConsoleAgent() const { return m_inspectorConsoleAgent; }
+ void setInspectorConsoleAgent(InspectorConsoleAgent* agent) { m_inspectorConsoleAgent = agent; }
+
+ InspectorDOMAgent* inspectorDOMAgent() const { return m_inspectorDOMAgent; }
+ void setInspectorDOMAgent(InspectorDOMAgent* agent) { m_inspectorDOMAgent = agent; }
+
+ InspectorResourceAgent* inspectorResourceAgent() const { return m_inspectorResourceAgent; }
+ void setInspectorResourceAgent(InspectorResourceAgent* agent) { m_inspectorResourceAgent = agent; }
+
+ InspectorRuntimeAgent* inspectorRuntimeAgent() const { return m_inspectorRuntimeAgent; }
+ void setInspectorRuntimeAgent(InspectorRuntimeAgent* agent) { m_inspectorRuntimeAgent = agent; }
+
+ InspectorTimelineAgent* inspectorTimelineAgent() const { return m_inspectorTimelineAgent; }
+ void setInspectorTimelineAgent(InspectorTimelineAgent* agent) { m_inspectorTimelineAgent = agent; }
+
+#if ENABLE(DOM_STORAGE)
+ InspectorDOMStorageAgent* inspectorDOMStorageAgent() const { return m_inspectorDOMStorageAgent; }
+ void setInspectorDOMStorageAgent(InspectorDOMStorageAgent* agent) { m_inspectorDOMStorageAgent = agent; }
+#endif
+#if ENABLE(DATABASE)
+ InspectorDatabaseAgent* inspectorDatabaseAgent() const { return m_inspectorDatabaseAgent; }
+ void setInspectorDatabaseAgent(InspectorDatabaseAgent* agent) { m_inspectorDatabaseAgent = agent; }
+#endif
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ InspectorApplicationCacheAgent* inspectorApplicationCacheAgent() const { return m_inspectorApplicationCacheAgent; }
+ void setInspectorApplicationCacheAgent(InspectorApplicationCacheAgent* agent) { m_inspectorApplicationCacheAgent = agent; }
+#endif
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* inspectorDebuggerAgent() const { return m_inspectorDebuggerAgent; }
+ void setInspectorDebuggerAgent(InspectorDebuggerAgent* agent) { m_inspectorDebuggerAgent = agent; }
+
+ InspectorBrowserDebuggerAgent* inspectorBrowserDebuggerAgent() const { return m_inspectorBrowserDebuggerAgent; }
+ void setInspectorBrowserDebuggerAgent(InspectorBrowserDebuggerAgent* agent) { m_inspectorBrowserDebuggerAgent = agent; }
+
+ InspectorProfilerAgent* inspectorProfilerAgent() const { return m_inspectorProfilerAgent; }
+ void setInspectorProfilerAgent(InspectorProfilerAgent* agent) { m_inspectorProfilerAgent = agent; }
+#endif
+
+private:
+ InspectorCSSAgent* m_inspectorCSSAgent;
+ InspectorConsoleAgent* m_inspectorConsoleAgent;
+ InspectorDOMAgent* m_inspectorDOMAgent;
+ InspectorResourceAgent* m_inspectorResourceAgent;
+ InspectorRuntimeAgent* m_inspectorRuntimeAgent;
+ InspectorTimelineAgent* m_inspectorTimelineAgent;
+#if ENABLE(DOM_STORAGE)
+ InspectorDOMStorageAgent* m_inspectorDOMStorageAgent;
+#endif
+#if ENABLE(DATABASE)
+ InspectorDatabaseAgent* m_inspectorDatabaseAgent;
+#endif
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ InspectorApplicationCacheAgent* m_inspectorApplicationCacheAgent;
+#endif
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* m_inspectorDebuggerAgent;
+ InspectorBrowserDebuggerAgent* m_inspectorBrowserDebuggerAgent;
+ InspectorProfilerAgent* m_inspectorProfilerAgent;
+#endif
+};
+
+}
+
+#endif // !defined(InstrumentingAgents_h)
diff --git a/Source/WebCore/inspector/front-end/AuditRules.js b/Source/WebCore/inspector/front-end/AuditRules.js
index c122ba4..803e9e0 100644
--- a/Source/WebCore/inspector/front-end/AuditRules.js
+++ b/Source/WebCore/inspector/front-end/AuditRules.js
@@ -65,10 +65,16 @@ WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, nee
WebInspector.AuditRules.evaluateInTargetWindow = function(func, args, callback)
{
- InspectorBackend.evaluateOnSelf(func.toString(), args, callback);
+ function mycallback(result)
+ {
+ if (result)
+ callback(JSON.parse(result.description));
+ else
+ callback(null);
+ }
+ RuntimeAgent.evaluate("JSON.stringify((" + func + ")(" + JSON.stringify(args) + "))", "", false, mycallback);
}
-
WebInspector.AuditRules.GzipRule = function()
{
WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
@@ -83,6 +89,8 @@ WebInspector.AuditRules.GzipRule.prototype = {
var summary = result.addChild("", true);
for (var i = 0, length = resources.length; i < length; ++i) {
var resource = resources[i];
+ if (resource.statusCode === 304)
+ continue; // Do not test 304 Not Modified resources as their contents are always empty.
if (this._shouldCompress(resource)) {
var size = resource.resourceSize;
candidateSize += size;
@@ -104,8 +112,11 @@ WebInspector.AuditRules.GzipRule.prototype = {
_isCompressed: function(resource)
{
- var encoding = resource.responseHeaders["Content-Encoding"];
- return encoding === "gzip" || encoding === "deflate";
+ var encodingHeader = resource.responseHeaders["Content-Encoding"];
+ if (!encodingHeader)
+ return false;
+
+ return /\b(?:gzip|deflate)\b/.test(encodingHeader);
},
_shouldCompress: function(resource)
@@ -383,7 +394,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = {
WebInspector.CSSStyleSheet.createForId(styleSheetIds[i], styleSheetCallback.bind(null, styleSheets, i == styleSheetIds.length - 1 ? evalCallback : null));
}
- InspectorBackend.getAllStyles(allStylesCallback);
+ CSSAgent.getAllStyles(allStylesCallback);
}
}
@@ -639,24 +650,23 @@ WebInspector.AuditRules.ImageDimensionsRule = function()
WebInspector.AuditRules.ImageDimensionsRule.prototype = {
doRun: function(resources, result, callback)
{
- function doneCallback(context)
+ var urlToNoDimensionCount = {};
+
+ function doneCallback()
{
- var map = context.urlToNoDimensionCount;
- for (var url in map) {
+ for (var url in urlToNoDimensionCount) {
var entry = entry || result.addChild("A width and height should be specified for all images in order to speed up page display. The following image(s) are missing a width and/or height:", true);
var value = WebInspector.AuditRuleResult.linkifyDisplayName(url);
- if (map[url] > 1)
- value += String.sprintf(" (%d uses)", map[url]);
+ if (urlToNoDimensionCount[url] > 1)
+ value += String.sprintf(" (%d uses)", urlToNoDimensionCount[url]);
entry.addChild(value);
result.violationCount++;
}
callback(entry ? result : null);
}
- function imageStylesReady(imageId, context, styles)
+ function imageStylesReady(imageId, lastCall, styles)
{
- --context.imagesLeft;
-
const node = WebInspector.domAgent.nodeForId(imageId);
var src = node.getAttribute("src");
if (!src.asParsedURL()) {
@@ -672,14 +682,22 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
const computedStyle = styles.computedStyle;
if (computedStyle.getPropertyValue("position") === "absolute") {
- if (!context.imagesLeft)
- doneCallback(context);
+ if (lastCall)
+ doneCallback();
return;
}
var widthFound = "width" in styles.styleAttributes;
var heightFound = "height" in styles.styleAttributes;
+ var inlineStyle = styles.inlineStyle;
+ if (inlineStyle) {
+ if (inlineStyle.getPropertyValue("width") !== "")
+ widthFound = true;
+ if (inlineStyle.getPropertyValue("height") !== "")
+ heightFound = true;
+ }
+
for (var i = styles.matchedCSSRules.length - 1; i >= 0 && !(widthFound && heightFound); --i) {
var style = styles.matchedCSSRules[i].style;
if (style.getPropertyValue("width") !== "")
@@ -687,41 +705,25 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
if (style.getPropertyValue("height") !== "")
heightFound = true;
}
-
+
if (!widthFound || !heightFound) {
- if (src in context.urlToNoDimensionCount)
- ++context.urlToNoDimensionCount[src];
+ if (src in urlToNoDimensionCount)
+ ++urlToNoDimensionCount[src];
else
- context.urlToNoDimensionCount[src] = 1;
+ urlToNoDimensionCount[src] = 1;
}
- if (!context.imagesLeft)
- doneCallback(context);
+ if (lastCall)
+ doneCallback();
}
- function receivedImages(imageIds)
+ function getStyles(nodeIds)
{
- if (!imageIds || !imageIds.length)
- return callback(null);
- var context = {imagesLeft: imageIds.length, urlToNoDimensionCount: {}};
- for (var i = imageIds.length - 1; i >= 0; --i)
- WebInspector.cssModel.getStylesAsync(imageIds[i], imageStylesReady.bind(this, imageIds[i], context));
- }
-
- function pushImageNodes()
- {
- const nodeIds = [];
- var nodes = document.getElementsByTagName("img");
- for (var i = 0; i < nodes.length; ++i) {
- if (!nodes[i].src)
- continue;
- var nodeId = this.getNodeId(nodes[i]);
- nodeIds.push(nodeId);
- }
- return nodeIds;
+ for (var i = 0; i < nodeIds.length; ++i)
+ WebInspector.cssModel.getStylesAsync(nodeIds[i], imageStylesReady.bind(this, nodeIds[i], i === nodeIds.length - 1));
}
- WebInspector.AuditRules.evaluateInTargetWindow(pushImageNodes, [], receivedImages);
+ DOMAgent.querySelectorAll(0, "img[src]", true, getStyles);
}
}
diff --git a/Source/WebCore/inspector/front-end/AuditsPanel.js b/Source/WebCore/inspector/front-end/AuditsPanel.js
index 47c0b30..3144c78 100644
--- a/Source/WebCore/inspector/front-end/AuditsPanel.js
+++ b/Source/WebCore/inspector/front-end/AuditsPanel.js
@@ -192,7 +192,7 @@ WebInspector.AuditsPanel.prototype = {
_reloadResources: function(callback)
{
this._pageReloadCallback = callback;
- InspectorBackend.reloadPage(false);
+ InspectorAgent.reloadPage(false);
},
_didMainResourceLoad: function()
diff --git a/Source/WebCore/inspector/front-end/BreakpointManager.js b/Source/WebCore/inspector/front-end/BreakpointManager.js
index 94345d5..b62820e 100644
--- a/Source/WebCore/inspector/front-end/BreakpointManager.js
+++ b/Source/WebCore/inspector/front-end/BreakpointManager.js
@@ -207,7 +207,7 @@ WebInspector.BreakpointManager.prototype = {
}
if (!this._breakpointsPushedToFrontend) {
- InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+ BrowserDebuggerAgent.setAllBrowserBreakpoints(this._stickyBreakpoints);
this._breakpointsPushedToFrontend = true;
}
},
@@ -216,6 +216,9 @@ WebInspector.BreakpointManager.prototype = {
{
function didPushNodeByPathToFrontend(path, nodeId)
{
+ if (!nodeId)
+ return;
+
pathToNodeId[path] = nodeId;
pendingCalls -= 1;
if (pendingCalls)
@@ -243,7 +246,7 @@ WebInspector.BreakpointManager.prototype = {
continue;
pathToNodeId[path] = 0;
pendingCalls += 1;
- InspectorBackend.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
+ WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
}
if (!pendingCalls)
this._domBreakpointsRestored = true;
@@ -268,7 +271,7 @@ WebInspector.BreakpointManager.prototype = {
WebInspector.settings.nativeBreakpoints = breakpoints;
this._stickyBreakpoints[WebInspector.settings.projectId] = breakpoints;
- InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+ BrowserDebuggerAgent.setAllBrowserBreakpoints(this._stickyBreakpoints);
},
_validateBreakpoints: function(persistentBreakpoints)
@@ -331,12 +334,12 @@ WebInspector.DOMBreakpoint = function(node, type)
WebInspector.DOMBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setDOMBreakpoint(this._nodeId, this._type);
+ BrowserDebuggerAgent.setDOMBreakpoint(this._nodeId, this._type);
},
_disable: function()
{
- InspectorBackend.removeDOMBreakpoint(this._nodeId, this._type);
+ BrowserDebuggerAgent.removeDOMBreakpoint(this._nodeId, this._type);
},
_serializeToJSON: function()
@@ -354,12 +357,12 @@ WebInspector.EventListenerBreakpoint = function(eventName)
WebInspector.EventListenerBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setEventListenerBreakpoint(this._eventName);
+ BrowserDebuggerAgent.setEventListenerBreakpoint(this._eventName);
},
_disable: function()
{
- InspectorBackend.removeEventListenerBreakpoint(this._eventName);
+ BrowserDebuggerAgent.removeEventListenerBreakpoint(this._eventName);
},
_serializeToJSON: function()
@@ -377,12 +380,12 @@ WebInspector.XHRBreakpoint = function(url)
WebInspector.XHRBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setXHRBreakpoint(this._url);
+ BrowserDebuggerAgent.setXHRBreakpoint(this._url);
},
_disable: function()
{
- InspectorBackend.removeXHRBreakpoint(this._url);
+ BrowserDebuggerAgent.removeXHRBreakpoint(this._url);
},
_serializeToJSON: function()
@@ -476,7 +479,34 @@ WebInspector.DOMBreakpointView.prototype = {
populateStatusMessageElement: function(element, eventData)
{
+ if (this._type === WebInspector.DOMBreakpointTypes.SubtreeModified) {
+ var targetNodeObject = WebInspector.RemoteObject.fromPayload(eventData.targetNode);
+ targetNodeObject.pushNodeToFrontend(decorateNode.bind(this));
+ function decorateNode(targetNodeId)
+ {
+ if (!targetNodeId)
+ return;
+
+ RuntimeAgent.releaseObject(eventData.targetNode);
+ var targetNode = WebInspector.panels.elements.linkifyNodeById(targetNodeId);
+ if (eventData.insertion) {
+ if (targetNodeId !== this._nodeId)
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", targetNode);
+ else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.");
+ } else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", targetNode);
+ }
+ } else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s.");
+ },
+
+ _format: function(element, message, extraSubstitution)
+ {
var substitutions = [WebInspector.domBreakpointTypeLabel(this._type), WebInspector.panels.elements.linkifyNodeById(this._nodeId)];
+ if (extraSubstitution)
+ substitutions.push(extraSubstitution);
+
var formatters = {
s: function(substitution)
{
@@ -489,17 +519,7 @@ WebInspector.DOMBreakpointView.prototype = {
b = document.createTextNode(b);
element.appendChild(b);
}
- if (this._type === WebInspector.DOMBreakpointTypes.SubtreeModified) {
- var targetNode = WebInspector.panels.elements.linkifyNodeById(eventData.targetNodeId);
- if (eventData.insertion) {
- if (eventData.targetNodeId !== this._nodeId)
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", substitutions.concat(targetNode), formatters, "", append);
- else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.", substitutions, formatters, "", append);
- } else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", substitutions.concat(targetNode), formatters, "", append);
- } else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s.", substitutions, formatters, "", append);
+ WebInspector.formatLocalized(message, substitutions, formatters, "", append);
},
_onRemove: function()
diff --git a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 0a47bf8..0c46463 100644
--- a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -143,10 +143,10 @@ WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
_debuggerPaused: function(event)
{
- var breakpointId = this._breakpointIdForDebuggerPausedEvent(event.data);
- if (!breakpointId)
+ var breakpoint = event.data.breakpoint;
+ if (!breakpoint)
return;
- var breakpointItem = this._items[breakpointId];
+ var breakpointItem = this._items[breakpoint.id];
if (!breakpointItem)
return;
breakpointItem.element.addStyleClass("breakpoint-hit");
@@ -236,14 +236,6 @@ WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
element.addEventListener("click", clickHandler, false);
},
- _breakpointIdForDebuggerPausedEvent: function(details)
- {
- var callFrame = details.callFrames[0];
- var breakpoint = WebInspector.debuggerModel.findBreakpoint(callFrame.sourceID, callFrame.line);
- if (breakpoint)
- return breakpoint.id;
- },
-
_removeBreakpoint: function(breakpointId)
{
WebInspector.debuggerModel.removeBreakpoint(breakpointId);
diff --git a/Source/WebCore/inspector/front-end/CSSStyleModel.js b/Source/WebCore/inspector/front-end/CSSStyleModel.js
index 69bd7a9..700417e 100644
--- a/Source/WebCore/inspector/front-end/CSSStyleModel.js
+++ b/Source/WebCore/inspector/front-end/CSSStyleModel.js
@@ -83,7 +83,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(result);
}
- InspectorBackend.getStylesForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getStylesForNode(nodeId, callback.bind(null, userCallback));
},
getComputedStyleAsync: function(nodeId, userCallback)
@@ -96,7 +96,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}
- InspectorBackend.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
},
getInlineStyleAsync: function(nodeId, userCallback)
@@ -109,7 +109,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}
- InspectorBackend.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
},
setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback)
@@ -127,10 +127,10 @@ WebInspector.CSSStyleModel.prototype = {
if (!rulePayload)
failureCallback();
else
- InspectorBackend.querySelectorAll(nodeId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+ DOMAgent.querySelectorAll(nodeId, newSelector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
}
- InspectorBackend.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback));
+ CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback));
},
addRule: function(nodeId, selector, successCallback, failureCallback)
@@ -149,10 +149,10 @@ WebInspector.CSSStyleModel.prototype = {
// Invalid syntax for a selector
failureCallback();
} else
- InspectorBackend.querySelectorAll(nodeId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+ DOMAgent.querySelectorAll(nodeId, selector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
}
- InspectorBackend.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
+ CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
},
_styleSheetChanged: function(styleSheetId, majorChange)
@@ -166,7 +166,7 @@ WebInspector.CSSStyleModel.prototype = {
if (resource && resource.type === WebInspector.Resource.Type.Stylesheet)
resource.setContent(content, this._onRevert.bind(this, styleSheetId));
}
- InspectorBackend.getStyleSheetText(styleSheetId, callback.bind(this));
+ CSSAgent.getStyleSheetText(styleSheetId, callback.bind(this));
},
_onRevert: function(styleSheetId, contentToRevertTo)
@@ -176,7 +176,7 @@ WebInspector.CSSStyleModel.prototype = {
this._styleSheetChanged(styleSheetId, true);
this.dispatchEventToListeners("stylesheet changed");
}
- InspectorBackend.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this));
+ CSSAgent.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this));
}
}
@@ -348,7 +348,7 @@ WebInspector.CSSStyleDeclaration.prototype = {
}
}
- InspectorBackend.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
+ CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
},
appendProperty: function(name, value, userCallback)
@@ -488,7 +488,7 @@ WebInspector.CSSProperty.prototype = {
throw "No ownerStyle for property";
// An index past all the properties adds a new property to the style.
- InspectorBackend.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
+ CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
},
setValue: function(newValue, userCallback)
@@ -517,7 +517,7 @@ WebInspector.CSSProperty.prototype = {
}
}
- InspectorBackend.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
+ CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
}
}
@@ -548,7 +548,7 @@ WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback)
else
userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
}
- InspectorBackend.getStyleSheet(styleSheetId, callback.bind(this));
+ CSSAgent.getStyleSheet(styleSheetId, callback.bind(this));
}
WebInspector.CSSStyleSheet.prototype = {
@@ -569,6 +569,6 @@ WebInspector.CSSStyleSheet.prototype = {
}
}
- InspectorBackend.setStyleSheetText(this.id, newText, callback.bind(this));
+ CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
index 503e5f4..e1618b2 100644
--- a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -23,20 +23,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.CallStackSidebarPane = function()
+WebInspector.CallStackSidebarPane = function(model)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+ this._model = model;
}
WebInspector.CallStackSidebarPane.prototype = {
- update: function(callFrames, eventType, eventData)
+ update: function(details)
{
this.bodyElement.removeChildren();
this.placards = [];
- delete this._selectedCallFrame;
- if (!callFrames) {
+ if (!details) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
@@ -44,6 +44,7 @@ WebInspector.CallStackSidebarPane.prototype = {
return;
}
+ var callFrames = details.callFrames;
var title;
var subtitle;
var script;
@@ -65,12 +66,10 @@ WebInspector.CallStackSidebarPane.prototype = {
else
subtitle = WebInspector.UIString("(internal script)");
- if (callFrame.line > 0) {
- if (subtitle)
- subtitle += ":" + callFrame.line;
- else
- subtitle = WebInspector.UIString("line %d", callFrame.line);
- }
+ if (subtitle)
+ subtitle += ":" + (callFrame.line + 1);
+ else
+ subtitle = WebInspector.UIString("line %d", callFrame.line + 1);
var placard = new WebInspector.Placard(title, subtitle);
placard.callFrame = callFrame;
@@ -81,30 +80,20 @@ WebInspector.CallStackSidebarPane.prototype = {
this.bodyElement.appendChild(placard.element);
}
- if (WebInspector.debuggerModel.findBreakpoint(callFrames[0].sourceID, callFrames[0].line))
+ if (details.breakpoint)
this._scriptBreakpointHit();
- else if (eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
- this._nativeBreakpointHit(eventData);
- },
-
- get selectedCallFrame()
- {
- return this._selectedCallFrame;
+ else if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
+ this._nativeBreakpointHit(details.eventData);
},
set selectedCallFrame(x)
{
- if (this._selectedCallFrame === x)
- return;
-
- this._selectedCallFrame = x;
+ this._model.selectedCallFrame = x;
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
- placard.selected = (placard.callFrame === this._selectedCallFrame);
+ placard.selected = (placard.callFrame === x);
}
-
- this.dispatchEventToListeners("call frame selected");
},
handleShortcut: function(event)
@@ -143,11 +132,11 @@ WebInspector.CallStackSidebarPane.prototype = {
_selectedCallFrameIndex: function()
{
- if (!this._selectedCallFrame)
+ if (!this._model.selectedCallFrame)
return -1;
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
- if (placard.callFrame === this._selectedCallFrame)
+ if (placard.callFrame === this._model.selectedCallFrame)
return i;
}
return -1;
diff --git a/Source/WebCore/inspector/front-end/ConsoleView.js b/Source/WebCore/inspector/front-end/ConsoleView.js
index 35d1ebf..f59d87f 100644
--- a/Source/WebCore/inspector/front-end/ConsoleView.js
+++ b/Source/WebCore/inspector/front-end/ConsoleView.js
@@ -316,7 +316,7 @@ WebInspector.ConsoleView.prototype = {
requestClearMessages: function()
{
- InspectorBackend.clearConsoleMessages();
+ ConsoleAgent.clearConsoleMessages();
},
clearMessages: function()
@@ -353,21 +353,30 @@ WebInspector.ConsoleView.prototype = {
if (!expressionString && !prefix)
return;
- var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix);
- // Collect comma separated object properties for the completion.
+ this.evalInInspectedWindow(expressionString, "completion", true, evaluated.bind(this));
- var includeCommandLineAPI = (!dotNotation && !bracketNotation);
- var injectedScriptAccess;
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
- InspectorBackend.getCompletionsOnCallFrame(WebInspector.panels.scripts.selectedCallFrameId(), expressionString, includeCommandLineAPI, reportCompletions);
- else
- InspectorBackend.getCompletions(expressionString, includeCommandLineAPI, reportCompletions);
- },
+ function evaluated(result)
+ {
+ if (!result)
+ return;
+ result.getProperties(true, false, evaluatedProperties.bind(this));
+ }
- _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) {
- if (isException)
- return;
+ function evaluatedProperties(properties)
+ {
+ RuntimeAgent.releaseObjectGroup(0, "completion");
+ var propertyNames = [];
+ for (var i = 0; properties && i < properties.length; ++i)
+ propertyNames.push(properties[i].name);
+
+ var includeCommandLineAPI = (!dotNotation && !bracketNotation);
+ if (includeCommandLineAPI)
+ propertyNames.splice(0, 0, "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear");
+ this._reportCompletions(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, propertyNames);
+ }
+ },
+ _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, properties) {
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
@@ -376,7 +385,7 @@ WebInspector.ConsoleView.prototype = {
}
var results = [];
- var properties = Object.keys(result).sort();
+ properties.sort();
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
@@ -417,7 +426,7 @@ WebInspector.ConsoleView.prototype = {
var itemAction = function () {
WebInspector.settings.monitoringXHREnabled = !WebInspector.settings.monitoringXHREnabled;
- InspectorBackend.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
+ ConsoleAgent.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
}.bind(this);
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendCheckboxItem(WebInspector.UIString("XMLHttpRequest logging"), itemAction, WebInspector.settings.monitoringXHREnabled)
@@ -513,7 +522,7 @@ WebInspector.ConsoleView.prototype = {
evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, callback)
{
if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, objectGroup, includeCommandLineAPI, callback);
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, callback);
return;
}
@@ -526,7 +535,7 @@ WebInspector.ConsoleView.prototype = {
{
callback(WebInspector.RemoteObject.fromPayload(result));
}
- InspectorBackend.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
+ RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
},
_enterKeyPressed: function(event)
diff --git a/Source/WebCore/inspector/front-end/CookieItemsView.js b/Source/WebCore/inspector/front-end/CookieItemsView.js
index dc76b39..c8187bb 100644
--- a/Source/WebCore/inspector/front-end/CookieItemsView.js
+++ b/Source/WebCore/inspector/front-end/CookieItemsView.js
@@ -140,7 +140,7 @@ WebInspector.CookieItemsView.prototype = {
_deleteCookie: function(cookie)
{
- InspectorBackend.deleteCookie(cookie.name, this._cookieDomain);
+ InspectorAgent.deleteCookie(cookie.name, this._cookieDomain);
this._update();
},
diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js
index 3645bb9..cb28aba 100644
--- a/Source/WebCore/inspector/front-end/DOMAgent.js
+++ b/Source/WebCore/inspector/front-end/DOMAgent.js
@@ -223,12 +223,11 @@ WebInspector.DOMNode.prototype = {
}
}
-WebInspector.DOMDocument = function(domAgent, defaultView, payload)
+WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, this, payload);
this._listeners = {};
this._domAgent = domAgent;
- this.defaultView = defaultView;
}
WebInspector.DOMDocument.prototype = {
@@ -269,44 +268,48 @@ WebInspector.DOMDocument.prototype = {
WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;
-
-WebInspector.DOMWindow = function(domAgent)
-{
- this._domAgent = domAgent;
+WebInspector.DOMAgent = function() {
+ this._idToDOMNode = null;
+ this._document = null;
+ InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
}
-WebInspector.DOMWindow.prototype = {
- get document()
- {
- return this._domAgent.document;
- },
-
- get Node()
+WebInspector.DOMAgent.prototype = {
+ requestDocument: function(callback)
{
- return WebInspector.DOMNode;
+ if (this._document) {
+ if (callback)
+ callback(this._document);
+ } else
+ this._documentUpdated(callback);
},
- get Element()
+ pushNodeToFrontend: function(objectId, callback)
{
- return WebInspector.DOMNode;
+ function mycallback()
+ {
+ if (this._document)
+ DOMAgent.pushNodeToFrontend(objectId, callback);
+ else {
+ if (callback)
+ callback(0);
+ }
+ }
+ this.requestDocument(mycallback.bind(this));
},
- Object: function()
- {
- }
-}
-
-WebInspector.DOMAgent = function() {
- this._window = new WebInspector.DOMWindow(this);
- this._idToDOMNode = null;
- this.document = null;
- InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
-}
-
-WebInspector.DOMAgent.prototype = {
- get domWindow()
+ pushNodeByPathToFrontend: function(path, callback)
{
- return this._window;
+ function mycallback()
+ {
+ if (this._document)
+ DOMAgent.pushNodeByPathToFrontend(path, callback);
+ else {
+ if (callback)
+ callback(0);
+ }
+ }
+ this.requestDocument(mycallback.bind(this));
},
getChildNodesAsync: function(parent, callback)
@@ -319,25 +322,25 @@ WebInspector.DOMAgent.prototype = {
function mycallback() {
callback(parent.children);
}
- InspectorBackend.getChildNodes(parent.id, mycallback);
+ DOMAgent.getChildNodes(parent.id, mycallback);
},
setAttributeAsync: function(node, name, value, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setAttribute(node.id, name, value, mycallback);
+ DOMAgent.setAttribute(node.id, name, value, mycallback);
},
removeAttributeAsync: function(node, name, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.removeAttribute(node.id, name, mycallback);
+ DOMAgent.removeAttribute(node.id, name, mycallback);
},
setTextNodeValueAsync: function(node, text, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setTextNodeValue(node.id, text, mycallback);
+ DOMAgent.setTextNodeValue(node.id, text, mycallback);
},
_didApplyDomChange: function(node, callback, success)
@@ -356,7 +359,7 @@ WebInspector.DOMAgent.prototype = {
var node = this._idToDOMNode[nodeId];
node._setAttributesPayload(attrsArray);
var event = {target: node};
- this.document._fireDomEvent("DOMAttrModified", event);
+ this._document._fireDomEvent("DOMAttrModified", event);
},
_characterDataModified: function(nodeId, newValue)
@@ -365,7 +368,7 @@ WebInspector.DOMAgent.prototype = {
node._nodeValue = newValue;
node.textContent = newValue;
var event = { target : node };
- this.document._fireDomEvent("DOMCharacterDataModified", event);
+ this._document._fireDomEvent("DOMCharacterDataModified", event);
},
nodeForId: function(nodeId)
@@ -373,27 +376,43 @@ WebInspector.DOMAgent.prototype = {
return this._idToDOMNode[nodeId];
},
+ _documentUpdated: function(callback)
+ {
+ function mycallback(root)
+ {
+ this._setDocument(root);
+ if (callback)
+ callback(this._document);
+ }
+ DOMAgent.getDocument(mycallback.bind(this));
+ },
+
_setDocument: function(payload)
{
this._idToDOMNode = {};
if (payload && "id" in payload) {
- this.document = new WebInspector.DOMDocument(this, this._window, payload);
- this._idToDOMNode[payload.id] = this.document;
- this._bindNodes(this.document.children);
+ this._document = new WebInspector.DOMDocument(this, payload);
+ this._idToDOMNode[payload.id] = this._document;
+ this._bindNodes(this._document.children);
WebInspector.breakpointManager.restoreDOMBreakpoints();
} else
- this.document = null;
- WebInspector.panels.elements.setDocument(this.document);
+ this._document = null;
+ WebInspector.panels.elements.setDocument(this._document);
},
_setDetachedRoot: function(payload)
{
- var root = new WebInspector.DOMNode(this.document, payload);
+ var root = new WebInspector.DOMNode(this._document, payload);
this._idToDOMNode[payload.id] = root;
},
_setChildNodes: function(parentId, payloads)
{
+ if (!parentId && payloads.length) {
+ this._setDetachedRoot(payloads[0]);
+ return;
+ }
+
var parent = this._idToDOMNode[parentId];
parent._setChildrenPayload(payloads);
this._bindNodes(parent.children);
@@ -426,7 +445,7 @@ WebInspector.DOMAgent.prototype = {
var node = parent._insertChild(prev, payload);
this._idToDOMNode[node.id] = node;
var event = { target : node, relatedNode : parent };
- this.document._fireDomEvent("DOMNodeInserted", event);
+ this._document._fireDomEvent("DOMNodeInserted", event);
},
_childNodeRemoved: function(parentId, nodeId)
@@ -435,7 +454,7 @@ WebInspector.DOMAgent.prototype = {
var node = this._idToDOMNode[nodeId];
parent.removeChild_(node);
var event = { target : node, relatedNode : parent };
- this.document._fireDomEvent("DOMNodeRemoved", event);
+ this._document._fireDomEvent("DOMNodeRemoved", event);
delete this._idToDOMNode[nodeId];
this._removeBreakpoints(node);
},
@@ -457,9 +476,9 @@ WebInspector.DOMDispatcher = function(domAgent)
}
WebInspector.DOMDispatcher.prototype = {
- setDocument: function(payload)
+ documentUpdated: function()
{
- this._domAgent._setDocument(payload);
+ this._domAgent._documentUpdated();
},
attributesUpdated: function(nodeId, attrsArray)
@@ -477,11 +496,6 @@ WebInspector.DOMDispatcher.prototype = {
this._domAgent._setChildNodes(parentId, payloads);
},
- setDetachedRoot: function(payload)
- {
- this._domAgent._setDetachedRoot(payload);
- },
-
childNodeCountUpdated: function(nodeId, newValue)
{
this._domAgent._childNodeCountUpdated(nodeId, newValue);
@@ -495,6 +509,16 @@ WebInspector.DOMDispatcher.prototype = {
childNodeRemoved: function(parentId, nodeId)
{
this._domAgent._childNodeRemoved(parentId, nodeId);
+ },
+
+ inspectElementRequested: function(nodeId)
+ {
+ WebInspector.updateFocusedNode(nodeId);
+ },
+
+ addNodesToSearchResult: function(nodeIds)
+ {
+ WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
}
}
@@ -511,7 +535,7 @@ WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync = function(cal
callback(applicationCaches);
}
- InspectorBackend.getApplicationCaches(mycallback);
+ ApplicationCacheAgent.getApplicationCaches(mycallback);
}
WebInspector.ApplicationCacheDispatcher.prototype = {
@@ -540,7 +564,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback)
callback(cookies, true);
}
- InspectorBackend.getCookies(mycallback);
+ InspectorAgent.getCookies(mycallback);
}
WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
@@ -585,5 +609,5 @@ WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callb
{
if (!node)
return;
- InspectorBackend.getEventListenersForNode(node.id, callback);
+ DOMAgent.getEventListenersForNode(node.id, callback);
}
diff --git a/Source/WebCore/inspector/front-end/DOMStorage.js b/Source/WebCore/inspector/front-end/DOMStorage.js
index d3d2226..ea24921 100644
--- a/Source/WebCore/inspector/front-end/DOMStorage.js
+++ b/Source/WebCore/inspector/front-end/DOMStorage.js
@@ -39,11 +39,6 @@ WebInspector.DOMStorage.prototype = {
return this._id;
},
- get domStorage()
- {
- return this._domStorage;
- },
-
get domain()
{
return this._domain;
@@ -56,17 +51,17 @@ WebInspector.DOMStorage.prototype = {
getEntries: function(callback)
{
- InspectorBackend.getDOMStorageEntries(this._id, callback);
+ DOMStorageAgent.getDOMStorageEntries(this._id, callback);
},
setItem: function(key, value, callback)
{
- InspectorBackend.setDOMStorageItem(this._id, key, value, callback);
+ DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback);
},
removeItem: function(key, callback)
{
- InspectorBackend.removeDOMStorageItem(this._id, key, callback);
+ DOMStorageAgent.removeDOMStorageItem(this._id, key, callback);
}
}
@@ -87,12 +82,6 @@ WebInspector.DOMStorageDispatcher.prototype = {
WebInspector.panels.resources.addDOMStorage(domStorage);
},
- selectDOMStorage: function(o)
- {
- WebInspector.showPanel("resources");
- WebInspector.panels.resources.selectDOMStorage(o);
- },
-
updateDOMStorage: function(storageId)
{
WebInspector.panels.resources.updateDOMStorage(storageId);
diff --git a/Source/WebCore/inspector/front-end/DataGrid.js b/Source/WebCore/inspector/front-end/DataGrid.js
index 45f0b55..6d54941 100644
--- a/Source/WebCore/inspector/front-end/DataGrid.js
+++ b/Source/WebCore/inspector/front-end/DataGrid.js
@@ -809,14 +809,14 @@ WebInspector.DataGrid.prototype = {
dataGridNodeFromNode: function(target)
{
var rowElement = target.enclosingNodeOrSelfWithNodeName("tr");
- return rowElement._dataGridNode;
+ return rowElement && rowElement._dataGridNode;
},
dataGridNodeFromPoint: function(x, y)
{
var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
- return rowElement._dataGridNode;
+ return rowElement && rowElement._dataGridNode;
},
_clickInHeaderCell: function(event)
diff --git a/Source/WebCore/inspector/front-end/Database.js b/Source/WebCore/inspector/front-end/Database.js
index faa17fa..e4bafea 100644
--- a/Source/WebCore/inspector/front-end/Database.js
+++ b/Source/WebCore/inspector/front-end/Database.js
@@ -81,7 +81,7 @@ WebInspector.Database.prototype = {
{
callback(names.sort());
}
- InspectorBackend.getDatabaseTableNames(this._id, sortingCallback);
+ DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback);
},
executeSql: function(query, onSuccess, onError)
@@ -94,7 +94,7 @@ WebInspector.Database.prototype = {
}
WebInspector.DatabaseDispatcher._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError};
}
- InspectorBackend.executeSQL(this._id, query, callback);
+ DatabaseAgent.executeSQL(this._id, query, callback);
}
}
@@ -107,8 +107,6 @@ WebInspector.DatabaseDispatcher._callbacks = {};
WebInspector.DatabaseDispatcher.prototype = {
addDatabase: function(payload)
{
- if (!WebInspector.panels.resources)
- return;
var database = new WebInspector.Database(
payload.id,
payload.domain,
@@ -117,12 +115,6 @@ WebInspector.DatabaseDispatcher.prototype = {
WebInspector.panels.resources.addDatabase(database);
},
- selectDatabase: function(o)
- {
- WebInspector.showPanel("resources");
- WebInspector.panels.resources.selectDatabase(o);
- },
-
sqlTransactionSucceeded: function(transactionId, columnNames, values)
{
if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
diff --git a/Source/WebCore/inspector/front-end/DebuggerModel.js b/Source/WebCore/inspector/front-end/DebuggerModel.js
index 1bf1e47..d31ff24 100644
--- a/Source/WebCore/inspector/front-end/DebuggerModel.js
+++ b/Source/WebCore/inspector/front-end/DebuggerModel.js
@@ -52,7 +52,7 @@ WebInspector.DebuggerModel.Events = {
WebInspector.DebuggerModel.prototype = {
enableDebugger: function()
{
- InspectorBackend.enableDebugger();
+ DebuggerAgent.enable();
if (this._breakpointsPushedToBackend)
return;
var breakpoints = WebInspector.settings.breakpoints;
@@ -68,12 +68,12 @@ WebInspector.DebuggerModel.prototype = {
disableDebugger: function()
{
- InspectorBackend.disableDebugger();
+ DebuggerAgent.disable();
},
- continueToLine: function(sourceID, lineNumber)
+ continueToLocation: function(sourceID, lineNumber, columnNumber)
{
- InspectorBackend.continueToLocation(sourceID, lineNumber, 0);
+ DebuggerAgent.continueToLocation(sourceID, lineNumber, columnNumber);
},
setBreakpoint: function(url, lineNumber, columnNumber, condition, enabled)
@@ -89,7 +89,7 @@ WebInspector.DebuggerModel.prototype = {
this._saveBreakpoints();
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
}
- InspectorBackend.setJavaScriptBreakpoint(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this, this._breakpointsPushedToBackend));
+ DebuggerAgent.setJavaScriptBreakpoint(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this, this._breakpointsPushedToBackend));
},
setBreakpointBySourceId: function(sourceID, lineNumber, columnNumber, condition, enabled)
@@ -103,12 +103,12 @@ WebInspector.DebuggerModel.prototype = {
this._breakpoints[breakpointId] = breakpoint;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
}
- InspectorBackend.setJavaScriptBreakpointBySourceId(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this));
+ DebuggerAgent.setJavaScriptBreakpointBySourceId(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this));
},
removeBreakpoint: function(breakpointId)
{
- InspectorBackend.removeJavaScriptBreakpoint(breakpointId);
+ DebuggerAgent.removeJavaScriptBreakpoint(breakpointId);
var breakpoint = this._breakpoints[breakpointId];
delete this._breakpoints[breakpointId];
this._saveBreakpoints();
@@ -173,17 +173,6 @@ WebInspector.DebuggerModel.prototype = {
return breakpoints;
},
- findBreakpoint: function(sourceID, lineNumber)
- {
- for (var id in this._breakpoints) {
- var locations = this._breakpoints[id].locations;
- for (var i = 0; i < locations.length; ++i) {
- if (locations[i].sourceID == sourceID && locations[i].lineNumber + 1 === lineNumber)
- return this._breakpoints[id];
- }
- }
- },
-
reset: function()
{
this._paused = false;
@@ -230,7 +219,7 @@ WebInspector.DebuggerModel.prototype = {
} else
WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Warning);
}
- InspectorBackend.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
+ DebuggerAgent.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
},
_updateScriptSource: function(sourceID, scriptSource)
@@ -286,6 +275,7 @@ WebInspector.DebuggerModel.prototype = {
{
this._paused = true;
this._callFrames = details.callFrames;
+ details.breakpoint = this._breakpointForCallFrame(details.callFrames[0]);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
},
@@ -296,6 +286,23 @@ WebInspector.DebuggerModel.prototype = {
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
},
+ _breakpointForCallFrame: function(callFrame)
+ {
+ function match(location)
+ {
+ if (location.sourceID != callFrame.sourceID)
+ return false;
+ return location.lineNumber === callFrame.line && location.columnNumber === callFrame.column;
+ }
+ for (var id in this._breakpoints) {
+ var breakpoint = this._breakpoints[id];
+ for (var i = 0; i < breakpoint.locations.length; ++i) {
+ if (match(breakpoint.locations[i]))
+ return breakpoint;
+ }
+ }
+ },
+
_parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType)
{
var script = new WebInspector.Script(sourceID, sourceURL, "", lineOffset, columnOffset, length, undefined, undefined, scriptWorldType);
diff --git a/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js
new file mode 100644
index 0000000..a97db34
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+WebInspector.DebuggerPresentationModel = function()
+{
+ this._breakpoints = {};
+ this._sourceLocationToBreakpointId = {};
+
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+}
+
+WebInspector.DebuggerPresentationModel.Events = {
+ BreakpointAdded: "breakpoint-added",
+ BreakpointRemoved: "breakpoint-removed"
+}
+
+WebInspector.DebuggerPresentationModel.prototype = {
+ breakpointsForSourceFileId: function(sourceFileId)
+ {
+ var breakpoints = [];
+ for (var id in this._breakpoints) {
+ var breakpoint = this._breakpoints[id];
+ if (breakpoint.sourceFileId === sourceFileId)
+ breakpoints.push(breakpoint);
+ }
+ return breakpoints;
+ },
+
+ _breakpointAdded: function(event)
+ {
+ var breakpoint = event.data;
+ var location = breakpoint.locations.length ? breakpoint.locations[0] : breakpoint;
+ var sourceLocation = this._actualLocationToSourceLocation(breakpoint.url || breakpoint.sourceID, location.lineNumber, location.columnNumber);
+
+ var encodedSourceLocation = this._encodeSourceLocation(sourceLocation.sourceFileId, sourceLocation.lineNumber);
+ if (encodedSourceLocation in this._sourceLocationToBreakpointId) {
+ // We can't show more than one breakpoint on a single source frame line. Remove newly added breakpoint.
+ WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+ return;
+ }
+
+ var presentationBreakpoint = {
+ sourceFileId: sourceLocation.sourceFileId,
+ lineNumber: sourceLocation.lineNumber,
+ url: breakpoint.url,
+ resolved: !!breakpoint.locations.length,
+ condition: breakpoint.condition,
+ enabled: breakpoint.enabled
+ };
+
+ this._sourceLocationToBreakpointId[encodedSourceLocation] = breakpoint.id;
+ this._breakpoints[breakpoint.id] = presentationBreakpoint;
+
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, presentationBreakpoint);
+ },
+
+ _breakpointRemoved: function(event)
+ {
+ var breakpointId = event.data;
+ var breakpoint = this._breakpoints[breakpointId];
+ var encodedSourceLocation = this._encodeSourceLocation(breakpoint.sourceFileId, breakpoint.lineNumber);
+ delete this._breakpoints[breakpointId];
+ delete this._sourceLocationToBreakpointId[encodedSourceLocation];
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint);
+ },
+
+ _breakpointResolved: function(event)
+ {
+ var breakpoint = event.data;
+ this._breakpointRemoved({ data: breakpoint.id });
+ this._breakpointAdded({ data: breakpoint });
+ },
+
+ _encodeSourceLocation: function(sourceFileId, lineNumber)
+ {
+ return sourceFileId + ":" + lineNumber;
+ },
+
+ set selectedCallFrame(callFrame)
+ {
+ this._selectedCallFrame = callFrame;
+ if (!callFrame)
+ return;
+
+ var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.sourceID);
+ callFrame.sourceLocation = this._actualLocationToSourceLocation(script.sourceURL || script.sourceID, callFrame.line, callFrame.column);
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame);
+ },
+
+ get selectedCallFrame()
+ {
+ return this._selectedCallFrame;
+ },
+
+ _actualLocationToSourceLocation: function(sourceID, lineNumber, columnNumber)
+ {
+ // TODO: use source mapping to obtain source location.
+ return { sourceFileId: sourceID, lineNumber: lineNumber, columnNumber: columnNumber };
+ }
+}
+
+WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js
new file mode 100644
index 0000000..14ba142
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js
@@ -0,0 +1,707 @@
+/*
+ * 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.
+ */
+
+WebInspector.HeapSnapshotGridNode = function(tree, hasChildren, populateCount)
+{
+ WebInspector.DataGridNode.call(this, null, hasChildren);
+ this._defaultPopulateCount = populateCount;
+ this._provider = null;
+ this.addEventListener("populate", this._populate, this);
+}
+
+WebInspector.HeapSnapshotGridNode.prototype = {
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+ if (this._searchMatched)
+ cell.addStyleClass("highlight");
+ return cell;
+ },
+
+ _populate: function(event)
+ {
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doPopulate.bind(this));
+
+ function doPopulate()
+ {
+ this._provider.sort(this.comparator());
+ this._provider.first();
+ this.populateChildren();
+ this.removeEventListener("populate", this._populate, this);
+ }
+ },
+
+ populateChildren: function(provider, howMany, atIndex)
+ {
+ if (!howMany && provider) {
+ howMany = provider.instancesCount;
+ provider.resetInstancesCount();
+ }
+ provider = provider || this._provider;
+ howMany = howMany || this._defaultPopulateCount;
+ atIndex = atIndex || this.children.length;
+ var haveSavedChildren = !!this._savedChildren;
+ if (haveSavedChildren) {
+ haveSavedChildren = false;
+ for (var c in this._savedChildren) {
+ haveSavedChildren = true;
+ break;
+ }
+ }
+ for ( ; howMany > 0 && provider.hasNext(); provider.next(), provider.incInstancesCount(), --howMany) {
+ var item = provider.item;
+ if (haveSavedChildren) {
+ var hash = this._childHashForEntity(item);
+ if (hash in this._savedChildren) {
+ this.insertChild(this._savedChildren[hash], atIndex++);
+ continue;
+ }
+ }
+ this.insertChild(this._createChildNode(provider), atIndex++);
+ }
+ if (provider.hasNext())
+ this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, provider.length), atIndex++);
+ },
+
+ _saveChildren: function()
+ {
+ this._savedChildren = {};
+ for (var i = 0, childrenCount = this.children.length; i < childrenCount; ++i) {
+ var child = this.children[i];
+ if (child.expanded)
+ this._savedChildren[this._childHashForNode(child)] = child;
+ }
+ },
+
+ sort: function()
+ {
+ var comparator = this.comparator();
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doSort.bind(this));
+
+ function doSort()
+ {
+ if (!this._provider.sort(comparator))
+ return;
+ this._saveChildren();
+ this.removeChildren();
+ this._provider.first();
+ this.populateChildren(this._provider);
+ for (var i = 0, l = this.children.length; i < l; ++i) {
+ var child = this.children[i];
+ if (child.expanded)
+ child.sort();
+ }
+ }
+ }
+};
+
+WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.HeapSnapshotGenericObjectNode = function(tree, node, hasChildren, populateCount)
+{
+ WebInspector.HeapSnapshotGridNode.call(this, tree, hasChildren, populateCount);
+ this._name = node.name;
+ this._type = node.type;
+ this._shallowSize = node.selfSize;
+ this._retainedSize = node.retainedSize;
+ this._retainedSizeExact = this._shallowSize === this._retainedSize;
+ this.snapshotNodeId = node.id;
+ this.snapshotNodeIndex = node.nodeIndex;
+};
+
+WebInspector.HeapSnapshotGenericObjectNode.prototype = {
+ createCell: function(columnIdentifier)
+ {
+ var cell = columnIdentifier !== "object" ? WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier) : this._createObjectCell();
+ if (this._searchMatched)
+ cell.addStyleClass("highlight");
+ return cell;
+ },
+
+ _createObjectCell: function()
+ {
+ var cell = document.createElement("td");
+ cell.className = "object-column";
+ var div = document.createElement("div");
+ div.className = "source-code event-properties";
+ div.style.overflow = "hidden";
+ var data = this.data["object"];
+ if (this._prefixObjectCell)
+ this._prefixObjectCell(div, data);
+ var valueSpan = document.createElement("span");
+ valueSpan.className = "value console-formatted-" + data.valueStyle;
+ valueSpan.textContent = data.value;
+ div.appendChild(valueSpan);
+ cell.appendChild(div);
+ cell.addStyleClass("disclosure");
+ if (this.depth)
+ cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+ return cell;
+ },
+
+ get _countPercent()
+ {
+ return this._count / this.tree.snapshot.nodesCount * 100.0;
+ },
+
+ get data()
+ {
+ var data = this._emptyData();
+
+ var value = this._name;
+ var valueStyle = "object";
+ switch (this._type) {
+ case "string":
+ value = "\"" + value + "\"";
+ valueStyle = "string";
+ break;
+ case "regexp":
+ value = "/" + value + "/";
+ valueStyle = "string";
+ break;
+ case "closure":
+ value = "function " + value + "()";
+ valueStyle = "function";
+ break;
+ case "number":
+ valueStyle = "number";
+ break;
+ case "hidden":
+ valueStyle = "null";
+ break;
+ case "array":
+ value += "[]";
+ break;
+ };
+ data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId };
+
+ var view = this.dataGrid.snapshotView;
+ data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
+ data["retainedSize"] = (this._retainedSizeExact ? "" : "\u2248") + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize));
+
+ return this._enhanceData ? this._enhanceData(data) : data;
+ },
+
+ set exactRetainedSize(size)
+ {
+ this._retainedSize = size;
+ this._retainedSizeExact = true;
+ this.refresh();
+ },
+
+ get _retainedSizePercent()
+ {
+ return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
+ },
+
+ get _shallowSizePercent()
+ {
+ return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
+ }
+}
+
+WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotObjectNode = function(tree, edge)
+{
+ var node = edge.node;
+ var provider = this._createProvider(tree.snapshot, node.rawEdges);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 100);
+ this._referenceName = edge.name;
+ this._referenceType = edge.type;
+ this._provider = provider;
+}
+
+WebInspector.HeapSnapshotObjectNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, rawEdges)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotEdgesProvider(
+ snapshot,
+ rawEdges,
+ function(edge) {
+ return !edge.isInvisible
+ && (showHiddenData || (!edge.isHidden && !edge.node.isHidden));
+ });
+ },
+
+ _childHashForEntity: function(edge)
+ {
+ return edge.type + "#" + edge.name;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode._referenceType + "#" + childNode._referenceName;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["!edgeName", sortAscending, "retainedSize", false],
+ count: ["!edgeName", true, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "!edgeName", true],
+ retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
+ }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {count:"", addedCount: "", removedCount: "", countDelta:"", addedSize: "", removedSize: "", sizeDelta: ""};
+ },
+
+ _enhanceData: function(data)
+ {
+ var name = this._referenceName;
+ if (name === "") name = "(empty)";
+ var nameClass = "name";
+ switch (this._referenceType) {
+ case "context":
+ nameClass = "console-formatted-number";
+ break;
+ case "internal":
+ case "hidden":
+ nameClass = "console-formatted-null";
+ break;
+ }
+ data["object"].nameClass = nameClass;
+ data["object"].name = name;
+ return data;
+ },
+
+ _prefixObjectCell: function(div, data)
+ {
+ var nameSpan = document.createElement("span");
+ nameSpan.className = data.nameClass;
+ nameSpan.textContent = data.name;
+ var separatorSpan = document.createElement("span");
+ separatorSpan.className = "separator";
+ separatorSpan.textContent = ": ";
+ div.appendChild(nameSpan);
+ div.appendChild(separatorSpan);
+ }
+}
+
+WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node)
+{
+ var provider = this._createProvider(baseSnapshot || snapshot, node.rawEdges);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 100);
+ this._isDeletedNode = !!baseSnapshot;
+ this._provider = provider;
+};
+
+WebInspector.HeapSnapshotInstanceNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, rawEdges)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotEdgesProvider(
+ snapshot,
+ rawEdges,
+ function(edge) {
+ return !edge.isInvisible
+ && (showHiddenData || (!edge.isHidden && !edge.node.isHidden));
+ });
+ },
+
+ _childHashForEntity: function(edge)
+ {
+ return edge.type + "#" + edge.name;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode._referenceType + "#" + childNode._referenceName;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["!edgeName", sortAscending, "retainedSize", false],
+ count: ["!edgeName", true, "retainedSize", false],
+ addedSize: ["selfSize", sortAscending, "!edgeName", true],
+ removedSize: ["selfSize", sortAscending, "!edgeName", true],
+ shallowSize: ["selfSize", sortAscending, "!edgeName", true],
+ retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
+ }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {count:"", countDelta:"", sizeDelta: ""};
+ },
+
+ _enhanceData: function(data)
+ {
+ if (this._isDeletedNode) {
+ data["addedCount"] = "";
+ data["addedSize"] = "";
+ data["removedCount"] = "\u2022";
+ data["removedSize"] = Number.bytesToString(this._shallowSize);
+ } else {
+ data["addedCount"] = "\u2022";
+ data["addedSize"] = Number.bytesToString(this._shallowSize);
+ data["removedCount"] = "";
+ data["removedSize"] = "";
+ }
+ return data;
+ }
+}
+
+WebInspector.HeapSnapshotInstanceNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+WebInspector.HeapSnapshotConstructorNode = function(tree, constructor, aggregate)
+{
+ WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0, 100);
+ this._name = constructor;
+ this._count = aggregate.count;
+ this._shallowSize = aggregate.self;
+ this._retainedSize = aggregate.maxRet;
+ this._provider = this._createNodesProvider(tree.snapshot, aggregate.type, aggregate.name);
+}
+
+WebInspector.HeapSnapshotConstructorNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, provider.item);
+ },
+
+ _createNodesProvider: function(snapshot, nodeType, nodeName)
+ {
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ return node.type === nodeType
+ && (nodeName === null || node.name === nodeName);
+ });
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "retainedSize", false],
+ count: ["id", true, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "id", true],
+ retainedSize: ["retainedSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _childHashForEntity: function(node)
+ {
+ return node.id;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode.snapshotNodeId;
+ },
+
+ get data()
+ {
+ var data = {object: this._name, count: this._count};
+ var view = this.dataGrid.snapshotView;
+ data["count"] = view.showCountAsPercent ? WebInspector.UIString("%.2f%%", this._countPercent) : this._count;
+ data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
+ data["retainedSize"] = "> " + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize));
+ return data;
+ },
+
+ get _countPercent()
+ {
+ return this._count / this.dataGrid.snapshot.nodesCount * 100.0;
+ },
+
+ get _retainedSizePercent()
+ {
+ return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
+ },
+
+ get _shallowSizePercent()
+ {
+ return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
+ }
+};
+
+WebInspector.HeapSnapshotConstructorNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2)
+{
+ this._it1 = it1;
+ this._it2 = it2;
+}
+
+WebInspector.HeapSnapshotIteratorsTuple.prototype = {
+ first: function()
+ {
+ this._it1.first();
+ this._it2.first();
+ },
+
+ resetInstancesCount: function()
+ {
+ this._it1.resetInstancesCount();
+ this._it2.resetInstancesCount();
+ },
+
+ sort: function(comparator)
+ {
+ this._it1.sort(comparator);
+ this._it2.sort(comparator);
+ }
+};
+
+WebInspector.HeapSnapshotDiffNode = function(tree, constructor, baseAggregate, aggregate)
+{
+ if (!baseAggregate)
+ baseAggregate = { count: 0, self: 0, maxRet: 0, type:aggregate.type, name:aggregate.name, idxs: [] };
+ if (!aggregate)
+ aggregate = { count: 0, self: 0, maxRet: 0, type:baseAggregate.type, name:baseAggregate.name, idxs: [] };
+ WebInspector.HeapSnapshotGridNode.call(this, tree, true, 50);
+ this._name = constructor;
+ this._calculateDiff(tree.baseSnapshot, tree.snapshot, baseAggregate.idxs, aggregate.idxs);
+ this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate.type, aggregate.name);
+}
+
+WebInspector.HeapSnapshotDiffNode.prototype = {
+ _calculateDiff: function(baseSnapshot, snapshot, baseIndexes, currentIndexes)
+ {
+ var i = 0, l = baseIndexes.length;
+ var j = 0, m = currentIndexes.length;
+ this._addedCount = 0;
+ this._removedCount = 0;
+ this._addedSize = 0;
+ this._removedSize = 0;
+ var nodeA = new WebInspector.HeapSnapshotNode(baseSnapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(snapshot);
+ nodeA.nodeIndex = baseIndexes[i];
+ nodeB.nodeIndex = currentIndexes[j];
+ while (i < l && j < m) {
+ if (nodeA.id < nodeB.id) {
+ this._removedCount++;
+ this._removedSize += nodeA.selfSize;
+ nodeA.nodeIndex = baseIndexes[++i];
+ } else if (nodeA.id > nodeB.id) {
+ this._addedCount++;
+ this._addedSize += nodeB.selfSize;
+ nodeB.nodeIndex = currentIndexes[++j];
+ } else {
+ nodeA.nodeIndex = baseIndexes[++i];
+ nodeB.nodeIndex = currentIndexes[++j];
+ }
+ }
+ while (i < l) {
+ this._removedCount++;
+ this._removedSize += nodeA.selfSize;
+ nodeA.nodeIndex = baseIndexes[++i];
+ }
+ while (j < m) {
+ this._addedCount++;
+ this._addedSize += nodeB.selfSize;
+ nodeB.nodeIndex = currentIndexes[++j];
+ }
+ this._countDelta = this._addedCount - this._removedCount;
+ this._sizeDelta = this._addedSize - this._removedSize;
+ },
+
+ _createChildNode: function(provider)
+ {
+ if (provider === this._provider._it1)
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, provider.item);
+ else
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, provider.item);
+ },
+
+ _createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeName)
+ {
+ return new WebInspector.HeapSnapshotIteratorsTuple(
+ createProvider(snapshot, baseSnapshot), createProvider(baseSnapshot, snapshot));
+
+ function createProvider(snapshot, otherSnapshot)
+ {
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ return node.type === nodeType
+ && (nodeName === null || node.name === nodeName)
+ && !(node.id in otherSnapshot.idsMap);
+ });
+ }
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "selfSize", false],
+ addedCount: ["selfSize", sortAscending, "id", true],
+ removedCount: ["selfSize", sortAscending, "id", true],
+ countDelta: ["selfSize", sortAscending, "id", true],
+ addedSize: ["selfSize", sortAscending, "id", true],
+ removedSize: ["selfSize", sortAscending, "id", true],
+ sizeDelta: ["selfSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ populateChildren: function(provider, howMany, atIndex)
+ {
+ if (!provider && !howMany) {
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount);
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount);
+ } else if (!howMany) {
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1);
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2);
+ } else
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex);
+ },
+
+ _signForDelta: function(delta)
+ {
+ if (delta === 0)
+ return "";
+ if (delta > 0)
+ return "+";
+ else
+ return "\u2212"; // Math minus sign, same width as plus.
+ },
+
+ get data()
+ {
+ var data = {object: this._name};
+
+ data["addedCount"] = this._addedCount;
+ data["removedCount"] = this._removedCount;
+ data["countDelta"] = WebInspector.UIString("%s%d", this._signForDelta(this._countDelta), Math.abs(this._countDelta));
+ data["addedSize"] = Number.bytesToString(this._addedSize);
+ data["removedSize"] = Number.bytesToString(this._removedSize);
+ data["sizeDelta"] = WebInspector.UIString("%s%s", this._signForDelta(this._sizeDelta), Number.bytesToString(Math.abs(this._sizeDelta)));
+
+ return data;
+ },
+
+ get zeroDiff()
+ {
+ return this._addedCount === 0 && this._removedCount === 0;
+ }
+};
+
+WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node)
+{
+ var provider = this._createProvider(tree.snapshot, node.nodeIndex);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 25);
+ this._provider = provider;
+};
+
+WebInspector.HeapSnapshotDominatorObjectNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, nodeIndex)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ var dominatorIndex = node.dominatorIndex();
+ return dominatorIndex === nodeIndex
+ && dominatorIndex !== node.nodeIndex
+ && (showHiddenData || !node.isHidden);
+ });
+ },
+
+ _childHashForEntity: function(node)
+ {
+ return node.id;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode.snapshotNodeId;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "id", true],
+ retainedSize: ["retainedSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {};
+ }
+};
+
+WebInspector.HeapSnapshotDominatorObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+function MixInSnapshotNodeFunctions(sourcePrototype, targetPrototype)
+{
+ targetPrototype._childHashForEntity = sourcePrototype._childHashForEntity;
+ targetPrototype._childHashForNode = sourcePrototype._childHashForNode;
+ targetPrototype.comparator = sourcePrototype.comparator;
+ targetPrototype._createChildNode = sourcePrototype._createChildNode;
+ targetPrototype._createProvider = sourcePrototype._createProvider;
+ targetPrototype.populateChildren = sourcePrototype.populateChildren;
+ targetPrototype._saveChildren = sourcePrototype._saveChildren;
+ targetPrototype.sort = sourcePrototype.sort;
+}
diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
index 5291bf2..ffce1dd 100644
--- a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
+++ b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
@@ -28,30 +28,879 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+WebInspector.HeapSnapshotContainmentDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true, sort: "ascending" },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sortable: true }
+ };
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sort, this);
+ this._defaultPopulateCount = 100;
+}
+
+WebInspector.HeapSnapshotContainmentDataGrid.prototype = {
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.snapshotNodeIndex = this.snapshot._rootNodeIndex;
+ this._provider = this._createProvider(snapshot, snapshot.rootNode.rawEdges);
+ this.sort();
+ }
+};
+
+MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotObjectNode.prototype, WebInspector.HeapSnapshotContainmentDataGrid.prototype);
+WebInspector.HeapSnapshotContainmentDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotSortableDataGrid = function(columns)
+{
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sortingChanged, this);
+}
+
+WebInspector.HeapSnapshotSortableDataGrid.prototype = {
+ sortingChanged: function()
+ {
+ var sortAscending = this.sortOrder === "ascending";
+ var sortColumnIdentifier = this.sortColumnIdentifier;
+ var sortFields = this._sortFields(sortColumnIdentifier, sortAscending);
+
+ function SortByTwoFields(nodeA, nodeB)
+ {
+ var field1 = nodeA[sortFields[0]];
+ var field2 = nodeB[sortFields[0]];
+ var result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
+ if (!sortFields[1])
+ result = -result;
+ if (result !== 0)
+ return result;
+ field1 = nodeA[sortFields[2]];
+ field2 = nodeB[sortFields[2]];
+ result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
+ if (!sortFields[3])
+ result = -result;
+ return result;
+ }
+
+ this._performSorting(SortByTwoFields);
+ },
+
+ _performSorting: function(sortFunction)
+ {
+ var children = this.children;
+ this.removeChildren();
+ children.sort(sortFunction);
+ for (var i = 0, l = children.length; i < l; ++i) {
+ var child = children[i];
+ this.appendChild(child);
+ if (child.expanded)
+ child.sort();
+ }
+ }
+};
+
+WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotConstructorsDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+ count: { title: WebInspector.UIString("#"), width: "45px", sortable: true },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotConstructorsDataGrid.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ object: ["_name", sortAscending, "_count", false],
+ count: ["_count", sortAscending, "_name", true],
+ shallowSize: ["_shallowSize", sortAscending, "_name", true],
+ retainedSize: ["_retainedSize", sortAscending, "_name", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.populateChildren();
+ this.sortingChanged();
+ },
+
+ populateChildren: function()
+ {
+ var aggregates = this.snapshot.aggregates();
+ for (var constructor in aggregates)
+ this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor]));
+ }
+};
+
+WebInspector.HeapSnapshotConstructorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
+WebInspector.HeapSnapshotDiffDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+ // \xb1 is a "plus-minus" sign.
+ addedCount: { title: WebInspector.UIString("# New"), width: "72px", sortable: true, sort: "descending" },
+ removedCount: { title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true },
+ // \u0394 is a Greek delta letter.
+ countDelta: { title: "\u0394", width: "40px", sortable: true },
+ addedSize: { title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true },
+ removedSize: { title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true },
+ sizeDelta: { title: "\u0394", width: "72px", sortable: true }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotDiffDataGrid.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ object: ["_name", sortAscending, "_count", false],
+ addedCount: ["_addedCount", sortAscending, "_name", true],
+ removedCount: ["_removedCount", sortAscending, "_name", true],
+ countDelta: ["_countDelta", sortAscending, "_name", true],
+ addedSize: ["_addedSize", sortAscending, "_name", true],
+ removedSize: ["_removedSize", sortAscending, "_name", true],
+ sizeDelta: ["_sizeDelta", sortAscending, "_name", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ },
+
+ setBaseDataSource: function(baseSnapshot)
+ {
+ this.baseSnapshot = baseSnapshot;
+ this.removeChildren();
+ if (this.baseSnapshot !== this.snapshot) {
+ this.populateChildren();
+ this.sortingChanged();
+ }
+ },
+
+ populateChildren: function()
+ {
+ var baseClasses = this.baseSnapshot.aggregates(true);
+ var classes = this.snapshot.aggregates(true);
+ for (var clss in baseClasses) {
+ var node = new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]);
+ if (!node.zeroDiff)
+ this.appendChild(node);
+ }
+ for (clss in classes) {
+ if (!(clss in baseClasses)) {
+ var node = new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]);
+ if (!node.zeroDiff)
+ this.appendChild(node);
+ }
+ }
+ }
+};
+
+WebInspector.HeapSnapshotDiffDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
+WebInspector.HeapSnapshotDominatorsDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
+ };
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sort, this);
+ this._defaultPopulateCount = 25;
+}
+
+WebInspector.HeapSnapshotDominatorsDataGrid.prototype = {
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.snapshotNodeIndex = this.snapshot._rootNodeIndex;
+ this._provider = this._createProvider(snapshot, this.snapshotNodeIndex);
+ this.sort();
+ }
+};
+
+MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotDominatorObjectNode.prototype, WebInspector.HeapSnapshotDominatorsDataGrid.prototype);
+WebInspector.HeapSnapshotDominatorsDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotRetainingPathsList = function()
+{
+ var columns = {
+ path: { title: WebInspector.UIString("Retaining path"), sortable: true },
+ len: { title: WebInspector.UIString("Length"), width: "90px", sortable: true, sort: "ascending" }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotRetainingPathsList.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ path: ["path", sortAscending, "len", true],
+ len: ["len", sortAscending, "path", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot, nodeIndex, prefix)
+ {
+ this.snapshotView = snapshotView;
+ this._prefix = prefix;
+
+ if (this.pathFinder)
+ this.searchCancelled();
+
+ this.pathFinder = new WebInspector.HeapSnapshotPathFinder(snapshot, nodeIndex);
+
+ this.removeChildren();
+
+ this._counter = 0;
+ this.showNext(10);
+ },
+
+ showNext: function(pathsCount)
+ {
+ WebInspector.PleaseWaitMessage.prototype.show(this.element, this.searchCancelled.bind(this, pathsCount));
+ window.setTimeout(startSearching.bind(this), 500);
+
+ function startSearching()
+ {
+ if (this._cancel !== this.pathFinder) {
+ if (this._counter < pathsCount) {
+ var result = this.pathFinder.findNext();
+ if (result === null) {
+ WebInspector.PleaseWaitMessage.prototype.hide();
+ if (!this.children.length)
+ this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("This object is either only accessible via hidden properties, or current path search depth isn't enough."), len:""}, false));
+ return;
+ } else if (result !== false) {
+ if (this._prefix)
+ result.path = this._prefix + result.path;
+ this.appendChild(new WebInspector.DataGridNode(result, false));
+ ++this._counter;
+ }
+ window.setTimeout(startSearching.bind(this), 0);
+ return;
+ } else
+ this.searchCancelled.call(this, pathsCount);
+ }
+ this._cancel = false;
+ }
+ },
+
+ searchCancelled: function(pathsCount)
+ {
+ WebInspector.PleaseWaitMessage.prototype.hide();
+ this._counter = 0;
+ this._cancel = this.pathFinder;
+ if (pathsCount) {
+ this.appendChild(new WebInspector.ShowMoreDataGridNode(this.showNext.bind(this), pathsCount));
+ this.sortingChanged();
+ }
+ },
+
+ _performSorting: function(sortFunction)
+ {
+ function DataExtractorWrapper(nodeA, nodeB)
+ {
+ return sortFunction(nodeA.data, nodeB.data);
+ }
+
+ this.sortNodes(DataExtractorWrapper);
+ }
+};
+
+WebInspector.HeapSnapshotRetainingPathsList.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
WebInspector.DetailedHeapshotView = function(parent, profile)
{
WebInspector.View.call(this);
- this.element.addStyleClass("heap-snapshot-view");
+ this.element.addStyleClass("detailed-heapshot-view");
this.parent = parent;
- this.profile = profile;
+ this.parent.addEventListener("profile added", this._updateBaseOptions, this);
+
+ this.showCountAsPercent = false;
+ this.showShallowSizeAsPercent = false;
+ this.showRetainedSizeAsPercent = false;
+
+ this.containmentView = new WebInspector.View();
+ this.containmentView.element.addStyleClass("view");
+ this.containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid();
+ this.containmentDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.containmentDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.containmentView.element.appendChild(this.containmentDataGrid.element);
+ this.element.appendChild(this.containmentView.element);
+
+ this.constructorsView = new WebInspector.View();
+ this.constructorsView.element.addStyleClass("view");
+ this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
+ this.constructorsDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.constructorsDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.constructorsView.element.appendChild(this.constructorsDataGrid.element);
+ this.element.appendChild(this.constructorsView.element);
+
+ this.diffView = new WebInspector.View();
+ this.diffView.element.addStyleClass("view");
+ this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
+ this.diffDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.diffDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.diffView.element.appendChild(this.diffDataGrid.element);
+ this.element.appendChild(this.diffView.element);
+
+ this.dominatorView = new WebInspector.View();
+ this.dominatorView.element.addStyleClass("view");
+ this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
+ this.dominatorDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.dominatorDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.dominatorView.element.appendChild(this.dominatorDataGrid.element);
+ this.element.appendChild(this.dominatorView.element);
+
+ var retainmentView = new WebInspector.View();
+ retainmentView.element.addStyleClass("view retaining-paths-view");
+ var retainingPathsTitleDiv = document.createElement("div");
+ retainingPathsTitleDiv.className = "title";
+ var retainingPathsTitle = document.createElement("span");
+ retainingPathsTitle.textContent = WebInspector.UIString("Retaining paths of the selected object");
+ retainingPathsTitleDiv.appendChild(retainingPathsTitle);
+ retainmentView.element.appendChild(retainingPathsTitleDiv);
+ this.retainmentDataGrid = new WebInspector.HeapSnapshotRetainingPathsList();
+ retainmentView.element.appendChild(this.retainmentDataGrid.element);
+ retainmentView.visible = true;
+ this.element.appendChild(retainmentView.element);
+
+ this.dataGrid = this.constructorsDataGrid;
+ this.currentView = this.constructorsView;
+
+ this.viewSelectElement = document.createElement("select");
+ this.viewSelectElement.className = "status-bar-item";
+ this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
+
+ var classesViewOption = document.createElement("option");
+ classesViewOption.label = WebInspector.UIString("Summary");
+ var diffViewOption = document.createElement("option");
+ diffViewOption.label = WebInspector.UIString("Comparison");
+ var containmentViewOption = document.createElement("option");
+ containmentViewOption.label = WebInspector.UIString("Containment");
+ var dominatorsViewOption = document.createElement("option");
+ dominatorsViewOption.label = WebInspector.UIString("Dominators");
+ this.viewSelectElement.appendChild(classesViewOption);
+ this.viewSelectElement.appendChild(diffViewOption);
+ this.viewSelectElement.appendChild(containmentViewOption);
+ this.viewSelectElement.appendChild(dominatorsViewOption);
+ this.views = ["Summary", "Comparison", "Containment", "Dominators"];
+ this.views.current = 0;
+
+ this._profileUid = profile.uid;
+
+ this.baseSelectElement = document.createElement("select");
+ this.baseSelectElement.className = "status-bar-item hidden";
+ this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
+ this._updateBaseOptions();
+
+ this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
+ this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+ this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item");
+ this.helpButton.addEventListener("click", this._helpClicked.bind(this), false);
+
+ this._loadProfile(this._profileUid, profileCallback.bind(this));
+
+ function profileCallback(profile)
+ {
+ var list = this._profiles();
+ var profileIndex;
+ for (var i = 0; i < list.length; ++i)
+ if (list[i].uid === profile.uid) {
+ profileIndex = i;
+ break;
+ }
+ if (profileIndex > 0)
+ this.baseSelectElement.selectedIndex = profileIndex - 1;
+ else
+ this.baseSelectElement.selectedIndex = profileIndex;
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ this._updatePercentButton();
+ }
}
WebInspector.DetailedHeapshotView.prototype = {
+ dispose: function()
+ {
+ if (this._profileWrapper)
+ this._profileWrapper.dispose();
+ if (this._baseProfileWrapper)
+ this._baseProfileWrapper.dispose();
+ },
+
+ get statusBarItems()
+ {
+ return [this.viewSelectElement, this.baseSelectElement, this.percentButton.element, this.helpButton.element];
+ },
+
get profile()
{
- return this._profile;
+ return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._profileUid);
},
- set profile(profile)
+ get profileWrapper()
{
- this._profile = profile;
+ if (!this._profileWrapper)
+ this._profileWrapper = new WebInspector.HeapSnapshot(this.profile);
+ return this._profileWrapper;
+ },
+
+ get baseProfile()
+ {
+ return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._baseProfileUid);
+ },
+
+ get baseProfileWrapper()
+ {
+ if (!this._baseProfileWrapper) {
+ if (this.baseProfile !== this.profile)
+ this._baseProfileWrapper = new WebInspector.HeapSnapshot(this.baseProfile);
+ else
+ this._baseProfileWrapper = this.profileWrapper;
+ }
+ return this._baseProfileWrapper;
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ if (!this.profile._loaded)
+ this._loadProfile(this._profileUid, profileCallback1.bind(this));
+ else
+ profileCallback1.call(this, this.profile);
+
+ function profileCallback1(profile) {
+ this.profileWrapper.restore(profile);
+ if (this.baseProfile && !this.baseProfile._loaded)
+ this._loadProfile(this._baseProfileUid, profileCallback2.bind(this));
+ else
+ profileCallback2.call(this, this.baseProfile);
+ }
+
+ function profileCallback2(profile) {
+ if (profile)
+ this.baseProfileWrapper.restore(profile);
+ this.currentView.show();
+ this.dataGrid.updateWidths();
+ }
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ resize: function()
+ {
+ if (this.dataGrid)
+ this.dataGrid.updateWidths();
+ },
+
+ refreshShowAsPercents: function()
+ {
+ this._updatePercentButton();
+ this.refreshVisibleData();
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var node = this._searchResults[i].node;
+ delete node._searchMatched;
+ node.refresh();
+ }
+ }
+
+ delete this._searchFinishedCallback;
+ this._currentSearchResultIndex = -1;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query, finishedCallback)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ query = query.trim();
+
+ if (!query.length)
+ return;
+ if (this.currentView !== this.constructorsView && this.currentView !== this.diffView)
+ return;
+
+ this._searchFinishedCallback = finishedCallback;
+
+ function matchesByName(gridNode) {
+ return ("name" in gridNode) && gridNode.name.hasSubstring(query, true);
+ }
+
+ function matchesById(gridNode) {
+ return ("snapshotNodeId" in gridNode) && gridNode.snapshotNodeId === query;
+ }
+
+ var matchPredicate;
+ if (query.charAt(0) !== "@")
+ matchPredicate = matchesByName;
+ else {
+ query = parseInt(query.substring(1), 10);
+ matchPredicate = matchesById;
+ }
+
+ function matchesQuery(gridNode)
+ {
+ delete gridNode._searchMatched;
+ if (matchPredicate(gridNode)) {
+ gridNode._searchMatched = true;
+ gridNode.refresh();
+ return true;
+ }
+ return false;
+ }
+
+ var current = this.dataGrid.children[0];
+ var depth = 0;
+ var info = {};
+
+ // Restrict to type nodes and instances.
+ const maxDepth = 1;
+
+ while (current) {
+ if (matchesQuery(current))
+ this._searchResults.push({ node: current });
+ current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+
+ finishedCallback(this, this._searchResults.length);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var searchResult = this._searchResults[index];
+ if (!searchResult)
+ return;
+
+ var node = searchResult.node;
+ node.reveal();
+ node.select();
+ },
+
+ refreshVisibleData: function()
+ {
+ var child = this.dataGrid.children[0];
+ while (child) {
+ child.refresh();
+ child = child.traverseNextNode(false, null, true);
+ }
+ },
+
+ _changeBase: function()
+ {
+ if (this._baseProfileUid === this._profiles()[this.baseSelectElement.selectedIndex].uid)
+ return;
+
+ this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid;
+ this._loadProfile(this._baseProfileUid, baseProfileLoaded.bind(this));
+
+ function baseProfileLoaded(profile)
+ {
+ delete this._baseProfileWrapper;
+ this.baseProfile._lastShown = Date.now();
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.currentView.element, showDiffData.bind(this));
+ }
+
+ function showDiffData()
+ {
+ this.diffDataGrid.setBaseDataSource(this.baseProfileWrapper);
+ }
+
+ if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+ return;
+
+ // The current search needs to be performed again. First negate out previous match
+ // count by calling the search finished callback with a negative number of matches.
+ // Then perform the search again with the same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ _profiles: function()
+ {
+ return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+ },
+
+ _loadProfile: function(profileUid, callback)
+ {
+ WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback);
+ },
+
+ isDetailedSnapshot: function(snapshot)
+ {
+ var s = new WebInspector.HeapSnapshot(snapshot);
+ for (var iter = s.rootNode.edges; iter.hasNext(); iter.next())
+ if (iter.edge.node.name === "(GC roots)")
+ return true;
+ return false;
+ },
+
+ processLoadedSnapshot: function(profile, snapshot)
+ {
+ profile.nodes = snapshot.nodes;
+ profile.strings = snapshot.strings;
+ var s = new WebInspector.HeapSnapshot(profile);
+ profile.sideBarElement.subtitle = Number.bytesToString(s.totalSize);
+ },
+
+ _dblClickInContainmentGrid: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || (!cell.hasStyleClass("retainedSize-column")))
+ return;
+ var nodeItem = event.target.enclosingNodeOrSelfWithNodeName("tr")._dataGridNode;
+ ProfilerAgent.getExactHeapSnapshotNodeRetainedSize(this._profileUid, nodeItem.snapshotNodeId, setExactRetainedSize);
+
+ function setExactRetainedSize(exactSize) {
+ if (exactSize && exactSize != -1)
+ nodeItem.exactRetainedSize = exactSize;
+ }
+ },
+
+ _mouseClickInContainmentGrid: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || !(cell.hasStyleClass("object-column") || cell.hasStyleClass("shallowSize-column")))
+ return;
+ var row = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ if (!row)
+ return;
+ var nodeItem = row._dataGridNode;
+ if (!nodeItem || nodeItem.isEventWithinDisclosureTriangle(event) || !nodeItem.snapshotNodeIndex)
+ return;
+
+ this.retainmentDataGrid.setDataSource(this, nodeItem.isDeletedNode ? nodeItem.dataGrid.baseSnapshot : nodeItem.dataGrid.snapshot, nodeItem.snapshotNodeIndex, nodeItem.isDeletedNode ? this.baseSelectElement.childNodes[this.baseSelectElement.selectedIndex].label + " | " : "");
+ },
+
+ _changeView: function(event)
+ {
+ if (!event || !this._profileUid)
+ return;
+ if (event.target.selectedIndex === this.views.current)
+ return;
+
+ this.views.current = event.target.selectedIndex;
+ this.currentView.hide();
+ if (this.views[this.views.current] === "Containment") {
+ this.currentView = this.containmentView;
+ this.dataGrid = this.containmentDataGrid;
+ } else if (this.views[this.views.current] === "Summary") {
+ this.currentView = this.constructorsView;
+ this.dataGrid = this.constructorsDataGrid;
+ } else if (this.views[this.views.current] === "Comparison") {
+ this.currentView = this.diffView;
+ this.dataGrid = this.diffDataGrid;
+ } else if (this.views[this.views.current] === "Dominators") {
+ this.currentView = this.dominatorView;
+ this.dataGrid = this.dominatorDataGrid;
+ }
+ this.currentView.show();
+ this.refreshVisibleData();
+ if (this.currentView === this.diffView) {
+ this.baseSelectElement.removeStyleClass("hidden");
+ if (!this.dataGrid.snapshotView) {
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ this._changeBase();
+ }
+ } else {
+ this.baseSelectElement.addStyleClass("hidden");
+ if (!this.dataGrid.snapshotView)
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.currentView.element, loadData.bind(this));
+ }
+
+ function loadData()
+ {
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ }
+
+ if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+ return;
+
+ // The current search needs to be performed again. First negate out previous match
+ // count by calling the search finished callback with a negative number of matches.
+ // Then perform the search again the with same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ get _isShowingAsPercent()
+ {
+ return this.showCountAsPercent && this.showShallowSizeAsPercent && this.showRetainedSizeAsPercent;
+ },
+
+ _percentClicked: function(event)
+ {
+ var currentState = this._isShowingAsPercent;
+ this.showCountAsPercent = !currentState;
+ this.showShallowSizeAsPercent = !currentState;
+ this.showRetainedSizeAsPercent = !currentState;
+ this.refreshShowAsPercents();
+ },
+
+ _helpClicked: function(event)
+ {
+ if (!this.helpPopover) {
+ var refTypes = ["a:", "console-formatted-name", WebInspector.UIString("property"),
+ "0:", "console-formatted-name", WebInspector.UIString("element"),
+ "a:", "console-formatted-number", WebInspector.UIString("context var"),
+ "a:", "console-formatted-null", WebInspector.UIString("system prop")];
+ var objTypes = [" a ", "console-formatted-object", "Object",
+ "\"a\"", "console-formatted-string", "String",
+ "/a/", "console-formatted-string", "RegExp",
+ "a()", "console-formatted-function", "Function",
+ "a[]", "console-formatted-object", "Array",
+ "num", "console-formatted-number", "Number",
+ " a ", "console-formatted-null", "System"];
+
+ var contentElement = document.createElement("table");
+ contentElement.className = "heapshot-help";
+ var headerRow = document.createElement("tr");
+ var propsHeader = document.createElement("th");
+ propsHeader.textContent = WebInspector.UIString("Property types:");
+ headerRow.appendChild(propsHeader);
+ var objsHeader = document.createElement("th");
+ objsHeader.textContent = WebInspector.UIString("Object types:");
+ headerRow.appendChild(objsHeader);
+ contentElement.appendChild(headerRow);
+ var len = Math.max(refTypes.length, objTypes.length);
+ for (var i = 0; i < len; i += 3) {
+ var row = document.createElement("tr");
+ var refCell = document.createElement("td");
+ if (refTypes[i])
+ appendHelp(refTypes, i, refCell);
+ row.appendChild(refCell);
+ var objCell = document.createElement("td");
+ if (objTypes[i])
+ appendHelp(objTypes, i, objCell);
+ row.appendChild(objCell);
+ contentElement.appendChild(row);
+ }
+ this.helpPopover = new WebInspector.Popover(contentElement);
+
+ function appendHelp(help, index, cell)
+ {
+ var div = document.createElement("div");
+ div.className = "source-code event-properties";
+ var name = document.createElement("span");
+ name.textContent = help[index];
+ name.className = help[index + 1];
+ div.appendChild(name);
+ var desc = document.createElement("span");
+ desc.textContent = " " + help[index + 2];
+ div.appendChild(desc);
+ cell.appendChild(div);
+ }
+ }
+ if (this.helpPopover.visible)
+ this.helpPopover.hide();
+ else
+ this.helpPopover.show(this.helpButton.element);
+ },
+
+ _updateBaseOptions: function()
+ {
+ var list = this._profiles();
+ // We're assuming that snapshots can only be added.
+ if (this.baseSelectElement.length === list.length)
+ return;
+
+ for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
+ var baseOption = document.createElement("option");
+ var title = list[i].title;
+ if (!title.indexOf(UserInitiatedProfileName))
+ title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
+ baseOption.label = title;
+ this.baseSelectElement.appendChild(baseOption);
+ }
+ },
+
+ _updatePercentButton: function()
+ {
+ if (this._isShowingAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
+ this.percentButton.toggled = true;
+ } else {
+ this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
+ this.percentButton.toggled = false;
+ }
}
};
WebInspector.DetailedHeapshotView.prototype.__proto__ = WebInspector.View.prototype;
+WebInspector.DetailedHeapshotView.prototype.showHiddenData = true;
+
WebInspector.DetailedHeapshotProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
diff --git a/Source/WebCore/inspector/front-end/ElementsPanel.js b/Source/WebCore/inspector/front-end/ElementsPanel.js
index e6af93c..246abe8 100644
--- a/Source/WebCore/inspector/front-end/ElementsPanel.js
+++ b/Source/WebCore/inspector/front-end/ElementsPanel.js
@@ -57,7 +57,7 @@ WebInspector.ElementsPanel = function()
this.panel.updateEventListeners();
if (this._focusedDOMNode) {
- InspectorBackend.addInspectedNode(this._focusedDOMNode.id);
+ DOMAgent.addInspectedNode(this._focusedDOMNode.id);
WebInspector.extensionServer.notifyObjectSelected(this.panel.name);
}
};
@@ -141,6 +141,9 @@ WebInspector.ElementsPanel.prototype = {
this.treeOutline.updateSelection();
if (this.recentlyModifiedNodes.length)
this.updateModifiedNodes();
+
+ if (!this.rootDOMNode)
+ WebInspector.domAgent.requestDocument();
},
hide: function()
@@ -211,7 +214,7 @@ WebInspector.ElementsPanel.prototype = {
}
if (this._selectedPathOnReset)
- InspectorBackend.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
+ WebInspector.domAgent.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
else
selectNode.call(this);
delete this._selectedPathOnReset;
@@ -222,11 +225,11 @@ WebInspector.ElementsPanel.prototype = {
delete this._searchQuery;
this._hideSearchHighlights();
- WebInspector.updateSearchMatchesCount(0, this);
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
- this._currentSearchResultIndex = 0;
+ delete this._currentSearchResultIndex;
this._searchResults = [];
- InspectorBackend.searchCanceled();
+ DOMAgent.searchCanceled();
},
performSearch: function(query)
@@ -242,7 +245,7 @@ WebInspector.ElementsPanel.prototype = {
this._matchesCountUpdateTimeout = null;
this._searchQuery = query;
- InspectorBackend.performSearch(whitespaceTrimmedQuery, false);
+ DOMAgent.performSearch(whitespaceTrimmedQuery, false);
},
populateHrefContextMenu: function(contextMenu, event, anchorElement)
@@ -264,14 +267,14 @@ WebInspector.ElementsPanel.prototype = {
switchToAndFocus: function(node)
{
// Reset search restore.
- WebInspector.cancelSearch();
+ WebInspector.searchController.cancelSearch();
WebInspector.currentPanel = this;
this.focusedDOMNode = node;
},
_updateMatchesCount: function()
{
- WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+ WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this);
this._matchesCountUpdateTimeout = null;
this._updatedMatchCountOnce = true;
},
@@ -291,6 +294,7 @@ WebInspector.ElementsPanel.prototype = {
if (!nodeIds.length)
return;
+ var oldSearchResultIndex = this._currentSearchResultIndex;
for (var i = 0; i < nodeIds.length; ++i) {
var nodeId = nodeIds[i];
var node = WebInspector.domAgent.nodeForId(nodeId);
@@ -300,7 +304,10 @@ WebInspector.ElementsPanel.prototype = {
this._currentSearchResultIndex = 0;
this._searchResults.push(node);
}
- this._highlightCurrentSearchResult();
+
+ // Avoid invocations of highlighting for every chunk of nodeIds.
+ if (oldSearchResultIndex !== this._currentSearchResultIndex)
+ this._highlightCurrentSearchResult();
this._updateMatchesCountSoon();
},
@@ -375,6 +382,9 @@ WebInspector.ElementsPanel.prototype = {
this.recentlyModifiedNodes.push({node: event.target, updated: true});
if (this.visible)
this._updateModifiedNodesSoon();
+
+ if (!this.sidebarPanes.styles.isModifyingStyle && event.target === this.focusedDOMNode)
+ this._styleSheetChanged();
},
_characterDataModified: function(event)
@@ -1023,7 +1033,7 @@ WebInspector.ElementsPanel.prototype = {
return;
event.clipboardData.clearData();
event.preventDefault();
- InspectorBackend.copyNode(this.focusedDOMNode.id);
+ DOMAgent.copyNode(this.focusedDOMNode.id);
},
rightSidebarResizerDragStart: function(event)
@@ -1070,7 +1080,7 @@ WebInspector.ElementsPanel.prototype = {
setSearchingForNode: function(enabled)
{
- InspectorBackend.setSearchingForNode(enabled, this._setSearchingForNode.bind(this));
+ InspectorAgent.setSearchingForNode(enabled, this._setSearchingForNode.bind(this));
},
toggleSearchingForNode: function()
diff --git a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
index 56c3e75..7b5ff2f 100644
--- a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -329,8 +329,11 @@ WebInspector.ElementsTreeElement.prototype = {
if (this._searchQuery === searchQuery)
return;
+ if (searchQuery)
+ delete this._searchHighlightedHTML; // A new search query (not clear-the-current-highlighting).
+
this._searchQuery = searchQuery;
- this.updateTitle();
+ this.updateTitle(true);
},
get hovered()
@@ -400,17 +403,35 @@ WebInspector.ElementsTreeElement.prototype = {
if (!node.nodeName || node.nodeName.toLowerCase() !== "img")
return;
- function setTooltip(properties)
+ function setTooltip(result)
{
- if (!properties)
+ if (!result || result.type !== "string")
return;
- if (properties.offsetHeight === properties.naturalHeight && properties.offsetWidth === properties.naturalWidth)
- this.tooltip = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight);
- else
- this.tooltip = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight);
+ try {
+ var properties = JSON.parse(result.description);
+ var offsetWidth = properties[0];
+ var offsetHeight = properties[1];
+ var naturalWidth = properties[2];
+ var naturalHeight = properties[3];
+ if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
+ this.tooltip = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
+ else
+ this.tooltip = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ function resolvedNode(objectPayload)
+ {
+ if (!objectPayload)
+ return;
+
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.evaluate("return '[' + this.offsetWidth + ',' + this.offsetHeight + ',' + this.naturalWidth + ',' + this.naturalHeight + ']'", setTooltip.bind(this));
}
- InspectorBackend.getNodeProperties(node.id, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], setTooltip.bind(this));
+ DOMAgent.resolveNode(node.id, "", resolvedNode.bind(this));
},
updateSelection: function()
@@ -1154,7 +1175,7 @@ WebInspector.ElementsTreeElement.prototype = {
moveToNextAttributeIfNeeded.call(newTreeItem);
}
- InspectorBackend.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
+ DOMAgent.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
},
_textNodeEditingCommitted: function(element, newText)
@@ -1198,14 +1219,20 @@ WebInspector.ElementsTreeElement.prototype = {
return (tags.length === 1 ? null : tags[tags.length-1]);
},
- updateTitle: function()
+ updateTitle: function(onlySearchQueryChanged)
{
// If we are editing, return early to prevent canceling the edit.
// After editing is committed updateTitle will be called.
if (this._editing)
return;
- this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
+ if (onlySearchQueryChanged && this._normalHTML)
+ this.titleHTML = this._normalHTML;
+ else {
+ delete this._normalHTML;
+ this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
+ }
+
delete this.selectionElement;
this.updateSelection();
this._preventFollowingLinksOnDoubleClick();
@@ -1381,7 +1408,7 @@ WebInspector.ElementsTreeElement.prototype = {
parentElement.adjustCollapsedRange(true);
}
- InspectorBackend.removeNode(this.representedObject.id, removeNodeCallback);
+ DOMAgent.removeNode(this.representedObject.id, removeNodeCallback);
},
_editAsHTML: function()
@@ -1408,32 +1435,41 @@ WebInspector.ElementsTreeElement.prototype = {
function commitChange(value)
{
- InspectorBackend.setOuterHTML(node.id, value, selectNode);
+ DOMAgent.setOuterHTML(node.id, value, selectNode);
}
- InspectorBackend.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
+ DOMAgent.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
},
_copyHTML: function()
{
- InspectorBackend.copyNode(this.representedObject.id);
+ DOMAgent.copyNode(this.representedObject.id);
},
_highlightSearchResults: function()
{
if (!this._searchQuery)
return;
+ if (this._searchHighlightedHTML) {
+ this.listItemElement.innerHTML = this._searchHighlightedHTML;
+ return;
+ }
+
+ if (!this._normalHTML)
+ this._normalHTML = this.titleHTML;
+
var text = this.listItemElement.textContent;
- var regexObject = createSearchRegex(this._searchQuery);
+ var regexObject = createSearchRegex(this._searchQuery, "g");
var offset = 0;
var match = regexObject.exec(text);
+ var matchRanges = [];
while (match) {
- highlightSearchResult(this.listItemElement, offset + match.index, match[0].length);
- offset += match.index + 1;
- text = text.substring(match.index + 1);
+ matchRanges.push({ offset: match.index, length: match[0].length });
match = regexObject.exec(text);
}
+ highlightSearchResults(this.listItemElement, matchRanges);
+ this._searchHighlightedHTML = this.listItemElement.innerHTML;
}
}
diff --git a/Source/WebCore/inspector/front-end/ExtensionPanel.js b/Source/WebCore/inspector/front-end/ExtensionPanel.js
index 144d55d..142b8c1 100644
--- a/Source/WebCore/inspector/front-end/ExtensionPanel.js
+++ b/Source/WebCore/inspector/front-end/ExtensionPanel.js
@@ -95,7 +95,7 @@ WebInspector.ExtensionWatchSidebarPane.prototype = {
setExpression: function(expression, title)
{
- InspectorBackend.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title));
+ RuntimeAgent.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title));
},
_onEvaluate: function(title, result)
diff --git a/Source/WebCore/inspector/front-end/ExtensionServer.js b/Source/WebCore/inspector/front-end/ExtensionServer.js
index 7d33b73..f9af7dc 100644
--- a/Source/WebCore/inspector/front-end/ExtensionServer.js
+++ b/Source/WebCore/inspector/front-end/ExtensionServer.js
@@ -34,6 +34,8 @@ WebInspector.ExtensionServer = function()
this._handlers = {};
this._subscribers = {};
this._extraHeaders = {};
+ this._resources = {};
+ this._lastResourceId = 0;
this._status = new WebInspector.ExtensionStatus();
this._registerHandler("addRequestHeaders", this._onAddRequestHeaders.bind(this));
@@ -108,10 +110,15 @@ WebInspector.ExtensionServer.prototype = {
delete this._clientObjects[auditRun.id];
},
+ resetResources: function()
+ {
+ this._resources = {};
+ },
+
_notifyResourceFinished: function(event)
{
var resource = event.data;
- this._postNotification("resource-finished", resource.identifier, (new WebInspector.HAREntry(resource)).build());
+ this._postNotification("resource-finished", this._resourceId(resource), (new WebInspector.HAREntry(resource)).build());
},
_postNotification: function(type, details)
@@ -166,7 +173,7 @@ WebInspector.ExtensionServer.prototype = {
allHeaders[name] = headers[name];
}
}
- InspectorBackend.setExtraHeaders(allHeaders);
+ NetworkAgent.setExtraHeaders(allHeaders);
},
_onCreatePanel: function(message, port)
@@ -176,13 +183,12 @@ WebInspector.ExtensionServer.prototype = {
// shouldn't be hit unless someone is bypassing the API.
if (id in this._clientObjects || id in WebInspector.panels)
return this._status.E_EXISTS(id);
+
var panel = new WebInspector.ExtensionPanel(id, message.title, message.icon);
this._clientObjects[id] = panel;
-
- var toolbarElement = document.getElementById("toolbar");
- var lastToolbarItem = WebInspector.panelOrder[WebInspector.panelOrder.length - 1].toolbarItem;
- WebInspector.addPanelToolbarIcon(toolbarElement, panel, lastToolbarItem);
WebInspector.panels[id] = panel;
+ WebInspector.addPanel(panel);
+
var iframe = this._createClientIframe(panel.element, message.url);
iframe.style.height = "100%";
return this._status.OK();
@@ -255,9 +261,9 @@ WebInspector.ExtensionServer.prototype = {
_onReload: function(message)
{
if (typeof message.userAgent === "string")
- InspectorBackend.setUserAgentOverride(message.userAgent);
+ InspectorAgent.setUserAgentOverride(message.userAgent);
- InspectorBackend.reloadPage(false);
+ InspectorAgent.reloadPage(false);
return this._status.OK();
},
@@ -273,7 +279,7 @@ WebInspector.ExtensionServer.prototype = {
this._dispatchCallback(message.requestId, port, result);
}
var evalExpression = "JSON.stringify(eval(unescape('" + escape(message.expression) + "')));";
- InspectorBackend.evaluate(evalExpression, "none", true, callback.bind(this));
+ RuntimeAgent.evaluate(evalExpression, "", true, callback.bind(this));
},
_onRevealAndSelect: function(message)
@@ -289,7 +295,7 @@ WebInspector.ExtensionServer.prototype = {
var id = message.id;
var resource = null;
- resource = WebInspector.networkResourceById(id) || WebInspector.resourceForURL(id);
+ resource = this._resourceById(id) || WebInspector.resourceForURL(id);
if (!resource)
return this._status.E_NOTFOUND(typeof id + ": " + id);
@@ -304,9 +310,10 @@ WebInspector.ExtensionServer.prototype = {
_onGetHAR: function(request)
{
- var harLog = new WebInspector.HARLog();
- harLog.includeResourceIds = true;
- return harLog.build();
+ var harLog = (new WebInspector.HARLog()).build();
+ for (var i = 0; i < harLog.entries.length; ++i)
+ harLog.entries[i]._resourceId = this._resourceId(WebInspector.networkResources[i]);
+ return harLog;
},
_onGetResourceContent: function(message, port)
@@ -319,12 +326,26 @@ WebInspector.ExtensionServer.prototype = {
};
this._dispatchCallback(message.requestId, port, response);
}
- var resource = WebInspector.networkResourceById(message.id);
+ var resource = this._resourceById(message.id);
if (!resource)
return this._status.E_NOTFOUND(message.id);
resource.requestContent(onContentAvailable.bind(this));
},
+ _resourceId: function(resource)
+ {
+ if (!resource._extensionResourceId) {
+ resource._extensionResourceId = ++this._lastResourceId;
+ this._resources[resource._extensionResourceId] = resource;
+ }
+ return resource._extensionResourceId;
+ },
+
+ _resourceById: function(id)
+ {
+ return this._resources[id];
+ },
+
_onAddAuditCategory: function(request)
{
var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.resultCount);
diff --git a/Source/WebCore/inspector/front-end/FontView.js b/Source/WebCore/inspector/front-end/FontView.js
index 82559ef..55110b7 100644
--- a/Source/WebCore/inspector/front-end/FontView.js
+++ b/Source/WebCore/inspector/front-end/FontView.js
@@ -33,6 +33,12 @@ WebInspector.FontView = function(resource)
this.element.addStyleClass("font");
}
+WebInspector.FontView._fontInnerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
+
+WebInspector.FontView._fontId = 0;
+
+WebInspector.FontView._measureFontSize = 50;
+
WebInspector.FontView.prototype = {
hasContent: function()
{
@@ -44,33 +50,57 @@ WebInspector.FontView.prototype = {
if (this.fontPreviewElement)
return;
- var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier;
+ var uniqueFontName = "WebInspectorFontPreview" + (++WebInspector.FontView._fontId);
this.fontStyleElement = document.createElement("style");
this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
document.head.appendChild(this.fontStyleElement);
this.fontPreviewElement = document.createElement("div");
- this.element.appendChild(this.fontPreviewElement);
-
+ this.fontPreviewElement.innerHTML = WebInspector.FontView._fontInnerHTML;
this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
- this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
- this._lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1;
+ this.fontPreviewElement.style.setProperty("visibility", "hidden", null);
- this.updateFontPreviewSize();
+ this._dummyElement = document.createElement("div");
+ this._dummyElement.style.visibility = "hidden";
+ this._dummyElement.style.zIndex = "-1";
+ this._dummyElement.style.display = "inline";
+ this._dummyElement.style.position = "absolute";
+ this._dummyElement.style.setProperty("font-family", uniqueFontName, null);
+ this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px", null);
+ this._dummyElement.innerHTML = WebInspector.FontView._fontInnerHTML;
+
+ this.element.appendChild(this.fontPreviewElement);
},
show: function(parentElement)
{
WebInspector.ResourceView.prototype.show.call(this, parentElement);
this._createContentIfNeeded();
+
this.updateFontPreviewSize();
},
resize: function()
{
- this.updateFontPreviewSize();
- WebInspector.ResourceView.prototype.resize.call(this);
+ if (this._inResize)
+ return;
+
+ this._inResize = true;
+ try {
+ this.updateFontPreviewSize();
+ } finally {
+ delete this._inResize;
+ }
+ },
+
+ _measureElement: function()
+ {
+ this.element.appendChild(this._dummyElement);
+ var result = { width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight };
+ this.element.removeChild(this._dummyElement);
+
+ return result;
},
updateFontPreviewSize: function()
@@ -78,31 +108,26 @@ WebInspector.FontView.prototype = {
if (!this.fontPreviewElement || !this.visible)
return;
- const measureFontSize = 50;
- this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null);
- this.fontPreviewElement.style.setProperty("position", "absolute", null);
- this.fontPreviewElement.style.removeProperty("height");
+ this.fontPreviewElement.style.removeProperty("visibility");
+ var dimension = this._measureElement();
- const height = this.fontPreviewElement.offsetHeight;
- const width = this.fontPreviewElement.offsetWidth;
+ const height = dimension.height;
+ const width = dimension.width;
- // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar.
+ // Subtract some padding. This should match the paddings in the CSS plus room for the scrollbar.
const containerWidth = this.element.offsetWidth - 50;
+ const containerHeight = this.element.offsetHeight - 30;
- if (!height || !width || !containerWidth) {
+ if (!height || !width || !containerWidth || !containerHeight) {
this.fontPreviewElement.style.removeProperty("font-size");
- this.fontPreviewElement.style.removeProperty("position");
return;
}
- var realLineHeight = Math.floor(height / this._lineCount);
- var fontSizeLineRatio = measureFontSize / realLineHeight;
var widthRatio = containerWidth / width;
- var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 2;
+ var heightRatio = containerHeight / height;
+ var finalFontSize = Math.floor(WebInspector.FontView._measureFontSize * Math.min(widthRatio, heightRatio)) - 2;
this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
- this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null);
- this.fontPreviewElement.style.removeProperty("position");
}
}
diff --git a/Source/WebCore/inspector/front-end/HAREntry.js b/Source/WebCore/inspector/front-end/HAREntry.js
index 4d690b3..b5223b6 100644
--- a/Source/WebCore/inspector/front-end/HAREntry.js
+++ b/Source/WebCore/inspector/front-end/HAREntry.js
@@ -189,7 +189,6 @@ WebInspector.HAREntry._toMilliseconds = function(time)
WebInspector.HARLog = function()
{
- this.includeResourceIds = false;
}
WebInspector.HARLog.prototype = {
@@ -230,10 +229,7 @@ WebInspector.HARLog.prototype = {
_convertResource: function(resource)
{
- var entry = (new WebInspector.HAREntry(resource)).build();
- if (this.includeResourceIds)
- entry._resourceId = resource.identifier;
- return entry;
+ return (new WebInspector.HAREntry(resource)).build();
},
_pageEventTime: function(time)
diff --git a/Source/WebCore/inspector/front-end/HeapSnapshot.js b/Source/WebCore/inspector/front-end/HeapSnapshot.js
index ef450af..215f31c 100644
--- a/Source/WebCore/inspector/front-end/HeapSnapshot.js
+++ b/Source/WebCore/inspector/front-end/HeapSnapshot.js
@@ -80,6 +80,11 @@ WebInspector.HeapSnapshotEdge.prototype = {
return this._type() === this._snapshot._edgeInternalType;
},
+ get isInvisible()
+ {
+ return this._type() === this._snapshot._edgeInvisibleType;
+ },
+
get isShortcut()
{
return this._type() === this._snapshot._edgeShortcutType;
@@ -123,6 +128,7 @@ WebInspector.HeapSnapshotEdge.prototype = {
return "[" + this.name + "]";
case "internal":
case "hidden":
+ case "invisible":
return "{" + this.name + "}";
};
return "?" + this.name + "?";
@@ -377,6 +383,10 @@ WebInspector.HeapSnapshot.prototype = {
this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
this._edgeInternalType = this._edgeTypes.indexOf("internal");
this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
+ this._edgeInvisibleType = this._edgeTypes.length;
+ this._edgeTypes.push("invisible");
+
+ this._markInvisibleEdges();
},
dispose: function()
@@ -549,17 +559,44 @@ WebInspector.HeapSnapshot.prototype = {
});
this._aggregatesWithIndexes = true;
+ },
+
+ _markInvisibleEdges: function()
+ {
+ // Mark hidden edges of global objects as invisible.
+ // FIXME: This is a temporary measure. Normally, we should
+ // really hide all hidden nodes.
+ for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
+ var edge = iter.edge;
+ if (!edge.isShortcut)
+ continue;
+ var node = edge.node;
+ var propNames = {};
+ for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
+ var globalObjEdge = innerIter.edge;
+ if (globalObjEdge.isShortcut)
+ propNames[globalObjEdge._nameOrIndex] = true;
+ }
+ for (innerIter.first(); innerIter.hasNext(); innerIter.next()) {
+ var globalObjEdge = innerIter.edge;
+ if (!globalObjEdge.isShortcut
+ && globalObjEdge.node.isHidden
+ && globalObjEdge._hasStringName
+ && (globalObjEdge._nameOrIndex in propNames))
+ this._nodes[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType;
+ }
+ }
}
};
-WebInspector.HeapSnapshotFilteredOrderedIterator = function(snapshot, iterator, filter)
+WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter)
{
- this._snapshot = snapshot;
this._filter = filter;
this._iterator = iterator;
this._iterationOrder = null;
this._position = 0;
this._lastComparator = null;
+ this._instancesCount = 0;
}
WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
@@ -588,6 +625,16 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
return this._position < this._iterationOrder.length;
},
+ incInstancesCount: function()
+ {
+ ++this._instancesCount;
+ },
+
+ get instancesCount()
+ {
+ return this._instancesCount;
+ },
+
get isEmpty()
{
if (this._iterationOrder)
@@ -623,6 +670,11 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
next: function()
{
++this._position;
+ },
+
+ resetInstancesCount: function()
+ {
+ this._instancesCount = 0;
}
}
@@ -633,7 +685,8 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = fu
WebInspector.HeapSnapshotEdgesProvider = function(snapshot, rawEdges, filter)
{
- WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, rawEdges)), filter);
+ this.snapshot = snapshot;
+ WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, rawEdges)), filter);
}
WebInspector.HeapSnapshotEdgesProvider.prototype = {
@@ -649,8 +702,8 @@ WebInspector.HeapSnapshotEdgesProvider.prototype = {
var edgeA = this._iterator.item.clone();
var edgeB = edgeA.clone();
- var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
- var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+ var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
function sortByEdgeFieldName(ascending, indexA, indexB)
{
@@ -715,7 +768,8 @@ WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSn
WebInspector.HeapSnapshotNodesProvider = function(snapshot, nodes, filter)
{
- WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, nodes, filter);
+ this.snapshot = snapshot;
+ WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, nodes, filter);
}
WebInspector.HeapSnapshotNodesProvider.prototype = {
@@ -729,8 +783,8 @@ WebInspector.HeapSnapshotNodesProvider.prototype = {
var ascending1 = comparator.ascending1;
var ascending2 = comparator.ascending2;
- var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
- var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+ var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
function sortByNodeField(fieldName, ascending, indexA, indexB)
{
@@ -832,7 +886,8 @@ WebInspector.HeapSnapshotPathFinder.prototype = {
_skipEdge: function(edge)
{
- return (this._skipHidden && (edge.isHidden || edge.node.isHidden))
+ return edge.isInvisible
+ || (this._skipHidden && (edge.isHidden || edge.node.isHidden))
|| this._hasInPath(edge.nodeIndex);
},
diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotView.js b/Source/WebCore/inspector/front-end/HeapSnapshotView.js
index 44b95c3..87e02f7 100644
--- a/Source/WebCore/inspector/front-end/HeapSnapshotView.js
+++ b/Source/WebCore/inspector/front-end/HeapSnapshotView.js
@@ -1010,7 +1010,7 @@ WebInspector.HeapSnapshotProfileType.prototype = {
buttonClicked: function()
{
- InspectorBackend.takeHeapSnapshot(false);
+ ProfilerAgent.takeHeapSnapshot(false);
},
get welcomeMessage()
diff --git a/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png b/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png
new file mode 100644
index 0000000..92fe59a
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png
Binary files differ
diff --git a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
index 3c0f315..14039ef 100644
--- a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -40,7 +40,7 @@ WebInspector.MetricsSidebarPane.prototype = {
else
node = this.node;
- if (!node || !node.ownerDocument.defaultView || node.nodeType !== Node.ELEMENT_NODE) {
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) {
this.bodyElement.removeChildren();
return;
}
diff --git a/Source/WebCore/inspector/front-end/NetworkManager.js b/Source/WebCore/inspector/front-end/NetworkManager.js
index da043fe..246b53c 100644
--- a/Source/WebCore/inspector/front-end/NetworkManager.js
+++ b/Source/WebCore/inspector/front-end/NetworkManager.js
@@ -33,7 +33,7 @@ WebInspector.NetworkManager = function(resourceTreeModel)
WebInspector.Object.call(this);
this._resourceTreeModel = resourceTreeModel;
this._dispatcher = new WebInspector.NetworkDispatcher(resourceTreeModel, this);
- InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+ NetworkAgent.enable(this._processCachedResources.bind(this));
}
WebInspector.NetworkManager.EventTypes = {
@@ -44,11 +44,11 @@ WebInspector.NetworkManager.EventTypes = {
}
WebInspector.NetworkManager.prototype = {
- reset: function()
+ frontendReused: function()
{
WebInspector.panels.network.clear();
this._resourceTreeModel.reset();
- InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+ NetworkAgent.enable(this._processCachedResources.bind(this));
},
requestContent: function(resource, base64Encode, callback)
@@ -57,7 +57,7 @@ WebInspector.NetworkManager.prototype = {
{
callback(success ? content : null);
}
- InspectorBackend.resourceContent(resource.loader.frameId, resource.url, base64Encode, callbackWrapper);
+ NetworkAgent.resourceContent(resource.loader.frameId, resource.url, base64Encode, callbackWrapper);
},
_processCachedResources: function(mainFramePayload)
diff --git a/Source/WebCore/inspector/front-end/NetworkPanel.js b/Source/WebCore/inspector/front-end/NetworkPanel.js
index 085f468..06983f0 100644
--- a/Source/WebCore/inspector/front-end/NetworkPanel.js
+++ b/Source/WebCore/inspector/front-end/NetworkPanel.js
@@ -110,7 +110,7 @@ WebInspector.NetworkPanel.prototype = {
{
WebInspector.Panel.prototype.resize.call(this);
this._dataGrid.updateWidths();
- this._positionSummaryBar();
+ this._updateOffscreenRows();
},
updateSidebarWidth: function(width)
@@ -133,41 +133,6 @@ WebInspector.NetworkPanel.prototype = {
}
},
- _positionSummaryBar: function()
- {
- // Position the total bar.
-
- var fillerRow = this._dataGrid.dataTableBody.lastChild;
- if (this._summaryBarElement.parentElement !== this.element && fillerRow.offsetHeight > 0) {
- // Glue status to bottom.
- if (this._summaryBarRowNode) {
- this._dataGrid.removeChild(this._summaryBarRowNode);
- delete this._summaryBarRowNode;
- }
- this._summaryBarElement.addStyleClass("network-summary-bar-bottom");
- this.element.appendChild(this._summaryBarElement);
- this._dataGrid.element.style.bottom = "20px";
- return;
- }
-
- if (!this._summaryBarRowNode && !fillerRow.offsetHeight) {
- // Glue status to table.
- this._summaryBarRowNode = new WebInspector.NetworkTotalGridNode(this._summaryBarElement);
- this._summaryBarElement.removeStyleClass("network-summary-bar-bottom");
- this._dataGrid.appendChild(this._summaryBarRowNode);
- this._dataGrid.element.style.bottom = 0;
- this._sortItems();
- }
- this._updateOffscreenRows();
- },
-
- _resetSummaryBar: function()
- {
- delete this._summaryBarRowNode;
- this._summaryBarElement.parentElement.removeChild(this._summaryBarElement);
- this._updateSummaryBar();
- },
-
_createTimelineGrid: function()
{
this._timelineGrid = new WebInspector.TimelineGrid();
@@ -368,14 +333,17 @@ WebInspector.NetworkPanel.prototype = {
_createSummaryBar: function()
{
- this._summaryBarElement = document.createElement("div");
- this._summaryBarElement.className = "network-summary-bar";
- this.containerElement.appendChild(this._summaryBarElement);
+ var tbody = this._dataGrid.dataTableBody;
+ var tfoot = document.createElement("tfoot");
+ var tr = tfoot.createChild("tr", "revealed network-summary-bar");
+ var td = tr.createChild("td");
+ td.setAttribute("colspan", 7);
+ tbody.parentNode.insertBefore(tfoot, tbody);
+ this._summaryBarElement = td;
},
_updateSummaryBar: function()
{
- this._positionSummaryBar(); // Grid is growing.
var numRequests = this._resources.length;
if (!numRequests) {
@@ -387,7 +355,6 @@ WebInspector.NetworkPanel.prototype = {
img.src = "Images/warningIcon.png";
this._summaryBarElement.removeChildren();
this._summaryBarElement.appendChild(img);
- this._summaryBarElement.appendChild(document.createTextNode(" "));
this._summaryBarElement.appendChild(document.createTextNode(
WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity.")));
return;
@@ -438,7 +405,6 @@ WebInspector.NetworkPanel.prototype = {
selectMultiple = true;
this._filter(e.target, selectMultiple);
- this._positionSummaryBar();
},
_filter: function(target, selectMultiple)
@@ -478,6 +444,7 @@ WebInspector.NetworkPanel.prototype = {
target.addStyleClass("selected");
this._showCategory(target.category);
+ this._updateOffscreenRows();
return;
}
@@ -655,7 +622,6 @@ WebInspector.NetworkPanel.prototype = {
this.visibleView.show(this._viewsContainerElement);
this._dataGrid.updateWidths();
- this._positionSummaryBar();
},
hide: function()
@@ -727,6 +693,7 @@ WebInspector.NetworkPanel.prototype = {
this._staleResources = [];
this._sortItems();
this._updateSummaryBar();
+ this._updateOffscreenRows();
this._dataGrid.updateWidths();
if (wasScrolledToLastRow)
@@ -756,7 +723,6 @@ WebInspector.NetworkPanel.prototype = {
this._resourceGridNodes = {};
this._dataGrid.removeChildren();
- delete this._summaryBarRowNode;
this._updateDividersIfNeeded(true);
// End reset timeline.
@@ -765,7 +731,8 @@ WebInspector.NetworkPanel.prototype = {
this._viewsContainerElement.removeChildren();
this._viewsContainerElement.appendChild(this._closeButtonElement);
- this._resetSummaryBar();
+ this._updateSummaryBar();
+ WebInspector.extensionServer.resetResources();
},
get resources()
@@ -904,7 +871,7 @@ WebInspector.NetworkPanel.prototype = {
this._timelineGrid.element.removeStyleClass("small");
this._viewsContainerElement.removeStyleClass("small");
}
- this._positionSummaryBar();
+ this._updateOffscreenRows();
},
_getPopoverAnchor: function(element)
@@ -1006,7 +973,7 @@ WebInspector.NetworkPanel.prototype = {
_contextMenu: function(event)
{
// createBlobURL is enabled conditionally, do not expose resource export if it's not available.
- if (typeof window.webkitURL.createObjectURL !== "function" || !Preferences.resourceExportEnabled)
+ if ((window.webkitURL && typeof window.webkitURL.createObjectURL !== "function") || !Preferences.resourceExportEnabled)
return;
var contextMenu = new WebInspector.ContextMenu();
@@ -1049,9 +1016,6 @@ WebInspector.NetworkPanel.prototype = {
var unfilteredRowIndex = 0;
for (var i = 0; i < recordsCount - 1; ++i) {
var row = rows[i];
- // Don't touch summaty - quit instead.
- if (this._summaryBarRowNode && row === this._summaryBarRowNode.element)
- break;
var dataGridNode = this._dataGrid.dataGridNodeFromNode(row);
if (dataGridNode.isFilteredOut()) {
@@ -1395,7 +1359,7 @@ WebInspector.NetworkDataGridNode.prototype = {
_openInNewTab: function()
{
- InspectorBackend.openInInspectedWindow(this._resource.url);
+ InspectorAgent.openInInspectedWindow(this._resource.url);
},
get selectable()
@@ -1711,32 +1675,3 @@ WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyN
}
WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
-
-WebInspector.NetworkTotalGridNode = function(element)
-{
- this._summaryBarElement = element;
- WebInspector.DataGridNode.call(this, {summaryRow: true});
-}
-
-WebInspector.NetworkTotalGridNode.prototype = {
- isFilteredOut: function()
- {
- return false;
- },
-
- get selectable()
- {
- return false;
- },
-
- createCells: function()
- {
- var td = document.createElement("td");
- td.setAttribute("colspan", 7);
- td.className = "network-summary";
- td.appendChild(this._summaryBarElement);
- this._element.appendChild(td);
- }
-}
-
-WebInspector.NetworkTotalGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/Source/WebCore/inspector/front-end/Panel.js b/Source/WebCore/inspector/front-end/Panel.js
index 4c42a60..1b99dd4 100644
--- a/Source/WebCore/inspector/front-end/Panel.js
+++ b/Source/WebCore/inspector/front-end/Panel.js
@@ -46,29 +46,7 @@ WebInspector.Panel.prototype = {
if (this._toolbarItem)
return this._toolbarItem;
- // Sample toolbar item as markup:
- // <button class="toolbar-item resources toggleable">
- // <div class="toolbar-icon"></div>
- // <div class="toolbar-label">Resources</div>
- // </button>
-
- this._toolbarItem = document.createElement("button");
- this._toolbarItem.className = "toolbar-item toggleable";
- this._toolbarItem.panel = this;
-
- this._toolbarItem.addStyleClass(this._panelName);
-
- var iconElement = document.createElement("div");
- iconElement.className = "toolbar-icon";
- this._toolbarItem.appendChild(iconElement);
-
- if ("toolbarItemLabel" in this) {
- var labelElement = document.createElement("div");
- labelElement.className = "toolbar-label";
- labelElement.textContent = this.toolbarItemLabel;
- this._toolbarItem.appendChild(labelElement);
- }
-
+ this._toolbarItem = WebInspector.Toolbar.createPanelToolbarItem(this);
return this._toolbarItem;
},
@@ -110,6 +88,12 @@ WebInspector.Panel.prototype = {
this._toolbarItem.removeStyleClass("toggled-on");
},
+ reset: function()
+ {
+ this.searchCanceled();
+ WebInspector.resetFocusElement();
+ },
+
get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
@@ -132,7 +116,7 @@ WebInspector.Panel.prototype = {
}
}
- WebInspector.updateSearchMatchesCount(0, this);
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
if (this._currentSearchChunkIntervalIdentifier) {
clearInterval(this._currentSearchChunkIntervalIdentifier);
@@ -161,7 +145,7 @@ WebInspector.Panel.prototype = {
function updateMatchesCount()
{
- WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this);
+ WebInspector.searchController.updateSearchMatchesCount(this._totalSearchMatches, this);
matchesCountUpdateTimeout = null;
}
diff --git a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
index 54d805d..e1980a0 100644
--- a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
+++ b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
@@ -59,7 +59,7 @@ WebInspector.PleaseWaitMessage.prototype = {
get instance()
{
- if (!"_instance" in WebInspector.PleaseWaitMessage.prototype)
+ if (!("_instance" in WebInspector.PleaseWaitMessage.prototype))
WebInspector.PleaseWaitMessage.prototype._instance = new WebInspector.PleaseWaitMessage();
return WebInspector.PleaseWaitMessage.prototype._instance;
},
diff --git a/Source/WebCore/inspector/front-end/Popover.js b/Source/WebCore/inspector/front-end/Popover.js
index 32535e9..f20b8c6 100644
--- a/Source/WebCore/inspector/front-end/Popover.js
+++ b/Source/WebCore/inspector/front-end/Popover.js
@@ -40,6 +40,7 @@ WebInspector.Popover = function(contentElement)
this.contentElement = contentElement;
this._contentDiv = document.createElement("div");
this._contentDiv.className = "content";
+ this._visible = false;
}
WebInspector.Popover.prototype = {
@@ -60,6 +61,7 @@ WebInspector.Popover.prototype = {
this.element.appendChild(this._contentDiv);
document.body.appendChild(this.element);
this._positionElement(anchor, preferredWidth, preferredHeight);
+ this._visible = true;
},
hide: function()
@@ -68,6 +70,12 @@ WebInspector.Popover.prototype = {
delete WebInspector.Popover._popoverElement;
document.body.removeChild(this.element);
}
+ this._visible = false;
+ },
+
+ get visible()
+ {
+ return this._visible;
},
_positionElement: function(anchorElement, preferredWidth, preferredHeight)
diff --git a/Source/WebCore/inspector/front-end/ProfileView.js b/Source/WebCore/inspector/front-end/ProfileView.js
index c325bf7..335bf03 100644
--- a/Source/WebCore/inspector/front-end/ProfileView.js
+++ b/Source/WebCore/inspector/front-end/ProfileView.js
@@ -94,7 +94,7 @@ WebInspector.CPUProfileView = function(profile)
self._updatePercentButton();
}
- InspectorBackend.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
+ ProfilerAgent.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
}
WebInspector.CPUProfileView.prototype = {
@@ -593,9 +593,9 @@ WebInspector.CPUProfileType.prototype = {
this._recording = !this._recording;
if (this._recording)
- InspectorBackend.startProfiling();
+ InspectorAgent.startProfiling();
else
- InspectorBackend.stopProfiling();
+ InspectorAgent.stopProfiling();
},
get welcomeMessage()
diff --git a/Source/WebCore/inspector/front-end/ProfilesPanel.js b/Source/WebCore/inspector/front-end/ProfilesPanel.js
index b87ea7f..e5fb49e 100644
--- a/Source/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/Source/WebCore/inspector/front-end/ProfilesPanel.js
@@ -185,8 +185,19 @@ WebInspector.ProfilesPanel.prototype = {
_reset: function()
{
- for (var i = 0; i < this._profiles.length; ++i)
+ WebInspector.Panel.prototype.reset.call(this);
+
+ for (var i = 0; i < this._profiles.length; ++i) {
+ var view = this._profiles[i]._profileView;
+ if (view && ("dispose" in view))
+ view.dispose();
delete this._profiles[i]._profileView;
+ var profile = this._profiles[i];
+ if (profile.nodes) {
+ delete profile.nodes;
+ delete profile.strings;
+ }
+ }
delete this.visibleView;
delete this.currentQuery;
@@ -215,7 +226,7 @@ WebInspector.ProfilesPanel.prototype = {
_clearProfiles: function()
{
- InspectorBackend.clearProfiles();
+ ProfilerAgent.clearProfiles();
this._reset();
},
@@ -351,7 +362,7 @@ WebInspector.ProfilesPanel.prototype = {
sidebarParent.removeChild(profile._profilesTreeElement);
if (!profile.isTemporary)
- InspectorBackend.removeProfile(profile.typeId, profile.uid);
+ ProfilerAgent.removeProfile(profile.typeId, profile.uid);
// No other item will be selected if there aren't any other profiles, so
// make sure that view gets cleared when the last profile is removed.
@@ -409,6 +420,11 @@ WebInspector.ProfilesPanel.prototype = {
return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)];
},
+ getProfile: function(typeId, uid)
+ {
+ return this._profilesIdMap[this._makeKey(uid, typeId)];
+ },
+
loadHeapSnapshot: function(uid, callback)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
@@ -424,7 +440,7 @@ WebInspector.ProfilesPanel.prototype = {
profile._callbacks = [callback];
profile._json = "";
profile.sideBarElement.subtitle = WebInspector.UIString("Loading…");
- InspectorBackend.getProfile(profile.typeId, profile.uid);
+ ProfilerAgent.getProfile(profile.typeId, profile.uid);
}
},
@@ -455,6 +471,12 @@ WebInspector.ProfilesPanel.prototype = {
delete profile._is_loading;
profile._loaded = true;
profile.sideBarElement.subtitle = "";
+
+ if (!Preferences.detailedHeapProfiles && WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) {
+ WebInspector.panels.profiles._enableDetailedHeapProfiles(false);
+ return;
+ }
+
if (!Preferences.detailedHeapProfiles)
WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
else
@@ -592,10 +614,10 @@ WebInspector.ProfilesPanel.prototype = {
{
if (this._profilerEnabled) {
WebInspector.settings.profilerEnabled = false;
- InspectorBackend.disableProfiler(true);
+ InspectorAgent.disableProfiler(true);
} else {
WebInspector.settings.profilerEnabled = !!optionalAlways;
- InspectorBackend.enableProfiler();
+ InspectorAgent.enableProfiler();
}
},
@@ -612,7 +634,7 @@ WebInspector.ProfilesPanel.prototype = {
this._addProfileHeader(profileHeaders[i]);
}
- InspectorBackend.getProfileHeaders(populateCallback.bind(this));
+ ProfilerAgent.getProfileHeaders(populateCallback.bind(this));
this._profilesWereRequested = true;
},
@@ -658,7 +680,7 @@ WebInspector.ProfilesPanel.prototype = {
}
this._addProfileHeader(this._temporaryTakingSnapshot);
}
- InspectorBackend.takeHeapSnapshot(detailed);
+ ProfilerAgent.takeHeapSnapshot(detailed);
},
_reportHeapSnapshotProgress: function(done, total)
@@ -668,6 +690,63 @@ WebInspector.ProfilesPanel.prototype = {
if (done >= total)
this._removeProfileHeader(this._temporaryTakingSnapshot);
}
+ },
+
+ handleShortcut: function(event)
+ {
+ if (!Preferences.heapProfilerPresent || Preferences.detailedHeapProfiles)
+ return;
+ var combo = ["U+004C", "U+0045", "U+0041", "U+004B", "U+005A"]; // "LEAKZ"
+ if (this._recognizeKeyboardCombo(combo, event)) {
+ this._displayDetailedHeapProfilesEnabledHint();
+ this._enableDetailedHeapProfiles(true);
+ }
+ },
+
+ _recognizeKeyboardCombo: function(combo, event)
+ {
+ var isRecognized = false;
+ if (!this._comboPosition) {
+ if (event.keyIdentifier === combo[0])
+ this._comboPosition = 1;
+ } else if (event.keyIdentifier === combo[this._comboPosition]) {
+ if (++this._comboPosition === combo.length)
+ isRecognized = true;
+ } else
+ delete this._comboPosition;
+ if (this._comboPosition)
+ event.handled = true;
+ return isRecognized;
+ },
+
+ _displayDetailedHeapProfilesEnabledHint: function()
+ {
+ var message = new WebInspector.HelpScreen("Congratulations!");
+ message.contentElement.addStyleClass("help-table");
+ message.contentElement.textContent = "Detailed Heap snapshots are now enabled.";
+ message.show();
+
+ function hideHint()
+ {
+ message._hide();
+ }
+
+ setTimeout(hideHint, 2000);
+ },
+
+ _enableDetailedHeapProfiles: function(resetAgent)
+ {
+ if (resetAgent)
+ this._clearProfiles();
+ else
+ this._reset();
+ var oldProfileType = this._profileTypesByIdMap[WebInspector.HeapSnapshotProfileType.TypeId];
+ var profileType = new WebInspector.DetailedHeapshotProfileType();
+ profileType.treeElement = oldProfileType.treeElement;
+ this._profileTypesByIdMap[profileType.id] = profileType;
+ Preferences.detailedHeapProfiles = true;
+ this.hide();
+ this.show();
}
}
diff --git a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
index a1e37bc..0c314bc 100644
--- a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
@@ -42,15 +42,40 @@ WebInspector.PropertiesSidebarPane.prototype = {
return;
}
- function callback(prototypes)
+ RuntimeAgent.releaseObjectGroup(0, "dom-selection");
+ WebInspector.RemoteObject.resolveNode(node, nodeResolved.bind(this));
+
+ function nodeResolved(objectPayload)
{
+ if (!objectPayload)
+ return;
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.evaluate("var proto = this; result = {}; var counter = 1; while (proto) { result[counter++] = proto; proto = proto.__proto__ }; return result;", nodePrototypesReady.bind(this));
+ }
+
+ function nodePrototypesReady(objectPayload)
+ {
+ if (!objectPayload)
+ return;
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.getOwnProperties(false, fillSection.bind(this));
+ }
+
+ function fillSection(prototypes)
+ {
+ if (!prototypes)
+ return;
+
var body = this.bodyElement;
body.removeChildren();
this.sections = [];
// Get array of prototype user-friendly names.
for (var i = 0; i < prototypes.length; ++i) {
- var prototype = WebInspector.RemoteObject.fromPayload(prototypes[i]);
+ if (!parseInt(prototypes[i].name))
+ continue;
+
+ var prototype = prototypes[i].value;
var title = prototype.description;
if (title.match(/Prototype$/))
title = title.replace(/Prototype$/, "");
@@ -59,7 +84,6 @@ WebInspector.PropertiesSidebarPane.prototype = {
body.appendChild(section.element);
}
}
- InspectorBackend.getNodePrototypes(node.id, callback.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/RemoteObject.js b/Source/WebCore/inspector/front-end/RemoteObject.js
index 10af2e3..4a20cf1 100644
--- a/Source/WebCore/inspector/front-end/RemoteObject.js
+++ b/Source/WebCore/inspector/front-end/RemoteObject.js
@@ -52,7 +52,7 @@ WebInspector.RemoteObject.resolveNode = function(node, callback)
{
callback(object ? WebInspector.RemoteObject.fromPayload(object) : null);
}
- InspectorBackend.resolveNode(node.id, mycallback);
+ DOMAgent.resolveNode(node.id, "dom-selection", mycallback);
}
WebInspector.RemoteObject.fromPayload = function(payload)
@@ -118,7 +118,7 @@ WebInspector.RemoteObject.prototype = {
properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value);
callback(properties);
}
- InspectorBackend.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder);
+ RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder);
},
setPropertyValue: function(name, value, callback)
@@ -127,12 +127,20 @@ WebInspector.RemoteObject.prototype = {
callback(false);
return;
}
- InspectorBackend.setPropertyValue(this._objectId, name, value, callback);
+ RuntimeAgent.setPropertyValue(this._objectId, name, value, callback);
},
pushNodeToFrontend: function(callback)
{
- InspectorBackend.pushNodeToFrontend(this._objectId, callback);
+ if (this._objectId)
+ WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback);
+ else
+ callback(0);
+ },
+
+ evaluate: function(expression, callback)
+ {
+ RuntimeAgent.evaluateOn(this._objectId, expression, callback);
}
}
diff --git a/Source/WebCore/inspector/front-end/ResourceHeadersView.js b/Source/WebCore/inspector/front-end/ResourceHeadersView.js
index ee1010f..e79078a 100644
--- a/Source/WebCore/inspector/front-end/ResourceHeadersView.js
+++ b/Source/WebCore/inspector/front-end/ResourceHeadersView.js
@@ -224,7 +224,7 @@ WebInspector.ResourceHeadersView.prototype = {
if (this._resource.statusCode) {
var statusImageSource = "";
- if (this._resource.statusCode < 300)
+ if (this._resource.statusCode < 300 || this._resource.statusCode === 304)
statusImageSource = "Images/successGreenDot.png";
else if (this._resource.statusCode < 400)
statusImageSource = "Images/warningOrangeDot.png";
diff --git a/Source/WebCore/inspector/front-end/ResourceView.js b/Source/WebCore/inspector/front-end/ResourceView.js
index e38cd0a..83cf99d5 100644
--- a/Source/WebCore/inspector/front-end/ResourceView.js
+++ b/Source/WebCore/inspector/front-end/ResourceView.js
@@ -50,9 +50,8 @@ WebInspector.ResourceView.createResourceView = function(resource)
case WebInspector.resourceCategories.stylesheets:
case WebInspector.resourceCategories.scripts:
case WebInspector.resourceCategories.xhr:
- var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
- var isScript = resource.type === WebInspector.Resource.Type.Script;
- var view = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
+ var delegate = new WebInspector.SourceFrameDelegateForResourcesPanel(resource);
+ var view = new WebInspector.SourceFrame(delegate, resource.url);
view.resource = resource;
return view;
case WebInspector.resourceCategories.images:
@@ -120,35 +119,31 @@ WebInspector.ResourceView.existingResourceViewForResource = function(resource)
}
-WebInspector.SourceFrameContentProviderForResource = function(resource)
+WebInspector.SourceFrameDelegateForResourcesPanel = function(resource)
{
- WebInspector.SourceFrameContentProvider.call(this);
+ WebInspector.SourceFrameDelegate.call(this);
this._resource = resource;
}
//This is a map from resource.type to mime types
//found in WebInspector.SourceTokenizer.Registry.
-WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType = {
+WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType = {
0: "text/html",
1: "text/css",
4: "text/javascript"
}
-WebInspector.SourceFrameContentProviderForResource.prototype = {
+WebInspector.SourceFrameDelegateForResourcesPanel.prototype = {
requestContent: function(callback)
{
- function contentLoaded(content)
+ function contentLoaded(text)
{
- var mimeType = WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType;
- callback(mimeType, content);
+ var mimeType = WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType;
+ var sourceMapping = new WebInspector.IdenticalSourceMapping();
+ callback(mimeType, new WebInspector.SourceFrameContent(text, sourceMapping, []));
}
this._resource.requestContent(contentLoaded.bind(this));
- },
-
- scripts: function()
- {
- return WebInspector.debuggerModel.scriptsForURL(this._resource.url);
}
}
-WebInspector.SourceFrameContentProviderForResource.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
+WebInspector.SourceFrameDelegateForResourcesPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype;
diff --git a/Source/WebCore/inspector/front-end/ResourcesPanel.js b/Source/WebCore/inspector/front-end/ResourcesPanel.js
index 7c0649f..3c85892 100644
--- a/Source/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/Source/WebCore/inspector/front-end/ResourcesPanel.js
@@ -904,7 +904,7 @@ WebInspector.FrameTreeElement.prototype = {
this._storagePanel.showCategoryView(this._displayName);
this.listItemElement.removeStyleClass("hovered");
- InspectorBackend.hideFrameHighlight();
+ InspectorAgent.hideFrameHighlight();
},
get displayName()
@@ -937,10 +937,10 @@ WebInspector.FrameTreeElement.prototype = {
{
if (hovered) {
this.listItemElement.addStyleClass("hovered");
- InspectorBackend.highlightFrame(this._frameId);
+ InspectorAgent.highlightFrame(this._frameId);
} else {
this.listItemElement.removeStyleClass("hovered");
- InspectorBackend.hideFrameHighlight();
+ InspectorAgent.hideFrameHighlight();
}
}
}
@@ -969,7 +969,7 @@ WebInspector.FrameResourceTreeElement.prototype = {
ondblclick: function(event)
{
- InspectorBackend.openInInspectedWindow(this._resource.url);
+ InspectorAgent.openInInspectedWindow(this._resource.url);
},
onattach: function()
diff --git a/Source/WebCore/inspector/front-end/Script.js b/Source/WebCore/inspector/front-end/Script.js
index 8d3eabf..3f27485 100644
--- a/Source/WebCore/inspector/front-end/Script.js
+++ b/Source/WebCore/inspector/front-end/Script.js
@@ -120,6 +120,6 @@ WebInspector.Script.prototype = {
this._source = source;
callback(this._source);
}
- InspectorBackend.getScriptSource(this.sourceID, didGetScriptSource.bind(this));
+ DebuggerAgent.getScriptSource(this.sourceID, didGetScriptSource.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/ScriptFormatter.js b/Source/WebCore/inspector/front-end/ScriptFormatter.js
index 5c00e51..f70d6c6 100644
--- a/Source/WebCore/inspector/front-end/ScriptFormatter.js
+++ b/Source/WebCore/inspector/front-end/ScriptFormatter.js
@@ -36,6 +36,38 @@ WebInspector.ScriptFormatter = function()
this._tasks = [];
}
+WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
+{
+ var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
+ return position + columnNumber;
+}
+
+WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position)
+{
+ var location = {};
+ location.lineNumber = lineEndings.upperBound(position - 1);
+ if (!location.lineNumber)
+ location.columnNumber = position;
+ else
+ location.columnNumber = position - lineEndings[location.lineNumber - 1] - 1;
+ return location;
+}
+
+WebInspector.ScriptFormatter.findScriptRanges = function(lineEndings, scripts)
+{
+ var scriptRanges = [];
+ for (var i = 0; i < scripts.length; ++i) {
+ var start = { lineNumber: scripts[i].lineOffset, columnNumber: scripts[i].columnOffset };
+ start.position = WebInspector.ScriptFormatter.locationToPosition(lineEndings, start.lineNumber, start.columnNumber);
+ var endPosition = start.position + scripts[i].length;
+ var end = WebInspector.ScriptFormatter.positionToLocation(lineEndings, endPosition);
+ end.position = endPosition;
+ scriptRanges.push({ start: start, end: end, sourceID: scripts[i].sourceID });
+ }
+ scriptRanges.sort(function(x, y) { return x.start.position - y.start.position; });
+ return scriptRanges;
+}
+
WebInspector.ScriptFormatter.prototype = {
formatContent: function(content, callback)
{
@@ -44,7 +76,18 @@ WebInspector.ScriptFormatter.prototype = {
function didFormatChunks()
{
var result = this._buildContentFromChunks(chunks);
- callback(new WebInspector.FormattedSourceFrameContent(content, result.text, result.mapping));
+
+ var sourceMapping = new WebInspector.SourceMappingForFormattedScript(content.text.lineEndings(), result.text.lineEndings(), result.mapping);
+ var formattedScriptRanges = [];
+ for (var i = 0; i < content.scriptRanges.length; ++i) {
+ var scriptRange = content.scriptRanges[i];
+ formattedScriptRange = {};
+ formattedScriptRange.start = sourceMapping.originalPositionToFormattedLocation(scriptRange.start.position);
+ formattedScriptRange.end = sourceMapping.originalPositionToFormattedLocation(scriptRange.end.position);
+ formattedScriptRange.sourceID = scriptRange.sourceID;
+ formattedScriptRanges.push(formattedScriptRange);
+ }
+ callback(new WebInspector.SourceFrameContent(result.text, sourceMapping, formattedScriptRanges));
}
this._formatChunks(chunks, 0, didFormatChunks.bind(this));
},
@@ -63,11 +106,12 @@ WebInspector.ScriptFormatter.prototype = {
}
var currentPosition = 0;
for (var i = 0; i < scriptRanges.length; ++i) {
- var scriptRange = scriptRanges[i];
- if (currentPosition < scriptRange.start)
- addChunk(currentPosition, scriptRange.start, false);
- addChunk(scriptRange.start, scriptRange.end, true);
- currentPosition = scriptRange.end;
+ var start = scriptRanges[i].start.position;
+ var end = scriptRanges[i].end.position;
+ if (currentPosition < start)
+ addChunk(currentPosition, start, false);
+ addChunk(start, end, true);
+ currentPosition = end;
}
if (currentPosition < text.length)
addChunk(currentPosition, text.length, false);
@@ -142,3 +186,48 @@ WebInspector.ScriptFormatter.prototype = {
task.callback(task.source, { original: [], formatted: [] });
}
}
+
+
+WebInspector.SourceMappingForFormattedScript = function(originalLineEndings, formattedLineEndings, mapping)
+{
+ WebInspector.SourceMapping.call(this);
+ this._originalLineEndings = originalLineEndings;
+ this._formattedLineEndings = formattedLineEndings;
+ this._mapping = mapping;
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
+ {
+ var position = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber);
+ return this.originalPositionToFormattedLocation(position);
+ },
+
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
+ {
+ var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber);
+ var position = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
+ return WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, position);
+ },
+
+ originalPositionToFormattedLocation: function(position)
+ {
+ var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, position);
+ var location = WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition);
+ location.position = formattedPosition;
+ return location;
+ },
+
+ _convertPosition: function(positions1, positions2, position)
+ {
+ var index = positions1.upperBound(position);
+ var range1 = positions1[index] - positions1[index - 1];
+ var range2 = positions2[index] - positions2[index - 1];
+ var position2 = positions2[index - 1];
+ if (range1)
+ position2 += Math.round((position - positions1[index - 1]) * range2 / range1);
+ return position2;
+ }
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/Source/WebCore/inspector/front-end/ScriptsPanel.js b/Source/WebCore/inspector/front-end/ScriptsPanel.js
index 264291f..2647cee 100644
--- a/Source/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/Source/WebCore/inspector/front-end/ScriptsPanel.js
@@ -27,6 +27,8 @@ WebInspector.ScriptsPanel = function()
{
WebInspector.Panel.call(this, "scripts");
+ this._presentationModel = new WebInspector.DebuggerPresentationModel();
+
this.topStatusBar = document.createElement("div");
this.topStatusBar.className = "status-bar";
this.topStatusBar.id = "scripts-status-bar";
@@ -50,11 +52,11 @@ WebInspector.ScriptsPanel = function()
this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
this.topStatusBar.appendChild(this.forwardButton);
- this.filesSelectElement = document.createElement("select");
- this.filesSelectElement.className = "status-bar-item";
- this.filesSelectElement.id = "scripts-files";
- this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
- this.topStatusBar.appendChild(this.filesSelectElement);
+ this._filesSelectElement = document.createElement("select");
+ this._filesSelectElement.className = "status-bar-item";
+ this._filesSelectElement.id = "scripts-files";
+ this._filesSelectElement.addEventListener("change", this._filesSelectChanged.bind(this), false);
+ this.topStatusBar.appendChild(this._filesSelectElement);
this.functionsSelectElement = document.createElement("select");
this.functionsSelectElement.className = "status-bar-item";
@@ -138,7 +140,7 @@ WebInspector.ScriptsPanel = function()
this.sidebarPanes = {};
this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
- this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+ this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel);
this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane();
if (Preferences.nativeInstrumentationEnabled) {
@@ -153,7 +155,6 @@ WebInspector.ScriptsPanel = function()
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
this.sidebarPanes.callstack.expanded = true;
- this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
this.sidebarPanes.scopechain.expanded = true;
this.sidebarPanes.jsBreakpoints.expanded = true;
@@ -189,6 +190,9 @@ WebInspector.ScriptsPanel = function()
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ScriptSourceChanged, this._scriptSourceChanged, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, this._breakpointAdded, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this);
}
// Keep these in sync with WebCore::ScriptDebugServer
@@ -211,7 +215,7 @@ WebInspector.ScriptsPanel.prototype = {
get defaultFocusedElement()
{
- return this.filesSelectElement;
+ return this._filesSelectElement;
},
get paused()
@@ -255,23 +259,14 @@ WebInspector.ScriptsPanel.prototype = {
var sourceID = event.data.sourceID;
var oldSource = event.data.oldSource;
- var oldView, newView;
var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
if (script.resource) {
- oldView = this._urlToSourceFrame[script.resource.url];
- delete this._urlToSourceFrame[script.resource.url];
- newView = this._sourceFrameForResource(script.resource);
var revertHandle = WebInspector.debuggerModel.editScriptSource.bind(WebInspector.debuggerModel, sourceID, oldSource);
script.resource.setContent(script.source, revertHandle);
- } else {
- var oldView = script._sourceFrame;
- delete script._sourceFrame;
- newView = this._sourceFrameForScript(script);
}
- newView.scrollTop = oldView.scrollTop;
- if (this.visibleView === oldView)
- this.visibleView = newView;
+ var sourceFileId = this._sourceFileIdForScript(script);
+ this._recreateSourceFrame(sourceFileId);
var callFrames = WebInspector.debuggerModel.callFrames;
if (callFrames.length)
@@ -280,11 +275,20 @@ WebInspector.ScriptsPanel.prototype = {
_addScript: function(script)
{
- var resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
+ if (!script.sourceURL) {
+ // Anonymous scripts are shown only when stepping.
+ return;
+ }
+
+ var resource = this._resourceForURL(script.sourceURL);
if (resource) {
if (resource.finished) {
// Resource is finished, bind the script right away.
script.resource = resource;
+
+ // Add resource url to files select if not already added while debugging inlined scripts.
+ if (!(resource.url in this._sourceFileIdToFilesSelectOption))
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(resource.url);
} else {
// Resource is not finished, bind the script later.
if (!resource._scriptsPendingResourceLoad) {
@@ -292,40 +296,84 @@ WebInspector.ScriptsPanel.prototype = {
resource.addEventListener("finished", this._resourceLoadingFinished, this);
}
resource._scriptsPendingResourceLoad.push(script);
+
+ // Source frame content is outdated since we have new script parsed.
+ this._recreateSourceFrame(script.sourceURL);
}
+ } else if (!(script.sourceURL in this._sourceFileIdToFilesSelectOption)) {
+ // This is a dynamic script with "//@ sourceURL=" comment.
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(script.sourceURL);
}
- this._addScriptToFilesMenu(script);
+ },
+
+ _resourceForURL: function(url)
+ {
+ return WebInspector.networkManager.inflightResourceForURL(url) || WebInspector.resourceForURL(url);
},
_resourceLoadingFinished: function(e)
{
var resource = e.target;
- var visible = false;
- var select = this.filesSelectElement;
+ // Bind scripts to resource.
for (var i = 0; i < resource._scriptsPendingResourceLoad.length; ++i) {
- // Bind script to resource.
var script = resource._scriptsPendingResourceLoad[i];
script.resource = resource;
+ }
+ delete resource._scriptsPendingResourceLoad;
+
+ // Recreate source frame to show resource content.
+ this._recreateSourceFrame(resource.url);
+
+ // Add resource url to files select if not already added while debugging inlined scripts.
+ if (!(resource.url in this._sourceFileIdToFilesSelectOption))
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(resource.url);
+ },
- if (select.options[select.selectedIndex] === script.filesSelectOption)
- visible = true;
+ _addOptionToFilesSelectAndShowSourceFrameIfNeeded: function(url)
+ {
+ this._addOptionToFilesSelect(url);
- // Remove script from the files list.
- script.filesSelectOption.parentElement.removeChild(script.filesSelectOption);
+ var lastViewedURL = WebInspector.settings.lastViewedScriptFile;
+ if (this._filesSelectElement.length === 1) {
+ // Option we just added is the only option in files select.
+ // We have to show corresponding source frame immediately.
+ this._showSourceFrameAndAddToHistory(url);
+ // Restore original value of lastViewedScriptFile because
+ // source frame was shown as a result of initial load.
+ WebInspector.settings.lastViewedScriptFile = lastViewedURL;
+ } else if (url === lastViewedURL)
+ this._showSourceFrameAndAddToHistory(url);
+ },
+
+ _addOptionToFilesSelect: function(sourceFileId)
+ {
+ var script = this._scriptForSourceFileId(sourceFileId);
+ var select = this._filesSelectElement;
+ var option = document.createElement("option");
+ option.text = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
+ if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
+ option.addStyleClass("extension-script");
+ function optionCompare(a, b)
+ {
+ if (a.text === b.text)
+ return 0;
+ return a.text < b.text ? -1 : 1;
}
- // Adding first script will add resource.
- this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
- delete resource._scriptsPendingResourceLoad;
+ var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
+ if (insertionIndex < 0)
+ select.appendChild(option);
+ else
+ select.insertBefore(option, select.childNodes.item(insertionIndex));
- if (visible)
- this._showScriptOrResource(resource, { initialLoad: true });
+ option._sourceFileId = sourceFileId;
+ this._sourceFileIdToFilesSelectOption[sourceFileId] = option;
},
addConsoleMessage: function(message)
{
this._messages.push(message);
- var sourceFrame = this._urlToSourceFrame[message.url];
+ var sourceFrame = this._sourceFileIdToSourceFrame[message.url];
if (sourceFrame)
sourceFrame.addMessage(message);
},
@@ -333,36 +381,40 @@ WebInspector.ScriptsPanel.prototype = {
clearConsoleMessages: function()
{
this._messages = [];
- for (var url in this._urlToSourceFrame)
- this._urlToSourceFrame[url].clearMessages();
+ for (var url in this._sourceFileIdToSourceFrame)
+ this._sourceFileIdToSourceFrame[url].clearMessages();
},
- selectedCallFrameId: function()
+ _breakpointAdded: function(event)
{
- var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
- if (!selectedCallFrame)
- return null;
- return selectedCallFrame.id;
+ var breakpoint = event.data;
+
+ var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
+ if (sourceFrame && sourceFrame.loaded)
+ sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
},
- evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, includeCommandLineAPI, callback)
+ _breakpointRemoved: function(event)
{
- var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ var breakpoint = event.data;
+
+ var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
+ if (sourceFrame && sourceFrame.loaded)
+ sourceFrame.removeBreakpoint(breakpoint.lineNumber);
+ },
+
+ evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, callback)
+ {
+ var selectedCallFrame = this._presentationModel.selectedCallFrame;
if (!this._paused || !selectedCallFrame)
return;
- if (typeof updateInterface === "undefined")
- updateInterface = true;
-
function updatingCallbackWrapper(result)
{
- if (result) {
+ if (result)
callback(WebInspector.RemoteObject.fromPayload(result));
- if (updateInterface)
- this.sidebarPanes.scopechain.update(selectedCallFrame);
- }
}
- InspectorBackend.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
+ DebuggerAgent.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
},
_debuggerPaused: function(event)
@@ -377,7 +429,7 @@ WebInspector.ScriptsPanel.prototype = {
WebInspector.currentPanel = this;
- this.sidebarPanes.callstack.update(callFrames, event.data.eventType, event.data.eventData);
+ this.sidebarPanes.callstack.update(event.data);
this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
window.focus();
@@ -386,6 +438,8 @@ WebInspector.ScriptsPanel.prototype = {
_debuggerResumed: function()
{
+ this._presentationModel.selectedCallFrame = null;
+
this._paused = false;
this._waitingToPause = false;
this._stepping = false;
@@ -425,10 +479,10 @@ WebInspector.ScriptsPanel.prototype = {
this._currentBackForwardIndex = -1;
this._updateBackAndForwardButtons();
- this._urlToSourceFrame = {};
+ this._sourceFileIdToSourceFrame = {};
+ this._sourceFileIdToFilesSelectOption = {};
this._messages = [];
- this._resourceForURLInFilesSelect = {};
- this.filesSelectElement.removeChildren();
+ this._filesSelectElement.removeChildren();
this.functionsSelectElement.removeChildren();
this.viewsContainerElement.removeChildren();
@@ -458,35 +512,15 @@ WebInspector.ScriptsPanel.prototype = {
canShowSourceLine: function(url, line)
{
- if (!this._debuggerEnabled)
- return false;
- return !!this._scriptOrResourceForURLAndLine(url, line);
+ return this._debuggerEnabled && (url in this._sourceFileIdToFilesSelectOption);
},
showSourceLine: function(url, line)
{
- var scriptOrResource = this._scriptOrResourceForURLAndLine(url, line);
- this._showScriptOrResource(scriptOrResource, {line: line, shouldHighlightLine: true});
- },
-
- _scriptOrResourceForURLAndLine: function(url, line)
- {
- var scripts = WebInspector.debuggerModel.scriptsForURL(url);
- for (var i = 0; i < scripts.length; ++i) {
- var script = scripts[i];
- if (script.resource)
- return script.resource;
- if (script.startingLine <= line && script.startingLine + script.linesCount > line)
- return script;
- }
- return null;
- },
-
- showView: function(view)
- {
- if (!view)
+ if (!(url in this._sourceFileIdToFilesSelectOption))
return;
- this._showScriptOrResource(view.resource || view.script);
+ var sourceFrame = this._showSourceFrameAndAddToHistory(url);
+ sourceFrame.highlightLine(line);
},
handleShortcut: function(event)
@@ -500,167 +534,114 @@ WebInspector.ScriptsPanel.prototype = {
this.sidebarPanes.callstack.handleShortcut(event);
},
- _sourceFrameForScriptOrResource: function(scriptOrResource)
+ _showSourceFrameAndAddToHistory: function(sourceFileId)
{
- if (scriptOrResource instanceof WebInspector.Resource)
- return this._sourceFrameForResource(scriptOrResource);
- return this._sourceFrameForScript(scriptOrResource);
+ var sourceFrame = this._showSourceFrame(sourceFileId);
+
+ var oldIndex = this._currentBackForwardIndex;
+ if (oldIndex >= 0)
+ this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
+
+ // Check for a previous entry of the same object in _backForwardList.
+ // If one is found, remove it.
+ var previousEntryIndex = this._backForwardList.indexOf(sourceFileId);
+ if (previousEntryIndex !== -1)
+ this._backForwardList.splice(previousEntryIndex, 1);
+
+ this._backForwardList.push(sourceFileId);
+ this._currentBackForwardIndex = this._backForwardList.length - 1;
+
+ this._updateBackAndForwardButtons();
+
+ return sourceFrame;
},
- _sourceFrameForResource: function(resource)
+ _showSourceFrame: function(sourceFileId)
{
- var sourceFrame = this._urlToSourceFrame[resource.url];
- if (sourceFrame)
- return sourceFrame;
- var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
- var isScript = resource.type === WebInspector.Resource.Type.Script;
- sourceFrame = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
- for (var i = 0; i < this._messages.length; ++i) {
- var message = this._messages[i];
- if (this._messages[i].url === resource.url)
- sourceFrame.addMessage(message);
- }
- this._urlToSourceFrame[resource.url] = sourceFrame;
+ var index = this._sourceFileIdToFilesSelectOption[sourceFileId].index;
+ this._filesSelectElement.selectedIndex = index;
+
+ var sourceFrame = this._sourceFrameForSourceFileId(sourceFileId);
+ this.visibleView = sourceFrame;
+
+ var script = this._scriptForSourceFileId(sourceFileId);
+ if (script.sourceURL)
+ WebInspector.settings.lastViewedScriptFile = script.sourceURL;
+
return sourceFrame;
},
- _sourceFrameForScript: function(script)
+ _sourceFrameForSourceFileId: function(sourceFileId)
{
- if (script._sourceFrame)
- return script._sourceFrame;
- var contentProvider = new WebInspector.SourceFrameContentProviderForScript(script);
- script._sourceFrame = new WebInspector.SourceFrame(contentProvider, script.sourceURL, true);
- return script._sourceFrame;
+ var sourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
+ return sourceFrame || this._createSourceFrame(sourceFileId);
},
- _showScriptOrResource: function(scriptOrResource, options)
+ _createSourceFrame: function(sourceFileId)
{
- // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:}
- options = options || {};
+ var script = this._scriptForSourceFileId(sourceFileId);
+ var delegate = new WebInspector.SourceFrameDelegateForScriptsPanel(script);
+ var sourceFrame = new WebInspector.SourceFrame(delegate, script.sourceURL);
+ sourceFrame._sourceFileId = sourceFileId;
+ sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ this._sourceFileIdToSourceFrame[sourceFileId] = sourceFrame;
+ return sourceFrame;
+ },
- if (!scriptOrResource)
+ _recreateSourceFrame: function(sourceFileId)
+ {
+ var oldSourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
+ if (!oldSourceFrame)
return;
-
- var view = this._sourceFrameForScriptOrResource(scriptOrResource);
- if (!view)
+ oldSourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ delete this._sourceFileIdToSourceFrame[sourceFileId];
+ oldSourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ if (this.visibleView !== oldSourceFrame)
return;
- var url = scriptOrResource.url || scriptOrResource.sourceURL;
- if (url && !options.initialLoad)
- WebInspector.settings.lastViewedScriptFile = url;
-
- if (!options.fromBackForwardAction) {
- var oldIndex = this._currentBackForwardIndex;
- if (oldIndex >= 0)
- this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
-
- // Check for a previous entry of the same object in _backForwardList.
- // If one is found, remove it and update _currentBackForwardIndex to match.
- var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
- if (previousEntryIndex !== -1) {
- this._backForwardList.splice(previousEntryIndex, 1);
- --this._currentBackForwardIndex;
- }
+ var newSourceFrame = this._createSourceFrame(sourceFileId)
+ newSourceFrame.scrollTop = oldSourceFrame.scrollTop;
+ this.visibleView = newSourceFrame;
+ },
- this._backForwardList.push(scriptOrResource);
- ++this._currentBackForwardIndex;
+ _sourceFrameLoaded: function(event)
+ {
+ var sourceFrame = event.target;
+ var sourceFileId = sourceFrame._sourceFileId;
- this._updateBackAndForwardButtons();
+ for (var i = 0; i < this._messages.length; ++i) {
+ var message = this._messages[i];
+ if (message.url === sourceFileId)
+ sourceFrame.addMessage(message);
}
- this.visibleView = view;
-
- if (options.line) {
- if (view.revealLine)
- view.revealLine(options.line);
- if (view.highlightLine && options.shouldHighlightLine)
- view.highlightLine(options.line);
+ var breakpoints = this._presentationModel.breakpointsForSourceFileId(sourceFileId);
+ for (var i = 0; i < breakpoints.length; ++i) {
+ var breakpoint = breakpoints[i];
+ sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
}
- var option;
- if (scriptOrResource instanceof WebInspector.Script) {
- option = scriptOrResource.filesSelectOption;
-
- // hasn't been added yet - happens for stepping in evals,
- // so use the force option to force the script into the menu.
- if (!option) {
- this._addScriptToFilesMenu(scriptOrResource, true);
- option = scriptOrResource.filesSelectOption;
+ var selectedCallFrame = this._presentationModel.selectedCallFrame;
+ if (selectedCallFrame) {
+ if (selectedCallFrame.sourceLocation.sourceFileId === sourceFileId) {
+ sourceFrame.setExecutionLine(selectedCallFrame.sourceLocation.lineNumber);
+ this._executionSourceFrame = sourceFrame;
}
-
- console.assert(option);
- } else
- option = scriptOrResource.filesSelectOption;
-
- if (option)
- this.filesSelectElement.selectedIndex = option.index;
+ }
},
- _addScriptToFilesMenu: function(script, force)
+ _sourceFileIdForScript: function(script)
{
- if (!script.sourceURL && !force)
- return;
-
- if (script.resource) {
- if (this._resourceForURLInFilesSelect[script.resource.url])
- return;
- this._resourceForURLInFilesSelect[script.resource.url] = script.resource;
- }
-
- var displayName = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
-
- var select = this.filesSelectElement;
- var option = document.createElement("option");
- option.representedObject = script.resource || script;
- option.url = displayName;
- option.startingLine = script.startingLine;
- option.text = script.resource || script.startingLine === 1 ? displayName : String.sprintf("%s:%d", displayName, script.startingLine);
+ return script.sourceURL || script.sourceID;
+ },
- function optionCompare(a, b)
+ _scriptForSourceFileId: function(sourceFileId)
+ {
+ function filter(script)
{
- if (a.url < b.url)
- return -1;
- else if (a.url > b.url)
- return 1;
-
- if (typeof a.startingLine !== "number")
- return -1;
- if (typeof b.startingLine !== "number")
- return -1;
- return a.startingLine - b.startingLine;
- }
-
- var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
- if (insertionIndex < 0)
- select.appendChild(option);
- else
- select.insertBefore(option, select.childNodes.item(insertionIndex));
-
- if (script.resource)
- script.resource.filesSelectOption = option;
- else
- script.filesSelectOption = option;
-
- if (select.options[select.selectedIndex] === option) {
- // Call _showScriptOrResource if the option we just appended ended up being selected.
- // This will happen for the first item added to the menu.
- this._showScriptOrResource(option.representedObject, {initialLoad: true});
- } else {
- // If not first item, check to see if this was the last viewed
- var url = option.representedObject.url || option.representedObject.sourceURL;
- var lastURL = WebInspector.settings.lastViewedScriptFile;
- if (url && url === lastURL) {
- // For resources containing multiple <script> tags, we first report them separately and
- // then glue them all together. They all share url and there is no need to show them all one
- // by one.
- var isResource = !!option.representedObject.url;
- if (isResource || !this.visibleView || !this.visibleView.script || this.visibleView.script.sourceURL !== url)
- this._showScriptOrResource(option.representedObject, {initialLoad: true});
- }
+ return (script.sourceURL || script.sourceID) === sourceFileId;
}
-
- if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
- script.filesSelectOption.addStyleClass("extension-script");
+ return WebInspector.debuggerModel.queryScripts(filter)[0];
},
_clearCurrentExecutionLine: function()
@@ -670,31 +651,36 @@ WebInspector.ScriptsPanel.prototype = {
delete this._executionSourceFrame;
},
- _callFrameSelected: function()
+ _callFrameSelected: function(event)
{
+ var callFrame = event.data;
+
this._clearCurrentExecutionLine();
- var callStackPane = this.sidebarPanes.callstack;
- var currentFrame = callStackPane.selectedCallFrame;
- if (!currentFrame)
+ if (!callFrame)
return;
- this.sidebarPanes.scopechain.update(currentFrame);
+ this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
- var script = WebInspector.debuggerModel.scriptForSourceID(currentFrame.sourceID);
- var scriptOrResource = script.resource || script;
- this._showScriptOrResource(scriptOrResource, {line: currentFrame.line});
-
- this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
- if (this._executionSourceFrame)
- this._executionSourceFrame.setExecutionLine(currentFrame.line);
+ var sourceFileId = callFrame.sourceLocation.sourceFileId;
+ if (!(sourceFileId in this._sourceFileIdToFilesSelectOption)) {
+ // This happens in two cases:
+ // 1) Current call frame function is defined in anonymous script (anonymous scripts aren't added to files select by default)
+ // 2) We are debugging synchronously executed inlined script and there is no resource so far
+ this._addOptionToFilesSelect(sourceFileId);
+ }
+ var sourceFrame = this._showSourceFrameAndAddToHistory(sourceFileId);
+ if (sourceFrame.loaded) {
+ sourceFrame.setExecutionLine(callFrame.sourceLocation.lineNumber);
+ this._executionSourceFrame = sourceFrame;
+ }
},
- _changeVisibleFile: function(event)
+ _filesSelectChanged: function()
{
- var select = this.filesSelectElement;
- this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
+ var sourceFileId = this._filesSelectElement[this._filesSelectElement.selectedIndex]._sourceFileId;
+ this._showSourceFrameAndAddToHistory(sourceFileId);
},
_startSidebarResizeDrag: function(event)
@@ -747,7 +733,7 @@ WebInspector.ScriptsPanel.prototype = {
this._pauseOnExceptionButton.state = pauseOnExceptionsState;
WebInspector.settings.pauseOnExceptionState = pauseOnExceptionsState;
}
- InspectorBackend.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
+ DebuggerAgent.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
},
_updateDebuggerButtons: function()
@@ -812,7 +798,7 @@ WebInspector.ScriptsPanel.prototype = {
return;
}
- this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true});
+ this._showSourceFrame(this._backForwardList[--this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},
@@ -823,7 +809,7 @@ WebInspector.ScriptsPanel.prototype = {
return;
}
- this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true});
+ this._showSourceFrame(this._backForwardList[++this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},
@@ -865,11 +851,11 @@ WebInspector.ScriptsPanel.prototype = {
if (this._paused) {
this._paused = false;
this._waitingToPause = false;
- InspectorBackend.resume();
+ DebuggerAgent.resume();
} else {
this._stepping = false;
this._waitingToPause = true;
- InspectorBackend.pause();
+ DebuggerAgent.pause();
}
this._clearInterface();
@@ -882,7 +868,7 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepOver();
+ DebuggerAgent.stepOver();
},
_stepIntoClicked: function()
@@ -892,7 +878,7 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepInto();
+ DebuggerAgent.stepInto();
},
_stepOutClicked: function()
@@ -902,18 +888,18 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepOut();
+ DebuggerAgent.stepOut();
},
toggleBreakpointsClicked: function()
{
this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
if (this.toggleBreakpointsButton.toggled) {
- InspectorBackend.activateBreakpoints();
+ DebuggerAgent.activateBreakpoints();
this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
} else {
- InspectorBackend.deactivateBreakpoints();
+ DebuggerAgent.deactivateBreakpoints();
this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
}
@@ -976,8 +962,6 @@ WebInspector.ScriptsPanel.prototype = {
searchCanceled: function()
{
- WebInspector.updateSearchMatchesCount(0, this);
-
if (this._searchView)
this._searchView.searchCanceled();
@@ -987,6 +971,8 @@ WebInspector.ScriptsPanel.prototype = {
performSearch: function(query)
{
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
+
if (!this.visibleView)
return;
@@ -1001,7 +987,7 @@ WebInspector.ScriptsPanel.prototype = {
if (!searchMatches)
return;
- WebInspector.updateSearchMatchesCount(searchMatches, this);
+ WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
view.jumpToFirstSearchResult();
}
@@ -1053,39 +1039,205 @@ WebInspector.ScriptsPanel.prototype = {
WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.SourceFrameContentProviderForScript = function(script)
+WebInspector.SourceFrameDelegateForScriptsPanel = function(script)
{
- WebInspector.SourceFrameContentProvider.call(this);
+ WebInspector.SourceFrameDelegate.call(this);
this._script = script;
+ this._popoverObjectGroup = "popover";
}
-WebInspector.SourceFrameContentProviderForScript.prototype = {
+WebInspector.SourceFrameDelegateForScriptsPanel.prototype = {
requestContent: function(callback)
{
- if (this._script.source) {
- callback("text/javascript", this._script.source);
+ function didGetTextAndScriptRanges(mimeType, text, scriptRanges)
+ {
+ this._content = new WebInspector.SourceFrameContent(text, new WebInspector.IdenticalSourceMapping(), scriptRanges);
+ callback(mimeType, this._content);
+ }
+
+ if (this._script.resource)
+ this._loadResourceContent(this._script.resource, didGetTextAndScriptRanges.bind(this));
+ else
+ this._loadAndConcatenateScriptsContent(didGetTextAndScriptRanges.bind(this));
+ },
+
+ _loadResourceContent: function(resource, callback)
+ {
+ function didRequestContent(text)
+ {
+ var mimeType = "text/javascript";
+ if (resource.type !== WebInspector.Resource.Type.Script) {
+ mimeType = "text/html";
+ // WebKit html lexer normalizes line endings and scripts are passed to VM with "\n" line endings.
+ // However, resource content has original line endings, so we have to normalize line endings here.
+ text = text.replace(/\r\n/g, "\n");
+ }
+ var scripts = this._scripts();
+ var scriptRanges = WebInspector.ScriptFormatter.findScriptRanges(text.lineEndings(), scripts);
+ callback(mimeType, text, scriptRanges);
+ }
+ resource.requestContent(didRequestContent.bind(this));
+ },
+
+ _loadAndConcatenateScriptsContent: function(callback)
+ {
+ var scripts = this._scripts();
+ var scriptsLeft = scripts.length;
+ var sources = [];
+ function didRequestSource(index, source)
+ {
+ sources[index] = source;
+ if (--scriptsLeft)
+ return;
+ var result = this._buildSource(scripts, sources);
+ callback(result.mimeType, result.source, result.scriptRanges);
+ }
+ for (var i = 0; i < scripts.length; ++i)
+ scripts[i].requestSource(didRequestSource.bind(this, i));
+ },
+
+ _buildSource: function(scripts, sources)
+ {
+ var source = "";
+ var lineNumber = 0;
+ var columnNumber = 0;
+ var scriptRanges = [];
+ function appendChunk(chunk, script)
+ {
+ var start = { lineNumber: lineNumber, columnNumber: columnNumber };
+ source += chunk;
+ var lineEndings = chunk.lineEndings();
+ var lineCount = lineEndings.length;
+ if (lineCount === 1)
+ columnNumber += chunk.length;
+ else {
+ lineNumber += lineCount - 1;
+ columnNumber = lineEndings[lineCount - 1] - lineEndings[lineCount - 2] - 1;
+ }
+ var end = { lineNumber: lineNumber, columnNumber: columnNumber };
+ if (script)
+ scriptRanges.push({ start: start, end: end, sourceID: script.sourceID });
+ }
+
+ var mimeType;
+ if (scripts.length === 1 && !scripts[0].lineOffset && !scripts[0].columnOffset) {
+ // Single script source.
+ mimeType = "text/javascript";
+ appendChunk(sources[0], scripts[0]);
+ } else {
+ // Scripts inlined in html document.
+ mimeType = "text/html";
+ var scriptOpenTag = "<script>";
+ var scriptCloseTag = "</script>";
+ for (var i = 0; i < scripts.length; ++i) {
+ // Fill the gap with whitespace characters.
+ while (lineNumber < scripts[i].lineOffset)
+ appendChunk("\n");
+ while (columnNumber < scripts[i].columnOffset - scriptOpenTag.length)
+ appendChunk(" ");
+
+ // Add script tag.
+ appendChunk(scriptOpenTag);
+ appendChunk(sources[i], scripts[i]);
+ appendChunk(scriptCloseTag);
+ }
+ }
+ return { mimeType: mimeType, source: source, scriptRanges: scriptRanges };
+ },
+
+ _scripts: function()
+ {
+ var scripts = [this._script];
+ if (this._script.sourceURL)
+ scripts = WebInspector.debuggerModel.scriptsForURL(this._script.sourceURL);
+ scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });
+ return scripts;
+ },
+
+ debuggingSupported: function()
+ {
+ return true;
+ },
+
+ setBreakpoint: function(lineNumber, condition, enabled)
+ {
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ if (this._script.sourceURL)
+ WebInspector.debuggerModel.setBreakpoint(this._script.sourceURL, location.lineNumber, location.columnNumber, condition, enabled);
+ else if (location.sourceID)
+ WebInspector.debuggerModel.setBreakpointBySourceId(location.sourceID, location.lineNumber, location.columnNumber, condition, enabled);
+ else
return;
+
+ if (!WebInspector.panels.scripts.breakpointsActivated)
+ WebInspector.panels.scripts.toggleBreakpointsClicked();
+ },
+
+ removeBreakpoint: function(breakpointId)
+ {
+ WebInspector.debuggerModel.removeBreakpoint(breakpointId);
+ },
+
+ updateBreakpoint: function(breakpointId, condition, enabled)
+ {
+ WebInspector.debuggerModel.updateBreakpoint(breakpointId, condition, enabled);
+ },
+
+ findBreakpoint: function(lineNumber)
+ {
+ var url = this._script.sourceURL;
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ function filter(breakpoint)
+ {
+ if (breakpoint.url) {
+ if (breakpoint.url !== url)
+ return false;
+ } else {
+ if (breakpoint.sourceID !== location.sourceID)
+ return false;
+ }
+ var lineNumber = breakpoint.locations.length ? breakpoint.locations[0].lineNumber : breakpoint.lineNumber;
+ return lineNumber === location.lineNumber;
}
+ return WebInspector.debuggerModel.queryBreakpoints(filter)[0];
+ },
+
+ continueToLine: function(lineNumber)
+ {
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ if (location.sourceID)
+ WebInspector.debuggerModel.continueToLocation(location.sourceID, location.lineNumber, location.columnNumber);
+ },
- function didRequestSource(content)
+ canEditScriptSource: function()
+ {
+ return Preferences.canEditScriptSource && !this._script.lineOffset && !this._script.columnOffset;
+ },
+
+ editScriptSource: function(text)
+ {
+ WebInspector.debuggerModel.editScriptSource(this._script.sourceID, text);
+ },
+
+ debuggerPaused: function()
+ {
+ return WebInspector.panels.scripts.paused;
+ },
+
+ evaluateInSelectedCallFrame: function(string, callback)
+ {
+ function didEvaluateInSelectedCallFrame(result)
{
- var source;
- if (content) {
- var prefix = "";
- for (var i = 0; i < this._script.startingLine - 1; ++i)
- prefix += "\n";
- source = prefix + content;
- } else
- source = WebInspector.UIString("<source is not available>");
- callback("text/javascript", source);
+ if (!result.isError() && this.debuggerPaused())
+ callback(result);
}
- this._script.requestSource(didRequestSource.bind(this));
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(string, this._popoverObjectGroup, false, didEvaluateInSelectedCallFrame.bind(this));
},
- scripts: function()
+ releaseEvaluationResult: function()
{
- return [this._script];
+ RuntimeAgent.releaseObjectGroup(0, this._popoverObjectGroup);
}
}
-WebInspector.SourceFrameContentProviderForScript.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
+WebInspector.SourceFrameDelegateForScriptsPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype;
diff --git a/Source/WebCore/inspector/front-end/SearchController.js b/Source/WebCore/inspector/front-end/SearchController.js
new file mode 100755
index 0000000..735c424
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/SearchController.js
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
+ * 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+WebInspector.SearchController = function()
+{
+ this.element = document.getElementById("search");
+ this._matchesElement = document.getElementById("search-results-matches");
+ this._toolbarLabelElement = document.getElementById("search-toolbar-label");
+
+ this.element.addEventListener("search", this._onSearch.bind(this), false); // when the search is emptied
+ this.element.addEventListener("mousedown", this._onSearchFieldManualFocus.bind(this), false); // when the search field is manually selected
+ this.element.addEventListener("keydown", this._onKeyDown.bind(this), true);
+}
+
+WebInspector.SearchController.prototype = {
+ updateSearchMatchesCount: function(matches, panel)
+ {
+ if (!panel)
+ panel = WebInspector.currentPanel;
+
+ panel.currentSearchMatches = matches;
+
+ if (panel === WebInspector.currentPanel)
+ this._updateSearchMatchesCount(WebInspector.currentPanel.currentQuery && matches);
+ },
+
+ updateSearchLabel: function()
+ {
+ var panelName = WebInspector.currentPanel && WebInspector.currentPanel.toolbarItemLabel;
+ if (!panelName)
+ return;
+ var newLabel = WebInspector.UIString("Search %s", panelName);
+ if (WebInspector.attached)
+ this.element.setAttribute("placeholder", newLabel);
+ else {
+ this.element.removeAttribute("placeholder");
+ this._toolbarLabelElement.textContent = newLabel;
+ }
+ },
+
+ cancelSearch: function()
+ {
+ this.element.value = "";
+ this._performSearch("");
+ },
+
+ handleShortcut: function(event)
+ {
+ var isMac = WebInspector.isMac();
+
+ switch (event.keyIdentifier) {
+ case "U+0046": // F key
+ if (isMac)
+ var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
+ else
+ var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
+
+ if (isFindKey) {
+ this._focusSearchField();
+ event.handled = true;
+ }
+ break;
+
+
+ case "F3":
+ if (!isMac) {
+ this._focusSearchField();
+ event.handled = true;
+ }
+ break;
+
+ case "U+0047": // G key
+ var currentPanel = WebInspector.currentPanel;
+
+ if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
+ if (event.shiftKey) {
+ if (currentPanel.jumpToPreviousSearchResult)
+ currentPanel.jumpToPreviousSearchResult();
+ } else if (currentPanel.jumpToNextSearchResult)
+ currentPanel.jumpToNextSearchResult();
+ event.handled = true;
+ }
+ break;
+ }
+ },
+
+ activePanelChanged: function()
+ {
+ this.updateSearchLabel();
+
+ if (!this._currentQuery)
+ return;
+
+ panel = WebInspector.currentPanel;
+ if (panel.performSearch) {
+ function performPanelSearch()
+ {
+ this._updateSearchMatchesCount();
+
+ panel.currentQuery = this._currentQuery;
+ panel.performSearch(this._currentQuery);
+ }
+
+ // Perform the search on a timeout so the panel switches fast.
+ setTimeout(performPanelSearch.bind(this), 0);
+ } else {
+ // Update to show Not found for panels that can't be searched.
+ this._updateSearchMatchesCount();
+ }
+ },
+
+ _updateSearchMatchesCount: function(matches)
+ {
+ if (matches == null) {
+ this._matchesElement.addStyleClass("hidden");
+ return;
+ }
+
+ if (matches) {
+ if (matches === 1)
+ var matchesString = WebInspector.UIString("1 match");
+ else
+ var matchesString = WebInspector.UIString("%d matches", matches);
+ } else
+ var matchesString = WebInspector.UIString("Not Found");
+
+ this._matchesElement.removeStyleClass("hidden");
+ this._matchesElement.textContent = matchesString;
+ WebInspector.toolbar.resize();
+ },
+
+ _focusSearchField: function()
+ {
+ this.element.focus();
+ this.element.select();
+ },
+
+ _onSearchFieldManualFocus: function(event)
+ {
+ WebInspector.currentFocusElement = event.target;
+ },
+
+ _onKeyDown: function(event)
+ {
+ // Escape Key will clear the field and clear the search results
+ if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+ // If focus belongs here and text is empty - nothing to do, return unhandled.
+ // When search was selected manually and is currently blank, we'd like Esc stay unhandled
+ // and hit console drawer handler.
+ if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
+ return;
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.cancelSearch(event);
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+ if (WebInspector.currentFocusElement === event.target)
+ WebInspector.currentFocusElement.currentFocusElement.select();
+ return false;
+ }
+
+ if (!isEnterKey(event))
+ return false;
+
+ // Select all of the text so the user can easily type an entirely new query.
+ event.target.select();
+
+ // Only call performSearch if the Enter key was pressed. Otherwise the search
+ // performance is poor because of searching on every key. The search field has
+ // the incremental attribute set, so we still get incremental searches.
+ this._onSearch(event);
+
+ // Call preventDefault since this was the Enter key. This prevents a "search" event
+ // from firing for key down. This stops performSearch from being called twice in a row.
+ event.preventDefault();
+ },
+
+ _onSearch: function(event)
+ {
+ var forceSearch = event.keyIdentifier === "Enter";
+ this._performSearch(event.target.value, forceSearch, event.shiftKey, false);
+ },
+
+ _performSearch: function(query, forceSearch, isBackwardSearch, repeatSearch)
+ {
+ var isShortSearch = (query.length < 3);
+
+ // Clear a leftover short search flag due to a non-conflicting forced search.
+ if (isShortSearch && this._shortSearchWasForcedByKeyEvent && this._currentQuery !== query)
+ delete this._shortSearchWasForcedByKeyEvent;
+
+ // Indicate this was a forced search on a short query.
+ if (isShortSearch && forceSearch)
+ this._shortSearchWasForcedByKeyEvent = true;
+
+ if (!query || !query.length || (!forceSearch && isShortSearch)) {
+ // Prevent clobbering a short search forced by the user.
+ if (this._shortSearchWasForcedByKeyEvent) {
+ delete this._shortSearchWasForcedByKeyEvent;
+ return;
+ }
+
+ delete this._currentQuery;
+
+ for (var panelName in WebInspector.panels) {
+ var panel = WebInspector.panels[panelName];
+ var hadCurrentQuery = !!panel.currentQuery;
+ delete panel.currentQuery;
+ if (hadCurrentQuery && panel.searchCanceled)
+ panel.searchCanceled();
+ }
+
+ this._updateSearchMatchesCount();
+
+ return;
+ }
+
+ var currentPanel = WebInspector.currentPanel;
+ if (!repeatSearch && query === currentPanel.currentQuery && currentPanel.currentQuery === this._currentQuery) {
+ // When this is the same query and a forced search, jump to the next
+ // search result for a good user experience.
+ if (forceSearch) {
+ if (!isBackwardSearch && currentPanel.jumpToNextSearchResult)
+ currentPanel.jumpToNextSearchResult();
+ else if (isBackwardSearch && currentPanel.jumpToPreviousSearchResult)
+ currentPanel.jumpToPreviousSearchResult();
+ }
+ return;
+ }
+
+ this._currentQuery = query;
+
+ this._updateSearchMatchesCount();
+
+ if (!currentPanel.performSearch)
+ return;
+
+ currentPanel.currentQuery = query;
+ currentPanel.performSearch(query);
+ }
+}
diff --git a/Source/WebCore/inspector/front-end/SourceFrame.js b/Source/WebCore/inspector/front-end/SourceFrame.js
index f2e0be1..3120159 100644
--- a/Source/WebCore/inspector/front-end/SourceFrame.js
+++ b/Source/WebCore/inspector/front-end/SourceFrame.js
@@ -28,15 +28,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.SourceFrame = function(contentProvider, url, isScript)
+WebInspector.SourceFrame = function(delegate, url)
{
WebInspector.View.call(this);
this.element.addStyleClass("script-view");
- this._contentProvider = contentProvider;
+ this._delegate = delegate;
this._url = url;
- this._isScript = isScript;
this._textModel = new WebInspector.TextEditorModel();
this._textModel.replaceTabsWithSpaces = true;
@@ -47,8 +46,10 @@ WebInspector.SourceFrame = function(contentProvider, url, isScript)
this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};
+}
- this._popoverObjectGroup = "popover";
+WebInspector.SourceFrame.Events = {
+ Loaded: "loaded"
}
WebInspector.SourceFrame.prototype = {
@@ -59,7 +60,7 @@ WebInspector.SourceFrame.prototype = {
if (!this._contentRequested) {
this._contentRequested = true;
- this._contentProvider.requestContent(this._createTextViewer.bind(this));
+ this._delegate.requestContent(this._createTextViewer.bind(this));
}
if (this._textViewer) {
@@ -85,6 +86,11 @@ WebInspector.SourceFrame.prototype = {
this._clearLineHighlight();
},
+ get loaded()
+ {
+ return !!this._content;
+ },
+
hasContent: function()
{
return true;
@@ -132,12 +138,6 @@ WebInspector.SourceFrame.prototype = {
this._textViewer.resize();
},
- sizeToFitContentHeight: function()
- {
- if (this._textViewer)
- this._textViewer.revalidateDecorationsAndPaint();
- },
-
get textModel()
{
return this._textModel;
@@ -171,18 +171,34 @@ WebInspector.SourceFrame.prototype = {
delete this._lineToHighlight;
},
- _createTextViewer: function(mimeType, text)
+ _startEditing: function()
{
- this._content = new WebInspector.SourceFrameContent(text, this._contentProvider.scripts());
- this._textModel.setText(null, text);
+ WebInspector.searchController.cancelSearch();
+ this.clearMessages();
+ },
+
+ _endEditing: function(oldRange, newRange)
+ {
+ // FIXME: Implement this.
+ },
+
+ _createTextViewer: function(mimeType, content)
+ {
+ this._content = content;
+ this._textModel.setText(null, content.text);
this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url);
+ this._textViewer.startEditingListener = this._startEditing.bind(this);
+ this._textViewer.endEditingListener = this._endEditing.bind(this);
+
var element = this._textViewer.element;
- element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
- element.addEventListener("mousedown", this._mouseDown.bind(this), true);
- element.addEventListener("mousemove", this._mouseMove.bind(this), true);
- element.addEventListener("scroll", this._scroll.bind(this), true);
- element.addEventListener("dblclick", this._doubleClick.bind(this), true);
+ if (this._delegate.debuggingSupported()) {
+ element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
+ element.addEventListener("mousedown", this._mouseDown.bind(this), true);
+ element.addEventListener("mousemove", this._mouseMove.bind(this), true);
+ element.addEventListener("dblclick", this._doubleClick.bind(this), true);
+ element.addEventListener("scroll", this._scroll.bind(this), true);
+ }
this.element.appendChild(element);
this._textViewer.beginUpdates();
@@ -205,11 +221,9 @@ WebInspector.SourceFrame.prototype = {
delete this._delayedFindSearchMatches;
}
- this._textViewer.endUpdates();
+ this.dispatchEventToListeners(WebInspector.SourceFrame.Events.Loaded);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+ this._textViewer.endUpdates();
},
_setTextViewerDecorations: function()
@@ -222,32 +236,11 @@ WebInspector.SourceFrame.prototype = {
this._addExistingMessagesToSource();
this._updateDiffDecorations();
- if (this._executionLine)
- this.setExecutionLine(this._executionLine);
-
- this._breakpointIdToTextViewerLineNumber = {};
- this._textViewerLineNumberToBreakpointId = {};
- var breakpoints = WebInspector.debuggerModel.breakpoints;
- for (var id in breakpoints)
- this._breakpointAdded({ data: breakpoints[id] });
-
this._textViewer.resize();
this._textViewer.endUpdates();
},
- _shouldDisplayBreakpoint: function(breakpoint)
- {
- if (this._url)
- return this._url === breakpoint.url;
- var scripts = this._contentProvider.scripts();
- for (var i = 0; i < scripts.length; ++i) {
- if (breakpoint.sourceID === scripts[i].sourceID)
- return true;
- }
- return false;
- },
-
performSearch: function(query, callback)
{
// Call searchCanceled since it will reset everything we need before doing a new search.
@@ -363,20 +356,15 @@ WebInspector.SourceFrame.prototype = {
setExecutionLine: function(lineNumber)
{
- this._executionLine = lineNumber;
- if (!this._textViewer)
- return;
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(this._executionLine - 1, 0);
- this._textViewer.addDecoration(textViewerLineNumber, "webkit-execution-line");
+ this._executionLineNumber = lineNumber;
+ this._textViewer.addDecoration(lineNumber, "webkit-execution-line");
+ this._textViewer.revealLine(lineNumber);
},
clearExecutionLine: function()
{
- if (!this._textViewer)
- return;
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(this._executionLine - 1, 0);
- this._textViewer.removeDecoration(textViewerLineNumber, "webkit-execution-line");
- delete this._executionLine;
+ this._textViewer.removeDecoration(this._executionLineNumber, "webkit-execution-line");
+ delete this._executionLineNumber;
},
_updateDiffDecorations: function()
@@ -467,63 +455,18 @@ WebInspector.SourceFrame.prototype = {
msg._resourceMessageLineElement = messageLineElement;
},
- _breakpointAdded: function(event)
- {
- var breakpoint = event.data;
-
- if (!this._shouldDisplayBreakpoint(breakpoint))
- return;
-
- var resolved = breakpoint.locations.length;
- var location = resolved ? breakpoint.locations[0] : breakpoint;
-
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(location.lineNumber, location.columnNumber);
- if (textViewerLineNumber >= this._textModel.linesCount)
- return;
-
- var existingBreakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- if (existingBreakpointId) {
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
- return;
- }
-
- this._breakpointIdToTextViewerLineNumber[breakpoint.id] = textViewerLineNumber;
- this._textViewerLineNumberToBreakpointId[textViewerLineNumber] = breakpoint.id;
- this._setBreakpointDecoration(textViewerLineNumber, resolved, breakpoint.enabled, !!breakpoint.condition);
- },
-
- _breakpointRemoved: function(event)
- {
- var breakpointId = event.data;
-
- var textViewerLineNumber = this._breakpointIdToTextViewerLineNumber[breakpointId];
- if (textViewerLineNumber === undefined)
- return;
-
- delete this._breakpointIdToTextViewerLineNumber[breakpointId];
- delete this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- this._removeBreakpointDecoration(textViewerLineNumber);
- },
-
- _breakpointResolved: function(event)
- {
- var breakpoint = event.data;
- this._breakpointRemoved({ data: breakpoint.id });
- this._breakpointAdded({ data: breakpoint });
- },
-
- _setBreakpointDecoration: function(lineNumber, resolved, enabled, hasCondition)
+ addBreakpoint: function(lineNumber, resolved, conditional, enabled)
{
this._textViewer.beginUpdates();
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint");
if (!enabled)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
- if (hasCondition)
+ if (conditional)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional");
this._textViewer.endUpdates();
},
- _removeBreakpointDecoration: function(lineNumber)
+ removeBreakpoint: function(lineNumber)
{
this._textViewer.beginUpdates();
this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint");
@@ -534,55 +477,48 @@ WebInspector.SourceFrame.prototype = {
_contextMenu: function(event)
{
- if (!WebInspector.panels.scripts)
- return;
-
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (!target)
return;
- var textViewerLineNumber = target.lineNumber;
+ var lineNumber = target.lineNumber;
var contextMenu = new WebInspector.ContextMenu();
- contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._continueToLine.bind(this, textViewerLineNumber));
+ contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._delegate.continueToLine.bind(this._delegate, lineNumber));
- var breakpoint = this._findBreakpoint(textViewerLineNumber);
+ var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (!breakpoint) {
// This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
- contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._setBreakpoint.bind(this, textViewerLineNumber, "", true));
+ contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._delegate.setBreakpoint.bind(this._delegate, lineNumber, "", true));
function addConditionalBreakpoint()
{
- this._setBreakpointDecoration(textViewerLineNumber, true, true, true);
+ this.addBreakpoint(lineNumber, true, true, true);
function didEditBreakpointCondition(committed, condition)
{
- this._removeBreakpointDecoration(textViewerLineNumber);
+ this.removeBreakpoint(lineNumber);
if (committed)
- this._setBreakpoint(textViewerLineNumber, condition, true);
+ this._delegate.setBreakpoint(lineNumber, condition, true);
}
- this._editBreakpointCondition(textViewerLineNumber, "", didEditBreakpointCondition.bind(this));
+ this._editBreakpointCondition(lineNumber, "", didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this));
} else {
// This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
- function removeBreakpoint()
- {
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
- }
- contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint);
+ contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), this._delegate.removeBreakpoint.bind(this._delegate, breakpoint.id));
function editBreakpointCondition()
{
function didEditBreakpointCondition(committed, condition)
{
if (committed)
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, condition, breakpoint.enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, condition, breakpoint.enabled);
}
- this._editBreakpointCondition(textViewerLineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
+ this._editBreakpointCondition(lineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint…"), editBreakpointCondition.bind(this));
function setBreakpointEnabled(enabled)
{
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, breakpoint.condition, enabled);
}
if (breakpoint.enabled)
contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), setBreakpointEnabled.bind(this, false));
@@ -606,16 +542,16 @@ WebInspector.SourceFrame.prototype = {
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (!target)
return;
- var textViewerLineNumber = target.lineNumber;
+ var lineNumber = target.lineNumber;
- var breakpoint = this._findBreakpoint(textViewerLineNumber);
+ var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (breakpoint) {
if (event.shiftKey)
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, !breakpoint.enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, breakpoint.condition, !breakpoint.enabled);
else
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+ this._delegate.removeBreakpoint(breakpoint.id);
} else
- this._setBreakpoint(textViewerLineNumber, "", true);
+ this._delegate.setBreakpoint(lineNumber, "", true);
event.preventDefault();
},
@@ -641,7 +577,7 @@ WebInspector.SourceFrame.prototype = {
this._hoverElement = event.target;
// Now that cleanup routines are set up above, leave this in case we are not on a break.
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+ if (!this._delegate.debuggerPaused())
return;
// We are interested in identifiers and "this" keyword.
@@ -680,16 +616,13 @@ WebInspector.SourceFrame.prototype = {
this._popup.hide();
delete this._popup;
- InspectorBackend.releaseWrapperObjectGroup(0, this._popoverObjectGroup);
+ this._delegate.releaseEvaluationResult();
},
_mouseHover: function(element)
{
delete this._hoverTimer;
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
- return;
-
var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return;
@@ -729,9 +662,6 @@ WebInspector.SourceFrame.prototype = {
function showObjectPopup(result)
{
- if (!WebInspector.panels.scripts.paused)
- return;
-
var popupContentElement = null;
if (result.type !== "object" && result.type !== "node" && result.type !== "array") {
popupContentElement = document.createElement("span");
@@ -766,15 +696,7 @@ WebInspector.SourceFrame.prototype = {
popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true);
}
- function evaluateCallback(result)
- {
- if (result.isError())
- return;
- if (!WebInspector.panels.scripts.paused)
- return;
- showObjectPopup.call(this, result);
- }
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(element.textContent, false, this._popoverObjectGroup, false, evaluateCallback.bind(this));
+ this._delegate.evaluateInSelectedCallFrame(element.textContent, showObjectPopup.bind(this));
},
_editBreakpointCondition: function(lineNumber, condition, callback)
@@ -820,24 +742,6 @@ WebInspector.SourceFrame.prototype = {
return conditionElement;
},
- _evalSelectionInCallFrame: function(event)
- {
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
- return;
-
- var selection = this.element.contentWindow.getSelection();
- if (!selection.rangeCount)
- return;
-
- var expression = selection.getRangeAt(0).toString().trim();
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result) {
- WebInspector.showConsole();
- var commandMessage = new WebInspector.ConsoleCommand(expression);
- WebInspector.console.addMessage(commandMessage);
- WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, commandMessage));
- });
- },
-
resize: function()
{
if (this._textViewer)
@@ -851,7 +755,7 @@ WebInspector.SourceFrame.prototype = {
function didFormat(formattedContent)
{
- this._formattedContent = formattedContent;
+ this._content = formattedContent;
this._textModel.setText(null, formattedContent.text);
this._setTextViewerDecorations();
}
@@ -859,91 +763,96 @@ WebInspector.SourceFrame.prototype = {
formatter.formatContent(this._content, didFormat.bind(this))
},
- _continueToLine: function(lineNumber)
- {
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (location.sourceID)
- WebInspector.debuggerModel.continueToLine(location.sourceID, location.lineNumber);
- },
-
_doubleClick: function(event)
{
- if (!Preferences.canEditScriptSource || !this._isScript)
+ if (!this._delegate.canEditScriptSource())
return;
var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return; // Do not trigger editing from line numbers.
- var lineNumber = lineRow.lineNumber;
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (!location.sourceID)
- return;
+ this._textViewer.editLine(lineRow, this._didEditLine.bind(this, lineRow.lineNumber));
+ },
- function didEditLine(newContent)
- {
- var lines = [];
- var oldLines = this._content.text.split('\n');
- for (var i = 0; i < oldLines.length; ++i) {
- if (i === lineNumber)
- lines.push(newContent);
- else
- lines.push(oldLines[i]);
- }
- WebInspector.debuggerModel.editScriptSource(location.sourceID, lines.join("\n"));
+ _didEditLine: function(lineNumber, newContent)
+ {
+ var lines = [];
+ var oldLines = this._content.text.split('\n');
+ for (var i = 0; i < oldLines.length; ++i) {
+ if (i === lineNumber)
+ lines.push(newContent);
+ else
+ lines.push(oldLines[i]);
}
- this._textViewer.editLine(lineRow, didEditLine.bind(this));
+ this._delegate.editScriptSource(lines.join("\n"));
+ }
+}
+
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;
+
+
+WebInspector.SourceFrameDelegate = function()
+{
+}
+
+WebInspector.SourceFrameDelegate.prototype = {
+ requestContent: function(callback)
+ {
+ // Should be implemented by subclasses.
},
- _setBreakpoint: function(lineNumber, condition, enabled)
+ debuggingSupported: function()
{
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (this._url)
- WebInspector.debuggerModel.setBreakpoint(this._url, location.lineNumber, location.columnNumber, condition, enabled);
- else if (location.sourceID)
- WebInspector.debuggerModel.setBreakpointBySourceId(location.sourceID, location.lineNumber, location.columnNumber, condition, enabled);
- else
- return;
+ return false;
+ },
- if (!WebInspector.panels.scripts.breakpointsActivated)
- WebInspector.panels.scripts.toggleBreakpointsClicked();
+ setBreakpoint: function(lineNumber, condition, enabled)
+ {
+ // Should be implemented by subclasses.
},
- _findBreakpoint: function(textViewerLineNumber)
+ removeBreakpoint: function(breakpointId)
{
- var breakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- return WebInspector.debuggerModel.breakpointForId(breakpointId);
+ // Should be implemented by subclasses.
},
- _originalLocationToTextViewerLineNumber: function(lineNumber, columnNumber)
+ updateBreakpoint: function(breakpointId, condition, enabled)
{
- if (!this._formattedContent)
- return lineNumber;
- return this._formattedContent.originalLocationToFormattedLocation(lineNumber, columnNumber).lineNumber;
+ // Should be implemented by subclasses.
},
- _textViewerLineNumberToScriptLocation: function(lineNumber)
+ findBreakpoint: function(lineNumber)
{
- if (!this._formattedContent)
- return this._content.scriptLocationForLineNumber(lineNumber);
- return this._formattedContent.scriptLocationForFormattedLineNumber(lineNumber);
- }
-}
+ // Should be implemented by subclasses.
+ },
-WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;
+ continueToLine: function(lineNumber)
+ {
+ // Should be implemented by subclasses.
+ },
+ canEditScriptSource: function()
+ {
+ return false;
+ },
-WebInspector.SourceFrameContentProvider = function()
-{
-}
+ editScriptSource: function(text)
+ {
+ // Should be implemented by subclasses.
+ },
-WebInspector.SourceFrameContentProvider.prototype = {
- requestContent: function(callback)
+ debuggerPaused: function()
+ {
+ // Should be implemented by subclasses.
+ },
+
+ evaluateInSelectedCallFrame: function(string)
{
// Should be implemented by subclasses.
},
- scripts: function()
+ releaseEvaluationResult: function()
{
// Should be implemented by subclasses.
}
diff --git a/Source/WebCore/inspector/front-end/SourceFrameContent.js b/Source/WebCore/inspector/front-end/SourceFrameContent.js
index e4a74ec..91b397b 100644
--- a/Source/WebCore/inspector/front-end/SourceFrameContent.js
+++ b/Source/WebCore/inspector/front-end/SourceFrameContent.js
@@ -28,24 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.SourceFrameContent = function(text, scripts)
+WebInspector.SourceFrameContent = function(text, mapping, scriptRanges)
{
- if (scripts.length && scripts[0].length < text.length) {
- // WebKit html lexer normalizes line endings and scripts are passed to VM with "\n" line endings.
- // However, resource content has original line endings, so we have to normalize line endings here.
- text = text.replace(/\r\n/g, "\n");
- }
this._text = text;
- this._lineEndings = text.findAll("\n");
- this._lineEndings.push(text.length);
-
- this._scriptRanges = [];
- for (var i = 0; i < scripts.length; ++i) {
- var script = scripts[i];
- var offset = this.locationToPosition(script.lineOffset, script.columnOffset);
- this._scriptRanges.push({ start: offset, end: offset + script.length, script: script });
- }
- this._scriptRanges.sort(function(x, y) { return x.start - y.start; });
+ this._mapping = mapping;
+ this._scriptRanges = scriptRanges;
}
WebInspector.SourceFrameContent.prototype = {
@@ -59,95 +46,77 @@ WebInspector.SourceFrameContent.prototype = {
return this._scriptRanges;
},
- locationToPosition: function(lineNumber, columnNumber)
- {
- var position = lineNumber ? this._lineEndings[lineNumber - 1] + 1 : 0;
- return position + columnNumber;
- },
-
- positionToLocation: function(position)
+ sourceFrameLineNumberToActualLocation: function(lineNumber)
{
- var location = {};
- location.lineNumber = this._lineEndings.upperBound(position - 1);
- if (!location.lineNumber)
- location.columnNumber = position;
- else
- location.columnNumber = position - this._lineEndings[location.lineNumber - 1] - 1;
+ // Script content may start right after <script> tag without new line (e.g. "<script>function f()...").
+ // In that case, column number should be equal to script column offset.
+ var columnNumber = 0;
+ for (var i = 0; i < this._scriptRanges.length; ++i) {
+ var scriptRange = this._scriptRanges[i];
+ if (scriptRange.start.lineNumber < lineNumber)
+ continue;
+ if (scriptRange.start.lineNumber === lineNumber)
+ columnNumber = scriptRange.start.columnNumber;
+ break;
+ }
+ var location = this._mapping.sourceLocationToActualLocation(lineNumber, columnNumber);
+ location.sourceID = this._sourceIDForSourceFrameLineNumber(lineNumber);
return location;
},
- scriptLocationForLineNumber: function(lineNumber)
- {
- var range = this.lineNumberToRange(lineNumber);
- return this.scriptLocationForRange(range.start, range.end);
- },
-
- scriptLocationForRange: function(start, end)
+ actualLocationToSourceFrameLineNumber: function(lineNumber, columnNumber)
{
- var position = start;
- var scriptRange = this._intersectingScriptRange(start, end);
- if (scriptRange)
- position = Math.max(position, scriptRange.start);
- var scriptLocation = this.positionToLocation(position);
- if (scriptRange)
- scriptLocation.sourceID = scriptRange.script.sourceID;
- return scriptLocation;
+ return this._mapping.actualLocationToSourceLocation(lineNumber, columnNumber).lineNumber;
},
- lineNumberToRange: function(lineNumber)
- {
- var previousLineEnd = this._lineEndings[lineNumber - 1] || 0;
- var lineEnd = this._lineEndings[lineNumber];
- return { start: previousLineEnd + 1, end: lineEnd };
- },
-
- _intersectingScriptRange: function(start, end)
+ _sourceIDForSourceFrameLineNumber: function(lineNumber)
{
for (var i = 0; i < this._scriptRanges.length; ++i) {
var scriptRange = this._scriptRanges[i];
- if (start < scriptRange.end && end > scriptRange.start)
- return scriptRange;
+ if (lineNumber < scriptRange.start.lineNumber)
+ return;
+ if (lineNumber > scriptRange.end.lineNumber)
+ continue;
+ if (lineNumber === scriptRange.end.lineNumber && !scriptRange.end.columnNumber)
+ continue;
+ return scriptRange.sourceID;
}
}
}
-WebInspector.FormattedSourceFrameContent = function(originalContent, text, mapping)
+WebInspector.SourceMapping = function()
{
- this._originalContent = originalContent;
- this._formattedContent = new WebInspector.SourceFrameContent(text, []);
- this._mapping = mapping;
}
-WebInspector.FormattedSourceFrameContent.prototype = {
- get text()
+WebInspector.SourceMapping.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
{
- return this._formattedContent.text;
+ // Should be implemented by subclasses.
},
- originalLocationToFormattedLocation: function(lineNumber, columnNumber)
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
{
- var originalPosition = this._originalContent.locationToPosition(lineNumber, columnNumber);
- var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition);
- return this._formattedContent.positionToLocation(formattedPosition);
- },
+ // Should be implemented by subclasses.
+ }
+}
+
+
+WebInspector.IdenticalSourceMapping = function()
+{
+ WebInspector.SourceMapping.call(this);
+}
- scriptLocationForFormattedLineNumber: function(lineNumber)
+WebInspector.IdenticalSourceMapping.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
{
- var range = this._formattedContent.lineNumberToRange(lineNumber);
- var start = this._convertPosition(this._mapping.formatted, this._mapping.original, range.start);
- var end = this._convertPosition(this._mapping.formatted, this._mapping.original, range.end);
- return this._originalContent.scriptLocationForRange(start, end);
+ return { lineNumber: lineNumber, columnNumber: columnNumber};
},
- _convertPosition: function(positions1, positions2, position)
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
{
- var index = positions1.upperBound(position);
- var range1 = positions1[index] - positions1[index - 1];
- var range2 = positions2[index] - positions2[index - 1];
- var position2 = positions2[index - 1];
- if (range1)
- position2 += Math.round((position - positions1[index - 1]) * range2 / range1);
- return position2;
+ return { lineNumber: lineNumber, columnNumber: columnNumber};
}
}
+
+WebInspector.IdenticalSourceMapping.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/Source/WebCore/inspector/front-end/SourceTokenizer.js b/Source/WebCore/inspector/front-end/SourceTokenizer.js
index d30744c..bb44a86 100644
--- a/Source/WebCore/inspector/front-end/SourceTokenizer.js
+++ b/Source/WebCore/inspector/front-end/SourceTokenizer.js
@@ -48,11 +48,6 @@ WebInspector.SourceTokenizer.prototype = {
return this._condition;
},
- get subTokenizer()
- {
- return this._condition.subTokenizer;
- },
-
getLexCondition: function()
{
return this.condition.lexCondition;
diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js
index 57d3b76..c7d151a 100644
--- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -438,7 +438,7 @@ WebInspector.StylesSidebarPane.prototype = {
if (computedStyle)
var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties, disabledComputedProperties, styleRules);
else
- var section = new WebInspector.StylePropertiesSection(styleRule, editable, styleRule.isInherited, lastWasSeparator);
+ var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator);
section.pane = this;
section.expanded = true;
@@ -503,7 +503,7 @@ WebInspector.StylesSidebarPane.prototype = {
addBlankSection: function()
{
- var blankSection = new WebInspector.BlankStylePropertiesSection(appropriateSelectorForNode(this.node, true));
+ var blankSection = new WebInspector.BlankStylePropertiesSection(this, appropriateSelectorForNode(this.node, true));
blankSection.pane = this;
var elementStyleSection = this.sections[0][1];
@@ -591,7 +591,7 @@ WebInspector.ComputedStyleSidebarPane = function()
WebInspector.ComputedStyleSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
-WebInspector.StylePropertiesSection = function(styleRule, editable, isInherited, isFirstSection)
+WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, isInherited, isFirstSection)
{
WebInspector.PropertiesSection.call(this, "");
this.element.className = "styles-section monospace" + (isFirstSection ? " first-styles-section" : "");
@@ -613,6 +613,7 @@ WebInspector.StylePropertiesSection = function(styleRule, editable, isInherited,
this._selectorElement.addEventListener("dblclick", this._handleSelectorDoubleClick.bind(this), false);
this.element.addEventListener("dblclick", this._handleEmptySpaceDoubleClick.bind(this), false);
+ this._parentPane = parentPane;
this.styleRule = styleRule;
this.rule = this.styleRule.rule;
this.editable = editable;
@@ -792,7 +793,7 @@ WebInspector.StylePropertiesSection.prototype = {
var inherited = this.isPropertyInherited(property.name);
var overloaded = this.isPropertyOverloaded(property.name, isShorthand);
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, isShorthand, inherited, overloaded);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded);
this.propertiesTreeOutline.appendChild(item);
handledProperties[property.name] = property;
}
@@ -813,7 +814,7 @@ WebInspector.StylePropertiesSection.prototype = {
{
var style = this.styleRule.style;
var property = style.newBlankProperty();
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, false, false);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, false, false);
this.propertiesTreeOutline.appendChild(item);
item.listItemElement.textContent = "";
item._newProperty = true;
@@ -1025,7 +1026,7 @@ WebInspector.ComputedStylePropertiesSection.prototype = {
for (var i = 0; i < uniqueProperties.length; ++i) {
var property = uniqueProperties[i];
var inherited = this._isPropertyInherited(property.name);
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, inherited, false);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, inherited, false);
this.propertiesTreeOutline.appendChild(item);
this._propertyTreeElements[property.name] = item;
}
@@ -1070,9 +1071,9 @@ WebInspector.ComputedStylePropertiesSection.prototype = {
WebInspector.ComputedStylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-WebInspector.BlankStylePropertiesSection = function(defaultSelectorText)
+WebInspector.BlankStylePropertiesSection = function(parentPane, defaultSelectorText)
{
- WebInspector.StylePropertiesSection.call(this, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
+ WebInspector.StylePropertiesSection.call(this, parentPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
this.element.addStyleClass("blank-section");
}
@@ -1121,8 +1122,9 @@ WebInspector.BlankStylePropertiesSection.prototype = {
WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype;
-WebInspector.StylePropertyTreeElement = function(styleRule, style, property, shorthand, inherited, overloaded)
+WebInspector.StylePropertyTreeElement = function(parentPane, styleRule, style, property, shorthand, inherited, overloaded)
{
+ this._parentPane = parentPane;
this._styleRule = styleRule;
this.style = style;
this.property = property;
@@ -1483,7 +1485,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
}
var liveProperty = this.style.getLiveProperty(name);
- var item = new WebInspector.StylePropertyTreeElement(this._styleRule, this.style, liveProperty, false, inherited, overloaded);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded);
this.appendChild(item);
}
},
@@ -1609,6 +1611,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
return "move-forward";
}
+ this._parentPane.isModifyingStyle = true;
WebInspector.startEditing(selectElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
@@ -1719,6 +1722,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
editedElement.parentElement.removeStyleClass("child-editing");
delete this.originalPropertyText;
+ delete this._parentPane.isModifyingStyle;
},
editingCancelled: function(element, context)
@@ -1767,6 +1771,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue);
var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput));
if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) {
+ this._parentPane.isModifyingStyle = true;
this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section);
var propertyText;
if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent)))
@@ -1781,7 +1786,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
} else {
if (!isDataPasted && !this._newProperty)
this.updateTitle();
- moveToNextCallback(this._newProperty, false, this.treeOutline.section);
+ moveToNextCallback.call(this, this._newProperty, false, this.treeOutline.section);
}
var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;
@@ -1789,6 +1794,8 @@ WebInspector.StylePropertyTreeElement.prototype = {
// The Callback to start editing the next/previous property/selector.
function moveToNextCallback(alreadyNew, valueChanged, section)
{
+ delete this._parentPane.isModifyingStyle;
+
if (!moveDirection)
return;
diff --git a/Source/WebCore/inspector/front-end/TestController.js b/Source/WebCore/inspector/front-end/TestController.js
index 3bfe28c..e6783f9 100644
--- a/Source/WebCore/inspector/front-end/TestController.js
+++ b/Source/WebCore/inspector/front-end/TestController.js
@@ -28,40 +28,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.TestController = function(callId)
+WebInspector.TestController = function()
{
- this._callId = callId;
- this._waitUntilDone = false;
- this.results = [];
}
WebInspector.TestController.prototype = {
- waitUntilDone: function()
+ notifyDone: function(callId, result)
{
- this._waitUntilDone = true;
- },
-
- notifyDone: function(result)
- {
- if (typeof result === "undefined" && this.results.length)
- result = this.results;
var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result);
- InspectorBackend.didEvaluateForTestInFrontend(this._callId, message);
- },
-
- runAfterPendingDispatches: function(callback)
- {
- if (WebInspector.pendingDispatches === 0) {
- callback();
- return;
- }
- setTimeout(this.runAfterPendingDispatches.bind(this), 0, callback);
+ InspectorAgent.didEvaluateForTestInFrontend(callId, message);
}
}
WebInspector.evaluateForTestInFrontend = function(callId, script)
{
- var controller = new WebInspector.TestController(callId);
function invokeMethod()
{
try {
@@ -71,11 +51,10 @@ WebInspector.evaluateForTestInFrontend = function(callId, script)
else
result = window.eval(script);
- if (!controller._waitUntilDone)
- controller.notifyDone(result);
+ WebInspector.TestController.prototype.notifyDone(callId, result);
} catch (e) {
- controller.notifyDone(e.toString());
+ WebInspector.testController.prototype.notifyDone(callId, e.toString());
}
}
- controller.runAfterPendingDispatches(invokeMethod);
+ InspectorBackend.runAfterPendingDispatches(invokeMethod);
}
diff --git a/Source/WebCore/inspector/front-end/TextEditorHighlighter.js b/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
index 4ac831e..9bdcc82 100644
--- a/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
+++ b/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
@@ -34,6 +34,7 @@ WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
this._textModel = textModel;
this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html");
this._damageCallback = damageCallback;
+ this._highlightChunkLimit = 1000;
this.reset();
}
@@ -43,18 +44,23 @@ WebInspector.TextEditorHighlighter.prototype = {
var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
if (tokenizer) {
this._tokenizer = tokenizer;
- this._tokenizerCondition = this._tokenizer.initialCondition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.initialCondition);
}
},
+ set highlightChunkLimit(highlightChunkLimit)
+ {
+ this._highlightChunkLimit = highlightChunkLimit;
+ },
+
reset: function()
{
this._lastHighlightedLine = 0;
this._lastHighlightedColumn = 0;
- this._tokenizerCondition = this._tokenizer.initialCondition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.initialCondition);
},
- highlight: function(endLine)
+ highlight: function(endLine, opt_forceRun)
{
// First check if we have work to do.
if (endLine <= this._lastHighlightedLine)
@@ -62,7 +68,7 @@ WebInspector.TextEditorHighlighter.prototype = {
this._requestedEndLine = endLine;
- if (this._highlightTimer) {
+ if (this._highlightTimer && !opt_forceRun) {
// There is a timer scheduled, it will catch the new job based on the new endLine set.
return;
}
@@ -75,6 +81,58 @@ WebInspector.TextEditorHighlighter.prototype = {
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
},
+ updateHighlight: function(startLine, endLine)
+ {
+ if (this._lastHighlightedLine < startLine) {
+ // Highlighter did not reach this point yet, nothing to update. It will reach it on subsequent timer tick and do the job.
+ return false;
+ }
+
+ var savedLastHighlightedLine = this._lastHighlightedLine;
+ var savedLastHighlightedColumn = this._lastHighlightedColumn;
+ var savedTokenizerCondition = this._tokenizerConditionStringified;
+
+ this._lastHighlightedLine = startLine;
+ this._lastHighlightedColumn = 0;
+
+ // Restore highlighter context taken from the previous line.
+ var attributes = this._textModel.getAttribute(startLine - 1, "highlight") || {};
+ this._tokenizerConditionStringified = attributes.postConditionStringified || JSON.stringify(this._tokenizer.initialCondition);
+
+ // Try to update highlight synchronously.
+ this._highlightLines(endLine);
+
+ if (this._lastHighlightedLine >= this._textModel.linesCount) {
+ // All is done up to the end.
+ return true;
+ }
+
+ var attributes1 = this._textModel.getAttribute(this._lastHighlightedLine - 1, "highlight") || {};
+ var attributes2 = this._textModel.getAttribute(this._lastHighlightedLine, "highlight") || {};
+ if (this._lastHighlightedColumn === 0 && attributes2.preConditionStringified && attributes1.postConditionStringified === attributes2.preConditionStringified) {
+ // Highlighting ended ahead of time. Restore previously saved state, unless we have done more than it was before.
+ if (savedLastHighlightedLine >= this._lastHighlightedLine) {
+ this._lastHighlightedLine = savedLastHighlightedLine;
+ this._lastHighlightedColumn = savedLastHighlightedColumn;
+ this._tokenizerConditionStringified = savedTokenizerCondition;
+ }
+ return true;
+ } else {
+ // If failed to update highlight synchronously, invalidate highlight data for the subsequent lines.
+ if (this._lastHighlightedColumn === 0)
+ this._textModel.removeAttribute(this._lastHighlightedLine, "highlight");
+ for (var i = this._lastHighlightedLine + 1; i < this._textModel.linesCount; ++i)
+ this._textModel.removeAttribute(i, "highlight");
+
+ // Continue highlighting on subsequent timer ticks.
+ this._requestedEndLine = endLine;
+ if (!this._highlightTimer)
+ this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
+
+ return false;
+ }
+ },
+
_highlightInChunks: function(endLine)
{
delete this._highlightTimer;
@@ -89,6 +147,10 @@ WebInspector.TextEditorHighlighter.prototype = {
return;
}
+ // The textModel may have been already updated.
+ if (this._requestedEndLine > this._textModel.linesCount)
+ this._requestedEndLine = this._textModel.linesCount;
+
this._highlightLines(this._requestedEndLine);
// Schedule tail highlight if necessary.
@@ -98,35 +160,49 @@ WebInspector.TextEditorHighlighter.prototype = {
_highlightLines: function(endLine)
{
- // Tokenizer is stateless and reused accross viewers, restore its condition before highlight and save it after.
- this._tokenizer.condition = this._tokenizerCondition;
+ // Tokenizer is stateless and reused across viewers, restore its condition before highlight and save it after.
+ this._tokenizer.condition = JSON.parse(this._tokenizerConditionStringified);
var tokensCount = 0;
for (var lineNumber = this._lastHighlightedLine; lineNumber < endLine; ++lineNumber) {
var line = this._textModel.line(lineNumber);
this._tokenizer.line = line;
- var attributes = this._textModel.getAttribute(lineNumber, "highlight") || {};
+
+ if (this._lastHighlightedColumn === 0) {
+ var attributes = {};
+ attributes.preConditionStringified = JSON.stringify(this._tokenizer.condition);
+ this._textModel.setAttribute(lineNumber, "highlight", attributes);
+ } else
+ var attributes = this._textModel.getAttribute(lineNumber, "highlight");
// Highlight line.
do {
var newColumn = this._tokenizer.nextToken(this._lastHighlightedColumn);
var tokenType = this._tokenizer.tokenType;
if (tokenType)
- attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType, subTokenizer: this._tokenizer.subTokenizer };
+ attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType };
this._lastHighlightedColumn = newColumn;
- if (++tokensCount > 1000)
+ if (++tokensCount > this._highlightChunkLimit)
break;
- } while (this._lastHighlightedColumn < line.length)
+ } while (this._lastHighlightedColumn < line.length);
- this._textModel.setAttribute(lineNumber, "highlight", attributes);
if (this._lastHighlightedColumn < line.length) {
// Too much work for single chunk - exit.
break;
- } else
+ } else {
this._lastHighlightedColumn = 0;
+ attributes.postConditionStringified = JSON.stringify(this._tokenizer.condition);
+
+ var nextAttributes = this._textModel.getAttribute(lineNumber + 1, "highlight") || {};
+ if (nextAttributes.preConditionStringified === attributes.postConditionStringified) {
+ // Following lines are up to date, no need to re-highlight.
+ ++lineNumber;
+ break;
+ }
+ }
}
this._damageCallback(this._lastHighlightedLine, lineNumber);
- this._tokenizerCondition = this._tokenizer.condition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.condition);
this._lastHighlightedLine = lineNumber;
}
}
diff --git a/Source/WebCore/inspector/front-end/TextViewer.js b/Source/WebCore/inspector/front-end/TextViewer.js
index ce6502d..65b4724 100644
--- a/Source/WebCore/inspector/front-end/TextViewer.js
+++ b/Source/WebCore/inspector/front-end/TextViewer.js
@@ -37,9 +37,11 @@ WebInspector.TextViewer = function(textModel, platform, url)
this.element = document.createElement("div");
this.element.className = "text-editor monospace";
+ var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this);
+ var exitTextChangeMode = this._exitInternalTextChangeMode.bind(this);
var syncScrollListener = this._syncScroll.bind(this);
var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this);
- this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener);
+ this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode);
this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener);
this.element.appendChild(this._mainPanel.element);
this.element.appendChild(this._gutterPanel.element);
@@ -51,6 +53,21 @@ WebInspector.TextViewer.prototype = {
this._mainPanel.mimeType = mimeType;
},
+ set readOnly(readOnly)
+ {
+ this._mainPanel.readOnly = readOnly;
+ },
+
+ set startEditingListener(startEditingListener)
+ {
+ this._startEditingListener = startEditingListener;
+ },
+
+ set endEditingListener(endEditingListener)
+ {
+ this._endEditingListener = endEditingListener;
+ },
+
get textModel()
{
return this._textModel;
@@ -129,6 +146,7 @@ WebInspector.TextViewer.prototype = {
{
this._mainPanel.endUpdates();
this._gutterPanel.endUpdates();
+ this._updatePanelOffsets();
},
resize: function()
@@ -141,9 +159,31 @@ WebInspector.TextViewer.prototype = {
// WebInspector.TextModel listener
_textChanged: function(oldRange, newRange, oldText, newText)
{
- this._mainPanel.textChanged();
- this._gutterPanel.textChanged();
+ if (!this._internalTextChangeMode) {
+ this._mainPanel.textChanged(oldRange, newRange);
+ this._gutterPanel.textChanged(oldRange, newRange);
+ this._updatePanelOffsets();
+ }
+ },
+
+ _enterInternalTextChangeMode: function()
+ {
+ this._internalTextChangeMode = true;
+
+ if (this._startEditingListener)
+ this._startEditingListener();
+ },
+
+ _exitInternalTextChangeMode: function(oldRange, newRange)
+ {
+ this._internalTextChangeMode = false;
+
+ // Update the gutter panel.
+ this._gutterPanel.textChanged(oldRange, newRange);
this._updatePanelOffsets();
+
+ if (this._endEditingListener)
+ this._endEditingListener(oldRange, newRange);
},
_updatePanelOffsets: function()
@@ -161,13 +201,8 @@ WebInspector.TextViewer.prototype = {
setTimeout(function() {
var mainElement = this._mainPanel.element;
var gutterElement = this._gutterPanel.element;
-
// Handle horizontal scroll bar at the bottom of the main panel.
- if (gutterElement.offsetHeight > mainElement.clientHeight)
- gutterElement.style.setProperty("padding-bottom", (gutterElement.offsetHeight - mainElement.clientHeight) + "px");
- else
- gutterElement.style.removeProperty("padding-bottom");
-
+ this._gutterPanel.syncClientHeight(mainElement.clientHeight);
gutterElement.scrollTop = mainElement.scrollTop;
}.bind(this), 0);
},
@@ -177,13 +212,19 @@ WebInspector.TextViewer.prototype = {
if (lineNumber >= this._textModel.linesCount)
return;
- var mainChunk = this._mainPanel.makeLineAChunk(lineNumber);
- var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
- var height = mainChunk.height;
- if (height)
- gutterChunk.element.style.setProperty("height", height + "px");
- else
- gutterChunk.element.style.removeProperty("height");
+ var mainChunk = this._mainPanel.chunkForLine(lineNumber);
+ if (mainChunk.linesCount === 1) {
+ var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
+ var height = mainChunk.height;
+ if (height)
+ gutterChunk.element.style.setProperty("height", height + "px");
+ else
+ gutterChunk.element.style.removeProperty("height");
+ } else {
+ var gutterChunk = this._gutterPanel.chunkForLine(lineNumber);
+ if (gutterChunk.linesCount === 1)
+ gutterChunk.element.style.removeProperty("height");
+ }
}
}
@@ -193,6 +234,7 @@ WebInspector.TextEditorChunkedPanel = function(textModel)
this._defaultChunkSize = 50;
this._paintCoalescingLevel = 0;
+ this._domUpdateCoalescingLevel = 0;
}
WebInspector.TextEditorChunkedPanel.prototype = {
@@ -222,23 +264,27 @@ WebInspector.TextEditorChunkedPanel.prototype = {
chunk.removeDecoration(decoration);
},
- textChanged: function(oldRange, newRange, oldText, newText)
+ textChanged: function(oldRange, newRange)
{
this._buildChunks();
},
_buildChunks: function()
{
- this.element.removeChildren();
+ this.beginDomUpdates();
+
+ this._container.removeChildren();
this._textChunks = [];
for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) {
var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
this._textChunks.push(chunk);
- this.element.appendChild(chunk.element);
+ this._container.appendChild(chunk.element);
}
this._repaintAll();
+
+ this.endDomUpdates();
},
makeLineAChunk: function(lineNumber)
@@ -251,6 +297,8 @@ WebInspector.TextEditorChunkedPanel.prototype = {
if (oldChunk.linesCount === 1)
return oldChunk;
+ this.beginDomUpdates();
+
var wasExpanded = oldChunk.expanded;
oldChunk.expanded = false;
@@ -260,24 +308,24 @@ WebInspector.TextEditorChunkedPanel.prototype = {
if (lineNumber > oldChunk.startLine) {
var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber);
this._textChunks.splice(insertIndex++, 0, prefixChunk);
- this.element.insertBefore(prefixChunk.element, oldChunk.element);
+ this._container.insertBefore(prefixChunk.element, oldChunk.element);
}
// Line chunk.
var lineChunk = this._createNewChunk(lineNumber, lineNumber + 1);
this._textChunks.splice(insertIndex++, 0, lineChunk);
- this.element.insertBefore(lineChunk.element, oldChunk.element);
+ this._container.insertBefore(lineChunk.element, oldChunk.element);
// Suffix chunk.
if (oldChunk.startLine + oldChunk.linesCount > lineNumber + 1) {
var suffixChunk = this._createNewChunk(lineNumber + 1, oldChunk.startLine + oldChunk.linesCount);
this._textChunks.splice(insertIndex, 0, suffixChunk);
- this.element.insertBefore(suffixChunk.element, oldChunk.element);
+ this._container.insertBefore(suffixChunk.element, oldChunk.element);
}
// Remove enclosing chunk.
this._textChunks.splice(chunkNumber, 1);
- this.element.removeChild(oldChunk.element);
+ this._container.removeChild(oldChunk.element);
if (wasExpanded) {
if (prefixChunk)
@@ -287,11 +335,17 @@ WebInspector.TextEditorChunkedPanel.prototype = {
suffixChunk.expanded = true;
}
+ this.endDomUpdates();
+
return lineChunk;
},
_scroll: function()
{
+ // FIXME: Replace the "2" with the padding-left value from CSS.
+ if (this.element.scrollLeft <= 2)
+ this.element.scrollLeft = 0;
+
this._scheduleRepaintAll();
if (this._syncScrollListener)
this._syncScrollListener();
@@ -316,26 +370,52 @@ WebInspector.TextEditorChunkedPanel.prototype = {
this._repaintAll();
},
+ beginDomUpdates: function()
+ {
+ this._domUpdateCoalescingLevel++;
+ },
+
+ endDomUpdates: function()
+ {
+ this._domUpdateCoalescingLevel--;
+ },
+
_chunkNumberForLine: function(lineNumber)
{
- for (var i = 0; i < this._textChunks.length; ++i) {
- var line = this._textChunks[i].startLine;
- if (lineNumber >= line && lineNumber < line + this._textChunks[i].linesCount)
- return i;
+ function compareLineNumbers(value, chunk)
+ {
+ return value < chunk.startLine ? -1 : 1;
}
- return this._textChunks.length - 1;
+ var insertBefore = insertionIndexForObjectInListSortedByFunction(lineNumber, this._textChunks, compareLineNumbers);
+ return insertBefore - 1;
},
- _chunkForLine: function(lineNumber)
+ chunkForLine: function(lineNumber)
{
return this._textChunks[this._chunkNumberForLine(lineNumber)];
},
+ _findVisibleChunks: function(visibleFrom, visibleTo)
+ {
+ function compareOffsetTops(value, chunk)
+ {
+ return value < chunk.offsetTop ? -1 : 1;
+ }
+ var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, this._textChunks, compareOffsetTops);
+
+ var from = insertBefore - 1;
+ for (var to = from + 1; to < this._textChunks.length; ++to) {
+ if (this._textChunks[to].offsetTop >= visibleTo)
+ break;
+ }
+ return { start: from, end: to };
+ },
+
_repaintAll: function()
{
delete this._repaintAllTimer;
- if (this._paintCoalescingLevel)
+ if (this._paintCoalescingLevel || this._dirtyLines)
return;
if (!this._textChunks)
@@ -344,25 +424,10 @@ WebInspector.TextEditorChunkedPanel.prototype = {
var visibleFrom = this.element.scrollTop;
var visibleTo = this.element.scrollTop + this.element.clientHeight;
- var offset = 0;
- var fromIndex = -1;
- var toIndex = 0;
- for (var i = 0; i < this._textChunks.length; ++i) {
- var chunk = this._textChunks[i];
- var chunkHeight = chunk.height;
- if (offset + chunkHeight > visibleFrom && offset < visibleTo) {
- if (fromIndex === -1)
- fromIndex = i;
- toIndex = i + 1;
- } else {
- if (offset >= visibleTo)
- break;
- }
- offset += chunkHeight;
+ if (visibleTo) {
+ var result = this._findVisibleChunks(visibleFrom, visibleTo);
+ this._expandChunks(result.start, result.end);
}
-
- if (toIndex)
- this._expandChunks(fromIndex, toIndex);
},
_totalHeight: function(firstElement, lastElement)
@@ -370,11 +435,19 @@ WebInspector.TextEditorChunkedPanel.prototype = {
lastElement = (lastElement || firstElement).nextElementSibling;
if (lastElement)
return lastElement.offsetTop - firstElement.offsetTop;
- else if (firstElement.offsetParent)
- return firstElement.offsetParent.scrollHeight - firstElement.offsetTop;
- return firstElement.offsetHeight;
+
+ var offsetParent = firstElement.offsetParent;
+ if (offsetParent && offsetParent.scrollHeight > offsetParent.clientHeight)
+ return offsetParent.scrollHeight - firstElement.offsetTop;
+
+ var total = 0;
+ while (firstElement && firstElement !== lastElement) {
+ total += firstElement.offsetHeight;
+ firstElement = firstElement.nextElementSibling;
+ }
+ return total;
},
-
+
resize: function()
{
this._repaintAll();
@@ -390,6 +463,10 @@ WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineL
this.element = document.createElement("div");
this.element.className = "text-editor-lines";
+ this._container = document.createElement("div");
+ this._container.className = "inner-container";
+ this.element.appendChild(this._container);
+
this.element.addEventListener("scroll", this._scroll.bind(this), false);
this.freeCachedElements();
@@ -409,9 +486,59 @@ WebInspector.TextEditorGutterPanel.prototype = {
_expandChunks: function(fromIndex, toIndex)
{
- for (var i = 0; i < this._textChunks.length; ++i) {
+ for (var i = 0; i < this._textChunks.length; ++i)
this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
+ },
+
+ textChanged: function(oldRange, newRange)
+ {
+ if (!this._textChunks) {
+ this._buildChunks();
+ return;
}
+
+ var linesDiff = newRange.linesCount - oldRange.linesCount;
+ if (linesDiff) {
+ // Remove old chunks (if needed).
+ for (var chunkNumber = this._textChunks.length - 1; chunkNumber >= 0 ; --chunkNumber) {
+ var chunk = this._textChunks[chunkNumber];
+ if (chunk.startLine + chunk.linesCount <= this._textModel.linesCount)
+ break;
+ chunk.expanded = false;
+ this._container.removeChild(chunk.element);
+ }
+ this._textChunks.length = chunkNumber + 1;
+
+ // Add new chunks (if needed).
+ var totalLines = 0;
+ if (this._textChunks.length) {
+ var lastChunk = this._textChunks[this._textChunks.length - 1];
+ totalLines = lastChunk.startLine + lastChunk.linesCount;
+ }
+ for (var i = totalLines; i < this._textModel.linesCount; i += this._defaultChunkSize) {
+ var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
+ this._textChunks.push(chunk);
+ this._container.appendChild(chunk.element);
+ }
+ this._repaintAll();
+ } else {
+ // Decorations may have been removed, so we may have to sync those lines.
+ var chunkNumber = this._chunkNumberForLine(newRange.startLine);
+ var chunk = this._textChunks[chunkNumber];
+ while (chunk && chunk.startLine <= newRange.endLine) {
+ if (chunk.linesCount === 1)
+ this._syncDecorationsForLineListener(chunk.startLine);
+ chunk = this._textChunks[++chunkNumber];
+ }
+ }
+ },
+
+ syncClientHeight: function(clientHeight)
+ {
+ if (this.element.offsetHeight > clientHeight)
+ this._container.style.setProperty("padding-bottom", (this.element.offsetHeight - clientHeight) + "px");
+ else
+ this._container.style.removeProperty("padding-bottom");
}
}
@@ -444,9 +571,8 @@ WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
this.element.appendChild(outerSpan);
} else {
var lineNumbers = [];
- for (var i = startLine; i < endLine; ++i) {
+ for (var i = startLine; i < endLine; ++i)
lineNumbers.push(i + 1);
- }
this.element.textContent = lineNumbers.join("\n");
}
}
@@ -454,16 +580,18 @@ WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
WebInspector.TextEditorGutterChunk.prototype = {
addDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.addStyleClass(decoration);
- }
+ this._textViewer.endDomUpdates();
},
removeDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
- }
+ this._textViewer.endDomUpdates();
},
get expanded()
@@ -484,6 +612,8 @@ WebInspector.TextEditorGutterChunk.prototype = {
if (this.linesCount === 1)
return;
+ this._textViewer.beginDomUpdates();
+
if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
@@ -503,12 +633,14 @@ WebInspector.TextEditorGutterChunk.prototype = {
elementInserted = true;
parentElement.insertBefore(this.element, lineRow);
}
- this._textViewer._cachedRows.push(lineRow);
parentElement.removeChild(lineRow);
}
+ this._textViewer._cachedRows.push(lineRow);
}
delete this._expandedLineRows;
}
+
+ this._textViewer.endDomUpdates();
},
get height()
@@ -518,6 +650,11 @@ WebInspector.TextEditorGutterChunk.prototype = {
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},
+ get offsetTop()
+ {
+ return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
+ },
+
_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
@@ -528,27 +665,42 @@ WebInspector.TextEditorGutterChunk.prototype = {
}
}
-WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener)
+WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode)
{
WebInspector.TextEditorChunkedPanel.call(this, textModel);
this._syncScrollListener = syncScrollListener;
this._syncDecorationsForLineListener = syncDecorationsForLineListener;
+ this._enterTextChangeMode = enterTextChangeMode;
+ this._exitTextChangeMode = exitTextChangeMode;
this._url = url;
this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this));
+ this._readOnly = true;
this.element = document.createElement("div");
this.element.className = "text-editor-contents";
this.element.tabIndex = 0;
+ this._container = document.createElement("div");
+ this._container.className = "inner-container";
+ this._container.tabIndex = 0;
+ this.element.appendChild(this._container);
+
this.element.addEventListener("scroll", this._scroll.bind(this), false);
- this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
- var handleDOMUpdates = this._handleDOMUpdates.bind(this);
- this.element.addEventListener("DOMCharacterDataModified", handleDOMUpdates, false);
- this.element.addEventListener("DOMNodeInserted", handleDOMUpdates, false);
- this.element.addEventListener("DOMNodeRemoved", handleDOMUpdates, false);
+ // FIXME: Remove old live editing functionality and Preferences.sourceEditorEnabled flag.
+ if (!Preferences.sourceEditorEnabled)
+ this._container.addEventListener("keydown", this._handleKeyDown.bind(this), false);
+
+ // In WebKit the DOMNodeRemoved event is fired AFTER the node is removed, thus it should be
+ // attached to all DOM nodes that we want to track. Instead, we attach the DOMNodeRemoved
+ // listeners only on the line rows, and use DOMSubtreeModified to track node removals inside
+ // the line rows. For more info see: https://bugs.webkit.org/show_bug.cgi?id=55666
+ this._handleDOMUpdatesCallback = this._handleDOMUpdates.bind(this);
+ this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false);
+ this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false);
+ this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false);
this.freeCachedElements();
this._buildChunks();
@@ -560,6 +712,21 @@ WebInspector.TextEditorMainPanel.prototype = {
this._highlighter.mimeType = mimeType;
},
+ set readOnly(readOnly)
+ {
+ // FIXME: Remove the Preferences.sourceEditorEnabled flag.
+ if (!Preferences.sourceEditorEnabled)
+ return;
+
+ this.beginDomUpdates();
+ this._readOnly = readOnly;
+ if (this._readOnly)
+ this._container.removeStyleClass("text-editor-editable");
+ else
+ this._container.addStyleClass("text-editor-editable");
+ this.endDomUpdates();
+ },
+
markAndRevealRange: function(range)
{
if (this._rangeToMark) {
@@ -653,6 +820,9 @@ WebInspector.TextEditorMainPanel.prototype = {
_buildChunks: function()
{
this._highlighter.reset();
+ for (var i = 0; i < this._textModel.linesCount; ++i)
+ this._textModel.removeAttribute(i, "highlight");
+
WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this);
},
@@ -672,9 +842,8 @@ WebInspector.TextEditorMainPanel.prototype = {
this._highlighter.highlight(lastVisibleLine);
delete this._muteHighlightListener;
- for (var i = 0; i < this._textChunks.length; ++i) {
+ for (var i = 0; i < this._textChunks.length; ++i)
this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
- }
this._restoreSelection(selection);
},
@@ -686,13 +855,46 @@ WebInspector.TextEditorMainPanel.prototype = {
this._paintLines(fromLine, toLine, true /*restoreSelection*/);
},
+ _markSkippedPaintLines: function(startLine, endLine)
+ {
+ if (!this._skippedPaintLines)
+ this._skippedPaintLines = [ { startLine: startLine, endLine: endLine } ];
+ else {
+ for (var i = 0; i < this._skippedPaintLines.length; ++i) {
+ var chunk = this._skippedPaintLines[i];
+ if (chunk.startLine <= endLine && chunk.endLine >= startLine) {
+ chunk.startLine = Math.min(chunk.startLine, startLine);
+ chunk.endLine = Math.max(chunk.endLine, endLine);
+ return;
+ }
+ }
+ this._skippedPaintLines.push({ startLine: startLine, endLine: endLine });
+ }
+ },
+
+ _paintSkippedLines: function()
+ {
+ if (!this._skippedPaintLines || this._dirtyLines)
+ return;
+ for (var i = 0; i < this._skippedPaintLines.length; ++i) {
+ var chunk = this._skippedPaintLines[i];
+ this._paintLines(chunk.startLine, chunk.endLine);
+ }
+ delete this._skippedPaintLines;
+ },
+
_paintLines: function(fromLine, toLine, restoreSelection)
{
+ if (this._dirtyLines) {
+ this._markSkippedPaintLines(fromLine, toLine);
+ return;
+ }
+
var selection;
- var chunk = this._chunkForLine(fromLine);
+ var chunk = this.chunkForLine(fromLine);
for (var i = fromLine; i < toLine; ++i) {
if (i >= chunk.startLine + chunk.linesCount)
- chunk = this._chunkForLine(i);
+ chunk = this.chunkForLine(i);
var lineRow = chunk.getExpandedLineRow(i);
if (!lineRow)
continue;
@@ -706,46 +908,56 @@ WebInspector.TextEditorMainPanel.prototype = {
_paintLine: function(lineRow, lineNumber)
{
- var highlight = this._textModel.getAttribute(lineNumber, "highlight");
- if (!highlight) {
- if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
- this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ if (this._dirtyLines) {
+ this._markSkippedPaintLines(lineNumber, lineNumber + 1);
return;
}
- lineRow.removeChildren();
- var line = this._textModel.line(lineNumber);
- if (!line)
- lineRow.appendChild(document.createElement("br"));
-
- var plainTextStart = -1;
- for (var j = 0; j < line.length;) {
- if (j > 1000) {
- // This line is too long - do not waste cycles on minified js highlighting.
- if (plainTextStart === -1)
- plainTextStart = j;
- break;
+ this.beginDomUpdates();
+ try {
+ var highlight = this._textModel.getAttribute(lineNumber, "highlight");
+ if (!highlight) {
+ if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+ this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ return;
}
- var attribute = highlight[j];
- if (!attribute || !attribute.tokenType) {
- if (plainTextStart === -1)
- plainTextStart = j;
- j++;
- } else {
- if (plainTextStart !== -1) {
- this._appendTextNode(lineRow, line.substring(plainTextStart, j));
- plainTextStart = -1;
+
+ lineRow.removeChildren();
+ var line = this._textModel.line(lineNumber);
+ if (!line)
+ lineRow.appendChild(document.createElement("br"));
+
+ var plainTextStart = -1;
+ for (var j = 0; j < line.length;) {
+ if (j > 1000) {
+ // This line is too long - do not waste cycles on minified js highlighting.
+ if (plainTextStart === -1)
+ plainTextStart = j;
+ break;
+ }
+ var attribute = highlight[j];
+ if (!attribute || !attribute.tokenType) {
+ if (plainTextStart === -1)
+ plainTextStart = j;
+ j++;
+ } else {
+ if (plainTextStart !== -1) {
+ this._appendTextNode(lineRow, line.substring(plainTextStart, j));
+ plainTextStart = -1;
+ }
+ this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
+ j += attribute.length;
}
- this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
- j += attribute.length;
}
+ if (plainTextStart !== -1)
+ this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
+ if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+ this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ if (lineRow.decorationsElement)
+ lineRow.appendChild(lineRow.decorationsElement);
+ } finally {
+ this.endDomUpdates();
}
- if (plainTextStart !== -1)
- this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
- if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
- this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
- if (lineRow.decorationsElement)
- lineRow.appendChild(lineRow.decorationsElement);
},
_releaseLinesHighlight: function(lineRow)
@@ -774,7 +986,7 @@ WebInspector.TextEditorMainPanel.prototype = {
return null;
var selectionRange = selection.getRangeAt(0);
// Selection may be outside of the viewer.
- if (!this.element.isAncestor(selectionRange.startContainer) || !this.element.isAncestor(selectionRange.endContainer))
+ if (!this._container.isAncestor(selectionRange.startContainer) || !this._container.isAncestor(selectionRange.endContainer))
return null;
var start = this._selectionToPosition(selectionRange.startContainer, selectionRange.startOffset);
var end = selectionRange.collapsed ? start : this._selectionToPosition(selectionRange.endContainer, selectionRange.endOffset);
@@ -795,9 +1007,9 @@ WebInspector.TextEditorMainPanel.prototype = {
_selectionToPosition: function(container, offset)
{
- if (container === this.element && offset === 0)
+ if (container === this._container && offset === 0)
return { line: 0, column: 0 };
- if (container === this.element && offset === 1)
+ if (container === this._container && offset === 1)
return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) };
var lineRow = container.enclosingNodeOrSelfWithNodeName("DIV");
@@ -835,7 +1047,7 @@ WebInspector.TextEditorMainPanel.prototype = {
_positionToSelection: function(line, column)
{
- var chunk = this._chunkForLine(line);
+ var chunk = this.chunkForLine(line);
var lineRow = chunk.getExpandedLineRow(line);
if (lineRow)
var rangeBoundary = lineRow.rangeBoundaryForOffset(column);
@@ -909,17 +1121,268 @@ WebInspector.TextEditorMainPanel.prototype = {
_handleDOMUpdates: function(e)
{
+ if (this._domUpdateCoalescingLevel)
+ return;
+
var target = e.target;
+ if (target === this._container)
+ return;
+
var lineRow = target.enclosingNodeOrSelfWithClass("webkit-line-content");
- if (lineRow === target || !lineRow || !lineRow.decorationsElement || !lineRow.decorationsElement.isAncestor(target))
+ if (!lineRow)
return;
- if (this._syncDecorationsForLineListener) {
- // Wait until this event is processed and only then sync the sizes. This is necessary in
- // case of the DOMNodeRemoved event, because it is dispatched before the removal takes place.
- setTimeout(function() {
+
+ if (lineRow.decorationsElement && (lineRow.decorationsElement === target || lineRow.decorationsElement.isAncestor(target))) {
+ if (this._syncDecorationsForLineListener)
this._syncDecorationsForLineListener(lineRow.lineNumber);
- }.bind(this), 0);
+ return;
+ }
+
+ if (this._readOnly)
+ return;
+
+ var lineNumber = lineRow.lineNumber;
+ if (this._dirtyLines) {
+ this._dirtyLines.start = Math.min(this._dirtyLines.start, lineNumber);
+ this._dirtyLines.end = Math.max(this._dirtyLines.end, lineNumber + 1);
+ } else {
+ this._dirtyLines = { start: lineNumber, end: lineNumber + 1 };
+ setTimeout(this._applyDomUpdates.bind(this), 0);
+ // Remove marked ranges, if any.
+ this.markAndRevealRange(null);
+ }
+ },
+
+ _applyDomUpdates: function()
+ {
+ if (!this._dirtyLines)
+ return;
+
+ // Check if the editor had been set readOnly by the moment when this async callback got executed.
+ if (this._readOnly) {
+ delete this._dirtyLines;
+ return;
+ }
+
+ // This is a "foreign" call outside of this class. Should be before we delete the dirty lines flag.
+ this._enterTextChangeMode();
+
+ var dirtyLines = this._dirtyLines;
+ delete this._dirtyLines;
+
+ var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start);
+ var startLine = this._textChunks[firstChunkNumber].startLine;
+ var endLine = this._textModel.linesCount;
+
+ // Collect lines.
+ var firstLineRow;
+ if (firstChunkNumber) {
+ var chunk = this._textChunks[firstChunkNumber - 1];
+ firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
+ firstLineRow = firstLineRow.nextSibling;
+ } else
+ firstLineRow = this._container.firstChild;
+
+ var lines = [];
+ for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) {
+ if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) {
+ endLine = lineRow.lineNumber;
+ break;
+ }
+ // Update with the newest lineNumber, so that the call to the _getSelection method below should work.
+ lineRow.lineNumber = startLine + lines.length;
+ this._collectLinesFromDiv(lines, lineRow);
+ }
+
+ // Try to decrease the range being replaced if possible.
+ var startOffset = 0;
+ while (startLine < dirtyLines.start && startOffset < lines.length) {
+ if (this._textModel.line(startLine) !== lines[startOffset])
+ break;
+ ++startOffset;
+ ++startLine;
+ }
+
+ var endOffset = lines.length;
+ while (endLine > dirtyLines.end && endOffset > startOffset) {
+ if (this._textModel.line(endLine - 1) !== lines[endOffset - 1])
+ break;
+ --endOffset;
+ --endLine;
+ }
+
+ lines = lines.slice(startOffset, endOffset);
+
+ var selection = this._getSelection();
+
+ if (lines.length === 0 && endLine < this._textModel.linesCount) {
+ var oldRange = new WebInspector.TextRange(startLine, 0, endLine, 0);
+ var newRange = this._textModel.setText(oldRange, "");
+ } else {
+ var oldRange = new WebInspector.TextRange(startLine, 0, endLine - 1, this._textModel.lineLength(endLine - 1));
+ var newRange = this._textModel.setText(oldRange, lines.join("\n"));
+ }
+
+ this.beginDomUpdates();
+ this._removeDecorationsInRange(oldRange);
+ this._updateChunksForRanges(oldRange, newRange);
+ this._updateHighlightsForRange(newRange);
+ this._paintSkippedLines();
+ this.endDomUpdates();
+
+ this._restoreSelection(selection);
+
+ this._exitTextChangeMode(oldRange, newRange);
+ },
+
+ _removeDecorationsInRange: function(range)
+ {
+ for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) {
+ var chunk = this._textChunks[i];
+ if (chunk.startLine > range.endLine)
+ break;
+ chunk.removeAllDecorations();
+ }
+ },
+
+ _updateChunksForRanges: function(oldRange, newRange)
+ {
+ // Update the chunks in range: firstChunkNumber <= index <= lastChunkNumber
+ var firstChunkNumber = this._chunkNumberForLine(oldRange.startLine);
+ var lastChunkNumber = firstChunkNumber;
+ while (lastChunkNumber + 1 < this._textChunks.length) {
+ if (this._textChunks[lastChunkNumber + 1].startLine > oldRange.endLine)
+ break;
+ ++lastChunkNumber;
+ }
+
+ var startLine = this._textChunks[firstChunkNumber].startLine;
+ var linesCount = this._textChunks[lastChunkNumber].startLine + this._textChunks[lastChunkNumber].linesCount - startLine;
+ var linesDiff = newRange.linesCount - oldRange.linesCount;
+ linesCount += linesDiff;
+
+ if (linesDiff) {
+ // Lines shifted, update the line numbers of the chunks below.
+ for (var chunkNumber = lastChunkNumber + 1; chunkNumber < this._textChunks.length; ++chunkNumber)
+ this._textChunks[chunkNumber].startLine += linesDiff;
+ }
+
+ var firstLineRow;
+ if (firstChunkNumber) {
+ var chunk = this._textChunks[firstChunkNumber - 1];
+ firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
+ firstLineRow = firstLineRow.nextSibling;
+ } else
+ firstLineRow = this._container.firstChild;
+
+ // Most frequent case: a chunk remained the same.
+ for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) {
+ var chunk = this._textChunks[chunkNumber];
+ var lineNumber = chunk.startLine;
+ for (var lineRow = firstLineRow; lineRow && lineNumber < chunk.startLine + chunk.linesCount; lineRow = lineRow.nextSibling) {
+ if (lineRow.lineNumber !== lineNumber || lineRow !== chunk.getExpandedLineRow(lineNumber) || lineRow.textContent !== this._textModel.line(lineNumber) || !lineRow.firstChild)
+ break;
+ ++lineNumber;
+ }
+ if (lineNumber < chunk.startLine + chunk.linesCount)
+ break;
+ chunk.updateCollapsedLineRow();
+ ++firstChunkNumber;
+ firstLineRow = lineRow;
+ startLine += chunk.linesCount;
+ linesCount -= chunk.linesCount;
+ }
+
+ if (firstChunkNumber > lastChunkNumber && linesCount === 0)
+ return;
+
+ // Maybe merge with the next chunk, so that we should not create 1-sized chunks when appending new lines one by one.
+ var chunk = this._textChunks[lastChunkNumber + 1];
+ var linesInLastChunk = linesCount % this._defaultChunkSize;
+ if (chunk && !chunk.decorated && linesInLastChunk > 0 && linesInLastChunk + chunk.linesCount <= this._defaultChunkSize) {
+ ++lastChunkNumber;
+ linesCount += chunk.linesCount;
+ }
+
+ var scrollTop = this.element.scrollTop;
+ var scrollLeft = this.element.scrollLeft;
+
+ // Delete all DOM elements that were either controlled by the old chunks, or have just been inserted.
+ var firstUnmodifiedLineRow = null;
+ var chunk = this._textChunks[lastChunkNumber + 1];
+ if (chunk) {
+ firstUnmodifiedLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine) : chunk.element;
}
+ while (firstLineRow && firstLineRow !== firstUnmodifiedLineRow) {
+ var lineRow = firstLineRow;
+ firstLineRow = firstLineRow.nextSibling;
+ this._container.removeChild(lineRow);
+ }
+
+ // Replace old chunks with the new ones.
+ for (var chunkNumber = firstChunkNumber; linesCount > 0; ++chunkNumber) {
+ var chunkLinesCount = Math.min(this._defaultChunkSize, linesCount);
+ var newChunk = this._createNewChunk(startLine, startLine + chunkLinesCount);
+ this._container.insertBefore(newChunk.element, firstUnmodifiedLineRow);
+
+ if (chunkNumber <= lastChunkNumber)
+ this._textChunks[chunkNumber] = newChunk;
+ else
+ this._textChunks.splice(chunkNumber, 0, newChunk);
+ startLine += chunkLinesCount;
+ linesCount -= chunkLinesCount;
+ }
+ if (chunkNumber <= lastChunkNumber)
+ this._textChunks.splice(chunkNumber, lastChunkNumber - chunkNumber + 1);
+
+ this.element.scrollTop = scrollTop;
+ this.element.scrollLeft = scrollLeft;
+ },
+
+ _updateHighlightsForRange: function(range)
+ {
+ var visibleFrom = this.element.scrollTop;
+ var visibleTo = this.element.scrollTop + this.element.clientHeight;
+
+ var result = this._findVisibleChunks(visibleFrom, visibleTo);
+ var chunk = this._textChunks[result.end - 1];
+ var lastVisibleLine = chunk.startLine + chunk.linesCount;
+
+ lastVisibleLine = Math.max(lastVisibleLine, range.endLine);
+
+ var updated = this._highlighter.updateHighlight(range.startLine, lastVisibleLine);
+ if (!updated) {
+ // Highlights for the chunks below are invalid, so just collapse them.
+ for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i)
+ this._textChunks[i].expanded = false;
+ }
+
+ this._repaintAll();
+ },
+
+ _collectLinesFromDiv: function(lines, element)
+ {
+ var textContents = [];
+ var node = element.traverseNextNode(element);
+ while (node) {
+ if (element.decorationsElement === node) {
+ node = node.nextSibling;
+ continue;
+ }
+ if (node.nodeName.toLowerCase() === "br")
+ textContents.push("\n");
+ else if (node.nodeType === Node.TEXT_NODE)
+ textContents.push(node.textContent);
+ node = node.traverseNextNode(element);
+ }
+
+ var textContent = textContents.join("");
+ // The last \n (if any) does not "count" in a DIV.
+ textContent = textContent.replace(/\n$/, "");
+
+ textContents = textContent.split("\n");
+ for (var i = 0; i < textContents.length; ++i)
+ lines.push(textContents[i]);
}
}
@@ -933,49 +1396,73 @@ WebInspector.TextEditorMainChunk = function(textViewer, startLine, endLine)
this.element = document.createElement("div");
this.element.lineNumber = startLine;
this.element.className = "webkit-line-content";
+ this.element.addEventListener("DOMNodeRemoved", this._textViewer._handleDOMUpdatesCallback, false);
- this.startLine = startLine;
+ this._startLine = startLine;
endLine = Math.min(this._textModel.linesCount, endLine);
this.linesCount = endLine - startLine;
this._expanded = false;
- var lines = [];
- for (var i = startLine; i < endLine; ++i) {
- lines.push(this._textModel.line(i));
- }
-
- this.element.textContent = lines.join("\n");
-
- // The last empty line will get swallowed otherwise.
- if (!lines[lines.length - 1])
- this.element.appendChild(document.createElement("br"));
+ this.updateCollapsedLineRow();
}
WebInspector.TextEditorMainChunk.prototype = {
addDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.addStyleClass(decoration);
- return;
- }
- if (!this.element.decorationsElement) {
- this.element.decorationsElement = document.createElement("div");
- this.element.decorationsElement.className = "webkit-line-decorations";
- this.element.appendChild(this.element.decorationsElement);
+ else {
+ if (!this.element.decorationsElement) {
+ this.element.decorationsElement = document.createElement("div");
+ this.element.decorationsElement.className = "webkit-line-decorations";
+ this.element.appendChild(this.element.decorationsElement);
+ }
+ this.element.decorationsElement.appendChild(decoration);
}
- this.element.decorationsElement.appendChild(decoration);
+ this._textViewer.endDomUpdates();
},
removeDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
- return;
+ else if (this.element.decorationsElement)
+ this.element.decorationsElement.removeChild(decoration);
+ this._textViewer.endDomUpdates();
+ },
+
+ removeAllDecorations: function()
+ {
+ this._textViewer.beginDomUpdates();
+ this.element.className = "webkit-line-content";
+ if (this.element.decorationsElement) {
+ this.element.removeChild(this.element.decorationsElement);
+ delete this.element.decorationsElement;
+ }
+ this._textViewer.endDomUpdates();
+ },
+
+ get decorated()
+ {
+ return this.element.className !== "webkit-line-content" || !!(this.element.decorationsElement && this.element.decorationsElement.firstChild);
+ },
+
+ get startLine()
+ {
+ return this._startLine;
+ },
+
+ set startLine(startLine)
+ {
+ this._startLine = startLine;
+ this.element.lineNumber = startLine;
+ if (this._expandedLineRows) {
+ for (var i = 0; i < this._expandedLineRows.length; ++i)
+ this._expandedLineRows[i].lineNumber = startLine + i;
}
- if (!this.element.decorationsElement)
- return;
- this.element.decorationsElement.removeChild(decoration);
},
get expanded()
@@ -996,6 +1483,8 @@ WebInspector.TextEditorMainChunk.prototype = {
return;
}
+ this._textViewer.beginDomUpdates();
+
if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
@@ -1016,12 +1505,14 @@ WebInspector.TextEditorMainChunk.prototype = {
elementInserted = true;
parentElement.insertBefore(this.element, lineRow);
}
- this._textViewer._releaseLinesHighlight(lineRow);
parentElement.removeChild(lineRow);
}
+ this._textViewer._releaseLinesHighlight(lineRow);
}
delete this._expandedLineRows;
}
+
+ this._textViewer.endDomUpdates();
},
get height()
@@ -1031,11 +1522,17 @@ WebInspector.TextEditorMainChunk.prototype = {
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},
+ get offsetTop()
+ {
+ return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
+ },
+
_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
lineRow.lineNumber = lineNumber;
lineRow.className = "webkit-line-content";
+ lineRow.addEventListener("DOMNodeRemoved", this._textViewer._handleDOMUpdatesCallback, false);
lineRow.textContent = this._textModel.line(lineNumber);
if (!lineRow.textContent)
lineRow.appendChild(document.createElement("br"));
@@ -1049,5 +1546,22 @@ WebInspector.TextEditorMainChunk.prototype = {
if (!this._expandedLineRows)
return this.element;
return this._expandedLineRows[lineNumber - this.startLine];
+ },
+
+ updateCollapsedLineRow: function()
+ {
+ if (this.linesCount === 1 && this._expanded)
+ return;
+
+ var lines = [];
+ for (var i = this.startLine; i < this.startLine + this.linesCount; ++i)
+ lines.push(this._textModel.line(i));
+
+ this.element.removeChildren();
+ this.element.textContent = lines.join("\n");
+
+ // The last empty line will get swallowed otherwise.
+ if (!lines[lines.length - 1])
+ this.element.appendChild(document.createElement("br"));
}
}
diff --git a/Source/WebCore/inspector/front-end/TimelinePanel.js b/Source/WebCore/inspector/front-end/TimelinePanel.js
index 1d8b9c9..62c5de0 100644
--- a/Source/WebCore/inspector/front-end/TimelinePanel.js
+++ b/Source/WebCore/inspector/front-end/TimelinePanel.js
@@ -270,10 +270,10 @@ WebInspector.TimelinePanel.prototype = {
_toggleTimelineButtonClicked: function()
{
if (this.toggleTimelineButton.toggled)
- InspectorBackend.stopTimelineProfiler();
+ TimelineAgent.stop();
else {
this._clearPanel();
- InspectorBackend.startTimelineProfiler();
+ TimelineAgent.start();
}
},
@@ -865,7 +865,6 @@ WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, pane
this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime;
this._selfTime = this.endTime - this.startTime;
this._lastChildEndTime = this.endTime;
- this.originalRecordForTests = record;
if (record.stackTrace && record.stackTrace.length)
this.stackTrace = record.stackTrace;
this.totalHeapSize = record.totalHeapSize;
diff --git a/Source/WebCore/inspector/front-end/Toolbar.js b/Source/WebCore/inspector/front-end/Toolbar.js
new file mode 100755
index 0000000..d1cc9a6
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/Toolbar.js
@@ -0,0 +1,220 @@
+ /*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
+ * 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+WebInspector.Toolbar = function()
+{
+ this.element = document.getElementById("toolbar");
+ this.element.addEventListener("mousedown", this._toolbarDragStart.bind(this), true);
+
+ this._dropdownButton = document.getElementById("toolbar-dropdown-arrow");
+ this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false);
+
+ document.getElementById("close-button-left").addEventListener("click", this._onClose, true);
+ document.getElementById("close-button-right").addEventListener("click", this._onClose, true);
+}
+
+WebInspector.Toolbar.prototype = {
+ resize: function()
+ {
+ this._updateDropdownButtonAndHideDropdown();
+ },
+
+ addPanel: function(panel)
+ {
+ this.element.appendChild(panel.toolbarItem);
+ this.resize();
+ },
+
+ _toolbarDragStart: function(event)
+ {
+ if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
+ return;
+
+ var target = event.target;
+ if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
+ return;
+
+ if (target !== this.element && !target.hasStyleClass("toolbar-item"))
+ return;
+
+ this.element.lastScreenX = event.screenX;
+ this.element.lastScreenY = event.screenY;
+
+ WebInspector.elementDragStart(this.element, this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), event, (WebInspector.attached ? "row-resize" : "default"));
+ },
+
+ _toolbarDragEnd: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this.element.lastScreenX;
+ delete this.element.lastScreenY;
+ },
+
+ _toolbarDrag: function(event)
+ {
+ if (WebInspector.attached) {
+ var height = window.innerHeight - (event.screenY - this.element.lastScreenY);
+
+ InspectorFrontendHost.setAttachedWindowHeight(height);
+ } else {
+ var x = event.screenX - this.element.lastScreenX;
+ var y = event.screenY - this.element.lastScreenY;
+
+ // We cannot call window.moveBy here because it restricts the movement
+ // of the window at the edges.
+ InspectorFrontendHost.moveWindowBy(x, y);
+ }
+
+ this.element.lastScreenX = event.screenX;
+ this.element.lastScreenY = event.screenY;
+
+ event.preventDefault();
+ },
+
+ _onClose: function()
+ {
+ WebInspector.close();
+ },
+
+ _setDropdownVisible: function(visible)
+ {
+ if (!this._dropdown) {
+ if (!visible)
+ return;
+ this._dropdown = new WebInspector.ToolbarDropdown();
+ }
+ if (visible)
+ this._dropdown.show();
+ else
+ this._dropdown.hide();
+ },
+
+ _toggleDropdown: function()
+ {
+ this._setDropdownVisible(!this._dropdown || !this._dropdown.visible);
+ },
+
+ _updateDropdownButtonAndHideDropdown: function()
+ {
+ this._setDropdownVisible(false);
+
+ var toolbar = document.getElementById("toolbar");
+ if (this.element.scrollHeight > this.element.clientHeight)
+ this._dropdownButton.removeStyleClass("hidden");
+ else
+ this._dropdownButton.addStyleClass("hidden");
+ }
+};
+
+WebInspector.Toolbar.createPanelToolbarItem = function(panel)
+{
+ var toolbarItem = document.createElement("button");
+ toolbarItem.className = "toolbar-item toggleable";
+ toolbarItem.panel = panel;
+ toolbarItem.addStyleClass(panel._panelName);
+ function onToolbarItemClicked()
+ {
+ WebInspector.toolbar._updateDropdownButtonAndHideDropdown();
+ WebInspector.currentPanel = panel;
+ }
+ toolbarItem.addEventListener("click", onToolbarItemClicked);
+
+ var iconElement = toolbarItem.createChild("div", "toolbar-icon");
+
+ if ("toolbarItemLabel" in panel)
+ toolbarItem.createChild("div", "toolbar-label").textContent = panel.toolbarItemLabel;
+
+ if (panel === WebInspector.currentPanel)
+ toolbarItem.addStyleClass("toggled-on");
+
+ return toolbarItem;
+}
+
+WebInspector.ToolbarDropdown = function()
+{
+ this._toolbar = document.getElementById("toolbar");
+ this._arrow = document.getElementById("toolbar-dropdown-arrow");
+ this.element = document.createElement("div");
+ this.element.id = "toolbar-dropdown";
+ this._contentElement = this.element.createChild("div", "scrollable-content");
+ this._contentElement.tabIndex = 0;
+ this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true);
+}
+
+WebInspector.ToolbarDropdown.prototype = {
+ show: function()
+ {
+ if (this.visible)
+ return;
+ var style = this.element.style;
+ this._populate();
+ var top = this._arrow.totalOffsetTop + this._arrow.clientHeight;
+ this._arrow.addStyleClass("dropdown-visible");
+ this.element.style.top = top + "px";
+ this.element.style.left = this._arrow.totalOffsetLeft + "px";
+ this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px";
+ this._toolbar.appendChild(this.element);
+ WebInspector.currentFocusElement = this.contentElement;
+ },
+
+ hide: function()
+ {
+ if (!this.visible)
+ return;
+ this._arrow.removeStyleClass("dropdown-visible");
+ this.element.parentNode.removeChild(this.element);
+ this._contentElement.removeChildren();
+ },
+
+ get visible()
+ {
+ return !!this.element.parentNode;
+ },
+
+ _populate: function()
+ {
+ var toolbarItems = this._toolbar.querySelectorAll(".toolbar-item.toggleable");
+
+ for (var i = 0; i < toolbarItems.length; ++i) {
+ if (toolbarItems[i].offsetTop > 0)
+ this._contentElement.appendChild(WebInspector.Toolbar.createPanelToolbarItem(toolbarItems[i].panel));
+ }
+ },
+
+ _onKeyDown: function(event)
+ {
+ if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code)
+ return;
+ event.stopPropagation();
+ this.hide();
+ }
+};
diff --git a/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
index a6f59ca..bb3460d 100644
--- a/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
@@ -120,7 +120,7 @@ WebInspector.WatchExpressionsSection.prototype = {
}
// TODO: pass exact injected script id.
- InspectorBackend.releaseWrapperObjectGroup(0, this._watchObjectGroupId)
+ RuntimeAgent.releaseObjectGroup(0, this._watchObjectGroupId)
var properties = [];
// Count the properties, so we known when to call this.updateProperties()
diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc
index dd325ba..91d72d8 100644
--- a/Source/WebCore/inspector/front-end/WebKit.qrc
+++ b/Source/WebCore/inspector/front-end/WebKit.qrc
@@ -27,9 +27,11 @@
<file>Database.js</file>
<file>DatabaseQueryView.js</file>
<file>DatabaseTableView.js</file>
+ <file>DetailedHeapshotGridNodes.js</file>
<file>DetailedHeapshotView.js</file>
<file>DataGrid.js</file>
<file>DebuggerModel.js</file>
+ <file>DebuggerPresentationModel.js</file>
<file>DOMAgent.js</file>
<file>DOMStorage.js</file>
<file>DOMStorageItemsView.js</file>
@@ -85,6 +87,7 @@
<file>ScriptFormatter.js</file>
<file>ScriptFormatterWorker.js</file>
<file>ScriptsPanel.js</file>
+ <file>SearchController.js</file>
<file>Section.js</file>
<file>Settings.js</file>
<file>ShortcutsHelp.js</file>
@@ -110,6 +113,7 @@
<file>TimelineGrid.js</file>
<file>TimelineOverviewPane.js</file>
<file>TimelinePanel.js</file>
+ <file>Toolbar.js</file>
<file>TopDownProfileDataGridTree.js</file>
<file>treeoutline.js</file>
<file>utilities.js</file>
diff --git a/Source/WebCore/inspector/front-end/WorkersSidebarPane.js b/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
index b254f3c..efdb936 100644
--- a/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
@@ -74,9 +74,9 @@ WebInspector.WorkersSidebarPane.prototype = {
setInstrumentation: function(enabled)
{
- InspectorBackend.removeAllScriptsToEvaluateOnLoad();
+ InspectorAgent.removeAllScriptsToEvaluateOnLoad();
if (enabled)
- InspectorBackend.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
+ InspectorAgent.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
},
reset: function()
diff --git a/Source/WebCore/inspector/front-end/heapProfiler.css b/Source/WebCore/inspector/front-end/heapProfiler.css
index 03a6dd0..add02a1 100644
--- a/Source/WebCore/inspector/front-end/heapProfiler.css
+++ b/Source/WebCore/inspector/front-end/heapProfiler.css
@@ -134,3 +134,108 @@
width: 50%;
left: 25%;
}
+
+.detailed-heapshot-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ -webkit-box-orient: vertical;
+}
+
+.detailed-heapshot-view.visible {
+ display: -webkit-box;
+}
+
+.detailed-heapshot-view .view {
+ display: none;
+ -webkit-box-flex: 3;
+ -webkit-box-orient: vertical;
+}
+
+.detailed-heapshot-view .view.visible {
+ display: -webkit-box;
+}
+
+.detailed-heapshot-view .data-grid {
+ border: none;
+ position: relative;
+ -webkit-box-flex: 1;
+}
+
+.detailed-heapshot-view .data-grid td.count-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.addedCount-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.removedCount-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.countDelta-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.addedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.removedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.sizeDelta-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.shallowSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.retainedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .console-formatted-object, .console-formatted-node {
+ display: inline;
+ position: static;
+}
+
+.detailed-heapshot-view .delimiter {
+ height: 24px;
+ background-color: #d6dde5;
+}
+
+.detailed-heapshot-view .retaining-paths-view {
+ -webkit-box-flex: 1;
+}
+
+.detailed-heapshot-view .retaining-paths-view .title {
+ background-color: rgb(235, 235, 235);
+ background-image: url(Images/statusbarBackground.png);
+ background-repeat: repeat-x;
+ height: 23px;
+ font: -webkit-small-control;
+ font-weight: bold;
+ color: rgb(48, 48, 48);
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+}
+
+.detailed-heapshot-view .retaining-paths-view .title > span {
+ vertical-align: middle;
+ margin-left: 4px;
+}
+
+.heapshot-help-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/helpButtonGlyph.png);
+}
+
+table.heapshot-help {
+ border-spacing: 12px 2px;
+}
diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css
index c992806..a7bd3b3 100644
--- a/Source/WebCore/inspector/front-end/inspector.css
+++ b/Source/WebCore/inspector/front-end/inspector.css
@@ -76,7 +76,6 @@ img {
left: 0;
right: 0;
height: 56px;
- display: -webkit-box;
padding: 0 5px;
background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
border-bottom: 1px solid rgb(80, 80, 80);
@@ -111,32 +110,23 @@ body.attached.inactive #toolbar {
}
.toolbar-item {
- display: -webkit-box;
- padding: 4px 6px;
margin: 0;
+ padding: 0 6px;
background-color: transparent;
border-style: none;
border-color: transparent;
- -webkit-box-orient: vertical;
- -webkit-box-align: center;
- -webkit-box-pack: end;
+}
+
+.toolbar-item.toggleable {
+ padding-top: 4px;
}
.toolbar-item.toggleable.toggled-on {
border-width: 0 2px 0 2px;
- padding: 4px 4px;
+ padding: 4px 4px 0 4px;
-webkit-border-image: url(Images/toolbarItemSelected.png) 0 2 0 2;
}
-.toolbar-item.flexable-space {
- -webkit-box-flex: 1;
- visibility: hidden;
-}
-
-.toolbar-item input {
- margin-bottom: 8px;
-}
-
.toolbar-icon {
display: inline-block;
width: 32px;
@@ -144,7 +134,8 @@ body.attached.inactive #toolbar {
-webkit-background-size: 100% auto;
}
-body.attached .toolbar-icon {
+body.attached .toolbar-icon,
+#toolbar-dropdown .toolbar-icon {
width: 24px;
height: 24px;
vertical-align: middle;
@@ -168,9 +159,9 @@ body.attached .toolbar-item:active .toolbar-icon {
text-shadow: none;
}
-body.attached .toolbar-label {
+body.attached .toolbar-label,
+#toolbar-dropdown .toolbar-label {
display: inline-block;
- vertical-align: middle;
margin-left: 3px;
}
@@ -178,25 +169,145 @@ body.attached #search-toolbar-label {
display: none;
}
+#toolbar-controls {
+ float: right;
+ display: -webkit-box;
+ -webkit-box-align: center;
+ height: 100%;
+}
+
+#toolbar-dropdown-arrow {
+ font-size: 16px;
+ font-weight: bold;
+ border: 0;
+ background-color: transparent;
+ -webkit-border-radius: 5px;
+ text-shadow: none;
+}
+
+body.attached #toolbar-dropdown-arrow {
+ font-size: 14px;
+ padding-bottom: 4px;
+}
+
+#toolbar-dropdown-arrow.dropdown-visible {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(251, 251, 251, 0.9)), to(rgba(231, 231, 231, 0.9)));
+}
+
+#toolbar-dropdown-arrow:hover {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(191, 191, 191, 0.7)), to(rgba(171, 171, 171, 0.5)));
+}
+
+#toolbar-dropdown-arrow:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(111, 111, 111, 0.8)), to(rgba(91, 91, 91, 0.8)));
+}
+
+#toolbar-dropdown {
+ position: absolute;
+ z-index: 1000;
+ -webkit-box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.4);
+ border: 1px solid rgb(128, 128, 128);
+ padding: 4px;
+ background-color: inherit;
+ background-image: inherit;
+}
+
+body.detached.platform-mac-leopard #toolbar-dropdown,
+body.detached.platform-mac-snowleopard #toolbar-dropdown {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
+}
+
+#toolbar-dropdown .scrollable-content {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: start;
+}
+
+#toolbar-dropdown .toolbar-item {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ margin: 0px 2px;
+ padding: 4px;
+ width: 100%;
+ border: 1px solid rgba(0, 0, 0, 0);
+}
+
+#toolbar-dropdown .toolbar-item.toggleable.toggled-on {
+ border: 1px solid rgba(100, 100, 120, 0.4);
+ -webkit-border-image: none;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgba(128, 128, 128, 0.6)), to(rgba(128, 128, 128, 0.6)), color-stop(20%, rgba(158, 158, 158, 0.2)), color-stop(80%, rgba(158, 158, 158, 0.2)));
+}
+
+#toolbar-dropdown .toolbar-item:hover {
+ -webkit-border-image: none;
+ border: 1px solid rgba(100, 100, 120, 0.8);
+}
+
+#toolbar-dropdown .toolbar-item.toggleable.toggled-on:hover {
+ border: 1px solid rgba(100, 100, 120, 1);
+}
+
+#toolbar-dropdown .toolbar-icon {
+ margin-right: 0.5em;
+}
+
+#toolbar-dropdown .toolbar-item:active .toolbar-icon {
+ background-position: 0 24px;
+}
+
+.scrollable-content {
+ position: static;
+ height: 100%;
+ overflow-y: auto;
+ width: 100%;
+ margin-right: 12px;
+ padding-right: 3px;
+}
+
+.scrollable-content::-webkit-scrollbar {
+ width: 11px;
+}
+
+.scrollable-content::-webkit-scrollbar-corner,
+.scrollable-content::-webkit-resizer {
+ display: none;
+}
+
+.scrollable-content::-webkit-scrollbar-thumb:vertical {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(192, 192, 192)), to(rgb(192, 192, 192)), color-stop(40%, rgb(214, 214, 214)));
+ border-radius: 5px;
+ min-height: 20px;
+}
+
+.scrollable-content::-webkit-scrollbar-thumb:vertical:hover,
+.scrollable-content::-webkit-scrollbar-thumb:vertical:active {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(230, 230, 230)), to(rgb(230, 230, 230)), color-stop(40%, rgb(252, 252, 252)));
+}
+
+.scrollable-content::-webkit-scrollbar-track:vertical {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(128, 128, 128)), to(rgb(164, 164, 164)), color-stop(25%, rgb(164, 164, 164)));
+ border-radius: 5px;
+}
+
+.toolbar-search-item {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+}
+
#search {
width: 205px;
font-size: 16px;
- margin-bottom: 5px;
}
body.attached #search {
font-size: 11px;
- margin-bottom: 8px;
}
#search-results-matches {
font-size: 11px;
text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
- margin-bottom: 22px;
-}
-
-body.attached #search-results-matches {
- margin-bottom: 6px;
}
.toolbar-item.elements .toolbar-icon {
@@ -238,7 +349,7 @@ body.attached #search-results-matches {
background-position: 0 0;
background-color: transparent;
border: 0 none transparent;
- margin: 5px 0;
+ margin-top: 9px;
}
#close-button-left:hover, #close-button-right:hover {
@@ -249,6 +360,10 @@ body.attached #search-results-matches {
background-position: 28px 0;
}
+.close-left {
+ float: left;
+}
+
body.detached .toolbar-item.close-left, body.detached .toolbar-item.close-right {
display: none;
}
diff --git a/Source/WebCore/inspector/front-end/inspector.html b/Source/WebCore/inspector/front-end/inspector.html
index 0435dc3..d6c810e 100644
--- a/Source/WebCore/inspector/front-end/inspector.html
+++ b/Source/WebCore/inspector/front-end/inspector.html
@@ -142,8 +142,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ProfileView.js"></script>
<script type="text/javascript" src="HeapSnapshot.js"></script>
<script type="text/javascript" src="HeapSnapshotView.js"></script>
+ <script type="text/javascript" src="DetailedHeapshotGridNodes.js"></script>
<script type="text/javascript" src="DetailedHeapshotView.js"></script>
<script type="text/javascript" src="DebuggerModel.js"></script>
+ <script type="text/javascript" src="DebuggerPresentationModel.js"></script>
<script type="text/javascript" src="DOMAgent.js"></script>
<script type="text/javascript" src="TimelineAgent.js"></script>
<script type="text/javascript" src="TimelinePanel.js"></script>
@@ -154,14 +156,18 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ShortcutsHelp.js"></script>
<script type="text/javascript" src="HAREntry.js"></script>
<script type="text/javascript" src="CookieParser.js"></script>
+ <script type="text/javascript" src="Toolbar.js"></script>
+ <script type="text/javascript" src="SearchController.js"></script>
</head>
<body class="detached">
<div id="toolbar">
<div class="toolbar-item close-left"><button id="close-button-left"></button></div>
- <div class="toolbar-item flexable-space"></div>
- <div class="toolbar-item hidden" id="search-results-matches"></div>
- <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
- <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
+ <div id="toolbar-controls">
+ <div class="toolbar-item"><button id="toolbar-dropdown-arrow" class="toolbar-label">&raquo;</button></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item toolbar-search-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
+ </div>
</div>
<div id="main">
<div id="main-panels" spellcheck="false"></div>
diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js
index 0959289..b4c3fda 100644
--- a/Source/WebCore/inspector/front-end/inspector.js
+++ b/Source/WebCore/inspector/front-end/inspector.js
@@ -138,6 +138,12 @@ var WebInspector = {
this._previousFocusElement.blur();
},
+ resetFocusElement: function()
+ {
+ this.currentFocusElement = null;
+ this._previousFocusElement = null;
+ },
+
get currentPanel()
{
return this._currentPanel;
@@ -153,30 +159,10 @@ var WebInspector = {
this._currentPanel = x;
- this.updateSearchLabel();
-
if (x) {
x.show();
-
- if (this.currentQuery) {
- if (x.performSearch) {
- function performPanelSearch()
- {
- this.updateSearchMatchesCount();
-
- x.currentQuery = this.currentQuery;
- x.performSearch(this.currentQuery);
- }
-
- // Perform the search on a timeout so the panel switches fast.
- setTimeout(performPanelSearch.bind(this), 0);
- } else {
- // Update to show Not found for panels that can't be searched.
- this.updateSearchMatchesCount();
- }
- }
+ WebInspector.searchController.activePanelChanged();
}
-
for (var panelName in WebInspector.panels) {
if (WebInspector.panels[panelName] === x) {
WebInspector.settings.lastActivePanel = panelName;
@@ -248,8 +234,6 @@ var WebInspector = {
this._attached = x;
- this.updateSearchLabel();
-
var dockToggleButton = document.getElementById("dock-status-bar-item");
var body = document.body;
@@ -262,8 +246,11 @@ var WebInspector = {
body.addStyleClass("detached");
dockToggleButton.title = WebInspector.UIString("Dock to main window.");
}
- if (this.drawer)
- this.drawer.resize();
+
+ // This may be called before onLoadedDone, hence the bulk of inspector objects may
+ // not be created yet.
+ if (WebInspector.searchController)
+ WebInspector.searchController.updateSearchLabel();
},
get errors()
@@ -360,9 +347,9 @@ var WebInspector = {
this._highlightedDOMNodeId = nodeId;
if (nodeId)
- InspectorBackend.highlightDOMNode(nodeId);
+ InspectorAgent.highlightDOMNode(nodeId);
else
- InspectorBackend.hideDOMNodeHighlight();
+ InspectorAgent.hideDOMNodeHighlight();
},
highlightDOMNodeForTwoSeconds: function(nodeId)
@@ -492,17 +479,16 @@ WebInspector.doLoadedDone = function()
this.debuggerModel = new WebInspector.DebuggerModel();
this.breakpointManager = new WebInspector.BreakpointManager();
+ this.searchController = new WebInspector.SearchController();
this.panels = {};
this._createPanels();
this._panelHistory = new WebInspector.PanelHistory();
-
- var toolbarElement = document.getElementById("toolbar");
- var previousToolbarItem = toolbarElement.children[0];
+ this.toolbar = new WebInspector.Toolbar();
this.panelOrder = [];
for (var panelName in this.panels)
- previousToolbarItem = WebInspector.addPanelToolbarIcon(toolbarElement, this.panels[panelName], previousToolbarItem);
+ this.addPanel(this.panels[panelName]);
this.Tips = {
ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
@@ -534,15 +520,6 @@ WebInspector.doLoadedDone = function()
errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
this._updateErrorAndWarningCounts();
- var searchField = document.getElementById("search");
- searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
- searchField.addEventListener("mousedown", this._searchFieldManualFocus.bind(this), false); // when the search field is manually selected
- searchField.addEventListener("keydown", this._searchKeyDown.bind(this), true);
-
- toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true);
- document.getElementById("close-button-left").addEventListener("click", this.close, true);
- document.getElementById("close-button-right").addEventListener("click", this.close, true);
-
this.extensionServer.initExtensions();
function onPopulateScriptObjects()
@@ -550,35 +527,29 @@ WebInspector.doLoadedDone = function()
if (!WebInspector.currentPanel)
WebInspector.showPanel(WebInspector.settings.lastActivePanel);
}
- InspectorBackend.populateScriptObjects(onPopulateScriptObjects);
+ InspectorAgent.populateScriptObjects(onPopulateScriptObjects);
if (Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled)
this.debuggerModel.enableDebugger();
if (Preferences.profilerAlwaysEnabled || WebInspector.settings.profilerEnabled)
- InspectorBackend.enableProfiler();
+ InspectorAgent.enableProfiler();
if (WebInspector.settings.monitoringXHREnabled)
- InspectorBackend.setMonitoringXHREnabled(true);
+ ConsoleAgent.setMonitoringXHREnabled(true);
- InspectorBackend.setConsoleMessagesEnabled(true);
+ ConsoleAgent.setConsoleMessagesEnabled(true);
function propertyNamesCallback(names)
{
WebInspector.cssNameCompletions = new WebInspector.CSSCompletions(names);
}
// As a DOMAgent method, this needs to happen after the frontend has loaded and the agent is available.
- InspectorBackend.getSupportedCSSProperties(propertyNamesCallback);
+ CSSAgent.getSupportedCSSProperties(propertyNamesCallback);
}
-WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
+WebInspector.addPanel = function(panel)
{
- var panelToolbarItem = panel.toolbarItem;
this.panelOrder.push(panel);
- panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
- if (previousToolbarItem)
- toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
- else
- toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
- return panelToolbarItem;
+ this.toolbar.addPanel(panel);
}
var windowLoaded = function()
@@ -599,16 +570,19 @@ var windowLoaded = function()
window.addEventListener("DOMContentLoaded", windowLoaded, false);
+// We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
+// It is needed to prevent re-entering the backend code.
+// Also, native dispatches do not guarantee setTimeouts to be serialized, so we
+// enforce serialization using 'messagesToDispatch' queue. It is also important that JSC debugger
+// tests require that each command was dispatch within individual timeout callback, so we don't batch them.
+
+var messagesToDispatch = [];
+
WebInspector.dispatch = function(message) {
- // We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
- // This is important to LayoutTests.
- function delayDispatch()
- {
- InspectorBackend.dispatch(message);
- WebInspector.pendingDispatches--;
- }
- WebInspector.pendingDispatches++;
- setTimeout(delayDispatch, 0);
+ messagesToDispatch.push(message);
+ setTimeout(function() {
+ InspectorBackend.dispatch(messagesToDispatch.shift());
+ }, 0);
}
WebInspector.dispatchMessageFromBackend = function(messageObject)
@@ -621,6 +595,7 @@ WebInspector.windowResize = function(event)
if (this.currentPanel)
this.currentPanel.resize();
this.drawer.resize();
+ this.toolbar.resize();
}
WebInspector.windowFocused = function(event)
@@ -727,7 +702,7 @@ WebInspector.openResource = function(resourceURL, inResourcesPanel)
WebInspector.panels.resources.showResource(resource);
WebInspector.showPanel("resources");
} else
- InspectorBackend.openInInspectedWindow(resource ? resource.url : resourceURL);
+ InspectorAgent.openInInspectedWindow(resource ? resource.url : resourceURL);
}
WebInspector._registerShortcuts = function()
@@ -783,6 +758,12 @@ WebInspector.documentKeyDown = function(event)
}
}
+ WebInspector.searchController.handleShortcut(event);
+ if (event.handled) {
+ event.preventDefault();
+ return;
+ }
+
var isMac = WebInspector.isMac();
switch (event.keyIdentifier) {
case "Left":
@@ -809,36 +790,6 @@ WebInspector.documentKeyDown = function(event)
this.drawer.visible = !this.drawer.visible;
break;
- case "U+0046": // F key
- if (isMac)
- var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
- else
- var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
-
- if (isFindKey) {
- WebInspector.focusSearchField();
- event.preventDefault();
- }
- break;
-
- case "F3":
- if (!isMac) {
- WebInspector.focusSearchField();
- event.preventDefault();
- }
- break;
-
- case "U+0047": // G key
- if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
- if (event.shiftKey) {
- if (this.currentPanel.jumpToPreviousSearchResult)
- this.currentPanel.jumpToPreviousSearchResult();
- } else if (this.currentPanel.jumpToNextSearchResult)
- this.currentPanel.jumpToNextSearchResult();
- event.preventDefault();
- }
- break;
-
// Windows and Mac have two different definitions of [, so accept both.
case "U+005B":
case "U+00DB": // [ key
@@ -875,13 +826,13 @@ WebInspector.documentKeyDown = function(event)
case "U+0052": // R key
if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
- InspectorBackend.reloadPage(event.shiftKey);
+ InspectorAgent.reloadPage(event.shiftKey);
event.preventDefault();
}
break;
case "F5":
if (!isMac)
- InspectorBackend.reloadPage(event.ctrlKey || event.shiftKey);
+ InspectorAgent.reloadPage(event.ctrlKey || event.shiftKey);
break;
}
}
@@ -1005,27 +956,6 @@ WebInspector.animateStyle = function(animations, duration, callback)
};
}
-WebInspector.updateSearchLabel = function()
-{
- if (!this.currentPanel)
- return;
-
- var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
- if (this.attached)
- document.getElementById("search").setAttribute("placeholder", newLabel);
- else {
- document.getElementById("search").removeAttribute("placeholder");
- document.getElementById("search-toolbar-label").textContent = newLabel;
- }
-}
-
-WebInspector.focusSearchField = function()
-{
- var searchField = document.getElementById("search");
- searchField.focus();
- searchField.select();
-}
-
WebInspector.toggleAttach = function()
{
if (!this.attached)
@@ -1034,58 +964,6 @@ WebInspector.toggleAttach = function()
InspectorFrontendHost.requestDetachWindow();
}
-WebInspector.toolbarDragStart = function(event)
-{
- if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
- return;
-
- var target = event.target;
- if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
- return;
-
- var toolbar = document.getElementById("toolbar");
- if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
- return;
-
- toolbar.lastScreenX = event.screenX;
- toolbar.lastScreenY = event.screenY;
-
- WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
-}
-
-WebInspector.toolbarDragEnd = function(event)
-{
- var toolbar = document.getElementById("toolbar");
-
- WebInspector.elementDragEnd(event);
-
- delete toolbar.lastScreenX;
- delete toolbar.lastScreenY;
-}
-
-WebInspector.toolbarDrag = function(event)
-{
- var toolbar = document.getElementById("toolbar");
-
- if (WebInspector.attached) {
- var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
-
- InspectorFrontendHost.setAttachedWindowHeight(height);
- } else {
- var x = event.screenX - toolbar.lastScreenX;
- var y = event.screenY - toolbar.lastScreenY;
-
- // We cannot call window.moveBy here because it restricts the movement
- // of the window at the edges.
- InspectorFrontendHost.moveWindowBy(x, y);
- }
-
- toolbar.lastScreenX = event.screenX;
- toolbar.lastScreenY = event.screenY;
-
- event.preventDefault();
-}
-
WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
{
if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
@@ -1307,6 +1185,23 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) {
g.fill();
}
+WebInspector.inspect = function(objectId, hints)
+{
+ var object = WebInspector.RemoteObject.fromPayload(objectId);
+ if (object.type === "node") {
+ // Request node from backend and focus it.
+ object.pushNodeToFrontend(WebInspector.updateFocusedNode.bind(WebInspector));
+ } else if (hints.databaseId) {
+ WebInspector.currentPanel = WebInspector.panels.resources;
+ WebInspector.panels.resources.selectDatabase(hints.databaseId);
+ } else if (hints.domStorageId) {
+ WebInspector.currentPanel = WebInspector.panels.resources;
+ WebInspector.panels.resources.selectDOMStorage(hints.domStorageId);
+ }
+
+ RuntimeAgent.releaseObject(objectId);
+}
+
WebInspector.updateFocusedNode = function(nodeId)
{
this._updateFocusedNode(nodeId);
@@ -1518,156 +1413,12 @@ WebInspector.addMainEventListeners = function(doc)
doc.addEventListener("click", this.documentClick.bind(this), true);
}
-WebInspector._searchFieldManualFocus = function(event)
-{
- this.currentFocusElement = event.target;
- this._previousFocusElement = event.target;
-}
-
-WebInspector._searchKeyDown = function(event)
-{
- // Escape Key will clear the field and clear the search results
- if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
- // If focus belongs here and text is empty - nothing to do, return unhandled.
- if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
- return;
- event.preventDefault();
- event.stopPropagation();
- // When search was selected manually and is currently blank, we'd like Esc stay unhandled
- // and hit console drawer handler.
- event.target.value = "";
-
- this.performSearch(event);
- this.currentFocusElement = this.previousFocusElement;
- if (this.currentFocusElement === event.target)
- this.currentFocusElement.select();
- return false;
- }
-
- if (!isEnterKey(event))
- return false;
-
- // Select all of the text so the user can easily type an entirely new query.
- event.target.select();
-
- // Only call performSearch if the Enter key was pressed. Otherwise the search
- // performance is poor because of searching on every key. The search field has
- // the incremental attribute set, so we still get incremental searches.
- this.performSearch(event);
-
- // Call preventDefault since this was the Enter key. This prevents a "search" event
- // from firing for key down. This stops performSearch from being called twice in a row.
- event.preventDefault();
-}
-
-WebInspector.performSearch = function(event)
-{
- var forceSearch = event.keyIdentifier === "Enter";
- this.doPerformSearch(event.target.value, forceSearch, event.shiftKey, false);
-}
-
-WebInspector.cancelSearch = function()
-{
- document.getElementById("search").value = "";
- this.doPerformSearch("");
-}
-
-WebInspector.doPerformSearch = function(query, forceSearch, isBackwardSearch, repeatSearch)
-{
- var isShortSearch = (query.length < 3);
-
- // Clear a leftover short search flag due to a non-conflicting forced search.
- if (isShortSearch && this.shortSearchWasForcedByKeyEvent && this.currentQuery !== query)
- delete this.shortSearchWasForcedByKeyEvent;
-
- // Indicate this was a forced search on a short query.
- if (isShortSearch && forceSearch)
- this.shortSearchWasForcedByKeyEvent = true;
-
- if (!query || !query.length || (!forceSearch && isShortSearch)) {
- // Prevent clobbering a short search forced by the user.
- if (this.shortSearchWasForcedByKeyEvent) {
- delete this.shortSearchWasForcedByKeyEvent;
- return;
- }
-
- delete this.currentQuery;
-
- for (var panelName in this.panels) {
- var panel = this.panels[panelName];
- var hadCurrentQuery = !!panel.currentQuery;
- delete panel.currentQuery;
- if (hadCurrentQuery && panel.searchCanceled)
- panel.searchCanceled();
- }
-
- this.updateSearchMatchesCount();
-
- return;
- }
-
- if (!repeatSearch && query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
- // When this is the same query and a forced search, jump to the next
- // search result for a good user experience.
- if (forceSearch) {
- if (!isBackwardSearch && this.currentPanel.jumpToNextSearchResult)
- this.currentPanel.jumpToNextSearchResult();
- else if (isBackwardSearch && this.currentPanel.jumpToPreviousSearchResult)
- this.currentPanel.jumpToPreviousSearchResult();
- }
- return;
- }
-
- this.currentQuery = query;
-
- this.updateSearchMatchesCount();
-
- if (!this.currentPanel.performSearch)
- return;
-
- this.currentPanel.currentQuery = query;
- this.currentPanel.performSearch(query);
-}
-
WebInspector.frontendReused = function()
{
- this.networkManager.reset();
+ this.networkManager.frontendReused();
this.reset();
}
-WebInspector.addNodesToSearchResult = function(nodeIds)
-{
- WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
-}
-
-WebInspector.updateSearchMatchesCount = function(matches, panel)
-{
- if (!panel)
- panel = this.currentPanel;
-
- panel.currentSearchMatches = matches;
-
- if (panel !== this.currentPanel)
- return;
-
- if (!this.currentPanel.currentQuery) {
- document.getElementById("search-results-matches").addStyleClass("hidden");
- return;
- }
-
- if (matches) {
- if (matches === 1)
- var matchesString = WebInspector.UIString("1 match");
- else
- var matchesString = WebInspector.UIString("%d matches", matches);
- } else
- var matchesString = WebInspector.UIString("Not Found");
-
- var matchesToolbarElement = document.getElementById("search-results-matches");
- matchesToolbarElement.removeStyleClass("hidden");
- matchesToolbarElement.textContent = matchesString;
-}
-
WebInspector.UIString = function(string)
{
if (window.localizedStrings && string in window.localizedStrings)
@@ -1675,7 +1426,7 @@ WebInspector.UIString = function(string)
else {
if (!(string in WebInspector.missingLocalizedStrings)) {
if (!WebInspector.InspectorBackendStub)
- console.error("Localized string \"" + string + "\" not found.");
+ console.warn("Localized string \"" + string + "\" not found.");
WebInspector.missingLocalizedStrings[string] = true;
}
diff --git a/Source/WebCore/inspector/front-end/networkPanel.css b/Source/WebCore/inspector/front-end/networkPanel.css
index c750323..2711347 100644
--- a/Source/WebCore/inspector/front-end/networkPanel.css
+++ b/Source/WebCore/inspector/front-end/networkPanel.css
@@ -22,7 +22,7 @@
-webkit-background-size: 1px 42px;
}
-.network-sidebar .data-grid td:not(.network-summary) {
+.network-sidebar .data-grid td {
line-height: 17px;
height: 37px;
border-right: 1px solid rgb(210, 210, 210);
@@ -496,34 +496,34 @@
/* Summary */
+.network-sidebar tr.filler td {
+ padding-bottom: 20px !important;
+}
+
.network-summary-bar {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin-right: -14px;
background-color: rgb(101, 111, 130);
+}
+
+.network-sidebar .data-grid .network-summary-bar td {
color: white;
height: 20px;
+ border: none;
font-size: 11px;
font-weight: bold;
- padding-top: 3px;
- padding-left: 10px;
- z-index: 2000;
+ padding: 0 0 0 8px;
white-space: pre;
overflow : hidden;
text-overflow : ellipsis;
}
-.network-summary-bar-bottom {
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- padding-top: 3px;
-}
-
-.data-grid td .network-summary-bar {
- white-space: pre;
-}
-
-.network-sidebar .data-grid td.network-summary {
- padding: 0;
+.network-summary-bar img {
+ vertical-align: middle;
+ padding-right: 8px;
}
/* Viewer */
diff --git a/Source/WebCore/inspector/front-end/textViewer.css b/Source/WebCore/inspector/front-end/textViewer.css
index f6aa65e..59f2a43 100644
--- a/Source/WebCore/inspector/front-end/textViewer.css
+++ b/Source/WebCore/inspector/front-end/textViewer.css
@@ -15,6 +15,9 @@
bottom: 0;
overflow: hidden;
-webkit-user-select: none;
+ background-color: rgb(240, 240, 240);
+ border-right: 1px solid rgb(187, 187, 187);
+ min-width: 19px;
}
.text-editor-contents {
@@ -27,6 +30,15 @@
-webkit-user-select: text;
}
+.text-editor-contents .inner-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: auto;
+ bottom: auto;
+ min-width: 100%;
+}
+
.text-editor-editable {
-webkit-user-modify: read-write-plaintext-only;
}
@@ -80,8 +92,6 @@
.webkit-line-number {
color: rgb(128, 128, 128);
- background-color: rgb(240, 240, 240);
- border-right: 1px solid rgb(187, 187, 187);
text-align: right;
vertical-align: top;
word-break: normal;
diff --git a/Source/WebCore/inspector/front-end/utilities.js b/Source/WebCore/inspector/front-end/utilities.js
index 5ed9a8c..31a5f0c 100644
--- a/Source/WebCore/inspector/front-end/utilities.js
+++ b/Source/WebCore/inspector/front-end/utilities.js
@@ -218,7 +218,8 @@ Element.prototype.pruneEmptyTextNodes = function()
Element.prototype.isScrolledToBottom = function()
{
- return this.scrollTop === this.scrollHeight - this.offsetHeight;
+ // This code works only for 0-width border
+ return this.scrollTop + this.clientHeight === this.scrollHeight;
}
Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
@@ -399,6 +400,15 @@ String.prototype.findAll = function(string)
return matches;
}
+String.prototype.lineEndings = function()
+{
+ if (!this._lineEndings) {
+ this._lineEndings = this.findAll("\n");
+ this._lineEndings.push(this.length);
+ }
+ return this._lineEndings;
+}
+
String.prototype.asParsedURL = function()
{
// RegExp groups:
@@ -1010,52 +1020,91 @@ function isEnterKey(event) {
return event.keyCode !== 229 && event.keyIdentifier === "Enter";
}
-
function highlightSearchResult(element, offset, length)
{
+ var result = highlightSearchResults(element, [{offset: offset, length: length }]);
+ return result.length ? result[0] : null;
+}
+
+function highlightSearchResults(element, resultRanges)
+{
+ var highlightNodes = [];
var lineText = element.textContent;
- var endOffset = offset + length;
- var highlightNode = document.createElement("span");
- highlightNode.className = "webkit-search-result";
- highlightNode.textContent = lineText.substring(offset, endOffset);
-
- var boundary = element.rangeBoundaryForOffset(offset);
- var textNode = boundary.container;
- var text = textNode.textContent;
-
- if (boundary.offset + length < text.length) {
- // Selection belong to a single split mode.
- textNode.textContent = text.substring(boundary.offset + length);
- textNode.parentElement.insertBefore(highlightNode, textNode);
- var prefixNode = document.createTextNode(text.substring(0, boundary.offset));
- textNode.parentElement.insertBefore(prefixNode, highlightNode);
- return highlightNode;
- }
+ var textNodeSnapshot = document.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+
+ var snapshotLength = textNodeSnapshot.snapshotLength;
+ var snapshotNodeOffset = 0;
+ var currentSnapshotItem = 0;
+
+ for (var i = 0; i < resultRanges.length; ++i) {
+ var resultLength = resultRanges[i].length;
+ var startOffset = resultRanges[i].offset;
+ var endOffset = startOffset + resultLength;
+ var length = resultLength;
+ var textNode;
+ var textNodeOffset;
+ var found;
+
+ while (currentSnapshotItem < snapshotLength) {
+ textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
+ var textNodeLength = textNode.nodeValue.length;
+ if (snapshotNodeOffset + textNodeLength >= startOffset) {
+ textNodeOffset = startOffset - snapshotNodeOffset;
+ snapshotNodeOffset += textNodeLength;
+ found = true;
+ break;
+ }
+ snapshotNodeOffset += textNodeLength;
+ }
- var parentElement = textNode.parentElement;
- var anchorElement = textNode.nextSibling;
+ if (!found) {
+ textNode = element;
+ textNodeOffset = 0;
+ }
- length -= text.length - boundary.offset;
- textNode.textContent = text.substring(0, boundary.offset);
- textNode = textNode.traverseNextTextNode(element);
+ var highlightNode = document.createElement("span");
+ highlightNode.className = "webkit-search-result";
+ highlightNode.textContent = lineText.substring(startOffset, endOffset);
- while (textNode) {
var text = textNode.textContent;
- if (length < text.length) {
- textNode.textContent = text.substring(length);
- break;
+ if (textNodeOffset + resultLength < text.length) {
+ // Selection belongs to a single split mode.
+ textNode.textContent = text.substring(textNodeOffset + resultLength);
+ textNode.parentElement.insertBefore(highlightNode, textNode);
+ var prefixNode = document.createTextNode(text.substring(0, textNodeOffset));
+ textNode.parentElement.insertBefore(prefixNode, highlightNode);
+
+ highlightNodes.push(highlightNode);
+ continue;
+ }
+
+ var parentElement = textNode.parentElement;
+ var anchorElement = textNode.nextSibling;
+
+ length -= text.length - textNodeOffset;
+ textNode.textContent = text.substring(0, textNodeOffset);
+
+ while (currentSnapshotItem < snapshotLength) {
+ textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
+ snapshotNodeOffset += textNode.nodeValue.length;
+ var text = textNode.textContent;
+ if (length < text.length) {
+ textNode.textContent = text.substring(length);
+ break;
+ }
+
+ length -= text.length;
+ textNode.textContent = "";
}
- length -= text.length;
- textNode.textContent = "";
- textNode = textNode.traverseNextTextNode(element);
+ parentElement.insertBefore(highlightNode, anchorElement);
+ highlightNodes.push(highlightNode);
}
- parentElement.insertBefore(highlightNode, anchorElement);
- return highlightNode;
+ return highlightNodes;
}
-function createSearchRegex(query)
+function createSearchRegex(query, extraFlags)
{
var regex = "";
for (var i = 0; i < query.length; ++i) {
@@ -1064,7 +1113,7 @@ function createSearchRegex(query)
char = "\\]";
regex += "[" + char + "]";
}
- return new RegExp(regex, "i");
+ return new RegExp(regex, "i" + (extraFlags || ""));
}
function offerFileForDownload(contents)