summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector')
-rw-r--r--WebCore/inspector/CodeGeneratorInspector.pm25
-rw-r--r--WebCore/inspector/ConsoleMessage.cpp18
-rw-r--r--WebCore/inspector/ConsoleMessage.h4
-rw-r--r--WebCore/inspector/Inspector.idl42
-rw-r--r--WebCore/inspector/InspectorApplicationCacheAgent.cpp2
-rw-r--r--WebCore/inspector/InspectorCSSAgent.cpp649
-rw-r--r--WebCore/inspector/InspectorCSSAgent.h126
-rw-r--r--WebCore/inspector/InspectorCSSStore.cpp14
-rw-r--r--WebCore/inspector/InspectorCSSStore.h6
-rw-r--r--WebCore/inspector/InspectorClient.cpp68
-rw-r--r--WebCore/inspector/InspectorClient.h4
-rw-r--r--WebCore/inspector/InspectorController.cpp549
-rw-r--r--WebCore/inspector/InspectorController.h86
-rw-r--r--WebCore/inspector/InspectorDOMAgent.cpp104
-rw-r--r--WebCore/inspector/InspectorDOMAgent.h25
-rw-r--r--WebCore/inspector/InspectorDebuggerAgent.cpp33
-rw-r--r--WebCore/inspector/InspectorDebuggerAgent.h7
-rw-r--r--WebCore/inspector/InspectorFrontendClientLocal.cpp8
-rw-r--r--WebCore/inspector/InspectorInstrumentation.cpp462
-rw-r--r--WebCore/inspector/InspectorInstrumentation.h500
-rw-r--r--WebCore/inspector/InspectorProfilerAgent.cpp12
-rw-r--r--WebCore/inspector/InspectorResource.cpp153
-rw-r--r--WebCore/inspector/InspectorResource.h15
-rw-r--r--WebCore/inspector/InspectorResourceAgent.cpp432
-rw-r--r--WebCore/inspector/InspectorResourceAgent.h114
-rw-r--r--WebCore/inspector/InspectorState.cpp184
-rw-r--r--WebCore/inspector/InspectorState.h101
-rw-r--r--WebCore/inspector/InspectorStyleSheet.cpp571
-rw-r--r--WebCore/inspector/InspectorStyleSheet.h135
-rw-r--r--WebCore/inspector/InspectorTimelineAgent.cpp11
-rw-r--r--WebCore/inspector/InspectorTimelineAgent.h20
-rw-r--r--WebCore/inspector/InspectorValues.cpp29
-rw-r--r--WebCore/inspector/InspectorValues.h8
-rw-r--r--WebCore/inspector/front-end/AuditRules.js23
-rw-r--r--WebCore/inspector/front-end/BreakpointManager.js387
-rw-r--r--WebCore/inspector/front-end/BreakpointsSidebarPane.js145
-rw-r--r--WebCore/inspector/front-end/CSSStyleModel.js4
-rw-r--r--WebCore/inspector/front-end/CallStackSidebarPane.js54
-rw-r--r--WebCore/inspector/front-end/ConsoleView.js35
-rw-r--r--WebCore/inspector/front-end/CookieItemsView.js4
-rwxr-xr-xWebCore/inspector/front-end/CookieParser.js204
-rw-r--r--WebCore/inspector/front-end/DOMAgent.js209
-rw-r--r--WebCore/inspector/front-end/DataGrid.js212
-rw-r--r--WebCore/inspector/front-end/ElementsPanel.js110
-rw-r--r--WebCore/inspector/front-end/ElementsTreeOutline.js16
-rw-r--r--WebCore/inspector/front-end/EventListenersSidebarPane.js2
-rw-r--r--WebCore/inspector/front-end/ExtensionAPI.js10
-rw-r--r--WebCore/inspector/front-end/ExtensionServer.js57
-rw-r--r--WebCore/inspector/front-end/HAREntry.js46
-rw-r--r--WebCore/inspector/front-end/InjectedScript.js19
-rw-r--r--WebCore/inspector/front-end/NetworkPanel.js764
-rw-r--r--WebCore/inspector/front-end/ProfilesPanel.js4
-rw-r--r--WebCore/inspector/front-end/PropertiesSection.js2
-rw-r--r--WebCore/inspector/front-end/Resource.js145
-rw-r--r--WebCore/inspector/front-end/ResourceCategory.js4
-rw-r--r--WebCore/inspector/front-end/ResourceManager.js297
-rw-r--r--WebCore/inspector/front-end/ResourceView.js1
-rw-r--r--WebCore/inspector/front-end/ResourcesPanel.js68
-rw-r--r--WebCore/inspector/front-end/ScriptsPanel.js15
-rw-r--r--WebCore/inspector/front-end/SourceFrame.js8
-rw-r--r--WebCore/inspector/front-end/SourceView.js4
-rw-r--r--WebCore/inspector/front-end/StoragePanel.js2
-rw-r--r--WebCore/inspector/front-end/StylesSidebarPane.js6
-rw-r--r--WebCore/inspector/front-end/TabbedPane.js2
-rw-r--r--WebCore/inspector/front-end/TextViewer.js14
-rw-r--r--WebCore/inspector/front-end/TimelineGrid.js16
-rw-r--r--WebCore/inspector/front-end/TimelineOverviewPane.js4
-rw-r--r--WebCore/inspector/front-end/WebKit.qrc2
-rw-r--r--WebCore/inspector/front-end/inspector.css149
-rw-r--r--WebCore/inspector/front-end/inspector.html2
-rw-r--r--WebCore/inspector/front-end/inspector.js101
-rw-r--r--WebCore/inspector/front-end/networkPanel.css984
-rw-r--r--WebCore/inspector/front-end/utilities.js35
73 files changed, 6705 insertions, 1978 deletions
diff --git a/WebCore/inspector/CodeGeneratorInspector.pm b/WebCore/inspector/CodeGeneratorInspector.pm
index 80e243b..a566576 100644
--- a/WebCore/inspector/CodeGeneratorInspector.pm
+++ b/WebCore/inspector/CodeGeneratorInspector.pm
@@ -28,6 +28,11 @@ $typeTransform{"Debug"} = {
"header" => "InspectorDebuggerAgent.h",
"domainAccessor" => "m_inspectorController->debuggerAgent()",
};
+$typeTransform{"Resource"} = {
+ "forward" => "InspectorResourceAgent",
+ "header" => "InspectorResourceAgent.h",
+ "domainAccessor" => "m_inspectorController->m_resourceAgent",
+};
$typeTransform{"DOM"} = {
"forward" => "InspectorDOMAgent",
"header" => "InspectorDOMAgent.h",
@@ -114,6 +119,14 @@ $typeTransform{"unsigned int"} = {
"header" => "",
"JSONType" => "Number"
};
+$typeTransform{"double"} = {
+ "param" => "double",
+ "variable" => "double",
+ "defaultValue" => "0.0",
+ "forward" => "",
+ "header" => "",
+ "JSONType" => "Number"
+};
$typeTransform{"boolean"} = {
"param" => "bool",
"variable"=> "bool",
@@ -306,7 +319,7 @@ sub generateBackendFunction
my $domainAccessor = $typeTransform{$domain}->{"domainAccessor"};
$backendTypes{$domain} = 1;
push(@function, " if (!$domainAccessor)");
- push(@function, " protocolErrors->pushString(String::format(\"Protocol Error: %s handler is not available.\", \"$domain\"));");
+ push(@function, " protocolErrors->pushString(\"Protocol Error: $domain handler is not available.\");");
push(@function, "");
if (scalar(@inArgs)) {
@@ -316,7 +329,7 @@ sub generateBackendFunction
push(@function, "");
push(@function, " RefPtr<InspectorObject> argumentsContainer;");
push(@function, " if (!(argumentsContainer = requestMessageObject->getObject(\"arguments\"))) {");
- push(@function, " protocolErrors->pushString(String::format(\"Protocol Error: 'arguments' property with type 'object' was not found.\"));");
+ push(@function, " protocolErrors->pushString(\"Protocol Error: 'arguments' property with type 'object' was not found.\");");
push(@function, " } else {");
push(@function, " InspectorObject::const_iterator argumentsEndIterator = argumentsContainer->end();");
@@ -329,10 +342,10 @@ sub generateBackendFunction
push(@function, "");
push(@function, " InspectorObject::const_iterator ${name}ValueIterator = argumentsContainer->find(\"$name\");");
push(@function, " if (${name}ValueIterator == argumentsEndIterator) {");
- push(@function, " protocolErrors->pushString(String::format(\"Protocol Error: Argument '%s' with type '%s' was not found.\", \"$name\", \"$JSONType\"));");
+ push(@function, " protocolErrors->pushString(\"Protocol Error: Argument '$name' with type '$JSONType' was not found.\");");
push(@function, " } else {");
push(@function, " if (!${name}ValueIterator->second->as$JSONType(&$name)) {");
- push(@function, " protocolErrors->pushString(String::format(\"Protocol Error: Argument '%s' has wrong type. It should be '%s'.\", \"$name\", \"$JSONType\"));");
+ push(@function, " protocolErrors->pushString(\"Protocol Error: Argument '$name' has wrong type. It should be '$JSONType'.\");");
push(@function, " }");
push(@function, " }");
}
@@ -446,7 +459,7 @@ $mapEntries
HashMap<String, CallHandler>::iterator it = dispatchMap.find(command);
if (it == dispatchMap.end()) {
- reportProtocolError(callId, String::format("Protocol Error: Invalid command was received. '%s' wasn't found.", command.utf8().data()));
+ reportProtocolError(callId, makeString("Protocol Error: Invalid command was received. '", command, "' wasn't found."));
return;
}
@@ -606,7 +619,7 @@ sub generateSource
my @sourceContent = split("\r", $licenseTemplate);
push(@sourceContent, "\n#include \"config.h\"");
push(@sourceContent, "#include \"$className.h\"");
- push(@sourceContent, "#include <wtf/text/CString.h>");
+ push(@sourceContent, "#include <wtf/text/StringConcatenate.h>");
push(@sourceContent, "");
push(@sourceContent, "#if ENABLE(INSPECTOR)");
push(@sourceContent, "");
diff --git a/WebCore/inspector/ConsoleMessage.cpp b/WebCore/inspector/ConsoleMessage.cpp
index f3bd6bc..67930cd 100644
--- a/WebCore/inspector/ConsoleMessage.cpp
+++ b/WebCore/inspector/ConsoleMessage.cpp
@@ -67,7 +67,7 @@ PassRefPtr<InspectorObject> ConsoleMessage::CallFrame::buildInspectorObject() co
{
RefPtr<InspectorObject> frame = InspectorObject::create();
frame->setString("functionName", m_functionName);
- frame->setString("sourceURL", m_sourceURL.string());
+ frame->setString("sourceURL", m_sourceURL);
frame->setNumber("lineNumber", m_lineNumber);
return frame;
}
@@ -100,7 +100,7 @@ ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, c
{
const ScriptCallFrame& lastCaller = callStack->at(0);
m_line = lastCaller.lineNumber();
- m_url = lastCaller.sourceURL().string();
+ m_url = lastCaller.sourceURL();
if (storeTrace) {
for (unsigned i = 0; i < callStack->size(); ++i)
@@ -155,22 +155,20 @@ void ConsoleMessage::updateRepeatCountInConsole(InspectorFrontend* frontend)
}
#endif // ENABLE(INSPECTOR)
-bool ConsoleMessage::isEqual(ScriptState* state, ConsoleMessage* msg) const
+bool ConsoleMessage::isEqual(ConsoleMessage* msg) const
{
#if ENABLE(INSPECTOR)
if (msg->m_arguments.size() != m_arguments.size())
return false;
- if (!state && msg->m_arguments.size())
+ if (!msg->m_scriptState.get() && msg->m_arguments.size()) {
+ ASSERT_NOT_REACHED();
return false;
+ }
- ASSERT_ARG(state, state || msg->m_arguments.isEmpty());
-
- for (size_t i = 0; i < msg->m_arguments.size(); ++i) {
- if (!m_arguments[i].isEqual(state, msg->m_arguments[i]))
+ for (size_t i = 0; i < m_arguments.size(); ++i) {
+ if (!m_arguments[i].isEqual(msg->m_scriptState.get(), msg->m_arguments[i]))
return false;
}
-#else
- UNUSED_PARAM(state);
#endif // ENABLE(INSPECTOR)
size_t frameCount = msg->m_frames.size();
diff --git a/WebCore/inspector/ConsoleMessage.h b/WebCore/inspector/ConsoleMessage.h
index d10fa3d..6c3f2c7 100644
--- a/WebCore/inspector/ConsoleMessage.h
+++ b/WebCore/inspector/ConsoleMessage.h
@@ -55,7 +55,7 @@ public:
void updateRepeatCountInConsole(InspectorFrontend* frontend);
#endif
void incrementCount() { ++m_repeatCount; }
- bool isEqual(ScriptState*, ConsoleMessage* msg) const;
+ bool isEqual(ConsoleMessage* msg) const;
MessageSource source() const { return m_source; }
const String& message() const { return m_message; }
@@ -72,7 +72,7 @@ private:
private:
String m_functionName;
- KURL m_sourceURL;
+ String m_sourceURL;
unsigned m_lineNumber;
};
diff --git a/WebCore/inspector/Inspector.idl b/WebCore/inspector/Inspector.idl
index a08a622..85c30a8 100644
--- a/WebCore/inspector/Inspector.idl
+++ b/WebCore/inspector/Inspector.idl
@@ -32,7 +32,6 @@
module core {
interface [Conditional=INSPECTOR] Inspector {
- [notify] void addConsoleMessage(out Object messageObj);
[notify] void addRecordToTimeline(out Object record);
[notify] void addNodesToSearchResult(out Array nodeIds);
[notify] void attributesUpdated(out long id, out Array attributes);
@@ -41,11 +40,12 @@ module core {
[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);
- [notify] void consoleMessagesCleared();
[notify] void didCommitLoad();
[notify] void evaluateForTestInFrontend(out long testCallId, out String script);
[notify] void disconnectFromBackend();
+ [notify] void domContentEventFired(out double time);
[notify] void inspectedURLChanged(out String url);
+ [notify] void loadEventFired(out double time);
[notify] void removeResource(out unsigned long identifier);
[notify] void reset();
[notify] void resetProfilesPanel();
@@ -55,8 +55,6 @@ module core {
[notify] void showPanel(out String panel);
[notify] void timelineProfilerWasStarted();
[notify] void timelineProfilerWasStopped();
- [notify] void updateConsoleMessageExpiredCount(out unsigned long count);
- [notify] void updateConsoleMessageRepeatCount(out unsigned long count);
[notify] void updateFocusedNode(out long nodeId);
[notify] void updateResource(out Value resource);
@@ -108,12 +106,31 @@ module core {
[handler=Controller] void setMonitoringXHREnabled(in boolean enable, out boolean newState);
[handler=Controller] void setResourceTrackingEnabled(in boolean enabled, in boolean always, out boolean newState);
- [handler=Controller] void getResourceContent(in unsigned long identifier, out String content);
+ [handler=Controller] void getResourceContent(in unsigned long identifier, in boolean encode, out String content);
[handler=Controller] void reloadPage();
[handler=Controller] void startTimelineProfiler();
[handler=Controller] void stopTimelineProfiler();
+ [handler=Resource] void cachedResources(out Array resources);
+ [handler=Resource] void resourceContent(in unsigned long frameID, in String url, out String content);
+ [notify] void identifierForInitialRequest(out long identifier, out String url, out unsigned long frameID, out boolean isMainResource);
+ [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 unsigned long frameID, out Object resource);
+ [notify] void setOverrideContent(out long identifier, out String sourceString, out String type);
+ [notify] void didCommitLoad(out unsigned long frameID);
+ [notify] void frameDetachedFromParent(out unsigned long frameID);
+
+ [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);
+
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
[handler=Backend] void enableDebugger(in boolean always);
[handler=Controller] void disableDebugger(in boolean always);
@@ -135,8 +152,8 @@ module core {
[handler=Debug] void editScriptSource(in String sourceID, in String newContent, out boolean success, out String result, out Value newCallFrames);
[handler=Debug] void getScriptSource(in String sourceID, out String scriptSource);
- [handler=Controller] void setNativeBreakpoint(in Object breakpoint, out unsigned int breakpointId);
- [handler=Controller] void removeNativeBreakpoint(in unsigned int breakpointId);
+ [handler=Controller] void setNativeBreakpoint(in Object breakpoint, out String breakpointId);
+ [handler=Controller] void removeNativeBreakpoint(in String breakpointId);
[handler=Controller] void enableProfiler(in boolean always);
[handler=Controller] void disableProfiler(in boolean always);
@@ -171,10 +188,15 @@ module core {
[handler=DOM] void performSearch(in String query, in boolean runSynchronously);
[handler=DOM] void searchCanceled();
[handler=DOM] void pushNodeByPathToFrontend(in String path, out long nodeId);
- [handler=DOM] void setDOMBreakpoint(in long nodeId, in long type);
- [handler=DOM] void removeDOMBreakpoint(in long nodeId, in long type);
+
+ [handler=Controller] 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);
[handler=Controller] void clearConsoleMessages();
+ [notify] void consoleMessagesCleared();
+
[handler=Controller] void highlightDOMNode(in long nodeId);
[handler=Controller] void hideDOMNodeHighlight();
[handler=Controller] void openInInspectedWindow(in String url);
@@ -185,7 +207,7 @@ module core {
[handler=DOM] void getComputedStyle(in long nodeId, out Value style);
[handler=DOM] void getStyleSheet(in long styleSheetId, out Object styleSheet);
[handler=DOM] void getStyleSourceData(in long styleSheetId, out Object styleSourceData);
- [handler=DOM] void applyStyleText(in long styleId, in String styleText, in String propertyName, out boolean success, out Value style, out Array changedProperties);
+ [handler=DOM] void applyStyleText(in long styleId, in String styleText, in String propertyName, out boolean success, out Value style);
[handler=DOM] void setStyleText(in long styleId, in String styleText, out boolean success);
[handler=DOM] void setStyleProperty(in long styleId, in String name, in String value, out boolean success);
[handler=DOM] void toggleStyleEnabled(in long styleId, in String propertyName, in boolean disabled, out Value style);
diff --git a/WebCore/inspector/InspectorApplicationCacheAgent.cpp b/WebCore/inspector/InspectorApplicationCacheAgent.cpp
index 918643b..ced61c5 100644
--- a/WebCore/inspector/InspectorApplicationCacheAgent.cpp
+++ b/WebCore/inspector/InspectorApplicationCacheAgent.cpp
@@ -48,7 +48,7 @@ InspectorApplicationCacheAgent::InspectorApplicationCacheAgent(InspectorControll
void InspectorApplicationCacheAgent::didReceiveManifestResponse(unsigned long identifier, const ResourceResponse& response)
{
- m_inspectorController->didReceiveResponse(identifier, response);
+ m_inspectorController->didReceiveResponse(identifier, 0, response);
}
void InspectorApplicationCacheAgent::updateApplicationCacheStatus(ApplicationCacheHost::Status status)
diff --git a/WebCore/inspector/InspectorCSSAgent.cpp b/WebCore/inspector/InspectorCSSAgent.cpp
new file mode 100644
index 0000000..e0fab85
--- /dev/null
+++ b/WebCore/inspector/InspectorCSSAgent.cpp
@@ -0,0 +1,649 @@
+/*
+ * Copyright (C) 2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "InspectorCSSAgent.h"
+
+#if ENABLE(INSPECTOR)
+
+#include "CSSComputedStyleDeclaration.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPropertyNames.h"
+#include "CSSPropertySourceData.h"
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSelector.h"
+#include "CSSStyleSheet.h"
+#include "DOMWindow.h"
+#include "HTMLHeadElement.h"
+#include "InspectorDOMAgent.h"
+#include "InspectorFrontend.h"
+#include "InspectorValues.h"
+#include "Node.h"
+#include "StyleSheetList.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+
+
+// cssProperty = {
+// name : <string>,
+// value : <string>,
+// priority : <string>, // "" for non-parsedOk properties
+// implicit : <boolean>,
+// parsedOk : <boolean>, // whether property is understood by WebCore
+// status : <string>, // "disabled" | "active" | "inactive" | "style"
+// shorthandName : <string>,
+// startOffset : <number>, // Optional - property text start offset in enclosing style declaration. Absent for computed styles and such.
+// endOffset : <number>, // Optional - property text end offset in enclosing style declaration. Absent for computed styles and such.
+// }
+//
+// status:
+// "disabled" == property disabled by user
+// "active" == property participates in the computed style calculation
+// "inactive" == property does no participate in the computed style calculation (i.e. overridden by a subsequent property with the same name)
+// "style" == property is active and originates from the WebCore CSSStyleDeclaration rather than CSS source code (e.g. implicit longhand properties)
+//
+//
+// cssStyle = {
+// styleId : <number>, // Optional
+// styleSheetId : <number>, // Parent: -1 for inline styles (<foo style="..">)
+// cssProperties : [
+// #cssProperty,
+// ...
+// #cssProperty
+// ],
+// shorthandValues : {
+// shorthandName1 : shorthandValue1,
+// shorthandName2 : shorthandValue2
+// },
+// cssText : <string>, // declaration text
+// properties : { } // ???
+// }
+//
+// // TODO:
+// // - convert disabledProperties to enabled flag.
+// // - convert width, height to properties
+//
+// cssRule = {
+// ruleId : <number>,
+// selectorText : <string>
+// sourceURL : <string>
+// sourceLine : <string>
+// styleSheetId : <number> // also found in style
+// origin : <string> // "" || "user-agent" || "user" || "inspector"
+// style : #cssStyle
+// }
+//
+// // TODO:
+// // - fix origin
+// // - add sourceURL
+// // - fix parentStyleSheetId
+//
+// cssStyleSheet = {
+// styleSheetId : <number>
+// href : <string>
+// title : <string>
+// disabled : <boolean>
+// documentNodeId : <number>
+// rules : [
+// #cssRule,
+// ...
+// #cssRule
+// ]
+// }
+
+namespace WebCore {
+
+// static
+PassRefPtr<InspectorObject> InspectorCSSAgent::buildObjectForStyle(CSSStyleDeclaration* style, const String& fullStyleId, CSSStyleSourceData* sourceData)
+{
+ RefPtr<InspectorObject> result = InspectorObject::create();
+ if (!fullStyleId.isEmpty())
+ result->setString("id", fullStyleId);
+
+ result->setString("width", style->getPropertyValue("width"));
+ result->setString("height", style->getPropertyValue("height"));
+ Vector<CSSPropertySourceData>* propertyData = 0;
+
+ if (sourceData) {
+ result->setNumber("startOffset", sourceData->styleBodyRange.start);
+ result->setNumber("endOffset", sourceData->styleBodyRange.end);
+ propertyData = &sourceData->propertyData;
+ }
+ populateObjectWithStyleProperties(style, result.get(), propertyData);
+
+ return result.release();
+}
+
+// static
+CSSStyleSheet* InspectorCSSAgent::parentStyleSheet(StyleBase* styleBase)
+{
+ if (!styleBase)
+ return 0;
+
+ StyleSheet* styleSheet = styleBase->stylesheet();
+ if (styleSheet && styleSheet->isCSSStyleSheet())
+ return static_cast<CSSStyleSheet*>(styleSheet);
+
+ return 0;
+}
+
+// static
+CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(StyleBase* styleBase)
+{
+ if (!styleBase->isStyleRule())
+ return 0;
+ CSSRule* rule = static_cast<CSSRule*>(styleBase);
+ if (rule->type() != CSSRule::STYLE_RULE)
+ return 0;
+ return static_cast<CSSStyleRule*>(rule);
+}
+
+
+InspectorCSSAgent::InspectorCSSAgent(InspectorDOMAgent* domAgent, InspectorFrontend* frontend)
+ : m_domAgent(domAgent)
+ , m_frontend(frontend)
+ , m_lastStyleSheetId(1)
+ , m_lastRuleId(1)
+ , m_lastStyleId(1)
+{
+ m_domAgent->setDOMListener(this);
+}
+
+InspectorCSSAgent::~InspectorCSSAgent()
+{
+ reset();
+}
+
+void InspectorCSSAgent::reset()
+{
+ m_domAgent->setDOMListener(0);
+}
+
+void InspectorCSSAgent::getMatchedRulesForNode2(long nodeId, RefPtr<InspectorArray>* result)
+{
+ Element* element = elementForId(nodeId);
+ if (!element)
+ return;
+
+ CSSStyleSelector* selector = element->ownerDocument()->styleSelector();
+ RefPtr<CSSRuleList> matchedRules = selector->styleRulesForElement(element, false, true);
+ *result = buildArrayForRuleList(matchedRules.get());
+}
+
+void InspectorCSSAgent::getMatchedPseudoRulesForNode2(long nodeId, RefPtr<InspectorArray>* result)
+{
+ Element* element = elementForId(nodeId);
+ if (!element)
+ return;
+
+ CSSStyleSelector* selector = element->ownerDocument()->styleSelector();
+ for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
+ RefPtr<CSSRuleList> matchedRules = selector->pseudoStyleRulesForElement(element, pseudoId, false, true);
+ if (matchedRules && matchedRules->length()) {
+ RefPtr<InspectorObject> pseudoStyles = InspectorObject::create();
+ pseudoStyles->setNumber("pseudoId", static_cast<int>(pseudoId));
+ pseudoStyles->setArray("rules", buildArrayForRuleList(matchedRules.get()));
+ (*result)->pushObject(pseudoStyles.release());
+ }
+ }
+}
+
+void InspectorCSSAgent::getAttributeStylesForNode2(long nodeId, RefPtr<InspectorValue>* result)
+{
+ Element* element = elementForId(nodeId);
+ if (!element)
+ return;
+
+ *result = buildObjectForAttributeStyles(element);
+}
+
+void InspectorCSSAgent::getInlineStyleForNode2(long nodeId, RefPtr<InspectorValue>* style)
+{
+ Element* element = elementForId(nodeId);
+ if (!element)
+ return;
+
+ InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
+ if (!styleSheet)
+ return;
+
+ *style = styleSheet->buildObjectForStyle(element->style());
+}
+
+void InspectorCSSAgent::getComputedStyleForNode2(long nodeId, RefPtr<InspectorValue>* style)
+{
+ Element* element = elementForId(nodeId);
+ if (!element)
+ return;
+
+ DOMWindow* defaultView = element->ownerDocument()->defaultView();
+ if (!defaultView)
+ return;
+
+ *style = buildObjectForStyle(defaultView->getComputedStyle(element, "").get(), "");
+}
+
+void InspectorCSSAgent::getInheritedStylesForNode2(long nodeId, RefPtr<InspectorArray>* style)
+{
+ Element* element = elementForId(nodeId);
+ if (!element) {
+ *style = InspectorArray::create();
+ return;
+ }
+ RefPtr<InspectorArray> inheritedStyles = InspectorArray::create();
+ Element* parentElement = element->parentElement();
+ while (parentElement) {
+ RefPtr<InspectorObject> parentStyle = InspectorObject::create();
+ if (parentElement->style() && parentElement->style()->length()) {
+ InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
+ if (styleSheet)
+ parentStyle->setObject("inlineStyle", styleSheet->buildObjectForStyle(styleSheet->styleForId("0")));
+ }
+
+ CSSStyleSelector* parentSelector = parentElement->ownerDocument()->styleSelector();
+ RefPtr<CSSRuleList> parentMatchedRules = parentSelector->styleRulesForElement(parentElement, false, true);
+ parentStyle->setArray("matchedCSSRules", buildArrayForRuleList(parentMatchedRules.get()));
+ inheritedStyles->pushObject(parentStyle.release());
+ parentElement = parentElement->parentElement();
+ }
+ *style = inheritedStyles.release();
+}
+
+void InspectorCSSAgent::getAllStyles2(RefPtr<InspectorArray>* styles)
+{
+ const ListHashSet<RefPtr<Document> >& documents = m_domAgent->documents();
+ for (ListHashSet<RefPtr<Document> >::const_iterator it = documents.begin(); it != documents.end(); ++it) {
+ StyleSheetList* list = (*it)->styleSheets();
+ for (unsigned i = 0; i < list->length(); ++i) {
+ StyleSheet* styleSheet = list->item(i);
+ if (styleSheet->isCSSStyleSheet()) {
+ InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
+ (*styles)->pushString(inspectorStyleSheet->id());
+ }
+ }
+ }
+}
+
+void InspectorCSSAgent::getStyleSheet2(const String& styleSheetId, RefPtr<InspectorValue>* styleSheetObject)
+{
+ InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(styleSheetId);
+ if (!inspectorStyleSheet)
+ return;
+
+ *styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
+}
+
+void InspectorCSSAgent::setStyleSheetText2(const String& styleSheetId, const String& text)
+{
+ InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(styleSheetId);
+ if (!inspectorStyleSheet)
+ return;
+
+ inspectorStyleSheet->setText(text);
+}
+
+void InspectorCSSAgent::setStyleText2(const String& fullStyleId, const String& text, RefPtr<InspectorValue>* result)
+{
+ Vector<String> idParts;
+ fullStyleId.split(':', idParts);
+ ASSERT(idParts.size() == 2);
+
+ InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(idParts.at(0));
+ if (!inspectorStyleSheet)
+ return;
+
+ if (!inspectorStyleSheet->setStyleText(idParts.at(1), text))
+ return;
+
+ *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(idParts.at(1)));
+}
+
+void InspectorCSSAgent::toggleProperty2(const String&, long, bool)
+{
+ // FIXME(apavlov): implement
+}
+
+void InspectorCSSAgent::setRuleSelector2(const String& fullRuleId, const String& selector, RefPtr<InspectorValue>* result)
+{
+ Vector<String> idParts;
+ fullRuleId.split(':', idParts);
+ ASSERT(idParts.size() == 2);
+
+ InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(idParts.at(0));
+ if (!inspectorStyleSheet)
+ return;
+
+ const String& ruleId = idParts.at(1);
+ bool success = inspectorStyleSheet->setRuleSelector(ruleId, selector);
+ if (!success)
+ return;
+
+ *result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(ruleId));
+}
+
+void InspectorCSSAgent::addRule2(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result)
+{
+ Node* node = m_domAgent->nodeForId(contextNodeId);
+ if (!node)
+ return;
+
+ InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
+ CSSStyleRule* newRule = inspectorStyleSheet->addRule(selector);
+ if (newRule)
+ *result = inspectorStyleSheet->buildObjectForRule(newRule);
+}
+
+void InspectorCSSAgent::getSupportedCSSProperties(RefPtr<InspectorArray>* cssProperties)
+{
+ RefPtr<InspectorArray> properties = InspectorArray::create();
+ for (int i = 0; i < numCSSProperties; ++i)
+ properties->pushString(propertyNameStrings[i]);
+
+ *cssProperties = properties.release();
+}
+
+// static
+Element* InspectorCSSAgent::inlineStyleElement(CSSStyleDeclaration* style)
+{
+ if (!style || !style->isMutableStyleDeclaration())
+ return 0;
+ Node* node = static_cast<CSSMutableStyleDeclaration*>(style)->node();
+ if (!node || !node->isStyledElement() || static_cast<StyledElement*>(node)->getInlineStyleDecl() != style)
+ return 0;
+ return static_cast<Element*>(node);
+}
+
+// static
+void InspectorCSSAgent::populateObjectWithStyleProperties(CSSStyleDeclaration* style, InspectorObject* result, Vector<CSSPropertySourceData>* propertyData)
+{
+ RefPtr<InspectorArray> properties = InspectorArray::create();
+ RefPtr<InspectorObject> shorthandValues = InspectorObject::create();
+ HashMap<String, RefPtr<InspectorObject> > propertyNameToPreviousActiveProperty;
+ HashSet<String> foundShorthands;
+ HashSet<String> sourcePropertyNames;
+ if (propertyData) {
+ for (Vector<CSSPropertySourceData>::const_iterator it = propertyData->begin(); it != propertyData->end(); ++it) {
+ const CSSPropertySourceData& propertyEntry = *it;
+ RefPtr<InspectorObject> property = InspectorObject::create();
+ properties->pushObject(property);
+ const String& name = propertyEntry.name;
+ sourcePropertyNames.add(name);
+ property->setString("name", name);
+ property->setString("value", propertyEntry.value);
+ property->setString("priority", propertyEntry.important ? "important" : "");
+ property->setString("status", "active");
+ property->setBoolean("parsedOk", propertyEntry.parsedOk);
+ property->setNumber("startOffset", propertyEntry.range.start);
+ property->setNumber("endOffset", propertyEntry.range.end);
+ if (propertyEntry.parsedOk) {
+ property->setBoolean("implicit", false);
+ String shorthand = style->getPropertyShorthand(name);
+ property->setString("shorthandName", shorthand);
+ if (!shorthand.isEmpty() && !foundShorthands.contains(shorthand)) {
+ foundShorthands.add(shorthand);
+ shorthandValues->setString(shorthand, shorthandValue(style, shorthand));
+ }
+ } else {
+ property->setBoolean("implicit", false);
+ property->setString("shorthandName", "");
+ }
+ HashMap<String, RefPtr<InspectorObject> >::iterator activeIt = propertyNameToPreviousActiveProperty.find(name);
+ if (activeIt != propertyNameToPreviousActiveProperty.end()) {
+ activeIt->second->setString("status", "inactive");
+ activeIt->second->setString("shorthandName", "");
+ }
+ propertyNameToPreviousActiveProperty.set(name, property);
+ }
+ }
+
+ for (int i = 0, size = style->length(); i < size; ++i) {
+ String name = style->item(i);
+ if (sourcePropertyNames.contains(name))
+ continue;
+
+ sourcePropertyNames.add(name);
+ RefPtr<InspectorObject> property = InspectorObject::create();
+ properties->pushObject(property);
+ property->setString("name", name);
+ property->setString("value", style->getPropertyValue(name));
+ property->setString("priority", style->getPropertyPriority("name"));
+ property->setBoolean("implicit", style->isPropertyImplicit(name));
+ property->setBoolean("parsedOk", true);
+ property->setString("status", "style");
+ String shorthand = style->getPropertyShorthand(name);
+ property->setString("shorthandName", shorthand);
+ if (!shorthand.isEmpty() && !foundShorthands.contains(shorthand)) {
+ foundShorthands.add(shorthand);
+ shorthandValues->setString(shorthand, shorthandValue(style, shorthand));
+ }
+ }
+
+ result->setArray("properties", properties);
+ result->setObject("shorthandValues", shorthandValues);
+}
+
+// static
+String InspectorCSSAgent::shorthandValue(CSSStyleDeclaration* style, const String& shorthandProperty)
+{
+ String value = style->getPropertyValue(shorthandProperty);
+ if (value.isEmpty()) {
+ for (unsigned i = 0; i < style->length(); ++i) {
+ String individualProperty = style->item(i);
+ if (style->getPropertyShorthand(individualProperty) != shorthandProperty)
+ continue;
+ if (style->isPropertyImplicit(individualProperty))
+ continue;
+ String individualValue = style->getPropertyValue(individualProperty);
+ if (individualValue == "initial")
+ continue;
+ if (value.length())
+ value.append(" ");
+ value.append(individualValue);
+ }
+ }
+ return value;
+}
+
+// static
+String InspectorCSSAgent::shorthandPriority(CSSStyleDeclaration* style, const String& shorthandProperty)
+{
+ String priority = style->getPropertyPriority(shorthandProperty);
+ if (priority.isEmpty()) {
+ for (unsigned i = 0; i < style->length(); ++i) {
+ String individualProperty = style->item(i);
+ if (style->getPropertyShorthand(individualProperty) != shorthandProperty)
+ continue;
+ priority = style->getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+}
+
+
+// static
+Vector<String> InspectorCSSAgent::longhandProperties(CSSStyleDeclaration* style, const String& shorthandProperty)
+{
+ Vector<String> properties;
+ HashSet<String> foundProperties;
+ for (unsigned i = 0; i < style->length(); ++i) {
+ String individualProperty = style->item(i);
+ if (foundProperties.contains(individualProperty) || style->getPropertyShorthand(individualProperty) != shorthandProperty)
+ continue;
+
+ foundProperties.add(individualProperty);
+ properties.append(individualProperty);
+ }
+ return properties;
+}
+
+InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
+{
+ NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
+ if (it == m_nodeToInspectorStyleSheet.end()) {
+ CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
+ if (!style)
+ return 0;
+
+ String newStyleSheetId = String::number(m_lastStyleSheetId++);
+ RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(newStyleSheetId, element, "");
+ m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
+ m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
+ return inspectorStyleSheet.get();
+ }
+
+ return it->second.get();
+}
+
+Element* InspectorCSSAgent::elementForId(long nodeId)
+{
+ Node* node = m_domAgent->nodeForId(nodeId);
+ return (!node || node->nodeType() != Node::ELEMENT_NODE) ? 0 : static_cast<Element*>(node);
+}
+
+InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
+{
+ RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
+ if (!inspectorStyleSheet) {
+ String id = String::number(m_lastStyleSheetId++);
+ inspectorStyleSheet = InspectorStyleSheet::create(id, styleSheet, detectOrigin(styleSheet, styleSheet->document()), m_domAgent->documentURLString(styleSheet->document()));
+ m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
+ m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
+ }
+ return inspectorStyleSheet.get();
+}
+
+InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
+{
+ if (!document) {
+ ASSERT(!createIfAbsent);
+ return 0;
+ }
+
+ RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
+ if (inspectorStyleSheet || !createIfAbsent)
+ return inspectorStyleSheet.get();
+
+ ExceptionCode ec = 0;
+ RefPtr<Element> styleElement = document->createElement("style", ec);
+ if (!ec)
+ styleElement->setAttribute("type", "text/css", ec);
+ if (!ec)
+ document->head()->appendChild(styleElement, ec);
+ if (ec)
+ return 0;
+ StyleSheetList* styleSheets = document->styleSheets();
+ StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1);
+ if (!styleSheet->isCSSStyleSheet())
+ return 0;
+ CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet);
+ String id = String::number(m_lastStyleSheetId++);
+ inspectorStyleSheet = InspectorStyleSheet::create(id, cssStyleSheet, "inspector", m_domAgent->documentURLString(document));
+ m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
+ m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet);
+ m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet);
+ return inspectorStyleSheet.get();
+}
+
+InspectorStyleSheet* InspectorCSSAgent::styleSheetForId(const String& styleSheetId)
+{
+ IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
+ return it == m_idToInspectorStyleSheet.end() ? 0 : it->second.get();
+}
+
+String InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
+{
+ DEFINE_STATIC_LOCAL(String, userAgent, ("user-agent"));
+ DEFINE_STATIC_LOCAL(String, user, ("user"));
+ DEFINE_STATIC_LOCAL(String, inspector, ("inspector"));
+
+ String origin("");
+ if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
+ origin = userAgent;
+ else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
+ origin = user;
+ else {
+ InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
+ if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
+ origin = inspector;
+ }
+ return origin;
+}
+
+PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList)
+{
+ RefPtr<InspectorArray> result = InspectorArray::create();
+ if (!ruleList)
+ return result.release();
+
+ for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
+ CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
+ if (!rule)
+ continue;
+
+ InspectorStyleSheet* styleSheet = bindStyleSheet(parentStyleSheet(rule));
+ if (styleSheet)
+ result->pushObject(styleSheet->buildObjectForRule(rule));
+ }
+ return result.release();
+}
+
+PassRefPtr<InspectorObject> InspectorCSSAgent::buildObjectForAttributeStyles(Element* element)
+{
+ RefPtr<InspectorObject> styleAttributes = InspectorObject::create();
+ NamedNodeMap* attributes = element->attributes();
+ for (unsigned i = 0; attributes && i < attributes->length(); ++i) {
+ Attribute* attribute = attributes->attributeItem(i);
+ if (attribute->style()) {
+ String attributeName = attribute->localName();
+ styleAttributes->setObject(attributeName.utf8().data(), buildObjectForStyle(attribute->style(), ""));
+ }
+ }
+
+ return styleAttributes;
+}
+
+void InspectorCSSAgent::didRemoveDocument(Document* document)
+{
+ m_documentToInspectorStyleSheet.remove(document);
+}
+
+void InspectorCSSAgent::didRemoveDOMNode(Node* node)
+{
+ NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
+ if (it == m_nodeToInspectorStyleSheet.end())
+ return;
+
+ m_idToInspectorStyleSheet.remove(it->second->id());
+ m_nodeToInspectorStyleSheet.remove(node);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorCSSAgent.h b/WebCore/inspector/InspectorCSSAgent.h
new file mode 100644
index 0000000..eb6013b
--- /dev/null
+++ b/WebCore/inspector/InspectorCSSAgent.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#ifndef InspectorCSSAgent_h
+#define InspectorCSSAgent_h
+
+#include "Document.h"
+#include "InspectorDOMAgent.h"
+#include "InspectorStyleSheet.h"
+#include "InspectorValues.h"
+#include "PlatformString.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSRule;
+class CSSRuleList;
+class CSSStyleDeclaration;
+class CSSStyleRule;
+class CSSStyleSheet;
+class Element;
+class InspectorFrontend;
+class NameNodeMap;
+class Node;
+
+#if ENABLE(INSPECTOR)
+
+class InspectorCSSAgent : public RefCounted<InspectorCSSAgent>, public InspectorDOMAgent::DOMListener {
+public:
+ static PassRefPtr<InspectorCSSAgent> create(InspectorDOMAgent* domAgent, InspectorFrontend* frontend)
+ {
+ return adoptRef(new InspectorCSSAgent(domAgent, frontend));
+ }
+
+ static PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*, const String& fullStyleId, CSSStyleSourceData* = 0);
+ static CSSStyleSheet* parentStyleSheet(StyleBase*);
+ static CSSStyleRule* asCSSStyleRule(StyleBase*);
+
+ InspectorCSSAgent(InspectorDOMAgent* domAgent, InspectorFrontend* frontend);
+ ~InspectorCSSAgent();
+
+ void reset();
+ void getMatchedRulesForNode2(long nodeId, RefPtr<InspectorArray>* rules);
+ void getMatchedPseudoRulesForNode2(long nodeId, RefPtr<InspectorArray>* rules);
+ void getAttributeStylesForNode2(long nodeId, RefPtr<InspectorValue>* styles);
+ void getInlineStyleForNode2(long nodeId, RefPtr<InspectorValue>* style);
+ void getComputedStyleForNode2(long nodeId, RefPtr<InspectorValue>* style);
+ void getInheritedStylesForNode2(long nodeId, RefPtr<InspectorArray>* result);
+ void getAllStyles2(RefPtr<InspectorArray>* styles);
+ void getStyleSheet2(const String& styleSheetId, RefPtr<InspectorValue>* result);
+ void setStyleSheetText2(const String& styleSheetId, const String& text);
+ void setStyleText2(const String& styleId, const String& text, RefPtr<InspectorValue>* result);
+ void toggleProperty2(const String& styleId, long propertyOrdinal, bool disabled);
+ void setRuleSelector2(const String& ruleId, const String& selector, RefPtr<InspectorValue>* result);
+ void addRule2(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result);
+ void getSupportedCSSProperties(RefPtr<InspectorArray>* result);
+
+private:
+ typedef HashMap<String, RefPtr<InspectorStyleSheet> > IdToInspectorStyleSheet;
+ typedef HashMap<CSSStyleSheet*, RefPtr<InspectorStyleSheet> > CSSStyleSheetToInspectorStyleSheet;
+ typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // for bogus "stylesheets" with inline node styles
+ typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet> > DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
+
+ static Element* inlineStyleElement(CSSStyleDeclaration*);
+ static void populateObjectWithStyleProperties(CSSStyleDeclaration*, InspectorObject* result, Vector<CSSPropertySourceData>* propertyData);
+ static String shorthandValue(CSSStyleDeclaration*, const String& shorthandProperty);
+ static String shorthandPriority(CSSStyleDeclaration*, const String& shorthandProperty);
+ static Vector<String> longhandProperties(CSSStyleDeclaration*, const String& shorthandProperty);
+
+ InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
+ Element* elementForId(long nodeId);
+
+ InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
+ InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
+ InspectorStyleSheet* styleSheetForId(const String& styleSheetId);
+ String detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
+
+ PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList* ruleList);
+ PassRefPtr<InspectorObject> buildObjectForAttributeStyles(Element* element);
+
+ // InspectorDOMAgent::DOMListener interface
+ virtual void didRemoveDocument(Document*);
+ virtual void didRemoveDOMNode(Node*);
+
+ RefPtr<InspectorDOMAgent> m_domAgent;
+ InspectorFrontend* m_frontend;
+
+ IdToInspectorStyleSheet m_idToInspectorStyleSheet;
+ CSSStyleSheetToInspectorStyleSheet m_cssStyleSheetToInspectorStyleSheet;
+ NodeToInspectorStyleSheet m_nodeToInspectorStyleSheet;
+ DocumentToViaInspectorStyleSheet m_documentToInspectorStyleSheet;
+
+ long m_lastStyleSheetId;
+ long m_lastRuleId;
+ long m_lastStyleId;
+};
+
+#endif
+
+} // namespace WebCore
+
+#endif // !defined(InspectorCSSAgent_h)
diff --git a/WebCore/inspector/InspectorCSSStore.cpp b/WebCore/inspector/InspectorCSSStore.cpp
index b019860..e0b658f 100644
--- a/WebCore/inspector/InspectorCSSStore.cpp
+++ b/WebCore/inspector/InspectorCSSStore.cpp
@@ -158,7 +158,7 @@ String InspectorCSSStore::inlineStyleSheetText(CSSStyleSheet* styleSheet)
// All ranges are: [start; end) (start - inclusive, end - exclusive).
-bool InspectorCSSStore::getStyleSourceData(CSSStyleDeclaration* style, RefPtr<CSSStyleSourceData>* result)
+bool InspectorCSSStore::getRuleSourceData(CSSStyleDeclaration* style, RefPtr<CSSRuleSourceData>* result)
{
if (!style)
return false;
@@ -166,11 +166,13 @@ bool InspectorCSSStore::getStyleSourceData(CSSStyleDeclaration* style, RefPtr<CS
Element* element = inlineStyleElement(style);
if (element) {
// Inline: style="...".
+ RefPtr<CSSRuleSourceData> ruleSourceData = CSSRuleSourceData::create();
RefPtr<CSSStyleSourceData> styleSourceData = CSSStyleSourceData::create();
bool success = getStyleAttributeRanges(element, &styleSourceData);
if (!success)
return false;
- *result = styleSourceData;
+ ruleSourceData->styleSourceData = styleSourceData.release();
+ *result = ruleSourceData;
return true;
}
@@ -178,7 +180,7 @@ bool InspectorCSSStore::getStyleSourceData(CSSStyleDeclaration* style, RefPtr<CS
if (!styleSheet)
return false;
- Vector<RefPtr<CSSStyleSourceData> >* rangesVector = 0;
+ Vector<RefPtr<CSSRuleSourceData> >* rangesVector = 0;
StyleSheetToOffsetsMap::iterator it = m_styleSheetToOffsets.find(styleSheet);
if (it == m_styleSheetToOffsets.end()) {
String text = styleSheetText(bindStyleSheet(styleSheet));
@@ -187,7 +189,7 @@ bool InspectorCSSStore::getStyleSourceData(CSSStyleDeclaration* style, RefPtr<CS
CSSParser p;
StyleRuleRangeMap ruleRangeMap;
p.parseSheet(newStyleSheet.get(), text, 0, &ruleRangeMap);
- rangesVector = new Vector<RefPtr<CSSStyleSourceData> >;
+ rangesVector = new Vector<RefPtr<CSSRuleSourceData> >;
extractRanges(newStyleSheet.get(), ruleRangeMap, rangesVector);
m_styleSheetToOffsets.set(styleSheet, rangesVector);
}
@@ -211,7 +213,7 @@ bool InspectorCSSStore::getStyleSourceData(CSSStyleDeclaration* style, RefPtr<CS
return false;
}
-void InspectorCSSStore::extractRanges(CSSStyleSheet* styleSheet, const StyleRuleRangeMap& ruleRangeMap, Vector<RefPtr<CSSStyleSourceData> >* rangesVector)
+void InspectorCSSStore::extractRanges(CSSStyleSheet* styleSheet, const StyleRuleRangeMap& ruleRangeMap, Vector<RefPtr<CSSRuleSourceData> >* rangesVector)
{
for (unsigned i = 0, length = styleSheet->length(); i < length; ++i) {
CSSStyleRule* rule = asCSSStyleRule(styleSheet->item(i));
@@ -237,7 +239,7 @@ bool InspectorCSSStore::getStyleAttributeRanges(Node* node, RefPtr<CSSStyleSourc
RefPtr<CSSMutableStyleDeclaration> tempDeclaration = CSSMutableStyleDeclaration::create();
CSSParser p;
- p.parseDeclaration(tempDeclaration.get(), styleText, result->get());
+ p.parseDeclaration(tempDeclaration.get(), styleText, result);
return true;
}
diff --git a/WebCore/inspector/InspectorCSSStore.h b/WebCore/inspector/InspectorCSSStore.h
index 9b329df..25a9d15 100644
--- a/WebCore/inspector/InspectorCSSStore.h
+++ b/WebCore/inspector/InspectorCSSStore.h
@@ -55,7 +55,7 @@ typedef HashMap<CSSStyleDeclaration*, long> StyleToIdMap;
typedef HashMap<long, RefPtr<CSSStyleDeclaration> > IdToStyleMap;
typedef HashMap<CSSStyleRule*, long> RuleToIdMap;
typedef HashMap<long, RefPtr<CSSStyleRule> > IdToRuleMap;
-typedef HashMap<CSSStyleSheet*, Vector<RefPtr<CSSStyleSourceData> >* > StyleSheetToOffsetsMap;
+typedef HashMap<CSSStyleSheet*, Vector<RefPtr<CSSRuleSourceData> >* > StyleSheetToOffsetsMap;
typedef HashMap<CSSStyleSheet*, long> StyleSheetToIdMap;
typedef HashMap<long, RefPtr<CSSStyleSheet> > IdToStyleSheetMap;
typedef HashMap<long, String> IdToStyleSheetTextMap;
@@ -71,7 +71,7 @@ public:
InspectorCSSStore(InspectorController* inspectorController);
~InspectorCSSStore();
void reset();
- bool getStyleSourceData(CSSStyleDeclaration*, RefPtr<CSSStyleSourceData>* result);
+ bool getRuleSourceData(CSSStyleDeclaration*, RefPtr<CSSRuleSourceData>* result);
CSSStyleDeclaration* styleForId(long styleId);
CSSStyleSheet* styleSheetForId(long styleSheetId);
CSSStyleRule* ruleForId(long styleRuleId);
@@ -88,7 +88,7 @@ private:
static CSSStyleRule* asCSSStyleRule(StyleBase*);
String inlineStyleSheetText(CSSStyleSheet*);
bool resourceStyleSheetText(CSSStyleSheet*, String* result);
- void extractRanges(CSSStyleSheet*, const StyleRuleRangeMap&, Vector<RefPtr<CSSStyleSourceData> >* rangesVector);
+ void extractRanges(CSSStyleSheet*, const StyleRuleRangeMap&, Vector<RefPtr<CSSRuleSourceData> >* rangesVector);
bool getStyleAttributeRanges(Node* parentNode, RefPtr<CSSStyleSourceData>* result);
StyleToIdMap m_styleToId;
diff --git a/WebCore/inspector/InspectorClient.cpp b/WebCore/inspector/InspectorClient.cpp
new file mode 100644
index 0000000..434d697
--- /dev/null
+++ b/WebCore/inspector/InspectorClient.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorClient.h"
+
+#if ENABLE(INSPECTOR)
+
+#include "Frame.h"
+#include "Page.h"
+#include "ScriptController.h"
+#include "ScriptSourceCode.h"
+
+namespace WebCore {
+
+bool InspectorClient::doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message)
+{
+ if (!frontendPage)
+ return false;
+
+ Frame* frame = frontendPage->mainFrame();
+ if (!frame)
+ return false;
+
+ ScriptController* scriptController = frame->script();
+ if (!scriptController)
+ return false;
+
+ String dispatchToFrontend("WebInspector.dispatchMessageFromBackend(");
+ dispatchToFrontend += message;
+ dispatchToFrontend += ");";
+
+ // Do not call executeInWorld here since it will end up calling Document::updateStyleForAllDocuments().
+ // As a result we might re-enter CSSStyleSelector::styleForElement() which is terrible.
+ scriptController->evaluate(ScriptSourceCode(dispatchToFrontend));
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorClient.h b/WebCore/inspector/InspectorClient.h
index bb71b13..0c78246 100644
--- a/WebCore/inspector/InspectorClient.h
+++ b/WebCore/inspector/InspectorClient.h
@@ -37,7 +37,7 @@ class Page;
class InspectorClient {
public:
- virtual ~InspectorClient() { }
+ virtual ~InspectorClient() { }
virtual void inspectorDestroyed() = 0;
@@ -55,6 +55,8 @@ public:
// However, there are some inspector controller states that should survive navigation (such as tracking resources
// or recording timeline). Following callbacks allow embedders to track these states.
virtual void updateInspectorStateCookie(const String&) { };
+
+ bool doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message);
};
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp
index f2ee2c1..f99d487 100644
--- a/WebCore/inspector/InspectorController.cpp
+++ b/WebCore/inspector/InspectorController.cpp
@@ -66,8 +66,11 @@
#include "InspectorDebuggerAgent.h"
#include "InspectorFrontend.h"
#include "InspectorFrontendClient.h"
+#include "InspectorInstrumentation.h"
#include "InspectorProfilerAgent.h"
#include "InspectorResource.h"
+#include "InspectorResourceAgent.h"
+#include "InspectorState.h"
#include "InspectorStorageAgent.h"
#include "InspectorTimelineAgent.h"
#include "InspectorValues.h"
@@ -85,14 +88,15 @@
#include "ScriptProfile.h"
#include "ScriptProfiler.h"
#include "ScriptSourceCode.h"
-#include "ScriptString.h"
+#include "ScriptState.h"
#include "SecurityOrigin.h"
#include "Settings.h"
#include "SharedBuffer.h"
#include "TextEncoding.h"
#include "TextIterator.h"
+#include "UserGestureIndicator.h"
#include "WindowFeatures.h"
-#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <wtf/CurrentTime.h>
#include <wtf/ListHashSet.h>
#include <wtf/RefCounted.h>
@@ -115,57 +119,34 @@ using namespace std;
namespace WebCore {
-static const char* const frontendSettingsSettingName = "frontendSettings";
-
-static const char* const debuggerAlwaysEnabledSettingName = "debuggerEnabled";
-static const char* const lastActivePanel = "lastActivePanel";
-static const char* const monitoringXHRSettingName = "xhrMonitor";
-static const char* const resourceTrackingAlwaysEnabledSettingName = "resourceTrackingEnabled";
-static const char* const profilerAlwaysEnabledSettingName = "profilerEnabled";
-
-static const char* const monitoringXHRStateName = "monitoringXHREnabled";
-static const char* const resourceTrackingEnabledStateName = "resourceTrackingEnabled";
-static const char* const searchingForNodeEnabledStateName = "searchingForNodeEnabled";
-static const char* const timelineProfilerEnabledStateName = "timelineProfilerEnabled";
-static const char* const pauseOnExceptionsStateStateName = "pauseOnExceptionsState";
-
-static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight";
+static const char* const domNativeBreakpointType = "DOM";
+static const char* const eventListenerNativeBreakpointType = "EventListener";
+static const char* const xhrNativeBreakpointType = "XHR";
+// FIXME: move last panel setting to the front-end
+const char* const InspectorController::LastActivePanel = "lastActivePanel";
const char* const InspectorController::ElementsPanel = "elements";
const char* const InspectorController::ConsolePanel = "console";
const char* const InspectorController::ScriptsPanel = "scripts";
const char* const InspectorController::ProfilesPanel = "profiles";
+const unsigned InspectorController::defaultAttachedHeight = 300;
-static int connectedFrontendCount = 0;
-
-const String& InspectorController::inspectorStartsAttachedSettingName()
-{
- DEFINE_STATIC_LOCAL(String, settingName, ("inspectorStartsAttached"));
- return settingName;
-}
-
-static const unsigned defaultAttachedHeight = 300;
-static const float minimumAttachedHeight = 250.0f;
-static const float maximumAttachedHeightRatio = 0.75f;
static const unsigned maximumConsoleMessages = 1000;
static const unsigned expireConsoleMessagesStep = 100;
-unsigned InspectorController::s_inspectorControllerCount = 0;
-
InspectorController::InspectorController(Page* page, InspectorClient* client)
: m_inspectedPage(page)
, m_client(client)
, m_openingFrontend(false)
, m_cssStore(new InspectorCSSStore(this))
+ , m_loadEventTime(-1.0)
+ , m_domContentEventTime(-1.0)
, m_expiredConsoleMessageCount(0)
- , m_showAfterVisible(lastActivePanel)
+ , m_showAfterVisible(LastActivePanel)
, m_sessionSettings(InspectorObject::create())
, m_groupLevel(0)
- , m_searchingForNode(false)
- , m_monitoringXHR(false)
, m_previousMessage(0)
- , m_resourceTrackingEnabled(false)
, m_settingsLoaded(false)
, m_inspectorBackend(InspectorBackend::create(this))
, m_inspectorBackendDispatcher(new InspectorBackendDispatcher(this))
@@ -176,9 +157,9 @@ InspectorController::InspectorController(Page* page, InspectorClient* client)
, m_profilerAgent(InspectorProfilerAgent::create(this))
#endif
{
+ m_state = new InspectorState(client);
ASSERT_ARG(page, page);
ASSERT_ARG(client, client);
- ++s_inspectorControllerCount;
}
InspectorController::~InspectorController()
@@ -190,9 +171,6 @@ InspectorController::~InspectorController()
deleteAllValues(m_frameResources);
- ASSERT(s_inspectorControllerCount);
- --s_inspectorControllerCount;
-
releaseFrontendLifetimeAgents();
m_inspectorBackend->disconnectController();
@@ -223,27 +201,39 @@ bool InspectorController::enabled() const
return m_inspectedPage->settings()->developerExtrasEnabled();
}
-String InspectorController::setting(const String& key) const
+bool InspectorController::inspectorStartsAttached()
+{
+ return m_state->getBoolean(InspectorState::inspectorStartsAttached);
+}
+
+void InspectorController::setInspectorStartsAttached(bool attached)
{
- Settings::iterator it = m_settings.find(key);
- if (it != m_settings.end())
- return it->second;
+ m_state->setBoolean(InspectorState::inspectorStartsAttached, attached);
+}
- String value;
- m_client->populateSetting(key, &value);
- m_settings.set(key, value);
- return value;
+void InspectorController::setInspectorAttachedHeight(long height)
+{
+ m_state->setLong(InspectorState::inspectorAttachedHeight, height);
}
-void InspectorController::setSetting(const String& key, const String& value)
+int InspectorController::inspectorAttachedHeight() const
{
- m_settings.set(key, value);
- m_client->storeSetting(key, value);
+ return m_state->getBoolean(InspectorState::inspectorAttachedHeight);
+}
+
+bool InspectorController::searchingForNodeInPage() const
+{
+ return m_state->getBoolean(InspectorState::searchingForNode);
+}
+
+bool InspectorController::resourceTrackingEnabled() const
+{
+ return m_state->getBoolean(InspectorState::resourceTrackingEnabled);
}
void InspectorController::saveApplicationSettings(const String& settings)
{
- setSetting(frontendSettingsSettingName, settings);
+ m_state->setString(InspectorState::frontendSettings, settings);
}
void InspectorController::saveSessionSettings(const String& settingsJSON)
@@ -253,50 +243,24 @@ void InspectorController::saveSessionSettings(const String& settingsJSON)
void InspectorController::getInspectorState(RefPtr<InspectorObject>* state)
{
- (*state)->setBoolean(monitoringXHRStateName, m_monitoringXHR);
- (*state)->setBoolean(resourceTrackingEnabledStateName, m_resourceTrackingEnabled);
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (m_debuggerAgent)
- (*state)->setNumber(pauseOnExceptionsStateStateName, m_debuggerAgent->pauseOnExceptionsState());
+ m_state->setLong(InspectorState::pauseOnExceptionsState, m_debuggerAgent->pauseOnExceptionsState());
#endif
+ *state = m_state->generateStateObjectForFrontend();
}
-void InspectorController::updateInspectorStateCookie()
+void InspectorController::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
{
- RefPtr<InspectorObject> state = InspectorObject::create();
- state->setBoolean(monitoringXHRStateName, m_monitoringXHR);
- state->setBoolean(resourceTrackingEnabledStateName, m_resourceTrackingEnabled);
- state->setBoolean(timelineProfilerEnabledStateName, m_timelineAgent);
- state->setBoolean(searchingForNodeEnabledStateName, m_searchingForNode);
- m_client->updateInspectorStateCookie(state->toJSONString());
-}
-
-void InspectorController::restoreInspectorStateFromCookie(const String& inspectorStateString)
-{
- RefPtr<InspectorValue> inspectorStateValue = InspectorValue::parseJSON(inspectorStateString);
- if (!inspectorStateValue)
- return;
-
- RefPtr<InspectorObject> inspectorState = inspectorStateValue->asObject();
- if (!inspectorState)
- return;
-
- inspectorState->getBoolean(monitoringXHRStateName, &m_monitoringXHR);
- inspectorState->getBoolean(resourceTrackingEnabledStateName, &m_resourceTrackingEnabled);
- inspectorState->getBoolean(searchingForNodeEnabledStateName, &m_searchingForNode);
-
- bool timelineProfilerEnabled = false;
- inspectorState->getBoolean(timelineProfilerEnabledStateName, &timelineProfilerEnabled);
- if (timelineProfilerEnabled)
+ m_state->restoreFromInspectorCookie(inspectorStateCookie);
+ if (m_state->getBoolean(InspectorState::timelineProfilerEnabled))
startTimelineProfiler();
- else
- stopTimelineProfiler();
}
void InspectorController::getSettings(RefPtr<InspectorObject>* settings)
{
*settings = InspectorObject::create();
- (*settings)->setString("application", setting(frontendSettingsSettingName));
+ (*settings)->setString("application", m_state->getString(InspectorState::frontendSettings));
(*settings)->setString("session", m_sessionSettings->toJSONString());
}
@@ -356,13 +320,32 @@ void InspectorController::hideHighlight()
m_client->hideHighlight();
}
+void InspectorController::setConsoleMessagesEnabled(bool enabled, bool* newState)
+{
+ *newState = enabled;
+ setConsoleMessagesEnabled(enabled);
+}
+
+void InspectorController::setConsoleMessagesEnabled(bool enabled)
+{
+ m_state->setBoolean(InspectorState::consoleMessagesEnabled, enabled);
+ if (!enabled)
+ return;
+
+ if (m_expiredConsoleMessageCount)
+ m_frontend->updateConsoleMessageExpiredCount(m_expiredConsoleMessageCount);
+ unsigned messageCount = m_consoleMessages.size();
+ for (unsigned i = 0; i < messageCount; ++i)
+ m_consoleMessages[i]->addToFrontend(m_frontend.get(), m_injectedScriptHost.get());
+}
+
void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, ScriptCallStack* callStack, const String& message)
{
if (!enabled())
return;
bool storeStackTrace = type == TraceMessageType || type == UncaughtExceptionMessageType || type == AssertMessageType;
- addConsoleMessage(callStack->state(), new ConsoleMessage(source, type, level, message, callStack, m_groupLevel, storeStackTrace));
+ addConsoleMessage(new ConsoleMessage(source, type, level, message, callStack, m_groupLevel, storeStackTrace));
}
void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
@@ -370,22 +353,22 @@ void InspectorController::addMessageToConsole(MessageSource source, MessageType
if (!enabled())
return;
- addConsoleMessage(0, new ConsoleMessage(source, type, level, message, lineNumber, sourceID, m_groupLevel));
+ addConsoleMessage(new ConsoleMessage(source, type, level, message, lineNumber, sourceID, m_groupLevel));
}
-void InspectorController::addConsoleMessage(ScriptState* scriptState, PassOwnPtr<ConsoleMessage> consoleMessage)
+void InspectorController::addConsoleMessage(PassOwnPtr<ConsoleMessage> consoleMessage)
{
ASSERT(enabled());
ASSERT_ARG(consoleMessage, consoleMessage);
- if (m_previousMessage && m_previousMessage->isEqual(scriptState, consoleMessage.get())) {
+ if (m_previousMessage && m_previousMessage->isEqual(consoleMessage.get())) {
m_previousMessage->incrementCount();
- if (m_frontend)
+ if (m_state->getBoolean(InspectorState::consoleMessagesEnabled) && m_frontend)
m_previousMessage->updateRepeatCountInConsole(m_frontend.get());
} else {
m_previousMessage = consoleMessage.get();
m_consoleMessages.append(consoleMessage);
- if (m_frontend)
+ if (m_state->getBoolean(InspectorState::consoleMessagesEnabled) && m_frontend)
m_previousMessage->addToFrontend(m_frontend.get(), m_injectedScriptHost.get());
}
@@ -412,7 +395,7 @@ void InspectorController::startGroup(MessageSource source, ScriptCallStack* call
{
++m_groupLevel;
- addConsoleMessage(callStack->state(), new ConsoleMessage(source, collapsed ? StartGroupCollapsedMessageType : StartGroupMessageType, LogMessageLevel, String(), callStack, m_groupLevel));
+ addConsoleMessage(new ConsoleMessage(source, collapsed ? StartGroupCollapsedMessageType : StartGroupMessageType, LogMessageLevel, String(), callStack, m_groupLevel));
}
void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL)
@@ -422,7 +405,7 @@ void InspectorController::endGroup(MessageSource source, unsigned lineNumber, co
--m_groupLevel;
- addConsoleMessage(0, new ConsoleMessage(source, EndGroupMessageType, LogMessageLevel, String(), lineNumber, sourceURL, m_groupLevel));
+ addConsoleMessage(new ConsoleMessage(source, EndGroupMessageType, LogMessageLevel, String(), lineNumber, sourceURL, m_groupLevel));
}
void InspectorController::markTimeline(const String& message)
@@ -433,12 +416,12 @@ void InspectorController::markTimeline(const String& message)
void InspectorController::storeLastActivePanel(const String& panelName)
{
- setSetting(lastActivePanel, panelName);
+ m_state->setString(InspectorState::lastActivePanel, panelName);
}
void InspectorController::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
{
- if (!enabled() || !m_searchingForNode)
+ if (!enabled() || !searchingForNodeInPage())
return;
Node* node = result.innerNode();
@@ -453,7 +436,7 @@ void InspectorController::handleMousePress()
if (!enabled())
return;
- ASSERT(m_searchingForNode);
+ ASSERT(searchingForNodeInPage());
if (!m_highlightedNode)
return;
@@ -492,12 +475,11 @@ void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame)
void InspectorController::setSearchingForNode(bool enabled)
{
- if (m_searchingForNode == enabled)
+ if (searchingForNodeInPage() == enabled)
return;
- m_searchingForNode = enabled;
- if (!m_searchingForNode)
+ m_state->setBoolean(InspectorState::searchingForNode, enabled);
+ if (!enabled)
hideHighlight();
- updateInspectorStateCookie();
}
void InspectorController::setSearchingForNode(bool enabled, bool* newState)
@@ -509,11 +491,7 @@ void InspectorController::setSearchingForNode(bool enabled, bool* newState)
void InspectorController::setMonitoringXHREnabled(bool enabled, bool* newState)
{
*newState = enabled;
- if (m_monitoringXHR == enabled)
- return;
- m_monitoringXHR = enabled;
- setSetting(monitoringXHRSettingName, enabled ? "true" : "false");
- updateInspectorStateCookie();
+ m_state->setBoolean(InspectorState::monitoringXHR, enabled);
}
void InspectorController::connectFrontend()
@@ -522,6 +500,8 @@ void InspectorController::connectFrontend()
releaseFrontendLifetimeAgents();
m_frontend = new InspectorFrontend(m_client);
m_domAgent = InspectorDOMAgent::create(m_cssStore.get(), m_frontend.get());
+ // FIXME: enable resource agent once front-end is ready.
+ // m_resourceAgent = InspectorResourceAgent::create(m_inspectedPage, m_frontend.get());
#if ENABLE(DATABASE)
m_storageAgent = InspectorStorageAgent::create(m_frontend.get());
@@ -537,9 +517,9 @@ void InspectorController::connectFrontend()
m_applicationCacheAgent = new InspectorApplicationCacheAgent(this, m_frontend.get());
#endif
- if (!connectedFrontendCount)
+ if (!InspectorInstrumentation::hasFrontends())
ScriptController::setCaptureCallStackForUncaughtExceptions(true);
- connectedFrontendCount++;
+ InspectorInstrumentation::frontendCreated();
}
void InspectorController::reuseFrontend()
@@ -577,7 +557,7 @@ void InspectorController::showPanel(const String& panel)
return;
}
- if (panel == lastActivePanel)
+ if (panel == LastActivePanel)
return;
m_frontend->showPanel(panel);
@@ -595,10 +575,13 @@ void InspectorController::disconnectFrontend()
{
if (!m_frontend)
return;
+
+ setConsoleMessagesEnabled(false);
+
m_frontend.clear();
- connectedFrontendCount--;
- if (!connectedFrontendCount)
+ InspectorInstrumentation::frontendDeleted();
+ if (!InspectorInstrumentation::hasFrontends())
ScriptController::setCaptureCallStackForUncaughtExceptions(false);
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -613,7 +596,7 @@ void InspectorController::disconnectFrontend()
unbindAllResources();
stopTimelineProfiler();
- m_showAfterVisible = lastActivePanel;
+ m_showAfterVisible = LastActivePanel;
hideHighlight();
@@ -628,6 +611,8 @@ void InspectorController::disconnectFrontend()
void InspectorController::releaseFrontendLifetimeAgents()
{
+ m_resourceAgent.clear();
+
// m_domAgent is RefPtr. Remove DOM listeners first to ensure that there are
// no references to the DOM agent from the DOM tree.
if (m_domAgent)
@@ -651,8 +636,8 @@ void InspectorController::populateScriptObjects()
if (!m_frontend)
return;
- if (m_showAfterVisible == lastActivePanel)
- m_showAfterVisible = setting(lastActivePanel);
+ if (m_showAfterVisible == LastActivePanel)
+ m_showAfterVisible = m_state->getString(InspectorState::lastActivePanel);
showPanel(m_showAfterVisible);
@@ -664,18 +649,16 @@ void InspectorController::populateScriptObjects()
ResourcesMap::iterator resourcesEnd = m_resources.end();
for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
it->second->updateScriptObject(m_frontend.get());
+ if (m_domContentEventTime != -1.0)
+ m_frontend->domContentEventFired(m_domContentEventTime);
+ if (m_loadEventTime != -1.0)
+ m_frontend->loadEventFired(m_loadEventTime);
m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
if (m_nodeToFocus)
focusNode();
- if (m_expiredConsoleMessageCount)
- m_frontend->updateConsoleMessageExpiredCount(m_expiredConsoleMessageCount);
- unsigned messageCount = m_consoleMessages.size();
- for (unsigned i = 0; i < messageCount; ++i)
- m_consoleMessages[i]->addToFrontend(m_frontend.get(), m_injectedScriptHost.get());
-
#if ENABLE(DATABASE)
DatabaseResourcesMap::iterator databasesEnd = m_databaseResources.end();
for (DatabaseResourcesMap::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it)
@@ -710,8 +693,7 @@ void InspectorController::restoreDebugger()
if (InspectorDebuggerAgent::isDebuggerAlwaysEnabled())
enableDebuggerFromFrontend(false);
else {
- String debuggerEnabled = setting(debuggerAlwaysEnabledSettingName);
- if (debuggerEnabled == "true" || m_attachDebuggerWhenShown)
+ if (m_state->getBoolean(InspectorState::debuggerAlwaysEnabled) || m_attachDebuggerWhenShown)
enableDebugger();
}
#endif
@@ -722,11 +704,8 @@ void InspectorController::restoreProfiler()
ASSERT(m_frontend);
#if ENABLE(JAVASCRIPT_DEBUGGER)
m_profilerAgent->setFrontend(m_frontend.get());
- if (!ScriptProfiler::isProfilerAlwaysEnabled()) {
- String profilerEnabledSetting = setting(profilerAlwaysEnabledSettingName);
- if (profilerEnabledSetting == "true")
- enableProfiler();
- }
+ if (!ScriptProfiler::isProfilerAlwaysEnabled() && m_state->getBoolean(InspectorState::profilerAlwaysEnabled))
+ enableProfiler();
#endif
}
@@ -774,6 +753,9 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didCommitLoad(loader);
+
ASSERT(m_inspectedPage);
if (loader->frame() == m_inspectedPage->mainFrame()) {
@@ -785,15 +767,21 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
m_times.clear();
m_counts.clear();
+
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (m_debuggerAgent)
m_debuggerAgent->clearForPageNavigation();
+ m_nativeBreakpoints.clear();
+ m_eventListenerBreakpoints.clear();
m_XHRBreakpoints.clear();
+ m_lastBreakpointId = 0;
#endif
+
#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
m_profilerAgent->resetState();
#endif
+
// unbindAllResources should be called before database and DOM storage
// resources are cleared so that it has a chance to unbind them.
unbindAllResources();
@@ -842,6 +830,10 @@ void InspectorController::frameDetachedFromParent(Frame* frame)
{
if (!enabled())
return;
+
+ if (m_resourceAgent)
+ m_resourceAgent->frameDetachedFromParent(frame);
+
if (ResourcesMap* resourceMap = m_frameResources.get(frame))
removeAllResources(resourceMap);
}
@@ -892,7 +884,7 @@ InspectorResource* InspectorController::getTrackedResource(unsigned long identif
if (!enabled())
return 0;
- if (m_resourceTrackingEnabled)
+ if (resourceTrackingEnabled())
return m_resources.get(identifier).get();
bool isMainResource = m_mainResource && m_mainResource->identifier() == identifier;
@@ -916,6 +908,9 @@ void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader,
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didLoadResourceFromMemoryCache(loader, cachedResource);
+
// If the resource URL is already known, we don't need to add it again since this is just a cached load.
if (m_knownResources.contains(cachedResource->url()))
return;
@@ -923,7 +918,7 @@ void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader,
ASSERT(m_inspectedPage);
bool isMainResource = isMainResourceLoader(loader, KURL(ParsedURLString, cachedResource->url()));
ensureSettingsLoaded();
- if (!isMainResource && !m_resourceTrackingEnabled)
+ if (!isMainResource && !resourceTrackingEnabled())
return;
RefPtr<InspectorResource> resource = InspectorResource::createCached(m_inspectedPage->progress()->createUniqueIdentifier(), loader, cachedResource);
@@ -946,8 +941,12 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier,
ASSERT(m_inspectedPage);
bool isMainResource = isMainResourceLoader(loader, request.url());
+
+ if (m_resourceAgent)
+ m_resourceAgent->identifierForInitialRequest(identifier, request.url(), loader, isMainResource);
+
ensureSettingsLoaded();
- if (!isMainResource && !m_resourceTrackingEnabled)
+ if (!isMainResource && !resourceTrackingEnabled())
return;
RefPtr<InspectorResource> resource = InspectorResource::create(identifier, loader, request.url());
@@ -968,13 +967,11 @@ void InspectorController::mainResourceFiredDOMContentEvent(DocumentLoader* loade
if (!enabled() || !isMainResourceLoader(loader, url))
return;
- if (m_mainResource) {
- m_mainResource->markDOMContentEventTime();
- if (m_timelineAgent)
- m_timelineAgent->didMarkDOMContentEvent();
- if (m_frontend)
- m_mainResource->updateScriptObject(m_frontend.get());
- }
+ m_domContentEventTime = currentTime();
+ if (m_timelineAgent)
+ m_timelineAgent->didMarkDOMContentEvent();
+ if (m_frontend)
+ m_frontend->domContentEventFired(m_domContentEventTime);
}
void InspectorController::mainResourceFiredLoadEvent(DocumentLoader* loader, const KURL& url)
@@ -982,13 +979,11 @@ void InspectorController::mainResourceFiredLoadEvent(DocumentLoader* loader, con
if (!enabled() || !isMainResourceLoader(loader, url))
return;
- if (m_mainResource) {
- m_mainResource->markLoadEventTime();
- if (m_timelineAgent)
- m_timelineAgent->didMarkLoadEvent();
- if (m_frontend)
- m_mainResource->updateScriptObject(m_frontend.get());
- }
+ m_loadEventTime = currentTime();
+ if (m_timelineAgent)
+ m_timelineAgent->didMarkLoadEvent();
+ if (m_frontend)
+ m_frontend->loadEventFired(m_loadEventTime);
}
bool InspectorController::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
@@ -1001,6 +996,9 @@ void InspectorController::willSendRequest(unsigned long identifier, ResourceRequ
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->willSendRequest(identifier, request, redirectResponse);
+
bool isMainResource = (m_mainResource && m_mainResource->identifier() == identifier);
if (m_timelineAgent)
m_timelineAgent->willSendResourceRequest(identifier, isMainResource, request);
@@ -1010,6 +1008,10 @@ void InspectorController::willSendRequest(unsigned long identifier, ResourceRequ
return;
request.setReportLoadTiming(true);
+ // Only enable raw headers if front-end is attached, as otherwise we may lack
+ // permissions to fetch the headers.
+ if (m_frontend)
+ request.setReportRawHeaders(true);
if (!redirectResponse.isNull()) {
// Redirect may have empty URL and we'd like to not crash with invalid HashMap entry.
@@ -1043,15 +1045,21 @@ void InspectorController::markResourceAsCached(unsigned long identifier)
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->markResourceAsCached(identifier);
+
if (RefPtr<InspectorResource> resource = getTrackedResource(identifier))
resource->markAsCached();
}
-void InspectorController::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
+void InspectorController::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response)
{
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didReceiveResponse(identifier, loader, response);
+
if (RefPtr<InspectorResource> resource = getTrackedResource(identifier)) {
resource->updateResponse(response);
@@ -1059,9 +1067,7 @@ void InspectorController::didReceiveResponse(unsigned long identifier, const Res
resource->updateScriptObject(m_frontend.get());
}
if (response.httpStatusCode() >= 400) {
- // The ugly code below is due to that String::format() is not utf8-safe at the moment.
- String message = String::format("Failed to load resource: the server responded with a status of %u (", response.httpStatusCode()) + response.httpStatusText() + ")";
-
+ String message = makeString("Failed to load resource: the server responded with a status of ", String::number(response.httpStatusCode()), " (", response.httpStatusText(), ')');
addMessageToConsole(OtherMessageSource, LogMessageType, ErrorMessageLevel, message, 0, response.url().string());
}
}
@@ -1071,6 +1077,9 @@ void InspectorController::didReceiveContentLength(unsigned long identifier, int
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didReceiveContentLength(identifier, lengthReceived);
+
RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -1086,8 +1095,11 @@ void InspectorController::didFinishLoading(unsigned long identifier, double fini
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didFinishLoading(identifier, finishTime);
+
if (m_timelineAgent)
- m_timelineAgent->didFinishLoadingResource(identifier, false);
+ m_timelineAgent->didFinishLoadingResource(identifier, false, finishTime);
RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
@@ -1105,8 +1117,11 @@ void InspectorController::didFailLoading(unsigned long identifier, const Resourc
if (!enabled())
return;
+ if (m_resourceAgent)
+ m_resourceAgent->didFailLoading(identifier, error);
+
if (m_timelineAgent)
- m_timelineAgent->didFinishLoadingResource(identifier, true);
+ m_timelineAgent->didFinishLoadingResource(identifier, true, 0);
String message = "Failed to load resource";
if (!error.localizedDescription().isEmpty())
@@ -1125,15 +1140,18 @@ void InspectorController::didFailLoading(unsigned long identifier, const Resourc
resource->updateScriptObject(m_frontend.get());
}
-void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber)
+void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber)
{
if (!enabled())
return;
- if (m_monitoringXHR)
+ if (m_resourceAgent)
+ m_resourceAgent->setOverrideContent(identifier, sourceString, InspectorResource::XHR);
+
+ if (m_state->getBoolean(InspectorState::monitoringXHR))
addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, "XHR finished loading: \"" + url + "\".", sendLineNumber, sendURL);
- if (!m_resourceTrackingEnabled)
+ if (!resourceTrackingEnabled())
return;
InspectorResource* resource = m_resources.get(identifier).get();
@@ -1148,14 +1166,20 @@ void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identi
void InspectorController::scriptImported(unsigned long identifier, const String& sourceString)
{
- if (!enabled() || !m_resourceTrackingEnabled)
+ if (!enabled())
+ return;
+
+ if (m_resourceAgent)
+ m_resourceAgent->setOverrideContent(identifier, sourceString, InspectorResource::Script);
+
+ if (!resourceTrackingEnabled())
return;
InspectorResource* resource = m_resources.get(identifier).get();
if (!resource)
return;
- resource->setOverrideContent(ScriptString(sourceString), InspectorResource::Script);
+ resource->setOverrideContent(sourceString, InspectorResource::Script);
if (m_frontend)
resource->updateScriptObject(m_frontend.get());
@@ -1167,8 +1191,7 @@ void InspectorController::setResourceTrackingEnabled(bool enable)
return;
ASSERT(m_inspectedPage);
- m_resourceTrackingEnabled = enable;
- updateInspectorStateCookie();
+ m_state->setBoolean(InspectorState::resourceTrackingEnabled, enable);
}
void InspectorController::setResourceTrackingEnabled(bool enable, bool always, bool* newState)
@@ -1176,18 +1199,16 @@ void InspectorController::setResourceTrackingEnabled(bool enable, bool always, b
*newState = enable;
if (always)
- setSetting(resourceTrackingAlwaysEnabledSettingName, enable ? "true" : "false");
+ m_state->setBoolean(InspectorState::resourceTrackingAlwaysEnabled, enable);
- if (m_resourceTrackingEnabled == enable)
+ if (resourceTrackingEnabled() == enable)
return;
ASSERT(m_inspectedPage);
- m_resourceTrackingEnabled = enable;
+ m_state->setBoolean(InspectorState::resourceTrackingEnabled, enable);
if (enable)
- m_inspectedPage->mainFrame()->redirectScheduler()->scheduleRefresh(true);
-
- updateInspectorStateCookie();
+ reloadPage();
}
void InspectorController::ensureSettingsLoaded()
@@ -1196,15 +1217,10 @@ void InspectorController::ensureSettingsLoaded()
return;
m_settingsLoaded = true;
- String resourceTrackingAlwaysEnabled = setting(resourceTrackingAlwaysEnabledSettingName);
- if (resourceTrackingAlwaysEnabled == "true")
- m_resourceTrackingEnabled = true;
-
- String monitoringXHRAlwaysEnabled = setting(monitoringXHRSettingName);
- if (monitoringXHRAlwaysEnabled == "true")
- m_monitoringXHR = true;
+ m_state->loadFromSettings();
- updateInspectorStateCookie();
+ if (m_state->getBoolean(InspectorState::resourceTrackingAlwaysEnabled))
+ m_state->setBoolean(InspectorState::resourceTrackingEnabled, true);
}
void InspectorController::startTimelineProfiler()
@@ -1219,7 +1235,7 @@ void InspectorController::startTimelineProfiler()
if (m_frontend)
m_frontend->timelineProfilerWasStarted();
- updateInspectorStateCookie();
+ m_state->setBoolean(InspectorState::timelineProfilerEnabled, true);
}
void InspectorController::stopTimelineProfiler()
@@ -1234,7 +1250,7 @@ void InspectorController::stopTimelineProfiler()
if (m_frontend)
m_frontend->timelineProfilerWasStopped();
- updateInspectorStateCookie();
+ m_state->setBoolean(InspectorState::timelineProfilerEnabled, false);
}
#if ENABLE(WORKERS)
@@ -1512,6 +1528,9 @@ void InspectorController::didCreateWebSocket(unsigned long identifier, const KUR
return;
ASSERT(m_inspectedPage);
+ if (m_resourceAgent)
+ m_resourceAgent->didCreateWebSocket(identifier, requestURL);
+
RefPtr<InspectorResource> resource = InspectorResource::createWebSocket(identifier, requestURL, documentURL);
addResource(resource.get());
@@ -1521,6 +1540,9 @@ void InspectorController::didCreateWebSocket(unsigned long identifier, const KUR
void InspectorController::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
{
+ if (m_resourceAgent)
+ m_resourceAgent->willSendWebSocketHandshakeRequest(identifier, request);
+
RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -1532,6 +1554,9 @@ void InspectorController::willSendWebSocketHandshakeRequest(unsigned long identi
void InspectorController::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
{
+ if (m_resourceAgent)
+ m_resourceAgent->didReceiveWebSocketHandshakeResponse(identifier, response);
+
RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -1545,6 +1570,9 @@ void InspectorController::didReceiveWebSocketHandshakeResponse(unsigned long ide
void InspectorController::didCloseWebSocket(unsigned long identifier)
{
+ if (m_resourceAgent)
+ m_resourceAgent->didCloseWebSocket(identifier);
+
RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -1606,14 +1634,14 @@ bool InspectorController::profilerEnabled() const
void InspectorController::enableProfiler(bool always, bool skipRecompile)
{
if (always)
- setSetting(profilerAlwaysEnabledSettingName, "true");
+ m_state->setBoolean(InspectorState::profilerAlwaysEnabled, true);
m_profilerAgent->enable(skipRecompile);
}
void InspectorController::disableProfiler(bool always)
{
if (always)
- setSetting(profilerAlwaysEnabledSettingName, "false");
+ m_state->setBoolean(InspectorState::profilerAlwaysEnabled, false);
m_profilerAgent->disable();
}
#endif
@@ -1623,7 +1651,7 @@ void InspectorController::enableDebuggerFromFrontend(bool always)
{
ASSERT(!debuggerEnabled());
if (always)
- setSetting(debuggerAlwaysEnabledSettingName, "true");
+ m_state->setBoolean(InspectorState::debuggerAlwaysEnabled, true);
ASSERT(m_inspectedPage);
@@ -1654,7 +1682,7 @@ void InspectorController::disableDebugger(bool always)
return;
if (always)
- setSetting(debuggerAlwaysEnabledSettingName, "false");
+ m_state->setBoolean(InspectorState::debuggerAlwaysEnabled, false);
ASSERT(m_inspectedPage);
@@ -1672,29 +1700,74 @@ void InspectorController::resume()
m_debuggerAgent->resume();
}
-void InspectorController::setNativeBreakpoint(PassRefPtr<InspectorObject> breakpoint, unsigned int* breakpointId)
+void InspectorController::setNativeBreakpoint(PassRefPtr<InspectorObject> breakpoint, String* breakpointId)
{
- *breakpointId = 0;
+ *breakpointId = "";
String type;
if (!breakpoint->getString("type", &type))
return;
- if (type == "XHR") {
- RefPtr<InspectorObject> condition = breakpoint->getObject("condition");
- if (!condition)
- return;
+ RefPtr<InspectorObject> condition = breakpoint->getObject("condition");
+ if (!condition)
+ return;
+ if (type == xhrNativeBreakpointType) {
String url;
if (!condition->getString("url", &url))
return;
- *breakpointId = ++m_lastBreakpointId;
+ *breakpointId = String::number(++m_lastBreakpointId);
m_XHRBreakpoints.set(*breakpointId, url);
+ m_nativeBreakpoints.set(*breakpointId, type);
+ } else if (type == eventListenerNativeBreakpointType) {
+ String eventName;
+ if (!condition->getString("eventName", &eventName))
+ return;
+ if (m_eventListenerBreakpoints.contains(eventName))
+ return;
+ *breakpointId = eventName;
+ m_eventListenerBreakpoints.add(eventName);
+ m_nativeBreakpoints.set(*breakpointId, type);
+ } else if (type == domNativeBreakpointType) {
+ if (!m_domAgent)
+ return;
+ double nodeIdNumber;
+ if (!condition->getNumber("nodeId", &nodeIdNumber))
+ return;
+ double domBreakpointTypeNumber;
+ if (!condition->getNumber("type", &domBreakpointTypeNumber))
+ return;
+ long nodeId = (long) nodeIdNumber;
+ long domBreakpointType = (long) domBreakpointTypeNumber;
+ *breakpointId = m_domAgent->setDOMBreakpoint(nodeId, domBreakpointType);
+ if (!breakpointId->isEmpty())
+ m_nativeBreakpoints.set(*breakpointId, type);
+ }
+}
+
+void InspectorController::removeNativeBreakpoint(const String& breakpointId)
+{
+ String type = m_nativeBreakpoints.take(breakpointId);
+ if (type == xhrNativeBreakpointType)
+ m_XHRBreakpoints.remove(breakpointId);
+ else if (type == eventListenerNativeBreakpointType)
+ m_eventListenerBreakpoints.remove(breakpointId);
+ else if (type == domNativeBreakpointType) {
+ if (m_domAgent)
+ m_domAgent->removeDOMBreakpoint(breakpointId);
}
}
-void InspectorController::removeNativeBreakpoint(unsigned int breakpointId)
+String InspectorController::findEventListenerBreakpoint(const String& eventName)
{
- m_XHRBreakpoints.remove(breakpointId);
+ return m_eventListenerBreakpoints.contains(eventName) ? eventName : "";
}
+String InspectorController::findXHRBreakpoint(const String& url)
+{
+ for (HashMap<String, String>::iterator it = m_XHRBreakpoints.begin(); it != m_XHRBreakpoints.end(); ++it) {
+ if (url.contains(it->second))
+ return it->first;
+ }
+ return "";
+}
#endif
void InspectorController::evaluateForTestInFrontend(long callId, const String& script)
@@ -1727,12 +1800,14 @@ String InspectorController::breakpointsSettingKey()
PassRefPtr<InspectorValue> InspectorController::loadBreakpoints()
{
- return InspectorValue::parseJSON(setting(breakpointsSettingKey()));
+ String jsonString;
+ m_client->populateSetting(breakpointsSettingKey(), &jsonString);
+ return InspectorValue::parseJSON(jsonString);
}
void InspectorController::saveBreakpoints(PassRefPtr<InspectorObject> breakpoints)
{
- setSetting(breakpointsSettingKey(), breakpoints->toJSONString());
+ m_client->storeSetting(breakpointsSettingKey(), breakpoints->toJSONString());
}
#endif
@@ -1763,7 +1838,7 @@ static void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, co
context.addPath(quadPath);
context.setStrokeThickness(outlineThickness);
- context.setStrokeColor(outlineColor, DeviceColorSpace);
+ context.setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
context.strokePath();
context.restore();
@@ -1771,7 +1846,7 @@ static void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, co
// Now do the fill
context.addPath(quadPath);
- context.setFillColor(fillColor, DeviceColorSpace);
+ context.setFillColor(fillColor, ColorSpaceDeviceRGB);
context.fillPath();
}
@@ -1953,11 +2028,11 @@ void InspectorController::drawElementTitle(GraphicsContext& context, const IntRe
if (titleRect.bottom() > overlayRect.bottom())
dy += overlayRect.bottom() - titleRect.bottom() - borderWidthPx;
titleRect.move(dx, dy);
- context.setStrokeColor(tooltipBorderColor, DeviceColorSpace);
+ context.setStrokeColor(tooltipBorderColor, ColorSpaceDeviceRGB);
context.setStrokeThickness(borderWidthPx);
- context.setFillColor(tooltipBackgroundColor, DeviceColorSpace);
+ context.setFillColor(tooltipBackgroundColor, ColorSpaceDeviceRGB);
context.drawRect(titleRect);
- context.setFillColor(tooltipFontColor, DeviceColorSpace);
+ context.setFillColor(tooltipFontColor, ColorSpaceDeviceRGB);
context.drawText(font, nodeTitleRun, IntPoint(titleRect.x() + rectInflatePx, titleRect.y() + font.height()));
}
@@ -1972,14 +2047,15 @@ void InspectorController::openInInspectedWindow(const String& url)
if (!newFrame)
return;
+ UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
newFrame->loader()->setOpener(mainFrame);
newFrame->page()->setOpenedByDOM();
- newFrame->loader()->changeLocation(newFrame->loader()->completeURL(url), "", false, false, true);
+ newFrame->loader()->changeLocation(newFrame->loader()->completeURL(url), "", false, false);
}
void InspectorController::count(const String& title, unsigned lineNumber, const String& sourceID)
{
- String identifier = title + String::format("@%s:%d", sourceID.utf8().data(), lineNumber);
+ String identifier = makeString(title, '@', sourceID, ':', String::number(lineNumber));
HashMap<String, unsigned>::iterator it = m_counts.find(identifier);
int count;
if (it == m_counts.end())
@@ -1991,7 +2067,7 @@ void InspectorController::count(const String& title, unsigned lineNumber, const
m_counts.add(identifier, count);
- String message = String::format("%s: %d", title.utf8().data(), count);
+ String message = makeString(title, ": ", String::number(count));
addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceID);
}
@@ -2049,10 +2125,14 @@ void InspectorController::setInspectorExtensionAPI(const String& source)
m_inspectorExtensionAPI = source;
}
-void InspectorController::getResourceContent(unsigned long identifier, String* content)
+void InspectorController::getResourceContent(unsigned long identifier, bool encode, String* content)
{
RefPtr<InspectorResource> resource = m_resources.get(identifier);
- *content = resource ? resource->sourceString() : String();
+ if (!resource) {
+ *content = String();
+ return;
+ }
+ *content = encode ? resource->sourceBytes() : resource->sourceString();
}
bool InspectorController::resourceContentForURL(const KURL& url, Document* frameDocument, String* result)
@@ -2100,86 +2180,11 @@ bool InspectorController::resourceContentForURL(const KURL& url, Document* frame
void InspectorController::reloadPage()
{
- m_inspectedPage->mainFrame()->redirectScheduler()->scheduleRefresh(true);
-}
-
-void InspectorController::willInsertDOMNodeImpl(Node* node, Node* parent)
-{
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (!m_debuggerAgent || !m_domAgent)
- return;
- PassRefPtr<InspectorValue> eventData;
- if (m_domAgent->shouldBreakOnNodeInsertion(node, parent, &eventData))
- m_debuggerAgent->breakProgram(DOMBreakpointDebuggerEventType, eventData);
-#endif
-}
-
-void InspectorController::didInsertDOMNodeImpl(Node* node)
-{
- if (m_domAgent)
- m_domAgent->didInsertDOMNode(node);
-}
-
-void InspectorController::willRemoveDOMNodeImpl(Node* node)
-{
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (!m_debuggerAgent || !m_domAgent)
- return;
- PassRefPtr<InspectorValue> eventData;
- if (m_domAgent->shouldBreakOnNodeRemoval(node, &eventData))
- m_debuggerAgent->breakProgram(DOMBreakpointDebuggerEventType, eventData);
-#endif
-}
-
-void InspectorController::didRemoveDOMNodeImpl(Node* node)
-{
- if (m_domAgent)
- m_domAgent->didRemoveDOMNode(node);
-}
-
-void InspectorController::willModifyDOMAttrImpl(Element* element)
-{
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (!m_debuggerAgent || !m_domAgent)
- return;
- PassRefPtr<InspectorValue> eventData;
- if (m_domAgent->shouldBreakOnAttributeModification(element, &eventData))
- m_debuggerAgent->breakProgram(DOMBreakpointDebuggerEventType, eventData);
-#endif
-}
-
-void InspectorController::didModifyDOMAttrImpl(Element* element)
-{
- if (m_domAgent)
- m_domAgent->didModifyDOMAttr(element);
-}
-
-void InspectorController::characterDataModifiedImpl(CharacterData* characterData)
-{
- if (m_domAgent)
- m_domAgent->characterDataModified(characterData);
+ // FIXME: Why do we set the user gesture indicator here?
+ UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
+ m_inspectedPage->mainFrame()->navigationScheduler()->scheduleRefresh();
}
-void InspectorController::instrumentWillSendXMLHttpRequestImpl(const KURL& url)
-{
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (m_debuggerAgent) {
- if (!m_XHRBreakpoints.size())
- return;
- for (HashMap<unsigned int, String>::iterator it = m_XHRBreakpoints.begin(); it != m_XHRBreakpoints.end(); ++it) {
- if (!url.string().contains(it->second))
- continue;
- RefPtr<InspectorObject> eventData = InspectorObject::create();
- eventData->setString("type", "XHR");
- eventData->setString("url", url);
- m_debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
- break;
- }
- }
-#endif
-}
-
-
} // namespace WebCore
#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h
index c6f516d..a047962 100644
--- a/WebCore/inspector/InspectorController.h
+++ b/WebCore/inspector/InspectorController.h
@@ -32,10 +32,8 @@
#include "CharacterData.h"
#include "Console.h"
#include "Cookie.h"
-#include "Element.h"
#include "Page.h"
#include "PlatformString.h"
-#include "ScriptState.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/ListHashSet.h>
@@ -51,7 +49,6 @@ class ConsoleMessage;
class Database;
class Document;
class DocumentLoader;
-class Element;
class FloatRect;
class GraphicsContext;
class HitTestResult;
@@ -71,6 +68,8 @@ class InspectorFrontendClient;
class InspectorObject;
class InspectorProfilerAgent;
class InspectorResource;
+class InspectorResourceAgent;
+class InspectorState;
class InspectorStorageAgent;
class InspectorTimelineAgent;
class InspectorValue;
@@ -84,7 +83,6 @@ class ResourceResponse;
class ResourceError;
class ScriptCallStack;
class ScriptProfile;
-class ScriptString;
class SharedBuffer;
class Storage;
class StorageArea;
@@ -105,6 +103,7 @@ public:
typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
+ static const char* const LastActivePanel;
static const char* const ConsolePanel;
static const char* const ElementsPanel;
static const char* const ProfilesPanel;
@@ -125,13 +124,11 @@ public:
Page* inspectedPage() const { return m_inspectedPage; }
void reloadPage();
- String setting(const String& key) const;
- void setSetting(const String& key, const String& value);
void saveApplicationSettings(const String& settings);
void saveSessionSettings(const String&);
void getSettings(RefPtr<InspectorObject>*);
- void restoreInspectorStateFromCookie(const String& inspectorState);
+ void restoreInspectorStateFromCookie(const String& inspectorCookie);
void inspect(Node*);
void highlight(Node*);
@@ -143,19 +140,17 @@ public:
void showPanel(const String&);
void close();
- // We are in transition from JS transport via webInspector to native
- // transport via InspectorClient. After migration, webInspector parameter should
- // be removed.
void connectFrontend();
void reuseFrontend();
void disconnectFrontend();
+ void setConsoleMessagesEnabled(bool enabled, bool* newState);
void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*, const String& message);
void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
void clearConsoleMessages();
const Vector<OwnPtr<ConsoleMessage> >& consoleMessages() const { return m_consoleMessages; }
- bool searchingForNodeInPage() const { return m_searchingForNode; }
+ bool searchingForNodeInPage() const;
void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
void handleMousePress();
@@ -171,16 +166,16 @@ public:
void identifierForInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
void willSendRequest(unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse);
void markResourceAsCached(unsigned long identifier);
- void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
+ void didReceiveResponse(unsigned long identifier, DocumentLoader*, const ResourceResponse&);
void didReceiveContentLength(unsigned long identifier, int lengthReceived);
void didFinishLoading(unsigned long identifier, double finishTime);
void didFailLoading(unsigned long identifier, const ResourceError&);
- void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber);
+ void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber);
void scriptImported(unsigned long identifier, const String& sourceString);
void setResourceTrackingEnabled(bool enabled);
void setResourceTrackingEnabled(bool enabled, bool always, bool* newState);
- bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; }
+ bool resourceTrackingEnabled() const;
void ensureSettingsLoaded();
@@ -198,15 +193,6 @@ public:
void mainResourceFiredLoadEvent(DocumentLoader*, const KURL&);
void mainResourceFiredDOMContentEvent(DocumentLoader*, const KURL&);
- static void willInsertDOMNode(Node* node, Node* parent);
- static void didInsertDOMNode(Node*);
- static void willRemoveDOMNode(Node*);
- static void willModifyDOMAttr(Element*);
- static void didModifyDOMAttr(Element*);
- static void characterDataModified(CharacterData*);
-
- static void instrumentWillSendXMLHttpRequest(ScriptExecutionContext*, const KURL&);
-
#if ENABLE(WORKERS)
enum WorkerAction { WorkerCreated, WorkerDestroyed };
@@ -270,9 +256,8 @@ public:
InspectorDebuggerAgent* debuggerAgent() const { return m_debuggerAgent.get(); }
void resume();
- void setNativeBreakpoint(PassRefPtr<InspectorObject> breakpoint, unsigned int* breakpointId);
- void removeNativeBreakpoint(unsigned int breakpointId);
-
+ void setNativeBreakpoint(PassRefPtr<InspectorObject> breakpoint, String* breakpointId);
+ void removeNativeBreakpoint(const String& breakpointId);
#endif
void evaluateForTestInFrontend(long testCallId, const String& script);
@@ -283,14 +268,20 @@ public:
void removeAllScriptsToEvaluateOnLoad();
void setInspectorExtensionAPI(const String& source);
- static const String& inspectorStartsAttachedSettingName();
+ bool inspectorStartsAttached();
+ void setInspectorStartsAttached(bool);
+ void setInspectorAttachedHeight(long height);
+ int inspectorAttachedHeight() const;
+
+ static const unsigned defaultAttachedHeight;
private:
- void updateInspectorStateCookie();
void getInspectorState(RefPtr<InspectorObject>* state);
+ void setConsoleMessagesEnabled(bool enabled);
friend class InspectorBackend;
friend class InspectorBackendDispatcher;
+ friend class InspectorInstrumentation;
friend class InjectedScriptHost;
void populateScriptObjects();
@@ -308,9 +299,11 @@ private:
void releaseFrontendLifetimeAgents();
#if ENABLE(JAVASCRIPT_DEBUGGER)
-
void toggleRecordButton(bool);
void enableDebuggerFromFrontend(bool always);
+
+ String findEventListenerBreakpoint(const String& eventName);
+ String findXHRBreakpoint(const String& url);
#endif
#if ENABLE(DATABASE)
void selectDatabase(Database* database);
@@ -325,12 +318,12 @@ private:
void focusNode();
- void addConsoleMessage(ScriptState*, PassOwnPtr<ConsoleMessage>);
+ void addConsoleMessage(PassOwnPtr<ConsoleMessage>);
void addResource(InspectorResource*);
void removeResource(InspectorResource*);
InspectorResource* getTrackedResource(unsigned long identifier);
- void getResourceContent(unsigned long identifier, String* content);
+ void getResourceContent(unsigned long identifier, bool encode, String* content);
void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0);
void removeAllResources(ResourcesMap* map) { pruneResources(map); }
@@ -339,20 +332,6 @@ private:
void didEvaluateForTestInFrontend(long callId, const String& jsonResult);
- static InspectorController* inspectorControllerForScriptExecutionContext(ScriptExecutionContext* context);
- static InspectorController* inspectorControllerForNode(Node*);
- static InspectorController* inspectorControllerForDocument(Document* document);
-
- void willInsertDOMNodeImpl(Node* node, Node* parent);
- void didInsertDOMNodeImpl(Node*);
- void willRemoveDOMNodeImpl(Node*);
- void didRemoveDOMNodeImpl(Node*);
- void willModifyDOMAttrImpl(Element*);
- void didModifyDOMAttrImpl(Element*);
- void characterDataModifiedImpl(CharacterData*);
-
- void instrumentWillSendXMLHttpRequestImpl(const KURL&);
-
#if ENABLE(JAVASCRIPT_DEBUGGER)
friend class InspectorDebuggerAgent;
String breakpointsSettingKey();
@@ -360,17 +339,17 @@ private:
void saveBreakpoints(PassRefPtr<InspectorObject> breakpoints);
#endif
- static unsigned s_inspectorControllerCount;
-
Page* m_inspectedPage;
InspectorClient* m_client;
OwnPtr<InspectorFrontendClient> m_inspectorFrontendClient;
bool m_openingFrontend;
OwnPtr<InspectorFrontend> m_frontend;
RefPtr<InspectorDOMAgent> m_domAgent;
+ RefPtr<InspectorResourceAgent> m_resourceAgent;
RefPtr<InspectorStorageAgent> m_storageAgent;
OwnPtr<InspectorCSSStore> m_cssStore;
OwnPtr<InspectorTimelineAgent> m_timelineAgent;
+ OwnPtr<InspectorState> m_state;
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
OwnPtr<InspectorApplicationCacheAgent> m_applicationCacheAgent;
@@ -381,6 +360,8 @@ private:
ResourcesMap m_resources;
HashSet<String> m_knownResources;
FrameResourcesMap m_frameResources;
+ double m_loadEventTime;
+ double m_domContentEventTime;
Vector<OwnPtr<ConsoleMessage> > m_consoleMessages;
unsigned m_expiredConsoleMessageCount;
HashMap<String, double> m_times;
@@ -397,10 +378,7 @@ private:
RefPtr<InspectorValue> m_sessionSettings;
#endif
unsigned m_groupLevel;
- bool m_searchingForNode;
- bool m_monitoringXHR;
ConsoleMessage* m_previousMessage;
- bool m_resourceTrackingEnabled;
bool m_settingsLoaded;
RefPtr<InspectorBackend> m_inspectorBackend;
OwnPtr<InspectorBackendDispatcher> m_inspectorBackendDispatcher;
@@ -416,7 +394,10 @@ private:
bool m_attachDebuggerWhenShown;
OwnPtr<InspectorDebuggerAgent> m_debuggerAgent;
- HashMap<unsigned int, String> m_XHRBreakpoints;
+ HashMap<String, String> m_nativeBreakpoints;
+ HashSet<String> m_eventListenerBreakpoints;
+ HashMap<String, String> m_XHRBreakpoints;
+
unsigned int m_lastBreakpointId;
OwnPtr<InspectorProfilerAgent> m_profilerAgent;
@@ -428,6 +409,7 @@ private:
#endif
};
+<<<<<<< HEAD
inline void InspectorController::willInsertDOMNode(Node* node, Node* parent)
{
#if ENABLE(INSPECTOR)
@@ -518,6 +500,8 @@ inline InspectorController* InspectorController::inspectorControllerForDocument(
#endif
}
+=======
+>>>>>>> webkit.org at r70209
} // namespace WebCore
#endif // !defined(InspectorController_h)
diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp
index f51da73..f5c5f8b 100644
--- a/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/WebCore/inspector/InspectorDOMAgent.cpp
@@ -77,6 +77,7 @@
#include "markup.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <wtf/HashSet.h>
#include <wtf/ListHashSet.h>
#include <wtf/OwnPtr.h>
@@ -187,6 +188,8 @@ public:
if (!ec)
resultCollector.add(node);
}
+#else
+ UNUSED_PARAM(resultCollector);
#endif
}
};
@@ -203,7 +206,8 @@ public:
enum DOMBreakpointType {
SubtreeModified = 0,
AttributeModified,
- NodeRemoved
+ NodeRemoved,
+ DOMBreakpointTypesCount
};
const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);
@@ -215,6 +219,7 @@ InspectorDOMAgent::InspectorDOMAgent(InspectorCSSStore* cssStore, InspectorFront
: EventListener(InspectorDOMAgentType)
, m_cssStore(cssStore)
, m_frontend(frontend)
+ , m_domListener(0)
, m_lastNodeId(1)
, m_matchJobsTimer(this, &InspectorDOMAgent::onMatchJobsTimer)
{
@@ -237,6 +242,11 @@ void InspectorDOMAgent::reset()
ASSERT(!m_documents.size());
}
+void InspectorDOMAgent::setDOMListener(DOMListener* listener)
+{
+ m_domListener = listener;
+}
+
void InspectorDOMAgent::setDocument(Document* doc)
{
if (doc == mainFrameDocument())
@@ -326,6 +336,8 @@ void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
if (node->isFrameOwnerElement()) {
const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
stopListening(frameOwner->contentDocument());
+ if (m_domListener)
+ m_domListener->didRemoveDocument(frameOwner->contentDocument());
cssStore()->removeDocument(frameOwner->contentDocument());
}
@@ -473,7 +485,7 @@ void InspectorDOMAgent::removeNode(long nodeId, long* outNodeId)
if (!node)
return;
- Node* parentNode = node->parentNode();
+ ContainerNode* parentNode = node->parentNode();
if (!parentNode)
return;
@@ -508,7 +520,7 @@ void InspectorDOMAgent::changeTagName(long nodeId, const String& tagName, long*
newElem->appendChild(child, ec);
// Replace the old node with the new node
- Node* parent = oldNode->parentNode();
+ ContainerNode* parent = oldNode->parentNode();
parent->insertBefore(newElem, oldNode->nextSibling(), ec);
parent->removeChild(oldNode, ec);
@@ -539,7 +551,7 @@ void InspectorDOMAgent::setOuterHTML(long nodeId, const String& outerHTML, long*
bool childrenRequested = m_childrenRequested.contains(nodeId);
Node* previousSibling = node->previousSibling();
- Node* parentNode = node->parentNode();
+ ContainerNode* parentNode = node->parentNode();
HTMLElement* htmlElement = static_cast<HTMLElement*>(node);
ExceptionCode ec = 0;
@@ -743,11 +755,17 @@ void InspectorDOMAgent::searchCanceled()
m_searchResults.clear();
}
-void InspectorDOMAgent::setDOMBreakpoint(long nodeId, long type)
+String InspectorDOMAgent::setDOMBreakpoint(long nodeId, long type)
{
Node* node = nodeForId(nodeId);
if (!node)
- return;
+ return "";
+
+ String breakpointId = createBreakpointId(nodeId, type);
+ if (m_idToBreakpoint.contains(breakpointId))
+ return "";
+
+ m_idToBreakpoint.set(breakpointId, std::make_pair(nodeId, type));
uint32_t rootBit = 1 << type;
m_breakpoints.set(node, m_breakpoints.get(node) | rootBit);
@@ -755,15 +773,19 @@ void InspectorDOMAgent::setDOMBreakpoint(long nodeId, long type)
for (Node* child = innerFirstChild(node); child; child = innerNextSibling(child))
updateSubtreeBreakpoints(child, rootBit, true);
}
+
+ return breakpointId;
}
-void InspectorDOMAgent::removeDOMBreakpoint(long nodeId, long type)
+void InspectorDOMAgent::removeDOMBreakpoint(const String& breakpointId)
{
- Node* node = nodeForId(nodeId);
+ Breakpoint breakpoint = m_idToBreakpoint.take(breakpointId);
+
+ Node* node = nodeForId(breakpoint.first);
if (!node)
return;
- uint32_t rootBit = 1 << type;
+ uint32_t rootBit = 1 << breakpoint.second;
uint32_t mask = m_breakpoints.get(node) & ~rootBit;
if (mask)
m_breakpoints.set(node, mask);
@@ -835,11 +857,7 @@ PassRefPtr<InspectorValue> InspectorDOMAgent::descriptionForDOMEvent(Node* targe
long breakpointOwnerNodeId = m_documentNodeToIdMap.get(breakpointOwner);
ASSERT(breakpointOwnerNodeId);
-
- RefPtr<InspectorObject> breakpoint = InspectorObject::create();
- breakpoint->setNumber("nodeId", breakpointOwnerNodeId);
- breakpoint->setNumber("type", breakpointType);
- description->setObject("breakpoint", breakpoint);
+ description->setString("breakpointId", createBreakpointId(breakpointOwnerNodeId, breakpointType));
return description;
}
@@ -1016,8 +1034,8 @@ unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
Node* InspectorDOMAgent::innerParentNode(Node* node)
{
- Node* parent = node->parentNode();
- if (parent && parent->nodeType() == Node::DOCUMENT_NODE)
+ ContainerNode* parent = node->parentNode();
+ if (parent && parent->isDocumentNode())
return static_cast<Document*>(parent)->ownerElement();
return parent;
}
@@ -1058,7 +1076,7 @@ void InspectorDOMAgent::didInsertDOMNode(Node* node)
// We could be attaching existing subtree. Forget the bindings.
unbind(node, &m_documentNodeToIdMap);
- Node* parent = node->parentNode();
+ ContainerNode* parent = node->parentNode();
long parentId = m_documentNodeToIdMap.get(parent);
// Return if parent is not mapped yet.
if (!parentId)
@@ -1083,25 +1101,28 @@ void InspectorDOMAgent::didRemoveDOMNode(Node* node)
if (m_breakpoints.size()) {
// Remove subtree breakpoints.
- m_breakpoints.remove(node);
+ removeBreakpointsForNode(node);
Vector<Node*> stack(1, innerFirstChild(node));
do {
Node* node = stack.last();
stack.removeLast();
if (!node)
continue;
- m_breakpoints.remove(node);
+ removeBreakpointsForNode(node);
stack.append(innerFirstChild(node));
stack.append(innerNextSibling(node));
} while (!stack.isEmpty());
}
- Node* parent = node->parentNode();
+ ContainerNode* parent = node->parentNode();
long parentId = m_documentNodeToIdMap.get(parent);
// If parent is not mapped yet -> ignore the event.
if (!parentId)
return;
+ if (m_domListener)
+ m_domListener->didRemoveDOMNode(node);
+
if (!m_childrenRequested.contains(parentId)) {
// No children are mapped yet -> only notify on changes of hasChildren.
if (innerChildNodeCount(parent) == 1)
@@ -1154,6 +1175,25 @@ void InspectorDOMAgent::updateSubtreeBreakpoints(Node* node, uint32_t rootMask,
updateSubtreeBreakpoints(child, newRootMask, set);
}
+void InspectorDOMAgent::removeBreakpointsForNode(Node* node)
+{
+ uint32_t mask = m_breakpoints.take(node);
+ if (!mask)
+ return;
+ long nodeId = m_documentNodeToIdMap.get(node);
+ if (!nodeId)
+ return;
+ for (int type = 0; type < DOMBreakpointTypesCount; ++type) {
+ if (mask && (1 << type))
+ m_idToBreakpoint.remove(createBreakpointId(nodeId, type));
+ }
+}
+
+String InspectorDOMAgent::createBreakpointId(long nodeId, long type)
+{
+ return makeString("dom:", String::number(nodeId), ':', String::number(type));
+}
+
void InspectorDOMAgent::getStyles(long nodeId, bool authorOnly, RefPtr<InspectorValue>* styles)
{
Node* node = nodeForId(nodeId);
@@ -1221,18 +1261,25 @@ void InspectorDOMAgent::getStyleSourceData(long styleId, RefPtr<InspectorObject>
CSSStyleDeclaration* style = cssStore()->styleForId(styleId);
if (!style)
return;
- RefPtr<CSSStyleSourceData> sourceData = CSSStyleSourceData::create();
- bool success = cssStore()->getStyleSourceData(style, &sourceData);
+ RefPtr<CSSRuleSourceData> sourceData = CSSRuleSourceData::create();
+ bool success = cssStore()->getRuleSourceData(style, &sourceData);
if (!success)
return;
RefPtr<InspectorObject> result = InspectorObject::create();
+
RefPtr<InspectorObject> bodyRange = InspectorObject::create();
result->setObject("bodyRange", bodyRange);
- bodyRange->setNumber("start", sourceData->styleBodyRange.start);
- bodyRange->setNumber("end", sourceData->styleBodyRange.end);
+ bodyRange->setNumber("start", sourceData->styleSourceData->styleBodyRange.start);
+ bodyRange->setNumber("end", sourceData->styleSourceData->styleBodyRange.end);
+
+ RefPtr<InspectorObject> selectorRange = InspectorObject::create();
+ result->setObject("selectorRange", selectorRange);
+ selectorRange->setNumber("start", sourceData->selectorListRange.start);
+ selectorRange->setNumber("end", sourceData->selectorListRange.end);
+
RefPtr<InspectorArray> propertyRanges = InspectorArray::create();
result->setArray("propertyData", propertyRanges);
- Vector<CSSPropertySourceData>& propertyData = sourceData->propertyData;
+ Vector<CSSPropertySourceData>& propertyData = sourceData->styleSourceData->propertyData;
for (Vector<CSSPropertySourceData>::iterator it = propertyData.begin(); it != propertyData.end(); ++it) {
RefPtr<InspectorObject> propertyRange = InspectorObject::create();
propertyRange->setString("name", it->name);
@@ -1311,7 +1358,7 @@ PassRefPtr<InspectorArray> InspectorDOMAgent::buildArrayForPseudoElements(Elemen
return result.release();
}
-void InspectorDOMAgent::applyStyleText(long styleId, const String& styleText, const String& propertyName, bool* success, RefPtr<InspectorValue>* styleObject, RefPtr<InspectorArray>* changedPropertiesArray)
+void InspectorDOMAgent::applyStyleText(long styleId, const String& styleText, const String& propertyName, bool* success, RefPtr<InspectorValue>* styleObject)
{
CSSStyleDeclaration* style = cssStore()->styleForId(styleId);
if (!style)
@@ -1348,7 +1395,6 @@ void InspectorDOMAgent::applyStyleText(long styleId, const String& styleText, co
// Notify caller that the property was successfully deleted.
if (!styleTextLength) {
- (*changedPropertiesArray)->pushString(propertyName);
*success = true;
return;
}
@@ -1359,7 +1405,6 @@ void InspectorDOMAgent::applyStyleText(long styleId, const String& styleText, co
// Iterate of the properties on the test element's style declaration and
// add them to the real style declaration. We take care to move shorthands.
HashSet<String> foundShorthands;
- Vector<String> changedProperties;
for (unsigned i = 0; i < tempStyle->length(); ++i) {
String name = tempStyle->item(i);
@@ -1386,11 +1431,9 @@ void InspectorDOMAgent::applyStyleText(long styleId, const String& styleText, co
// Remove disabled property entry for property with this name.
if (disabledStyle)
disabledStyle->remove(name);
- changedProperties.append(name);
}
*success = true;
*styleObject = buildObjectForStyle(style, true);
- *changedPropertiesArray = toArray(changedProperties);
}
void InspectorDOMAgent::setStyleText(long styleId, const String& cssText, bool* success)
@@ -1493,6 +1536,7 @@ void InspectorDOMAgent::getSupportedCSSProperties(RefPtr<InspectorArray>* cssPro
RefPtr<InspectorArray> properties = InspectorArray::create();
for (int i = 0; i < numCSSProperties; ++i)
properties->pushString(propertyNameStrings[i]);
+
*cssProperties = properties.release();
}
diff --git a/WebCore/inspector/InspectorDOMAgent.h b/WebCore/inspector/InspectorDOMAgent.h
index 89c6fd0..03e4d8d 100644
--- a/WebCore/inspector/InspectorDOMAgent.h
+++ b/WebCore/inspector/InspectorDOMAgent.h
@@ -80,6 +80,14 @@ namespace WebCore {
class InspectorDOMAgent : public EventListener {
public:
+ struct DOMListener {
+ virtual ~DOMListener()
+ {
+ }
+ virtual void didRemoveDocument(Document*) = 0;
+ virtual void didRemoveDOMNode(Node*) = 0;
+ };
+
static PassRefPtr<InspectorDOMAgent> create(InspectorCSSStore* cssStore, InspectorFrontend* frontend)
{
return adoptRef(new InspectorDOMAgent(cssStore, frontend));
@@ -112,8 +120,6 @@ namespace WebCore {
void addInspectedNode(long nodeId);
void performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously);
void searchCanceled();
- void setDOMBreakpoint(long nodeId, long type);
- void removeDOMBreakpoint(long nodeId, long type);
bool shouldBreakOnNodeInsertion(Node* node, Node* parent, PassRefPtr<InspectorValue>* details);
bool shouldBreakOnNodeRemoval(Node* node, PassRefPtr<InspectorValue>* details);
bool shouldBreakOnAttributeModification(Element* element, PassRefPtr<InspectorValue>* details);
@@ -125,7 +131,7 @@ namespace WebCore {
void getComputedStyle(long nodeId, RefPtr<InspectorValue>* styles);
void getStyleSheet(long styleSheetId, RefPtr<InspectorObject>* styleSheetObject);
void getStyleSourceData(long styleId, RefPtr<InspectorObject>* dataObject);
- void applyStyleText(long styleId, const String& styleText, const String& propertyName, bool* success, RefPtr<InspectorValue>* styleObject, RefPtr<InspectorArray>* changedProperties);
+ void applyStyleText(long styleId, const String& styleText, const String& propertyName, bool* success, RefPtr<InspectorValue>* styleObject);
void setStyleText(long styleId, const String& cssText, bool* success);
void setStyleProperty(long styleId, const String& name, const String& value, bool* success);
void toggleStyleEnabled(long styleId, const String& propertyName, bool disabled, RefPtr<InspectorValue>* styleObject);
@@ -148,6 +154,13 @@ namespace WebCore {
void pushNodeByPathToFrontend(const String& path, long* nodeId);
long inspectedNode(unsigned long num);
void copyNode(long nodeId);
+ const ListHashSet<RefPtr<Document> >& documents() { return m_documents; }
+ void setDOMListener(DOMListener*);
+
+ String documentURLString(Document* document) const;
+
+ String setDOMBreakpoint(long nodeId, long type);
+ void removeDOMBreakpoint(const String& breakpointId);
private:
void startListening(Document* document);
@@ -164,7 +177,9 @@ namespace WebCore {
bool hasBreakpoint(Node* node, long type);
void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);
+ void removeBreakpointsForNode(Node* node);
PassRefPtr<InspectorValue> descriptionForDOMEvent(Node* target, long breakpointType, bool insertion);
+ String createBreakpointId(long nodeId, long type);
PassRefPtr<InspectorObject> buildObjectForAttributeStyles(Element* element);
PassRefPtr<InspectorArray> buildArrayForCSSRules(Document* ownerDocument, CSSRuleList*);
@@ -185,7 +200,6 @@ namespace WebCore {
bool isWhitespace(Node* node);
Document* mainFrameDocument() const;
- String documentURLString(Document* document) const;
InspectorCSSStore* cssStore() { return m_cssStore; }
void onMatchJobsTimer(Timer<InspectorDOMAgent>*);
@@ -207,6 +221,7 @@ namespace WebCore {
InspectorCSSStore* m_cssStore;
InspectorFrontend* m_frontend;
+ DOMListener* m_domListener;
NodeToIdMap m_documentNodeToIdMap;
// Owns node mappings for dangling nodes.
Vector<NodeToIdMap*> m_danglingNodeToIdMaps;
@@ -220,6 +235,8 @@ namespace WebCore {
HashSet<RefPtr<Node> > m_searchResults;
Vector<long> m_inspectedNodes;
HashMap<Node*, uint32_t> m_breakpoints;
+ typedef pair<long, long> Breakpoint;
+ HashMap<String, Breakpoint> m_idToBreakpoint;
};
#endif
diff --git a/WebCore/inspector/InspectorDebuggerAgent.cpp b/WebCore/inspector/InspectorDebuggerAgent.cpp
index 4964c09..a7eacf6 100644
--- a/WebCore/inspector/InspectorDebuggerAgent.cpp
+++ b/WebCore/inspector/InspectorDebuggerAgent.cpp
@@ -38,13 +38,13 @@
#include "PlatformString.h"
#include "ScriptDebugServer.h"
#include <wtf/MD5.h>
-#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
namespace WebCore {
static String formatBreakpointId(const String& sourceID, unsigned lineNumber)
{
- return String::format("%s:%d", sourceID.utf8().data(), lineNumber);
+ return makeString(sourceID, ':', String::number(lineNumber));
}
PassOwnPtr<InspectorDebuggerAgent> InspectorDebuggerAgent::create(InspectorController* inspectorController, InspectorFrontend* frontend)
@@ -57,8 +57,6 @@ PassOwnPtr<InspectorDebuggerAgent> InspectorDebuggerAgent::create(InspectorContr
return agent.release();
}
-InspectorDebuggerAgent* InspectorDebuggerAgent::s_debuggerAgentOnBreakpoint = 0;
-
InspectorDebuggerAgent::InspectorDebuggerAgent(InspectorController* inspectorController, InspectorFrontend* frontend)
: m_inspectorController(inspectorController)
, m_frontend(frontend)
@@ -71,9 +69,6 @@ InspectorDebuggerAgent::~InspectorDebuggerAgent()
{
ScriptDebugServer::shared().removeListener(this, m_inspectorController->inspectedPage());
m_pausedScriptState = 0;
-
- if (this == s_debuggerAgentOnBreakpoint)
- s_debuggerAgentOnBreakpoint = 0;
}
bool InspectorDebuggerAgent::isDebuggerAlwaysEnabled()
@@ -147,9 +142,23 @@ void InspectorDebuggerAgent::getScriptSource(const String& sourceID, String* scr
*scriptSource = m_scriptIDToContent.get(sourceID);
}
+void InspectorDebuggerAgent::schedulePauseOnNextStatement(DebuggerEventType type, PassRefPtr<InspectorValue> data)
+{
+ m_breakProgramDetails = InspectorObject::create();
+ m_breakProgramDetails->setNumber("eventType", type);
+ m_breakProgramDetails->setValue("eventData", data);
+ ScriptDebugServer::shared().setPauseOnNextStatement(true);
+}
+
+void InspectorDebuggerAgent::cancelPauseOnNextStatement()
+{
+ m_breakProgramDetails = 0;
+ ScriptDebugServer::shared().setPauseOnNextStatement(false);
+}
+
void InspectorDebuggerAgent::pause()
{
- ScriptDebugServer::shared().pause();
+ schedulePauseOnNextStatement(JavaScriptPauseEventType, InspectorObject::create());
}
void InspectorDebuggerAgent::resume()
@@ -305,6 +314,7 @@ void InspectorDebuggerAgent::didPause(ScriptState* scriptState)
void InspectorDebuggerAgent::didContinue()
{
m_pausedScriptState = 0;
+ m_breakProgramDetails = 0;
m_frontend->resumedScript();
}
@@ -313,14 +323,7 @@ void InspectorDebuggerAgent::breakProgram(DebuggerEventType type, PassRefPtr<Ins
m_breakProgramDetails = InspectorObject::create();
m_breakProgramDetails->setNumber("eventType", type);
m_breakProgramDetails->setValue("eventData", data);
- s_debuggerAgentOnBreakpoint = this;
-
ScriptDebugServer::shared().breakProgram();
- if (!s_debuggerAgentOnBreakpoint)
- return;
-
- s_debuggerAgentOnBreakpoint = 0;
- m_breakProgramDetails = 0;
}
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorDebuggerAgent.h b/WebCore/inspector/InspectorDebuggerAgent.h
index 8a5379d..3825042 100644
--- a/WebCore/inspector/InspectorDebuggerAgent.h
+++ b/WebCore/inspector/InspectorDebuggerAgent.h
@@ -47,7 +47,8 @@ class InspectorObject;
class InspectorValue;
enum DebuggerEventType {
- DOMBreakpointDebuggerEventType,
+ JavaScriptPauseEventType,
+ JavaScriptBreakpointEventType,
NativeBreakpointDebuggerEventType
};
@@ -66,8 +67,10 @@ public:
void editScriptSource(const String& sourceID, const String& newContent, bool* success, String* result, RefPtr<InspectorValue>* newCallFrames);
void getScriptSource(const String& sourceID, String* scriptSource);
- void pause();
+ void schedulePauseOnNextStatement(DebuggerEventType type, PassRefPtr<InspectorValue> data);
+ void cancelPauseOnNextStatement();
void breakProgram(DebuggerEventType type, PassRefPtr<InspectorValue> data);
+ void pause();
void resume();
void stepOverStatement();
void stepIntoStatement();
diff --git a/WebCore/inspector/InspectorFrontendClientLocal.cpp b/WebCore/inspector/InspectorFrontendClientLocal.cpp
index 77616da..4812b2a 100644
--- a/WebCore/inspector/InspectorFrontendClientLocal.cpp
+++ b/WebCore/inspector/InspectorFrontendClientLocal.cpp
@@ -47,7 +47,6 @@
namespace WebCore {
-static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight";
static const unsigned defaultAttachedHeight = 300;
static const float minimumAttachedHeight = 250.0f;
static const float maximumAttachedHeightRatio = 0.75f;
@@ -108,7 +107,7 @@ void InspectorFrontendClientLocal::changeAttachedWindowHeight(unsigned height)
{
unsigned totalHeight = m_frontendPage->mainFrame()->view()->visibleHeight() + m_inspectorController->inspectedPage()->mainFrame()->view()->visibleHeight();
unsigned attachedHeight = constrainedAttachedWindowHeight(height, totalHeight);
- m_inspectorController->setSetting(inspectorAttachedHeightName, String::number(attachedHeight));
+ m_inspectorController->setInspectorAttachedHeight(attachedHeight);
setAttachedWindowHeight(attachedHeight);
}
@@ -134,10 +133,9 @@ void InspectorFrontendClientLocal::setAttachedWindow(bool attached)
void InspectorFrontendClientLocal::restoreAttachedWindowHeight()
{
unsigned inspectedPageHeight = m_inspectorController->inspectedPage()->mainFrame()->view()->visibleHeight();
- String attachedHeight = m_inspectorController->setting(inspectorAttachedHeightName);
+ int attachedHeight = m_inspectorController->inspectorAttachedHeight();
bool success = true;
- int height = attachedHeight.toInt(&success);
- unsigned preferredHeight = success ? static_cast<unsigned>(height) : defaultAttachedHeight;
+ unsigned preferredHeight = success ? static_cast<unsigned>(attachedHeight) : defaultAttachedHeight;
// This call might not go through (if the window starts out detached), but if the window is initially created attached,
// InspectorController::attachWindow is never called, so we need to make sure to set the attachedWindowHeight.
diff --git a/WebCore/inspector/InspectorInstrumentation.cpp b/WebCore/inspector/InspectorInstrumentation.cpp
new file mode 100644
index 0000000..ae89266
--- /dev/null
+++ b/WebCore/inspector/InspectorInstrumentation.cpp
@@ -0,0 +1,462 @@
+/*
+* Copyright (C) 2010 Google Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+* * Neither the name of Google Inc. nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+#include "InspectorInstrumentation.h"
+
+#if ENABLE(INSPECTOR)
+
+#include "DOMWindow.h"
+#include "Event.h"
+#include "InspectorController.h"
+#include "InspectorDOMAgent.h"
+#include "InspectorDebuggerAgent.h"
+#include "InspectorTimelineAgent.h"
+#include "XMLHttpRequest.h"
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+static const char* const listenerEventCategoryType = "listener";
+static const char* const instrumentationEventCategoryType = "instrumentation";
+
+static const char* const setTimerEventName = "setTimer";
+static const char* const clearTimerEventName = "clearTimer";
+static const char* const timerFiredEventName = "timerFired";
+
+int InspectorInstrumentation::s_frontendCounter = 0;
+
+static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+{
+ if (window && window->hasEventListeners(eventType))
+ return true;
+
+ if (node->hasEventListeners(eventType))
+ return true;
+
+ for (size_t i = 0; i < ancestors.size(); i++) {
+ ContainerNode* ancestor = ancestors[i].get();
+ if (ancestor->hasEventListeners(eventType))
+ return true;
+ }
+
+ return false;
+}
+
+void InspectorInstrumentation::willInsertDOMNodeImpl(InspectorController* inspectorController, Node* node, Node* parent)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get();
+ if (!debuggerAgent)
+ return;
+ InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get();
+ if (!domAgent)
+ return;
+ PassRefPtr<InspectorValue> eventData;
+ if (domAgent->shouldBreakOnNodeInsertion(node, parent, &eventData))
+ debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
+#endif
+}
+
+void InspectorInstrumentation::didInsertDOMNodeImpl(InspectorController* inspectorController, Node* node)
+{
+ if (InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get())
+ domAgent->didInsertDOMNode(node);
+}
+
+void InspectorInstrumentation::willRemoveDOMNodeImpl(InspectorController* inspectorController, Node* node)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get();
+ if (!debuggerAgent)
+ return;
+ InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get();
+ if (!domAgent)
+ return;
+ PassRefPtr<InspectorValue> eventData;
+ if (domAgent->shouldBreakOnNodeRemoval(node, &eventData))
+ debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
+#endif
+}
+
+void InspectorInstrumentation::didRemoveDOMNodeImpl(InspectorController* inspectorController, Node* node)
+{
+ if (InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get())
+ domAgent->didRemoveDOMNode(node);
+}
+
+void InspectorInstrumentation::willModifyDOMAttrImpl(InspectorController* inspectorController, Element* element)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get();
+ if (!debuggerAgent)
+ return;
+ InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get();
+ if (!domAgent)
+ return;
+ PassRefPtr<InspectorValue> eventData;
+ if (domAgent->shouldBreakOnAttributeModification(element, &eventData))
+ debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
+#endif
+}
+
+void InspectorInstrumentation::didModifyDOMAttrImpl(InspectorController* inspectorController, Element* element)
+{
+ if (InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get())
+ domAgent->didModifyDOMAttr(element);
+}
+
+void InspectorInstrumentation::characterDataModifiedImpl(InspectorController* inspectorController, CharacterData* characterData)
+{
+ if (InspectorDOMAgent* domAgent = inspectorController->m_domAgent.get())
+ domAgent->characterDataModified(characterData);
+}
+
+
+void InspectorInstrumentation::willSendXMLHttpRequestImpl(InspectorController* inspectorController, const String& url)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get();
+ if (!debuggerAgent)
+ return;
+
+ String breakpointId = inspectorController->findXHRBreakpoint(url);
+ if (breakpointId.isEmpty())
+ return;
+
+ RefPtr<InspectorObject> eventData = InspectorObject::create();
+ eventData->setString("breakpointId", breakpointId);
+ eventData->setString("url", url);
+ debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
+#endif
+}
+
+void InspectorInstrumentation::didScheduleResourceRequestImpl(InspectorController* inspectorController, const String& url)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController))
+ timelineAgent->didScheduleResourceRequest(url);
+}
+
+void InspectorInstrumentation::didInstallTimerImpl(InspectorController* inspectorController, int timerId, int timeout, bool singleShot)
+{
+ pauseOnNativeEventIfNeeded(inspectorController, instrumentationEventCategoryType, setTimerEventName, true);
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController))
+ timelineAgent->didInstallTimer(timerId, timeout, singleShot);
+}
+
+void InspectorInstrumentation::didRemoveTimerImpl(InspectorController* inspectorController, int timerId)
+{
+ pauseOnNativeEventIfNeeded(inspectorController, instrumentationEventCategoryType, clearTimerEventName, true);
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController))
+ timelineAgent->didRemoveTimer(timerId);
+}
+
+
+InspectorInstrumentationCookie InspectorInstrumentation::willCallFunctionImpl(InspectorController* inspectorController, const String& scriptName, int scriptLine)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willCallFunction(scriptName, scriptLine);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didCallFunctionImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didCallFunction();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willChangeXHRReadyStateImpl(InspectorController* inspectorController, XMLHttpRequest* request)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent && request->hasEventListeners(eventNames().readystatechangeEvent)) {
+ timelineAgent->willChangeXHRReadyState(request->url().string(), request->readyState());
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didChangeXHRReadyStateImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didChangeXHRReadyState();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventImpl(InspectorController* inspectorController, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+{
+ pauseOnNativeEventIfNeeded(inspectorController, listenerEventCategoryType, event.type(), false);
+
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent && eventHasListeners(event.type(), window, node, ancestors)) {
+ timelineAgent->willDispatchEvent(event);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didDispatchEventImpl(const InspectorInstrumentationCookie& cookie)
+{
+ cancelPauseOnNativeEvent(cookie.first);
+
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didDispatchEvent();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventOnWindowImpl(InspectorController* inspectorController, const Event& event, DOMWindow* window)
+{
+ pauseOnNativeEventIfNeeded(inspectorController, listenerEventCategoryType, event.type(), false);
+
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent && window->hasEventListeners(event.type())) {
+ timelineAgent->willDispatchEvent(event);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie& cookie)
+{
+ cancelPauseOnNativeEvent(cookie.first);
+
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didDispatchEvent();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willEvaluateScriptImpl(InspectorController* inspectorController, const String& url, int lineNumber)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willEvaluateScript(url, lineNumber);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didEvaluateScriptImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didEvaluateScript();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InspectorController* inspectorController, int timerId)
+{
+ pauseOnNativeEventIfNeeded(inspectorController, instrumentationEventCategoryType, timerFiredEventName, false);
+
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willFireTimer(timerId);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didFireTimerImpl(const InspectorInstrumentationCookie& cookie)
+{
+ cancelPauseOnNativeEvent(cookie.first);
+
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didFireTimer();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willLayoutImpl(InspectorController* inspectorController)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willLayout();
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didLayoutImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didLayout();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willLoadXHRImpl(InspectorController* inspectorController, XMLHttpRequest* request)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent && request->hasEventListeners(eventNames().loadEvent)) {
+ timelineAgent->willLoadXHR(request->url());
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didLoadXHRImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didLoadXHR();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willPaintImpl(InspectorController* inspectorController, const IntRect& rect)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willPaint(rect);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didPaintImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didPaint();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willRecalculateStyleImpl(InspectorController* inspectorController)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willRecalculateStyle();
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didRecalculateStyleImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didRecalculateStyle();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willReceiveResourceDataImpl(InspectorController* inspectorController, unsigned long identifier)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willReceiveResourceData(identifier);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didReceiveResourceDataImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didReceiveResourceData();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willReceiveResourceResponseImpl(InspectorController* inspectorController, unsigned long identifier, const ResourceResponse& response)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willReceiveResourceResponse(identifier, response);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didReceiveResourceResponseImpl(const InspectorInstrumentationCookie& cookie)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didReceiveResourceResponse();
+}
+
+InspectorInstrumentationCookie InspectorInstrumentation::willWriteHTMLImpl(InspectorController* inspectorController, unsigned int length, unsigned int startLine)
+{
+ int timelineAgentId = 0;
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(inspectorController);
+ if (timelineAgent) {
+ timelineAgent->willWriteHTML(length, startLine);
+ timelineAgentId = timelineAgent->id();
+ }
+ return InspectorInstrumentationCookie(inspectorController, timelineAgentId);
+}
+
+void InspectorInstrumentation::didWriteHTMLImpl(const InspectorInstrumentationCookie& cookie, unsigned int endLine)
+{
+ if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+ timelineAgent->didWriteHTML(endLine);
+}
+
+bool InspectorInstrumentation::hasFrontend(InspectorController* inspectorController)
+{
+ return inspectorController->hasFrontend();
+}
+
+void InspectorInstrumentation::pauseOnNativeEventIfNeeded(InspectorController* inspectorController, const String& categoryType, const String& eventName, bool synchronous)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get();
+ if (!debuggerAgent)
+ return;
+ String fullEventName = String::format("%s:%s", categoryType.utf8().data(), eventName.utf8().data());
+ String breakpointId = inspectorController->findEventListenerBreakpoint(fullEventName);
+ if (breakpointId.isEmpty())
+ return;
+ RefPtr<InspectorObject> eventData = InspectorObject::create();
+ eventData->setString("breakpointId", breakpointId);
+ if (synchronous)
+ debuggerAgent->breakProgram(NativeBreakpointDebuggerEventType, eventData);
+ else
+ debuggerAgent->schedulePauseOnNextStatement(NativeBreakpointDebuggerEventType, eventData);
+#endif
+}
+
+void InspectorInstrumentation::cancelPauseOnNativeEvent(InspectorController* inspectorController)
+{
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ if (InspectorDebuggerAgent* debuggerAgent = inspectorController->m_debuggerAgent.get())
+ debuggerAgent->cancelPauseOnNextStatement();
+#endif
+}
+
+InspectorTimelineAgent* InspectorInstrumentation::retrieveTimelineAgent(InspectorController* inspectorController)
+{
+ return inspectorController->m_timelineAgent.get();
+}
+
+InspectorTimelineAgent* InspectorInstrumentation::retrieveTimelineAgent(const InspectorInstrumentationCookie& cookie)
+{
+ InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie.first);
+ if (timelineAgent && timelineAgent->id() == cookie.second)
+ return timelineAgent;
+ return 0;
+}
+
+} // namespace WebCore
+
+#endif // !ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorInstrumentation.h b/WebCore/inspector/InspectorInstrumentation.h
new file mode 100644
index 0000000..e728a5e
--- /dev/null
+++ b/WebCore/inspector/InspectorInstrumentation.h
@@ -0,0 +1,500 @@
+/*
+* Copyright (C) 2010 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 InspectorInstrumentation_h
+#define InspectorInstrumentation_h
+
+#include "Document.h"
+#include "Frame.h"
+#include "Page.h"
+#include "ScriptExecutionContext.h"
+
+namespace WebCore {
+
+class CharacterData;
+class Element;
+class InspectorController;
+class InspectorTimelineAgent;
+class Node;
+class ResourceRequest;
+class ResourceResponse;
+class XMLHttpRequest;
+
+typedef pair<InspectorController*, int> InspectorInstrumentationCookie;
+
+class InspectorInstrumentation {
+public:
+ static void willInsertDOMNode(Document*, Node*, Node* parent);
+ static void didInsertDOMNode(Document*, Node*);
+ static void willRemoveDOMNode(Document*, Node*);
+ static void willModifyDOMAttr(Document*, Element*);
+ static void didModifyDOMAttr(Document*, Element*);
+ static void characterDataModified(Document*, CharacterData*);
+
+ static void willSendXMLHttpRequest(ScriptExecutionContext*, const String& url);
+ static void didScheduleResourceRequest(Document*, const String& url);
+ static void didInstallTimer(ScriptExecutionContext*, int timerId, int timeout, bool singleShot);
+ static void didRemoveTimer(ScriptExecutionContext*, int timerId);
+
+ static InspectorInstrumentationCookie willCallFunction(Frame*, const String& scriptName, int scriptLine);
+ static void didCallFunction(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willChangeXHRReadyState(ScriptExecutionContext*, XMLHttpRequest* request);
+ static void didChangeXHRReadyState(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willDispatchEvent(Document*, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors);
+ static void didDispatchEvent(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event& event, DOMWindow* window);
+ static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willEvaluateScript(Frame*, const String& url, int lineNumber);
+ static void didEvaluateScript(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext*, int timerId);
+ static void didFireTimer(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willLayout(Frame*);
+ static void didLayout(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willLoadXHR(ScriptExecutionContext*, XMLHttpRequest*);
+ static void didLoadXHR(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willPaint(Frame*, const IntRect& rect);
+ static void didPaint(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willRecalculateStyle(Document*);
+ static void didRecalculateStyle(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willReceiveResourceData(Frame*, unsigned long identifier);
+ static void didReceiveResourceData(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willReceiveResourceResponse(Frame*, unsigned long identifier, const ResourceResponse& response);
+ static void didReceiveResourceResponse(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willWriteHTML(Document*, unsigned int length, unsigned int startLine);
+ static void didWriteHTML(const InspectorInstrumentationCookie&, unsigned int endLine);
+
+#if ENABLE(INSPECTOR)
+ static void frontendCreated() { s_frontendCounter += 1; }
+ static void frontendDeleted() { s_frontendCounter -= 1; }
+ static bool hasFrontends() { return s_frontendCounter; }
+#else
+ static bool hasFrontends() { return false; }
+#endif
+
+private:
+#if ENABLE(INSPECTOR)
+ static void willInsertDOMNodeImpl(InspectorController*, Node* node, Node* parent);
+ static void didInsertDOMNodeImpl(InspectorController*, Node*);
+ static void willRemoveDOMNodeImpl(InspectorController*, Node*);
+ static void didRemoveDOMNodeImpl(InspectorController*, Node*);
+ static void willModifyDOMAttrImpl(InspectorController*, Element*);
+ static void didModifyDOMAttrImpl(InspectorController*, Element*);
+ static void characterDataModifiedImpl(InspectorController*, CharacterData*);
+
+ static void willSendXMLHttpRequestImpl(InspectorController*, const String& url);
+ static void didScheduleResourceRequestImpl(InspectorController*, const String& url);
+ static void didInstallTimerImpl(InspectorController*, int timerId, int timeout, bool singleShot);
+ static void didRemoveTimerImpl(InspectorController*, int timerId);
+
+ static InspectorInstrumentationCookie willCallFunctionImpl(InspectorController*, const String& scriptName, int scriptLine);
+ static void didCallFunctionImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willChangeXHRReadyStateImpl(InspectorController*, XMLHttpRequest* request);
+ static void didChangeXHRReadyStateImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willDispatchEventImpl(InspectorController*, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors);
+ static void didDispatchEventImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InspectorController*, const Event& event, DOMWindow* window);
+ static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willEvaluateScriptImpl(InspectorController*, const String& url, int lineNumber);
+ static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willFireTimerImpl(InspectorController*, int timerId);
+ static void didFireTimerImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willLayoutImpl(InspectorController*);
+ static void didLayoutImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willLoadXHRImpl(InspectorController*, XMLHttpRequest* request);
+ static void didLoadXHRImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willPaintImpl(InspectorController*, const IntRect& rect);
+ static void didPaintImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willRecalculateStyleImpl(InspectorController*);
+ static void didRecalculateStyleImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willReceiveResourceDataImpl(InspectorController*, unsigned long identifier);
+ static void didReceiveResourceDataImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willReceiveResourceResponseImpl(InspectorController*, unsigned long identifier, const ResourceResponse& response);
+ static void didReceiveResourceResponseImpl(const InspectorInstrumentationCookie&);
+ static InspectorInstrumentationCookie willWriteHTMLImpl(InspectorController*, unsigned int length, unsigned int startLine);
+ static void didWriteHTMLImpl(const InspectorInstrumentationCookie&, unsigned int endLine);
+
+ static InspectorController* inspectorControllerForContext(ScriptExecutionContext*);
+ static InspectorController* inspectorControllerForDocument(Document*);
+ static InspectorController* inspectorControllerForFrame(Frame*);
+ static InspectorController* inspectorControllerForPage(Page*);
+
+ static bool hasFrontend(InspectorController*);
+ static void pauseOnNativeEventIfNeeded(InspectorController*, const String& categoryType, const String& eventName, bool synchronous);
+ static void cancelPauseOnNativeEvent(InspectorController*);
+ static InspectorTimelineAgent* retrieveTimelineAgent(InspectorController*);
+ static InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&);
+
+ static int s_frontendCounter;
+#endif
+};
+
+inline void InspectorInstrumentation::willInsertDOMNode(Document* document, Node* node, Node* parent)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ willInsertDOMNodeImpl(inspectorController, node, parent);
+#endif
+}
+
+inline void InspectorInstrumentation::didInsertDOMNode(Document* document, Node* node)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ didInsertDOMNodeImpl(inspectorController, node);
+#endif
+}
+
+inline void InspectorInstrumentation::willRemoveDOMNode(Document* document, Node* node)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document)) {
+ willRemoveDOMNodeImpl(inspectorController, node);
+ didRemoveDOMNodeImpl(inspectorController, node);
+ }
+#endif
+}
+
+inline void InspectorInstrumentation::willModifyDOMAttr(Document* document, Element* element)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ willModifyDOMAttrImpl(inspectorController, element);
+#endif
+}
+
+inline void InspectorInstrumentation::didModifyDOMAttr(Document* document, Element* element)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ didModifyDOMAttrImpl(inspectorController, element);
+#endif
+}
+
+inline void InspectorInstrumentation::characterDataModified(Document* document, CharacterData* characterData)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ characterDataModifiedImpl(inspectorController, characterData);
+#endif
+}
+
+
+inline void InspectorInstrumentation::willSendXMLHttpRequest(ScriptExecutionContext* context, const String& url)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ willSendXMLHttpRequestImpl(inspectorController, url);
+#endif
+}
+
+inline void InspectorInstrumentation::didScheduleResourceRequest(Document* document, const String& url)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ didScheduleResourceRequestImpl(inspectorController, url);
+#endif
+}
+
+inline void InspectorInstrumentation::didInstallTimer(ScriptExecutionContext* context, int timerId, int timeout, bool singleShot)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ didInstallTimerImpl(inspectorController, timerId, timeout, singleShot);
+#endif
+}
+
+inline void InspectorInstrumentation::didRemoveTimer(ScriptExecutionContext* context, int timerId)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ didRemoveTimerImpl(inspectorController, timerId);
+#endif
+}
+
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willCallFunction(Frame* frame, const String& scriptName, int scriptLine)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willCallFunctionImpl(inspectorController, scriptName, scriptLine);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didCallFunction(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didCallFunctionImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willChangeXHRReadyState(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ return willChangeXHRReadyStateImpl(inspectorController, request);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didChangeXHRReadyState(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didChangeXHRReadyStateImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ return willDispatchEventImpl(inspectorController, event, window, node, ancestors);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didDispatchEvent(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didDispatchEventImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventOnWindow(Frame* frame, const Event& event, DOMWindow* window)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willDispatchEventOnWindowImpl(inspectorController, event, window);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didDispatchEventOnWindow(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didDispatchEventOnWindowImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willEvaluateScript(Frame* frame, const String& url, int lineNumber)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willEvaluateScriptImpl(inspectorController, url, lineNumber);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didEvaluateScript(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didEvaluateScriptImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext* context, int timerId)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ return willFireTimerImpl(inspectorController, timerId);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didFireTimer(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didFireTimerImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willLayout(Frame* frame)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willLayoutImpl(inspectorController);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didLayout(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didLayoutImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willLoadXHR(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForContext(context))
+ return willLoadXHRImpl(inspectorController, request);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didLoadXHR(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didLoadXHRImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willPaint(Frame* frame, const IntRect& rect)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willPaintImpl(inspectorController, rect);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didPaint(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didPaintImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willRecalculateStyle(Document* document)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ return willRecalculateStyleImpl(inspectorController);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didRecalculateStyle(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didRecalculateStyleImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willReceiveResourceData(Frame* frame, unsigned long identifier)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willReceiveResourceDataImpl(inspectorController, identifier);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didReceiveResourceData(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didReceiveResourceDataImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willReceiveResourceResponse(Frame* frame, unsigned long identifier, const ResourceResponse& response)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForFrame(frame))
+ return willReceiveResourceResponseImpl(inspectorController, identifier, response);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didReceiveResourceResponse(const InspectorInstrumentationCookie& cookie)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didReceiveResourceResponseImpl(cookie);
+#endif
+}
+
+inline InspectorInstrumentationCookie InspectorInstrumentation::willWriteHTML(Document* document, unsigned int length, unsigned int startLine)
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorController* inspectorController = inspectorControllerForDocument(document))
+ return willWriteHTMLImpl(inspectorController, length, startLine);
+#endif
+ return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didWriteHTML(const InspectorInstrumentationCookie& cookie, unsigned int endLine)
+{
+#if ENABLE(INSPECTOR)
+ if (hasFrontends() && cookie.first)
+ didWriteHTMLImpl(cookie, endLine);
+#endif
+}
+
+
+#if ENABLE(INSPECTOR)
+inline InspectorController* InspectorInstrumentation::inspectorControllerForContext(ScriptExecutionContext* context)
+{
+ if (hasFrontends() && context && context->isDocument())
+ return inspectorControllerForPage(static_cast<Document*>(context)->page());
+ return 0;
+}
+
+inline InspectorController* InspectorInstrumentation::inspectorControllerForDocument(Document* document)
+{
+ if (hasFrontends() && document)
+ return inspectorControllerForPage(document->page());
+ return 0;
+}
+
+inline InspectorController* InspectorInstrumentation::inspectorControllerForFrame(Frame* frame)
+{
+ if (hasFrontends() && frame)
+ return inspectorControllerForPage(frame->page());
+ return 0;
+}
+
+inline InspectorController* InspectorInstrumentation::inspectorControllerForPage(Page* page)
+{
+ if (page) {
+ if (InspectorController* inspectorController = page->inspectorController()) {
+ if (hasFrontend(inspectorController))
+ return inspectorController;
+ }
+ }
+ return 0;
+}
+#endif
+
+} // namespace WebCore
+
+#endif // !defined(InspectorInstrumentation_h)
diff --git a/WebCore/inspector/InspectorProfilerAgent.cpp b/WebCore/inspector/InspectorProfilerAgent.cpp
index 09b2b32..71c7231 100644
--- a/WebCore/inspector/InspectorProfilerAgent.cpp
+++ b/WebCore/inspector/InspectorProfilerAgent.cpp
@@ -43,7 +43,7 @@
#include "ScriptProfile.h"
#include "ScriptProfiler.h"
#include <wtf/OwnPtr.h>
-#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#if USE(JSC)
#include "JSDOMWindow.h"
@@ -89,13 +89,13 @@ void InspectorProfilerAgent::addProfileFinishedMessageToConsole(PassRefPtr<Scrip
{
RefPtr<ScriptProfile> profile = prpProfile;
String title = profile->title();
- String message = String::format("Profile \"webkit-profile://%s/%s#%d\" finished.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data(), profile->uid());
+ String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), '#', String::number(profile->uid()), "\" finished.");
m_inspectorController->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
}
void InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
{
- String message = String::format("Profile \"webkit-profile://%s/%s#0\" started.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data());
+ String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), "#0 \" started.");
m_inspectorController->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
}
@@ -143,7 +143,7 @@ String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool increment
if (incrementProfileNumber)
m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
- return String::format("%s.%d", UserInitiatedProfileName, m_currentUserInitiatedProfileNumber);
+ return makeString(UserInitiatedProfileName, '.', String::number(m_currentUserInitiatedProfileNumber));
}
void InspectorProfilerAgent::getProfileHeaders(RefPtr<InspectorArray>* headers)
@@ -232,7 +232,9 @@ void InspectorProfilerAgent::stopUserInitiatedProfiling()
void InspectorProfilerAgent::takeHeapSnapshot()
{
- String title = String::format("%s.%d", UserInitiatedProfileName, m_nextUserInitiatedHeapSnapshotNumber++);
+ String title = makeString(UserInitiatedProfileName, '.', String::number(m_nextUserInitiatedHeapSnapshotNumber));
+ ++m_nextUserInitiatedHeapSnapshotNumber;
+
RefPtr<ScriptHeapSnapshot> snapshot = ScriptProfiler::takeHeapSnapshot(title);
if (snapshot) {
m_snapshots.add(snapshot->uid(), snapshot);
diff --git a/WebCore/inspector/InspectorResource.cpp b/WebCore/inspector/InspectorResource.cpp
index ac2c9a0..05b1bff 100644
--- a/WebCore/inspector/InspectorResource.cpp
+++ b/WebCore/inspector/InspectorResource.cpp
@@ -33,22 +33,24 @@
#if ENABLE(INSPECTOR)
+#include "Base64.h"
#include "Cache.h"
#include "CachedResource.h"
#include "CachedResourceLoader.h"
#include "DocumentLoader.h"
#include "Frame.h"
#include "InspectorFrontend.h"
+#include "InspectorResourceAgent.h"
#include "InspectorValues.h"
#include "ResourceLoadTiming.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
-#include "StringBuffer.h"
#include "TextEncoding.h"
#include "WebSocketHandshakeRequest.h"
#include "WebSocketHandshakeResponse.h"
#include <wtf/Assertions.h>
+#include <wtf/text/StringBuffer.h>
namespace WebCore {
@@ -86,8 +88,6 @@ InspectorResource::InspectorResource(unsigned long identifier, DocumentLoader* l
, m_startTime(-1.0)
, m_responseReceivedTime(-1.0)
, m_endTime(-1.0)
- , m_loadEventTime(-1.0)
- , m_domContentEventTime(-1.0)
, m_connectionID(0)
, m_connectionReused(false)
, m_isMainResource(false)
@@ -147,6 +147,7 @@ PassRefPtr<InspectorResource> InspectorResource::createWebSocket(unsigned long i
RefPtr<InspectorResource> resource = adoptRef(new InspectorResource(identifier, 0, requestURL));
resource->markWebSocket();
resource->m_documentURL = documentURL;
+ resource->m_changes.setAll();
return resource.release();
}
#endif
@@ -175,7 +176,12 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
if (cachedResource)
m_mimeType = cachedResource->response().mimeType();
}
- m_responseHeaderFields = response.httpHeaderFields();
+ if (ResourceRawHeaders* headers = response.resourceRawHeaders().get()) {
+ m_requestHeaderFields = headers->requestHeaders;
+ m_responseHeaderFields = headers->responseHeaders;
+ m_changes.set(RequestChange);
+ } else
+ m_responseHeaderFields = response.httpHeaderFields();
m_responseStatusCode = response.httpStatusCode();
m_responseStatusText = response.httpStatusText();
m_suggestedFilename = response.suggestedFilename();
@@ -184,12 +190,7 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
m_connectionReused = response.connectionReused();
m_loadTiming = response.resourceLoadTiming();
m_cached = m_cached || response.wasCached();
-
- if (!m_cached && m_loadTiming && m_loadTiming->requestTime)
- m_responseReceivedTime = m_loadTiming->requestTime + m_loadTiming->receiveHeadersEnd / 1000.0;
- else
- m_responseReceivedTime = currentTime();
-
+ m_responseReceivedTime = currentTime();
m_changes.set(TimingChange);
m_changes.set(ResponseChange);
m_changes.set(TypeChange);
@@ -257,9 +258,6 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
m_documentURL = m_frame->document()->url();
jsonObject->setString("url", m_requestURL.string());
jsonObject->setString("documentURL", m_documentURL.string());
- jsonObject->setString("host", m_requestURL.host());
- jsonObject->setString("path", m_requestURL.path());
- jsonObject->setString("lastPathComponent", m_requestURL.lastPathComponent());
RefPtr<InspectorObject> requestHeaders = buildHeadersObject(m_requestHeaderFields);
jsonObject->setObject("requestHeaders", requestHeaders);
jsonObject->setBoolean("mainResource", m_isMainResource);
@@ -315,10 +313,6 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
jsonObject->setNumber("responseReceivedTime", m_responseReceivedTime);
if (m_endTime > 0)
jsonObject->setNumber("endTime", m_endTime);
- if (m_loadEventTime > 0)
- jsonObject->setNumber("loadEventTime", m_loadEventTime);
- if (m_domContentEventTime > 0)
- jsonObject->setNumber("domContentEventTime", m_domContentEventTime);
jsonObject->setBoolean("didTimingChange", true);
}
@@ -342,41 +336,25 @@ void InspectorResource::releaseScriptObject(InspectorFrontend* frontend)
frontend->removeResource(m_identifier);
}
-CachedResource* InspectorResource::cachedResource() const
+static InspectorResource::Type cachedResourceType(CachedResource* cachedResource)
{
- // Try hard to find a corresponding CachedResource. During preloading, CachedResourceLoader may not have the resource in document resources set yet,
- // but Inspector will already try to fetch data that is only available via CachedResource (and it won't update once the resource is added,
- // because m_changes will not have the appropriate bits set).
- if (!m_frame)
- return 0;
- const String& url = m_requestURL.string();
- CachedResource* cachedResource = m_frame->document()->cachedResourceLoader()->cachedResource(url);
if (!cachedResource)
- cachedResource = cache()->resourceForURL(url);
- return cachedResource;
-}
-
-InspectorResource::Type InspectorResource::cachedResourceType() const
-{
- CachedResource* cachedResource = this->cachedResource();
-
- if (!cachedResource)
- return Other;
+ return InspectorResource::Other;
switch (cachedResource->type()) {
- case CachedResource::ImageResource:
- return Image;
- case CachedResource::FontResource:
- return Font;
- case CachedResource::CSSStyleSheet:
+ case CachedResource::ImageResource:
+ return InspectorResource::Image;
+ case CachedResource::FontResource:
+ return InspectorResource::Font;
+ case CachedResource::CSSStyleSheet:
#if ENABLE(XSLT)
- case CachedResource::XSLStyleSheet:
+ case CachedResource::XSLStyleSheet:
#endif
- return Stylesheet;
- case CachedResource::Script:
- return Script;
- default:
- return Other;
+ return InspectorResource::Stylesheet;
+ case CachedResource::Script:
+ return InspectorResource::Script;
+ default:
+ return InspectorResource::Other;
}
}
@@ -391,21 +369,21 @@ InspectorResource::Type InspectorResource::type() const
#endif
ASSERT(m_loader);
- if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
- InspectorResource::Type resourceType = cachedResourceType();
- if (resourceType == Other)
- return Doc;
-
- return resourceType;
- }
if (m_loader->frameLoader() && equalIgnoringFragmentIdentifier(m_requestURL, m_loader->frameLoader()->iconURL()))
return Image;
- return cachedResourceType();
+ if (!m_frame)
+ return Other;
+
+ InspectorResource::Type resourceType = cachedResourceType(InspectorResourceAgent::cachedResource(m_frame.get(), m_requestURL));
+ if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL()) && resourceType == Other)
+ return Doc;
+
+ return resourceType;
}
-void InspectorResource::setOverrideContent(const ScriptString& data, Type type)
+void InspectorResource::setOverrideContent(const String& data, Type type)
{
m_overrideContent = data;
m_overrideContentType = type;
@@ -417,41 +395,27 @@ String InspectorResource::sourceString() const
if (!m_overrideContent.isNull())
return String(m_overrideContent);
- String textEncodingName;
- RefPtr<SharedBuffer> buffer = resourceData(&textEncodingName);
- if (!buffer)
+ String result;
+ if (!InspectorResourceAgent::resourceContent(m_frame.get(), m_requestURL, &result))
return String();
-
- TextEncoding encoding(textEncodingName);
- if (!encoding.isValid())
- encoding = WindowsLatin1Encoding();
- return encoding.decode(buffer->data(), buffer->size());
+ return result;
}
-PassRefPtr<SharedBuffer> InspectorResource::resourceData(String* textEncodingName) const
+String InspectorResource::sourceBytes() const
{
- if (m_loader && equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
- *textEncodingName = m_frame->document()->inputEncoding();
- return m_loader->mainResourceData();
- }
-
- CachedResource* cachedResource = this->cachedResource();
- if (!cachedResource)
- return 0;
-
- if (cachedResource->isPurgeable()) {
- // If the resource is purgeable then make it unpurgeable to get
- // get its data. This might fail, in which case we return an
- // empty String.
- // FIXME: should we do something else in the case of a purged
- // resource that informs the user why there is no data in the
- // inspector?
- if (!cachedResource->makePurgeable(false))
- return 0;
+ Vector<char> out;
+ if (!m_overrideContent.isNull()) {
+ Vector<char> data;
+ String overrideContent = m_overrideContent;
+ data.append(overrideContent.characters(), overrideContent.length());
+ base64Encode(data, out);
+ return String(out.data(), out.size());
}
- *textEncodingName = cachedResource->encoding();
- return cachedResource->data();
+ String result;
+ if (!InspectorResourceAgent::resourceContentBase64(m_frame.get(), m_requestURL, &result))
+ return String();
+ return result;
}
void InspectorResource::startTiming()
@@ -462,14 +426,9 @@ void InspectorResource::startTiming()
void InspectorResource::endTiming(double actualEndTime)
{
- if (actualEndTime) {
+ if (actualEndTime)
m_endTime = actualEndTime;
- // In case of fast load (or in case of cached resources), endTime on network stack
- // can be less then m_responseReceivedTime measured in WebCore. Normalize it here,
- // prefer actualEndTime to m_responseReceivedTime.
- if (m_endTime < m_responseReceivedTime)
- m_responseReceivedTime = m_endTime;
- } else
+ else
m_endTime = currentTime();
m_finished = true;
@@ -477,18 +436,6 @@ void InspectorResource::endTiming(double actualEndTime)
m_changes.set(CompletionChange);
}
-void InspectorResource::markDOMContentEventTime()
-{
- m_domContentEventTime = currentTime();
- m_changes.set(TimingChange);
-}
-
-void InspectorResource::markLoadEventTime()
-{
- m_loadEventTime = currentTime();
- m_changes.set(TimingChange);
-}
-
void InspectorResource::markFailed()
{
m_failed = true;
diff --git a/WebCore/inspector/InspectorResource.h b/WebCore/inspector/InspectorResource.h
index 914232e..aa6001f 100644
--- a/WebCore/inspector/InspectorResource.h
+++ b/WebCore/inspector/InspectorResource.h
@@ -33,7 +33,6 @@
#include "HTTPHeaderMap.h"
#include "KURL.h"
-#include "ScriptString.h"
#include "WebSocketHandshakeRequest.h"
#include "WebSocketHandshakeResponse.h"
@@ -98,10 +97,9 @@ namespace WebCore {
void updateWebSocketResponse(const WebSocketHandshakeResponse&);
#endif
- void setOverrideContent(const ScriptString& data, Type);
-
+ void setOverrideContent(const String& data, Type);
String sourceString() const;
- PassRefPtr<SharedBuffer> resourceData(String* textEncodingName) const;
+ String sourceBytes() const;
bool isSameLoader(DocumentLoader* loader) const { return loader == m_loader; }
void markMainResource() { m_isMainResource = true; }
@@ -116,8 +114,6 @@ namespace WebCore {
String requestFormData() const { return m_requestFormData; }
void startTiming();
- void markLoadEventTime();
- void markDOMContentEventTime();
void endTiming(double actualEndTime);
void markFailed();
@@ -162,9 +158,6 @@ namespace WebCore {
InspectorResource(unsigned long identifier, DocumentLoader*, const KURL& requestURL);
Type type() const;
- Type cachedResourceType() const;
- CachedResource* cachedResource() const;
-
#if ENABLE(WEB_SOCKETS)
void markWebSocket() { m_isWebSocket = true; }
#endif
@@ -188,12 +181,10 @@ namespace WebCore {
double m_startTime;
double m_responseReceivedTime;
double m_endTime;
- double m_loadEventTime;
- double m_domContentEventTime;
unsigned m_connectionID;
bool m_connectionReused;
RefPtr<ResourceLoadTiming> m_loadTiming;
- ScriptString m_overrideContent;
+ String m_overrideContent;
Type m_overrideContentType;
Changes m_changes;
bool m_isMainResource;
diff --git a/WebCore/inspector/InspectorResourceAgent.cpp b/WebCore/inspector/InspectorResourceAgent.cpp
new file mode 100644
index 0000000..f49e1d7
--- /dev/null
+++ b/WebCore/inspector/InspectorResourceAgent.cpp
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InspectorResourceAgent.h"
+
+#include "Base64.h"
+#include "Cache.h"
+#include "CachedResource.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "DocumentLoader.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTTPHeaderMap.h"
+#include "InspectorFrontend.h"
+#include "InspectorValues.h"
+#include "KURL.h"
+#include "Page.h"
+#include "ProgressTracker.h"
+#include "ResourceError.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "SharedBuffer.h"
+#include "TextEncoding.h"
+#include "WebSocketHandshakeRequest.h"
+#include "WebSocketHandshakeResponse.h"
+
+#include <wtf/ListHashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringBuffer.h>
+
+#if ENABLE(INSPECTOR)
+
+namespace WebCore {
+
+bool InspectorResourceAgent::resourceContent(Frame* frame, const KURL& url, String* result)
+{
+ if (!frame)
+ return false;
+
+ String textEncodingName;
+ RefPtr<SharedBuffer> buffer = InspectorResourceAgent::resourceData(frame, url, &textEncodingName);
+
+ if (buffer) {
+ TextEncoding encoding(textEncodingName);
+ if (!encoding.isValid())
+ encoding = WindowsLatin1Encoding();
+ *result = encoding.decode(buffer->data(), buffer->size());
+ return true;
+ }
+
+ return false;
+}
+
+bool InspectorResourceAgent::resourceContentBase64(Frame* frame, const KURL& url, String* result)
+{
+ Vector<char> out;
+ String textEncodingName;
+ RefPtr<SharedBuffer> data = InspectorResourceAgent::resourceData(frame, url, &textEncodingName);
+ if (!data) {
+ *result = String();
+ return false;
+ }
+
+ base64Encode(data->buffer(), out);
+ *result = String(out.data(), out.size());
+ return true;
+}
+
+PassRefPtr<SharedBuffer> InspectorResourceAgent::resourceData(Frame* frame, const KURL& url, String* textEncodingName)
+{
+ FrameLoader* frameLoader = frame->loader();
+ DocumentLoader* loader = frameLoader->documentLoader();
+ if (equalIgnoringFragmentIdentifier(url, loader->url())) {
+ *textEncodingName = frame->document()->inputEncoding();
+ return frameLoader->documentLoader()->mainResourceData();
+ }
+
+ CachedResource* cachedResource = InspectorResourceAgent::cachedResource(frame, url);
+ if (!cachedResource)
+ return 0;
+
+ if (cachedResource->isPurgeable()) {
+ // If the resource is purgeable then make it unpurgeable to get
+ // get its data. This might fail, in which case we return an
+ // empty String.
+ // FIXME: should we do something else in the case of a purged
+ // resource that informs the user why there is no data in the
+ // inspector?
+ if (!cachedResource->makePurgeable(false))
+ return 0;
+ }
+
+ *textEncodingName = cachedResource->encoding();
+ return cachedResource->data();
+}
+
+CachedResource* InspectorResourceAgent::cachedResource(Frame* frame, const KURL& url)
+{
+ const String& urlString = url.string();
+ CachedResource* cachedResource = frame->document()->cachedResourceLoader()->cachedResource(urlString);
+ if (!cachedResource)
+ cachedResource = cache()->resourceForURL(urlString);
+ return cachedResource;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
+{
+ RefPtr<InspectorObject> headersObject = InspectorObject::create();
+ HTTPHeaderMap::const_iterator end = headers.end();
+ for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
+ headersObject->setString(it->first.string(), it->second);
+ return headersObject;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForTiming(const ResourceLoadTiming& timing)
+{
+ RefPtr<InspectorObject> timingObject = InspectorObject::create();
+ timingObject->setNumber("requestTime", timing.requestTime);
+ timingObject->setNumber("proxyStart", timing.proxyStart);
+ timingObject->setNumber("proxyEnd", timing.proxyEnd);
+ timingObject->setNumber("dnsStart", timing.dnsStart);
+ timingObject->setNumber("dnsEnd", timing.dnsEnd);
+ timingObject->setNumber("connectStart", timing.connectStart);
+ timingObject->setNumber("connectEnd", timing.connectEnd);
+ timingObject->setNumber("sslStart", timing.sslStart);
+ timingObject->setNumber("sslEnd", timing.sslEnd);
+ timingObject->setNumber("sendStart", timing.sendStart);
+ timingObject->setNumber("sendEnd", timing.sendEnd);
+ timingObject->setNumber("receiveHeadersEnd", timing.receiveHeadersEnd);
+ return timingObject;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForResourceRequest(const ResourceRequest& request)
+{
+ RefPtr<InspectorObject> requestObject = InspectorObject::create();
+ requestObject->setString("url", request.url().string());
+ requestObject->setString("httpMethod", request.httpMethod());
+ requestObject->setObject("httpHeaderFields", buildObjectForHeaders(request.httpHeaderFields()));
+ if (request.httpBody() && !request.httpBody()->isEmpty())
+ requestObject->setString("requestFormData", request.httpBody()->flattenToString());
+ return requestObject;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForResourceResponse(const ResourceResponse& response)
+{
+ RefPtr<InspectorObject> responseObject = InspectorObject::create();
+ if (response.isNull()) {
+ responseObject->setBoolean("isNull", true);
+ return responseObject;
+ }
+ responseObject->setString("url", response.url().string());
+ responseObject->setString("mimeType", response.mimeType());
+ responseObject->setNumber("expectedContentLength", response.expectedContentLength());
+ responseObject->setString("textEncodingName", response.textEncodingName());
+ responseObject->setString("suggestedFilename", response.suggestedFilename());
+ responseObject->setNumber("httpStatusCode", response.httpStatusCode());
+ responseObject->setString("httpStatusText", response.httpStatusText());
+ responseObject->setObject("httpHeaderFields", buildObjectForHeaders(response.httpHeaderFields()));
+ responseObject->setBoolean("connectionReused", response.connectionReused());
+ responseObject->setNumber("connectionID", response.connectionID());
+ responseObject->setBoolean("wasCached", response.wasCached());
+ if (response.resourceLoadTiming())
+ responseObject->setObject("timing", buildObjectForTiming(*response.resourceLoadTiming()));
+ if (response.resourceRawHeaders()) {
+ RefPtr<InspectorObject> rawHeadersObject = InspectorObject::create();
+ rawHeadersObject->setObject("requestHeaders", buildObjectForHeaders(response.resourceRawHeaders()->requestHeaders));
+ rawHeadersObject->setObject("responseHeaders", buildObjectForHeaders(response.resourceRawHeaders()->responseHeaders));
+ responseObject->setObject("rawHeaders", rawHeadersObject);
+ }
+ return responseObject;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForMainResource(Frame* frame)
+{
+ FrameLoader* frameLoader = frame->loader();
+ DocumentLoader* loader = frameLoader->documentLoader();
+
+ RefPtr<InspectorObject> resourceObject = InspectorObject::create();
+ resourceObject->setString("url", loader->url().string());
+ resourceObject->setString("host", loader->url().host());
+ resourceObject->setString("path", loader->url().path());
+ resourceObject->setString("lastPathComponent", loader->url().lastPathComponent());
+ resourceObject->setString("type", "Document");
+ resourceObject->setObject("request", buildObjectForResourceRequest(loader->request()));
+ resourceObject->setObject("response", buildObjectForResourceResponse(loader->response()));
+ return resourceObject;
+}
+
+static String cachedResourceTypeString(const CachedResource& cachedResource)
+{
+ switch (cachedResource.type()) {
+ case CachedResource::ImageResource:
+ return "Image";
+ break;
+ case CachedResource::FontResource:
+ return "Font";
+ case CachedResource::CSSStyleSheet:
+ // Fall through.
+#if ENABLE(XSLT)
+ case CachedResource::XSLStyleSheet:
+#endif
+ return "Stylesheet";
+ case CachedResource::Script:
+ return "Script";
+ default:
+ return "Other";
+ }
+}
+
+static PassRefPtr<InspectorObject> buildObjectForCachedResource(const CachedResource& cachedResource)
+{
+ RefPtr<InspectorObject> resourceObject = InspectorObject::create();
+ resourceObject->setString("url", cachedResource.url());
+ resourceObject->setString("type", cachedResourceTypeString(cachedResource));
+ resourceObject->setNumber("encodedSize", cachedResource.encodedSize());
+ resourceObject->setObject("response", buildObjectForResourceResponse(cachedResource.response()));
+ return resourceObject;
+}
+
+static PassRefPtr<InspectorObject> buildObjectForFrameResources(Frame* frame)
+{
+ RefPtr<InspectorObject> frameResources = InspectorObject::create();
+ frameResources->setNumber("frameID", reinterpret_cast<uintptr_t>(frame));
+ frameResources->setObject("mainResource", buildObjectForMainResource(frame));
+ RefPtr<InspectorArray> subresources = InspectorArray::create();
+ frameResources->setArray("subresources", subresources);
+
+ const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources();
+ CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
+ for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
+ CachedResource* cachedResource = it->second.get();
+ if (cachedResource)
+ subresources->pushValue(buildObjectForCachedResource(*cachedResource));
+ }
+ return frameResources;
+}
+
+InspectorResourceAgent::~InspectorResourceAgent()
+{
+}
+
+void InspectorResourceAgent::identifierForInitialRequest(unsigned long identifier, const KURL& url, DocumentLoader* loader, bool isMainResource)
+{
+ m_frontend->identifierForInitialRequest(identifier, url.string(), reinterpret_cast<uintptr_t>(loader->frame()), isMainResource);
+}
+
+void InspectorResourceAgent::willSendRequest(unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+ m_frontend->willSendRequest(identifier, currentTime(), buildObjectForResourceRequest(request), buildObjectForResourceResponse(redirectResponse));
+}
+
+void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
+{
+ m_frontend->markResourceAsCached(identifier);
+}
+
+void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response)
+{
+ String type = "Other";
+ if (loader) {
+ if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->iconURL()))
+ type = "Image";
+ else {
+ CachedResource* cachedResource = InspectorResourceAgent::cachedResource(loader->frame(), response.url());
+ if (cachedResource)
+ type = cachedResourceTypeString(*cachedResource);
+
+ if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && type == "Other")
+ type = "Document";
+ }
+ }
+ m_frontend->didReceiveResponse(identifier, currentTime(), type, buildObjectForResourceResponse(response));
+}
+
+void InspectorResourceAgent::didReceiveContentLength(unsigned long identifier, int lengthReceived)
+{
+ m_frontend->didReceiveContentLength(identifier, currentTime(), lengthReceived);
+}
+
+void InspectorResourceAgent::didFinishLoading(unsigned long identifier, double finishTime)
+{
+ if (!finishTime)
+ finishTime = currentTime();
+
+ m_frontend->didFinishLoading(identifier, finishTime);
+}
+
+void InspectorResourceAgent::didFailLoading(unsigned long identifier, const ResourceError& error)
+{
+ m_frontend->didFailLoading(identifier, currentTime(), error.localizedDescription());
+}
+
+void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, const CachedResource* resource)
+{
+ Frame* frame = loader->frame();
+ m_frontend->didLoadResourceFromMemoryCache(currentTime(), reinterpret_cast<uintptr_t>(frame), buildObjectForCachedResource(*resource));
+}
+
+void InspectorResourceAgent::setOverrideContent(unsigned long identifier, const String& sourceString, InspectorResource::Type type)
+{
+ String typeString;
+ switch (type) {
+ case InspectorResource::XHR:
+ typeString = "XHR";
+ break;
+ case InspectorResource::Script:
+ typeString = "Script";
+ break;
+ default:
+ typeString = "Other";
+ }
+
+ m_frontend->setOverrideContent(identifier, sourceString, typeString);
+}
+
+void InspectorResourceAgent::didCommitLoad(DocumentLoader* loader)
+{
+ Frame* frame = loader->frame();
+ m_frontend->didCommitLoad(reinterpret_cast<uintptr_t>(frame));
+}
+
+void InspectorResourceAgent::frameDetachedFromParent(Frame* frame)
+{
+ m_frontend->frameDetachedFromParent(reinterpret_cast<uintptr_t>(frame));
+}
+
+
+#if ENABLE(WEB_SOCKETS)
+
+// FIXME: More this into the front-end?
+// Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
+static String createReadableStringFromBinary(const unsigned char* value, size_t length)
+{
+ ASSERT(length > 0);
+ static const char hexDigits[17] = "0123456789ABCDEF";
+ size_t bufferSize = length * 3 - 1;
+ StringBuffer buffer(bufferSize);
+ size_t index = 0;
+ for (size_t i = 0; i < length; ++i) {
+ if (i > 0)
+ buffer[index++] = ':';
+ buffer[index++] = hexDigits[value[i] >> 4];
+ buffer[index++] = hexDigits[value[i] & 0xF];
+ }
+ ASSERT(index == bufferSize);
+ return String::adopt(buffer);
+}
+
+void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL)
+{
+ m_frontend->didCreateWebSocket(identifier, requestURL.string());
+}
+
+void InspectorResourceAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
+{
+ RefPtr<InspectorObject> requestObject = InspectorObject::create();
+ requestObject->setObject("webSocketHeaderFields", buildObjectForHeaders(request.headerFields()));
+ requestObject->setString("webSocketRequestKey3", createReadableStringFromBinary(request.key3().value, sizeof(request.key3().value)));
+ m_frontend->willSendWebSocketHandshakeRequest(identifier, currentTime(), requestObject);
+}
+
+void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
+{
+ RefPtr<InspectorObject> responseObject = InspectorObject::create();
+ responseObject->setNumber("statusCode", response.statusCode());
+ responseObject->setString("statusText", response.statusText());
+ responseObject->setObject("webSocketHeaderFields", buildObjectForHeaders(response.headerFields()));
+ responseObject->setString("webSocketChallengeResponse", createReadableStringFromBinary(response.challengeResponse().value, sizeof(response.challengeResponse().value)));
+ m_frontend->didReceiveWebSocketHandshakeResponse(identifier, currentTime(), responseObject);
+}
+
+void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
+{
+ m_frontend->didCloseWebSocket(identifier, currentTime());
+}
+#endif // ENABLE(WEB_SOCKETS)
+
+void InspectorResourceAgent::cachedResources(RefPtr<InspectorArray>* resources)
+{
+ for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame()))
+ (*resources)->pushObject(buildObjectForFrameResources(frame));
+}
+
+void InspectorResourceAgent::resourceContent(unsigned long frameID, const String& url, String* content)
+{
+ RefPtr<InspectorArray> frameResources = InspectorArray::create();
+ for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame())) {
+ if (reinterpret_cast<uintptr_t>(frame) != frameID)
+ continue;
+ InspectorResourceAgent::resourceContent(frame, KURL(ParsedURLString, url), content);
+ break;
+ }
+}
+
+InspectorResourceAgent::InspectorResourceAgent(Page* page, InspectorFrontend* frontend)
+ : m_page(page)
+ , m_frontend(frontend)
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorResourceAgent.h b/WebCore/inspector/InspectorResourceAgent.h
new file mode 100644
index 0000000..f0bead8
--- /dev/null
+++ b/WebCore/inspector/InspectorResourceAgent.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 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 InspectorResourceAgent_h
+#define InspectorResourceAgent_h
+
+#include "InspectorResource.h"
+#include "PlatformString.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(INSPECTOR)
+
+namespace WTF {
+class String;
+}
+
+namespace WebCore {
+
+class CachedResource;
+class Document;
+class DocumentLoader;
+class InspectorArray;
+class InspectorObject;
+class InspectorFrontend;
+class KURL;
+class Page;
+class ResourceError;
+class ResourceRequest;
+class ResourceResponse;
+class SharedBuffer;
+
+#if ENABLE(WEB_SOCKETS)
+class WebSocketHandshakeRequest;
+class WebSocketHandshakeResponse;
+#endif
+
+class InspectorResourceAgent : public RefCounted<InspectorResourceAgent> {
+public:
+ static PassRefPtr<InspectorResourceAgent> create(Page* page, InspectorFrontend* frontend)
+ {
+ return adoptRef(new InspectorResourceAgent(page, frontend));
+ }
+
+ static bool resourceContent(Frame*, const KURL&, String* result);
+ static bool resourceContentBase64(Frame*, const KURL&, String* result);
+ static PassRefPtr<SharedBuffer> resourceData(Frame*, const KURL&, String* textEncodingName);
+ static CachedResource* cachedResource(Frame*, const KURL&);
+
+ ~InspectorResourceAgent();
+
+ void identifierForInitialRequest(unsigned long identifier, const KURL&, DocumentLoader*, bool isMainResource);
+ void willSendRequest(unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse);
+ void markResourceAsCached(unsigned long identifier);
+ void didReceiveResponse(unsigned long identifier, DocumentLoader* laoder, const ResourceResponse&);
+ void didReceiveContentLength(unsigned long identifier, int lengthReceived);
+ void didFinishLoading(unsigned long identifier, double finishTime);
+ void didFailLoading(unsigned long identifier, const ResourceError&);
+ void didLoadResourceFromMemoryCache(DocumentLoader*, const CachedResource*);
+ void setOverrideContent(unsigned long identifier, const String& sourceString, InspectorResource::Type);
+ void didCommitLoad(DocumentLoader*);
+ void frameDetachedFromParent(Frame*);
+
+#if ENABLE(WEB_SOCKETS)
+ void didCreateWebSocket(unsigned long identifier, const KURL& requestURL);
+ void willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest&);
+ void didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse&);
+ void didCloseWebSocket(unsigned long identifier);
+#endif
+
+ // Called from frontend
+ void cachedResources(RefPtr<InspectorArray>*);
+ void resourceContent(unsigned long frameID, const String& url, String* content);
+
+private:
+ InspectorResourceAgent(Page* page, InspectorFrontend* frontend);
+
+ Page* m_page;
+ InspectorFrontend* m_frontend;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
+
+#endif // !defined(InspectorResourceAgent_h)
diff --git a/WebCore/inspector/InspectorState.cpp b/WebCore/inspector/InspectorState.cpp
new file mode 100644
index 0000000..44065c0
--- /dev/null
+++ b/WebCore/inspector/InspectorState.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010 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 GOOGLE 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.
+ */
+
+#include "config.h"
+#include "InspectorState.h"
+
+#include "InspectorClient.h"
+#include "InspectorController.h"
+
+#if ENABLE(INSPECTOR)
+
+namespace WebCore {
+
+InspectorState::InspectorState(InspectorClient* client)
+ : m_client(client)
+{
+ registerBoolean(monitoringXHR, false, "monitoringXHR", "xhrMonitor");
+ registerBoolean(resourceTrackingEnabled, false, "resourceTrackingEnabled", (const char*)0);
+ registerBoolean(resourceTrackingAlwaysEnabled, false, (const char*)0, "resourceTrackingEnabled");
+ registerBoolean(timelineProfilerEnabled, false, "timelineProfilerEnabled", (const char*)0);
+ registerBoolean(searchingForNode, false, "searchingForNodeEnabled", (const char*)0);
+ registerBoolean(profilerAlwaysEnabled, false, (const char*)0, "profilerEnabled");
+ registerString(frontendSettings, "", (const char*)0, "frontendSettings");
+ registerBoolean(debuggerAlwaysEnabled, false, (const char*)0, "debuggerEnabled");
+ registerString(lastActivePanel, InspectorController::LastActivePanel, (const char*)0, "lastActivePanel");
+ registerBoolean(inspectorStartsAttached, true, (const char*)0, "InspectorStartsAttached");
+ registerLong(inspectorAttachedHeight, InspectorController::defaultAttachedHeight, (const char*)0, "inspectorAttachedHeight");
+ registerLong(pauseOnExceptionsState, 0, "pauseOnExceptionsState", (const char*)0);
+ registerBoolean(consoleMessagesEnabled, false, "consoleMessagesEnabled", (const char*)0);
+}
+
+void InspectorState::restoreFromInspectorCookie(const String& json)
+{
+ RefPtr<InspectorValue> jsonValue = InspectorValue::parseJSON(json);
+ if (!jsonValue)
+ return;
+
+ RefPtr<InspectorObject> jsonObject = jsonValue->asObject();
+ if (!jsonObject)
+ return;
+
+ for (InspectorObject::iterator i = jsonObject->begin(); i != jsonObject->end(); ++i) {
+ InspectorPropertyId id = (InspectorPropertyId)i->first.toInt();
+ ASSERT(id > 0 && id < lastPropertyId);
+ PropertyMap::iterator j = m_properties.find(id);
+ ASSERT(j != m_properties.end());
+ ASSERT(j->second.m_value->type() == i->second->type());
+ j->second.m_value = i->second;
+ }
+}
+
+PassRefPtr<InspectorObject> InspectorState::generateStateObjectForFrontend()
+{
+ RefPtr<InspectorObject> stateObject = InspectorObject::create();
+ for (PropertyMap::iterator i = m_properties.begin(); i != m_properties.end(); ++i) {
+ if (i->second.m_frontendAlias.length())
+ stateObject->setValue(i->second.m_frontendAlias, i->second.m_value);
+ }
+ return stateObject.release();
+}
+
+void InspectorState::loadFromSettings()
+{
+ for (PropertyMap::iterator i = m_properties.begin(); i != m_properties.end(); ++i) {
+ if (i->second.m_preferenceName.length()) {
+ String value;
+ m_client->populateSetting(i->second.m_preferenceName, &value);
+ switch (i->second.m_value->type()) {
+ case InspectorValue::TypeBoolean:
+ if (value.length())
+ i->second.m_value = InspectorBasicValue::create(value == "true");
+ break;
+ case InspectorValue::TypeString:
+ i->second.m_value = InspectorString::create(value);
+ break;
+ case InspectorValue::TypeNumber:
+ if (value.length())
+ i->second.m_value = InspectorBasicValue::create((double)value.toInt());
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ }
+ }
+}
+
+void InspectorState::updateCookie()
+{
+ RefPtr<InspectorObject> cookieObject = InspectorObject::create();
+ for (PropertyMap::iterator i = m_properties.begin(); i != m_properties.end(); ++i)
+ cookieObject->setValue(String::number(i->first), i->second.m_value);
+ m_client->updateInspectorStateCookie(cookieObject->toJSONString());
+}
+
+void InspectorState::setValue(InspectorPropertyId id, PassRefPtr<InspectorValue> value, const String& stringValue)
+{
+ PropertyMap::iterator i = m_properties.find(id);
+ ASSERT(i != m_properties.end());
+ i->second.m_value = value;
+ if (i->second.m_preferenceName.length())
+ m_client->storeSetting(i->second.m_preferenceName, stringValue);
+ updateCookie();
+}
+
+bool InspectorState::getBoolean(InspectorPropertyId id)
+{
+ PropertyMap::iterator i = m_properties.find(id);
+ ASSERT(i != m_properties.end());
+ bool value = false;
+ i->second.m_value->asBoolean(&value);
+ return value;
+}
+
+String InspectorState::getString(InspectorPropertyId id)
+{
+ PropertyMap::iterator i = m_properties.find(id);
+ ASSERT(i != m_properties.end());
+ String value;
+ i->second.m_value->asString(&value);
+ return value;
+}
+
+long InspectorState::getLong(InspectorPropertyId id)
+{
+ PropertyMap::iterator i = m_properties.find(id);
+ ASSERT(i != m_properties.end());
+ long value = 0;
+ i->second.m_value->asNumber(&value);
+ return value;
+}
+
+void InspectorState::registerBoolean(InspectorPropertyId propertyId, bool value, const String& frontendAlias, const String& preferenceName)
+{
+ m_properties.set(propertyId, Property::create(InspectorBasicValue::create(value), frontendAlias, preferenceName));
+}
+
+void InspectorState::registerString(InspectorPropertyId propertyId, const String& value, const String& frontendAlias, const String& preferenceName)
+{
+ m_properties.set(propertyId, Property::create(InspectorString::create(value), frontendAlias, preferenceName));
+}
+
+void InspectorState::registerLong(InspectorPropertyId propertyId, long value, const String& frontendAlias, const String& preferenceName)
+{
+ m_properties.set(propertyId, Property::create(InspectorBasicValue::create((double)value), frontendAlias, preferenceName));
+}
+
+InspectorState::Property InspectorState::Property::create(PassRefPtr<InspectorValue> value, const String& frontendAlias, const String& preferenceName)
+{
+ Property property;
+ property.m_value = value;
+ property.m_frontendAlias = frontendAlias;
+ property.m_preferenceName = preferenceName;
+ return property;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorState.h b/WebCore/inspector/InspectorState.h
new file mode 100644
index 0000000..5707600
--- /dev/null
+++ b/WebCore/inspector/InspectorState.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 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 GOOGLE 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.
+ */
+
+#ifndef InspectorState_h
+#define InspectorState_h
+
+#if ENABLE(INSPECTOR)
+
+#include "InspectorValues.h"
+#include "PlatformString.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class InspectorClient;
+
+class InspectorState {
+public:
+ enum InspectorPropertyId {
+ monitoringXHR = 1,
+ resourceTrackingEnabled,
+ resourceTrackingAlwaysEnabled,
+ timelineProfilerEnabled,
+ searchingForNode,
+ profilerAlwaysEnabled,
+ frontendSettings,
+ debuggerAlwaysEnabled,
+ lastActivePanel,
+ inspectorStartsAttached,
+ inspectorAttachedHeight,
+ pauseOnExceptionsState,
+ consoleMessagesEnabled,
+ lastPropertyId
+ };
+
+ InspectorState(InspectorClient* client);
+
+ PassRefPtr<InspectorObject> generateStateObjectForFrontend();
+ void restoreFromInspectorCookie(const String& jsonString);
+ void loadFromSettings();
+ String getFrontendAlias(InspectorPropertyId propertyId);
+
+ bool getBoolean(InspectorPropertyId propertyId);
+ String getString(InspectorPropertyId propertyId);
+ long getLong(InspectorPropertyId propertyId);
+
+ void setBoolean(InspectorPropertyId propertyId, bool value) { setValue(propertyId, InspectorBasicValue::create(value), value ? "true" : "false"); }
+ void setString(InspectorPropertyId propertyId, const String& value) { setValue(propertyId, InspectorString::create(value), value); }
+ void setLong(InspectorPropertyId propertyId, long value) { setValue(propertyId, InspectorBasicValue::create((double)value), String::number(value)); }
+
+private:
+ void updateCookie();
+ void setValue(InspectorPropertyId propertyId, PassRefPtr<InspectorValue> value, const String& stringValue);
+
+ struct Property {
+ static Property create(PassRefPtr<InspectorValue> value, const String& frontendAlias, const String& preferenceName);
+ String m_frontendAlias;
+ String m_preferenceName;
+ RefPtr<InspectorValue> m_value;
+ };
+ typedef HashMap<long, Property> PropertyMap;
+ PropertyMap m_properties;
+
+ void registerBoolean(InspectorPropertyId propertyId, bool value, const String& frontendAlias, const String& preferenceName);
+ void registerString(InspectorPropertyId propertyId, const String& value, const String& frontendAlias, const String& preferenceName);
+ void registerLong(InspectorPropertyId propertyId, long value, const String& frontendAlias, const String& preferenceName);
+
+ InspectorClient* m_client;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
+#endif // !defined(InspectorState_h)
diff --git a/WebCore/inspector/InspectorStyleSheet.cpp b/WebCore/inspector/InspectorStyleSheet.cpp
new file mode 100644
index 0000000..11cd649
--- /dev/null
+++ b/WebCore/inspector/InspectorStyleSheet.cpp
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "InspectorStyleSheet.h"
+
+#if ENABLE(INSPECTOR)
+
+#include "CSSParser.h"
+#include "CSSPropertySourceData.h"
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSelector.h"
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "Element.h"
+#include "HTMLHeadElement.h"
+#include "InspectorCSSAgent.h"
+#include "InspectorResourceAgent.h"
+#include "InspectorValues.h"
+#include "Node.h"
+#include "StyleSheetList.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+class ParsedStyleSheet {
+public:
+ typedef Vector<RefPtr<WebCore::CSSRuleSourceData> > SourceData;
+ ParsedStyleSheet();
+
+ WebCore::CSSStyleSheet* cssStyleSheet() const { return m_parserOutput; }
+ const String& text() const { return m_text; }
+ void setText(const String& text);
+ bool hasText() const { return m_hasText; }
+ SourceData* sourceData() const { return m_sourceData.get(); }
+ void setSourceData(PassOwnPtr<SourceData> sourceData);
+ bool hasSourceData() const { return m_sourceData; }
+ RefPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned index) const;
+
+private:
+
+ // StyleSheet constructed while parsing m_text.
+ WebCore::CSSStyleSheet* m_parserOutput;
+ String m_text;
+ bool m_hasText;
+ OwnPtr<SourceData> m_sourceData;
+};
+
+ParsedStyleSheet::ParsedStyleSheet()
+ : m_parserOutput(0)
+ , m_hasText(false)
+{
+}
+
+void ParsedStyleSheet::setText(const String& text)
+{
+ m_hasText = true;
+ m_text = text;
+ setSourceData(0);
+}
+
+void ParsedStyleSheet::setSourceData(PassOwnPtr<SourceData> sourceData)
+{
+ m_sourceData = sourceData;
+}
+
+RefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const
+{
+ if (!hasSourceData() || index >= m_sourceData->size())
+ return 0;
+
+ return m_sourceData->at(index);
+}
+
+namespace WebCore {
+
+InspectorStyleSheet::InspectorStyleSheet(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL)
+ : m_id(id)
+ , m_pageStyleSheet(pageStyleSheet)
+ , m_origin(origin)
+ , m_documentURL(documentURL)
+ , m_isRevalidating(false)
+{
+ m_parsedStyleSheet = new ParsedStyleSheet();
+}
+
+InspectorStyleSheet::~InspectorStyleSheet()
+{
+ delete m_parsedStyleSheet;
+}
+
+bool InspectorStyleSheet::setText(const String& text)
+{
+ if (!m_parsedStyleSheet)
+ return false;
+
+ m_parsedStyleSheet->setText(text);
+ for (unsigned i = 0, size = m_pageStyleSheet->length(); i < size; ++i)
+ m_pageStyleSheet->remove(i);
+
+ m_pageStyleSheet->parseString(text, m_pageStyleSheet->useStrictParsing());
+ return true;
+}
+
+bool InspectorStyleSheet::setRuleSelector(const String& ruleId, const String& selector)
+{
+ CSSStyleRule* rule = ruleForId(ruleId);
+ if (!rule)
+ return false;
+ CSSStyleSheet* styleSheet = InspectorCSSAgent::parentStyleSheet(rule);
+ if (!styleSheet || !ensureParsedDataReady())
+ return false;
+
+ rule->setSelectorText(selector);
+ RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style());
+ if (!sourceData)
+ return false;
+
+ const String& sheetText = m_parsedStyleSheet->text();
+ String newStyleSheetText = sheetText.substring(0, sourceData->selectorListRange.start);
+ newStyleSheetText += selector;
+ newStyleSheetText += sheetText.right(sheetText.length() - sourceData->selectorListRange.end);
+ m_parsedStyleSheet->setText(newStyleSheetText);
+ return true;
+}
+
+CSSStyleRule* InspectorStyleSheet::addRule(const String& selector)
+{
+ String text;
+ bool success = styleSheetText(&text);
+ if (!success)
+ return 0;
+
+ ExceptionCode ec = 0;
+ m_pageStyleSheet->addRule(selector, "", ec);
+ if (ec)
+ return 0;
+ RefPtr<CSSRuleList> rules = m_pageStyleSheet->cssRules();
+ ASSERT(rules->length());
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(rules->item(rules->length() - 1));
+ ASSERT(rule);
+
+ if (text.length())
+ text += "\n";
+
+ text += selector;
+ text += " {}";
+ m_parsedStyleSheet->setText(text);
+
+ return rule;
+}
+
+CSSStyleRule* InspectorStyleSheet::ruleForId(const String& id) const
+{
+ if (!m_pageStyleSheet)
+ return 0;
+
+ bool ok;
+ unsigned index = id.toUInt(&ok);
+ if (!ok)
+ return 0;
+
+ unsigned currentIndex = 0;
+ for (unsigned i = 0, size = m_pageStyleSheet->length(); i < size; ++i) {
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(m_pageStyleSheet->item(i));
+ if (!rule)
+ continue;
+ if (index == currentIndex)
+ return rule;
+
+ ++currentIndex;
+ }
+ return 0;
+}
+
+PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForStyleSheet()
+{
+ CSSStyleSheet* styleSheet = pageStyleSheet();
+ if (!styleSheet)
+ return 0;
+
+ RefPtr<InspectorObject> result = InspectorObject::create();
+ result->setString("id", id());
+ result->setBoolean("disabled", styleSheet->disabled());
+ result->setString("href", styleSheet->href());
+ result->setString("title", styleSheet->title());
+ RefPtr<CSSRuleList> cssRuleList = CSSRuleList::create(styleSheet, true);
+ RefPtr<InspectorArray> cssRules = buildArrayForRuleList(cssRuleList.get());
+ result->setArray("cssRules", cssRules.release());
+
+ String styleSheetText;
+ bool success = text(&styleSheetText);
+ if (success)
+ result->setString("text", styleSheetText);
+
+ return result.release();
+}
+
+PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule)
+{
+ CSSStyleSheet* styleSheet = pageStyleSheet();
+ if (!styleSheet)
+ return 0;
+
+ RefPtr<InspectorObject> result = InspectorObject::create();
+ result->setString("selectorText", rule->selectorText());
+ result->setString("cssText", rule->cssText());
+ result->setNumber("sourceLine", rule->sourceLine());
+ result->setString("documentURL", m_documentURL);
+
+ RefPtr<InspectorObject> parentStyleSheetValue = InspectorObject::create();
+ parentStyleSheetValue->setString("id", id());
+ parentStyleSheetValue->setString("href", styleSheet->href());
+ result->setObject("parentStyleSheet", parentStyleSheetValue.release());
+ result->setString("origin", m_origin);
+
+ RefPtr<CSSRuleSourceData> sourceData;
+ if (ensureParsedDataReady())
+ sourceData = ruleSourceDataFor(rule->style());
+ if (sourceData) {
+ result->setNumber("selectorStartOffset", sourceData->selectorListRange.start);
+ result->setNumber("selectorEndOffset", sourceData->selectorListRange.end);
+ }
+
+ result->setObject("style", buildObjectForStyle(rule->style()));
+ if (canBind())
+ result->setString("id", fullRuleId(rule));
+
+ return result.release();
+}
+
+PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style)
+{
+ RefPtr<CSSRuleSourceData> sourceData;
+ if (ensureParsedDataReady())
+ sourceData = ruleSourceDataFor(style);
+
+ RefPtr<InspectorObject> result = InspectorCSSAgent::buildObjectForStyle(style, fullStyleId(style), sourceData ? sourceData->styleSourceData.get() : 0);
+ result->setString("parentStyleSheetId", id());
+ return result.release();
+}
+
+CSSStyleDeclaration* InspectorStyleSheet::styleForId(const String& id) const
+{
+ CSSStyleRule* rule = ruleForId(id);
+ if (!rule)
+ return 0;
+
+ return rule->style();
+}
+
+bool InspectorStyleSheet::setStyleText(const String& styleId, const String& newText)
+{
+ CSSStyleDeclaration* style = styleForId(styleId);
+ if (!style)
+ return false;
+
+ return innerSetStyleText(style, newText);
+}
+
+Document* InspectorStyleSheet::ownerDocument() const
+{
+ return m_pageStyleSheet->document();
+}
+
+RefPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataFor(CSSStyleDeclaration* style) const
+{
+ return m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByStyle(style));
+}
+
+unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) const
+{
+ unsigned index = 0;
+ for (unsigned i = 0, size = m_pageStyleSheet->length(); i < size; ++i) {
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(m_pageStyleSheet->item(i));
+ if (!rule)
+ continue;
+ if (rule->style() == pageStyle)
+ return index;
+
+ ++index;
+ }
+ return UINT_MAX;
+}
+
+bool InspectorStyleSheet::ensureParsedDataReady()
+{
+ return ensureText() && ensureSourceData(pageStyleSheet()->ownerNode());
+}
+
+bool InspectorStyleSheet::text(String* result) const
+{
+ if (!ensureText())
+ return false;
+ *result = m_parsedStyleSheet->text();
+ return true;
+}
+
+bool InspectorStyleSheet::ensureText() const
+{
+ if (!m_parsedStyleSheet)
+ return false;
+ if (m_parsedStyleSheet->hasText())
+ return true;
+
+ String text;
+ bool success = styleSheetText(&text);
+ if (success)
+ m_parsedStyleSheet->setText(text);
+
+ return success;
+}
+
+bool InspectorStyleSheet::ensureSourceData(Node* ownerNode)
+{
+ if (m_parsedStyleSheet->hasSourceData())
+ return true;
+
+ if (!m_parsedStyleSheet->hasText())
+ return false;
+
+ RefPtr<CSSStyleSheet> newStyleSheet = CSSStyleSheet::create(ownerNode);
+ CSSParser p;
+ StyleRuleRangeMap ruleRangeMap;
+ p.parseSheet(newStyleSheet.get(), m_parsedStyleSheet->text(), 0, &ruleRangeMap);
+ OwnPtr<ParsedStyleSheet::SourceData> rangesVector(new ParsedStyleSheet::SourceData());
+
+ for (unsigned i = 0, length = newStyleSheet->length(); i < length; ++i) {
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(newStyleSheet->item(i));
+ if (!rule)
+ continue;
+ StyleRuleRangeMap::iterator it = ruleRangeMap.find(rule);
+ if (it != ruleRangeMap.end())
+ rangesVector->append(it->second);
+ }
+
+ m_parsedStyleSheet->setSourceData(rangesVector.release());
+ return m_parsedStyleSheet->hasSourceData();
+}
+
+void InspectorStyleSheet::innerSetStyleSheetText(const String& newText)
+{
+ m_parsedStyleSheet->setText(newText);
+}
+
+bool InspectorStyleSheet::innerSetStyleText(CSSStyleDeclaration* style, const String& text)
+{
+ if (!pageStyleSheet())
+ return false;
+ if (!ensureParsedDataReady())
+ return false;
+
+ String patchedStyleSheetText;
+ bool success = styleSheetTextWithChangedStyle(style, text, &patchedStyleSheetText);
+ if (!success)
+ return false;
+
+ String id = ruleOrStyleId(style);
+ if (id.isEmpty())
+ return false;
+
+ ExceptionCode ec = 0;
+ style->setCssText(text, ec);
+ if (!ec)
+ innerSetStyleSheetText(patchedStyleSheetText);
+
+ return !ec;
+}
+
+bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* style, const String& newStyleText, String* result)
+{
+ if (!style)
+ return false;
+
+ if (!ensureParsedDataReady())
+ return false;
+
+ RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(style);
+ unsigned bodyStart = sourceData->styleSourceData->styleBodyRange.start;
+ unsigned bodyEnd = sourceData->styleSourceData->styleBodyRange.end;
+ ASSERT(bodyStart <= bodyEnd);
+
+ String text = m_parsedStyleSheet->text();
+ ASSERT(bodyEnd <= text.length()); // bodyEnd is exclusive
+
+ String patchedText = text.substring(0, bodyStart);
+ patchedText += newStyleText;
+ patchedText += text.substring(bodyEnd, text.length());
+ *result = patchedText;
+ return true;
+}
+
+CSSStyleRule* InspectorStyleSheet::findPageRuleWithStyle(CSSStyleDeclaration* style)
+{
+ for (unsigned i = 0, size = m_pageStyleSheet->length(); i < size; ++i) {
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(m_pageStyleSheet->item(i));
+ if (!rule)
+ continue;
+ if (rule->style() == style)
+ return rule;
+ }
+ return 0;
+}
+
+String InspectorStyleSheet::fullRuleId(CSSStyleRule* rule) const
+{
+ return fullRuleOrStyleId(rule->style());
+}
+
+void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle)
+{
+ if (m_isRevalidating)
+ return;
+
+ m_isRevalidating = true;
+ CSSStyleSheet* parsedSheet = m_parsedStyleSheet->cssStyleSheet();
+ for (unsigned i = 0, size = parsedSheet->length(); i < size; ++i) {
+ StyleBase* styleBase = parsedSheet->item(i);
+ CSSStyleRule* parsedRule = InspectorCSSAgent::asCSSStyleRule(styleBase);
+ if (!parsedRule)
+ continue;
+ if (parsedRule->style() == pageStyle) {
+ if (parsedRule->style()->cssText() != pageStyle->cssText())
+ innerSetStyleText(pageStyle, pageStyle->cssText());
+ break;
+ }
+ }
+ m_isRevalidating = false;
+}
+
+bool InspectorStyleSheet::styleSheetText(String* result) const
+{
+ String text;
+ bool success = inlineStyleSheetText(&text);
+ if (!success)
+ success = resourceStyleSheetText(&text);
+ if (success)
+ *result = text;
+ return success;
+}
+
+bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
+{
+ if (!m_pageStyleSheet)
+ return false;
+
+ return InspectorResourceAgent::resourceContent(ownerDocument()->frame(), m_pageStyleSheet->finalURL(), result);
+}
+
+bool InspectorStyleSheet::inlineStyleSheetText(String* result) const
+{
+ if (!m_pageStyleSheet)
+ return false;
+
+ Node* ownerNode = m_pageStyleSheet->ownerNode();
+ if (!ownerNode || ownerNode->nodeType() != Node::ELEMENT_NODE)
+ return false;
+ Element* ownerElement = static_cast<Element*>(ownerNode);
+ if (ownerElement->tagName().lower() != "style")
+ return false;
+ *result = ownerElement->innerText();
+ return true;
+}
+
+PassRefPtr<InspectorArray> InspectorStyleSheet::buildArrayForRuleList(CSSRuleList* ruleList)
+{
+ RefPtr<InspectorArray> result = InspectorArray::create();
+ if (!ruleList)
+ return result.release();
+
+ for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
+ CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(ruleList->item(i));
+ if (!rule)
+ continue;
+
+ result->pushObject(buildObjectForRule(rule));
+ }
+ return result.release();
+}
+
+
+InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const String& id, Element* element, const String& origin)
+ : InspectorStyleSheet(id, 0, origin, "")
+ , m_element(element)
+ , m_ruleSourceData(0)
+{
+ ASSERT(element);
+}
+
+bool InspectorStyleSheetForInlineStyle::setStyleText(const String& styleId, const String& text)
+{
+ ASSERT(styleId == "0");
+ UNUSED_PARAM(styleId);
+ ExceptionCode ec = 0;
+ m_element->setAttribute("style", text, ec);
+ m_ruleSourceData.clear();
+ return !ec;
+}
+
+Document* InspectorStyleSheetForInlineStyle::ownerDocument() const
+{
+ return m_element->document();
+}
+
+bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
+{
+ if (m_ruleSourceData)
+ return true;
+
+ m_ruleSourceData = CSSRuleSourceData::create();
+ RefPtr<CSSStyleSourceData> sourceData = CSSStyleSourceData::create();
+ bool success = getStyleAttributeRanges(&sourceData);
+ if (!success)
+ return false;
+
+ m_ruleSourceData->styleSourceData = sourceData.release();
+ return true;
+}
+
+CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
+{
+ return m_element->style();
+}
+
+bool InspectorStyleSheetForInlineStyle::getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result)
+{
+ DEFINE_STATIC_LOCAL(String, styleAttributeName, ("style"));
+
+ if (!m_element->isStyledElement())
+ return false;
+
+ String styleText = static_cast<StyledElement*>(m_element)->getAttribute(styleAttributeName);
+ if (styleText.isEmpty()) {
+ (*result)->styleBodyRange.start = 0;
+ (*result)->styleBodyRange.end = 0;
+ return true;
+ }
+
+ RefPtr<CSSMutableStyleDeclaration> tempDeclaration = CSSMutableStyleDeclaration::create();
+ CSSParser p;
+ p.parseDeclaration(tempDeclaration.get(), styleText, result);
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorStyleSheet.h b/WebCore/inspector/InspectorStyleSheet.h
new file mode 100644
index 0000000..38ab777
--- /dev/null
+++ b/WebCore/inspector/InspectorStyleSheet.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#ifndef InspectorStyleSheet_h
+#define InspectorStyleSheet_h
+
+#include "CSSPropertySourceData.h"
+#include "Document.h"
+#include "InspectorValues.h"
+#include "PlatformString.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/UnusedParam.h>
+
+class ParsedStyleSheet;
+
+namespace WebCore {
+
+class CSSRuleList;
+class CSSStyleDeclaration;
+class Element;
+class Node;
+
+#if ENABLE(INSPECTOR)
+
+class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> {
+public:
+ static PassRefPtr<InspectorStyleSheet> create(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL)
+ {
+ return adoptRef(new InspectorStyleSheet(id, pageStyleSheet, origin, documentURL));
+ }
+
+ InspectorStyleSheet(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL);
+ virtual ~InspectorStyleSheet();
+
+ const String& id() const { return m_id; }
+ CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet; }
+ bool setText(const String&);
+ bool setRuleSelector(const String& ruleId, const String& selector);
+ CSSStyleRule* addRule(const String& selector);
+ CSSStyleRule* ruleForId(const String&) const;
+ PassRefPtr<InspectorObject> buildObjectForStyleSheet();
+ PassRefPtr<InspectorObject> buildObjectForRule(CSSStyleRule*);
+ PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*);
+ virtual CSSStyleDeclaration* styleForId(const String&) const;
+ virtual bool setStyleText(const String& styleId, const String& text);
+
+protected:
+ bool canBind() const { return m_origin != "userAgent" && m_origin != "user"; }
+ String fullRuleOrStyleId(CSSStyleDeclaration* style) const { return id() + ":" + ruleOrStyleId(style); }
+ String ruleOrStyleId(CSSStyleDeclaration* style) const { unsigned index = ruleIndexByStyle(style); return index == UINT_MAX ? "" : String::number(index); }
+ virtual Document* ownerDocument() const;
+ virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const;
+ virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
+ virtual bool ensureParsedDataReady();
+
+private:
+ bool text(String* result) const;
+ bool ensureText() const;
+ bool ensureSourceData(Node* ownerNode);
+ void innerSetStyleSheetText(const String& newText);
+ bool innerSetStyleText(CSSStyleDeclaration*, const String&);
+ bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result);
+ CSSStyleRule* findPageRuleWithStyle(CSSStyleDeclaration*);
+ String fullRuleId(CSSStyleRule* rule) const;
+ String fullStyleId(CSSStyleDeclaration* style) const { return fullRuleOrStyleId(style); }
+ void revalidateStyle(CSSStyleDeclaration*);
+ bool styleSheetText(String* result) const;
+ bool resourceStyleSheetText(String* result) const;
+ bool inlineStyleSheetText(String* result) const;
+ PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList*);
+
+ String m_id;
+ CSSStyleSheet* m_pageStyleSheet;
+ String m_origin;
+ String m_documentURL;
+ bool m_isRevalidating;
+ ParsedStyleSheet* m_parsedStyleSheet;
+};
+
+class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet {
+public:
+ static PassRefPtr<InspectorStyleSheetForInlineStyle> create(const String& id, Element* element, const String& origin)
+ {
+ return adoptRef(new InspectorStyleSheetForInlineStyle(id, element, origin));
+ }
+
+ InspectorStyleSheetForInlineStyle(const String& id, Element* element, const String& origin);
+ virtual CSSStyleDeclaration* styleForId(const String& id) const { ASSERT(id == "0"); UNUSED_PARAM(id); return inlineStyle(); }
+ virtual bool setStyleText(const String& styleId, const String& text);
+
+protected:
+ virtual Document* ownerDocument() const;
+ virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT(style == inlineStyle()); UNUSED_PARAM(style); return m_ruleSourceData; }
+ virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; }
+ virtual bool ensureParsedDataReady();
+
+private:
+ CSSStyleDeclaration* inlineStyle() const;
+ bool getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result);
+
+ Element* m_element;
+ RefPtr<CSSRuleSourceData> m_ruleSourceData;
+};
+
+#endif
+
+} // namespace WebCore
+
+#endif // !defined(InspectorStyleSheet_h)
diff --git a/WebCore/inspector/InspectorTimelineAgent.cpp b/WebCore/inspector/InspectorTimelineAgent.cpp
index fbb17c4..645b692 100644
--- a/WebCore/inspector/InspectorTimelineAgent.cpp
+++ b/WebCore/inspector/InspectorTimelineAgent.cpp
@@ -44,12 +44,12 @@
namespace WebCore {
-int InspectorTimelineAgent::s_instanceCount = 0;
+int InspectorTimelineAgent::s_id = 0;
InspectorTimelineAgent::InspectorTimelineAgent(InspectorFrontend* frontend)
: m_frontend(frontend)
+ , m_id(++s_id)
{
- ++s_instanceCount;
ScriptGCEvent::addEventListener(this);
ASSERT(m_frontend);
}
@@ -76,8 +76,6 @@ void InspectorTimelineAgent::didGC(double startTime, double endTime, size_t coll
InspectorTimelineAgent::~InspectorTimelineAgent()
{
- ASSERT(s_instanceCount);
- --s_instanceCount;
ScriptGCEvent::removeEventListener(this);
}
@@ -242,10 +240,11 @@ void InspectorTimelineAgent::didReceiveResourceResponse()
didCompleteCurrentRecord(ResourceReceiveResponseTimelineRecordType);
}
-void InspectorTimelineAgent::didFinishLoadingResource(unsigned long identifier, bool didFail)
+void InspectorTimelineAgent::didFinishLoadingResource(unsigned long identifier, bool didFail, double finishTime)
{
pushGCEventRecords();
- RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(WTF::currentTimeMS());
+ // Sometimes network stack can provide for us exact finish loading time. In the other case we will use currentTime.
+ RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(finishTime ? finishTime * 1000 : WTF::currentTimeMS());
record->setObject("data", TimelineRecordFactory::createResourceFinishData(identifier, didFail));
record->setNumber("type", ResourceFinishTimelineRecordType);
setHeapSizeStatistic(record.get());
diff --git a/WebCore/inspector/InspectorTimelineAgent.h b/WebCore/inspector/InspectorTimelineAgent.h
index 6b3324b..bc1e027 100644
--- a/WebCore/inspector/InspectorTimelineAgent.h
+++ b/WebCore/inspector/InspectorTimelineAgent.h
@@ -33,9 +33,7 @@
#if ENABLE(INSPECTOR)
-#include "Document.h"
#include "InspectorValues.h"
-#include "ScriptExecutionContext.h"
#include "ScriptGCEvent.h"
#include "ScriptGCEventListener.h"
#include <wtf/Vector.h>
@@ -77,6 +75,8 @@ public:
InspectorTimelineAgent(InspectorFrontend* frontend);
~InspectorTimelineAgent();
+ int id() const { return m_id; }
+
void reset();
void resetFrontendProxyObject(InspectorFrontend*);
@@ -122,15 +122,12 @@ public:
void willSendResourceRequest(unsigned long, bool isMainResource, const ResourceRequest&);
void willReceiveResourceResponse(unsigned long, const ResourceResponse&);
void didReceiveResourceResponse();
- void didFinishLoadingResource(unsigned long, bool didFail);
+ void didFinishLoadingResource(unsigned long, bool didFail, double finishTime);
void willReceiveResourceData(unsigned long identifier);
void didReceiveResourceData();
virtual void didGC(double, double, size_t);
- static int instanceCount() { return s_instanceCount; }
- static InspectorTimelineAgent* retrieve(ScriptExecutionContext*);
-
private:
struct TimelineRecordEntry {
TimelineRecordEntry(PassRefPtr<InspectorObject> record, PassRefPtr<InspectorObject> data, PassRefPtr<InspectorArray> children, TimelineRecordType type)
@@ -155,7 +152,9 @@ private:
InspectorFrontend* m_frontend;
Vector<TimelineRecordEntry> m_recordStack;
- static int s_instanceCount;
+
+ static int s_id;
+ const int m_id;
struct GCEvent {
GCEvent(double startTime, double endTime, size_t collectedBytes)
: startTime(startTime), endTime(endTime), collectedBytes(collectedBytes)
@@ -169,13 +168,6 @@ private:
GCEvents m_gcEvents;
};
-inline InspectorTimelineAgent* InspectorTimelineAgent::retrieve(ScriptExecutionContext* context)
-{
- if (context && context->isDocument())
- return static_cast<Document*>(context)->inspectorTimelineAgent();
- return 0;
-}
-
} // namespace WebCore
#endif // !ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorValues.cpp b/WebCore/inspector/InspectorValues.cpp
index c96e953..89e9b7c 100644
--- a/WebCore/inspector/InspectorValues.cpp
+++ b/WebCore/inspector/InspectorValues.cpp
@@ -33,6 +33,8 @@
#if ENABLE(INSPECTOR)
+#include <wtf/DecimalNumber.h>
+
namespace WebCore {
namespace {
@@ -604,9 +606,9 @@ void InspectorBasicValue::writeJSON(Vector<UChar>* output) const
else
output->append(falseString, 5);
} else if (type() == TypeNumber) {
- String value = String::format("%f", m_doubleValue);
- value.replace(',', '.');
- output->append(value.characters(), value.length());
+ NumberToStringBuffer buffer;
+ unsigned length = DecimalNumber(m_doubleValue).toStringDecimal(buffer, WTF::NumberToStringBufferLength);
+ output->append(buffer, length);
}
}
@@ -622,6 +624,10 @@ void InspectorString::writeJSON(Vector<UChar>* output) const
doubleQuoteString(m_stringValue, output);
}
+InspectorObject::~InspectorObject()
+{
+}
+
bool InspectorObject::asObject(RefPtr<InspectorObject>* output)
{
*output = this;
@@ -696,6 +702,17 @@ void InspectorObject::writeJSON(Vector<UChar>* output) const
output->append('}');
}
+InspectorObject::InspectorObject()
+ : InspectorValue(TypeObject)
+ , m_data()
+ , m_order()
+{
+}
+
+InspectorArray::~InspectorArray()
+{
+}
+
bool InspectorArray::asArray(RefPtr<InspectorArray>* output)
{
*output = this;
@@ -718,6 +735,12 @@ void InspectorArray::writeJSON(Vector<UChar>* output) const
output->append(']');
}
+InspectorArray::InspectorArray()
+ : InspectorValue(TypeArray)
+ , m_data()
+{
+}
+
PassRefPtr<InspectorValue> InspectorArray::get(size_t index)
{
ASSERT(index < m_data.size());
diff --git a/WebCore/inspector/InspectorValues.h b/WebCore/inspector/InspectorValues.h
index 4036f55..391372e 100644
--- a/WebCore/inspector/InspectorValues.h
+++ b/WebCore/inspector/InspectorValues.h
@@ -166,7 +166,7 @@ public:
{
return adoptRef(new InspectorObject());
}
- ~InspectorObject() { }
+ ~InspectorObject();
virtual bool asObject(RefPtr<InspectorObject>* output);
virtual PassRefPtr<InspectorObject> asObject();
@@ -194,7 +194,7 @@ public:
const_iterator end() const { return m_data.end(); }
private:
- InspectorObject() : InspectorValue(TypeObject) { }
+ InspectorObject();
Dictionary m_data;
Vector<String> m_order;
};
@@ -205,7 +205,7 @@ public:
{
return adoptRef(new InspectorArray());
}
- ~InspectorArray() { }
+ ~InspectorArray();
virtual bool asArray(RefPtr<InspectorArray>* output);
virtual PassRefPtr<InspectorArray> asArray();
@@ -223,7 +223,7 @@ public:
virtual void writeJSON(Vector<UChar>* output) const;
private:
- InspectorArray() : InspectorValue(TypeArray) { }
+ InspectorArray();
Vector<RefPtr<InspectorValue> > m_data;
};
diff --git a/WebCore/inspector/front-end/AuditRules.js b/WebCore/inspector/front-end/AuditRules.js
index a72de56..cd9f13e 100644
--- a/WebCore/inspector/front-end/AuditRules.js
+++ b/WebCore/inspector/front-end/AuditRules.js
@@ -42,17 +42,17 @@ WebInspector.AuditRules.CacheableResponseCodes =
304: true // Underlying resource is cacheable
}
-WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, regexp, needFullResources)
+WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, needFullResources)
{
var domainToResourcesMap = {};
for (var i = 0, size = resources.length; i < size; ++i) {
var resource = resources[i];
if (types && types.indexOf(resource.type) === -1)
continue;
- var match = resource.url.match(regexp);
- if (!match)
+ var parsedURL = resource.url.asParsedURL();
+ if (!parsedURL)
continue;
- var domain = match[2];
+ var domain = parsedURL.host;
var domainResources = domainToResourcesMap[domain];
if (domainResources === undefined) {
domainResources = [];
@@ -128,7 +128,7 @@ WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type,
WebInspector.AuditRules.CombineExternalResourcesRule.prototype = {
doRun: function(resources, result, callback)
{
- var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type], WebInspector.URLRegExp);
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type]);
var penalizedResourceCount = 0;
// TODO: refactor according to the chosen i18n approach
var summary = result.addChild("", true);
@@ -175,14 +175,14 @@ WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = {
doRun: function(resources, result, callback)
{
var summary = result.addChild("");
- var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined, WebInspector.URLRegExp);
+ var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined);
for (var domain in domainToResourcesMap) {
if (domainToResourcesMap[domain].length > 1)
continue;
- var match = domain.match(WebInspector.URLRegExp);
- if (!match)
+ var parsedURL = domain.asParsedURL();
+ if (!parsedURL)
continue;
- if (!match[2].search(WebInspector.AuditRules.IPAddressRegexp))
+ if (!parsedURL.host.search(WebInspector.AuditRules.IPAddressRegexp))
continue; // an IP address
summary.addSnippet(match[2]);
result.violationCount++;
@@ -220,7 +220,6 @@ WebInspector.AuditRules.ParallelizeDownloadRule.prototype = {
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(
resources,
[WebInspector.Resource.Type.Stylesheet, WebInspector.Resource.Type.Image],
- WebInspector.URLRegExp,
true);
var hosts = [];
@@ -647,7 +646,7 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
const node = WebInspector.domAgent.nodeForId(imageId);
var src = node.getAttribute("src");
- if (!WebInspector.URLRegExp.test(src)) {
+ if (!src.asParsedURL()) {
for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
if (frameOwnerCandidate.documentURL) {
var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src);
@@ -934,7 +933,6 @@ WebInspector.AuditRules.CookieSizeRule.prototype = {
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
null,
- WebInspector.URLRegExp,
true);
var matchingResourceData = {};
this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this));
@@ -998,7 +996,6 @@ WebInspector.AuditRules.StaticCookielessRule.prototype = {
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
[WebInspector.Resource.Type.Stylesheet,
WebInspector.Resource.Type.Image],
- WebInspector.URLRegExp,
true);
var totalStaticResources = 0;
for (var domain in domainToResourcesMap)
diff --git a/WebCore/inspector/front-end/BreakpointManager.js b/WebCore/inspector/front-end/BreakpointManager.js
index ec4e7cf..77ba89d 100644
--- a/WebCore/inspector/front-end/BreakpointManager.js
+++ b/WebCore/inspector/front-end/BreakpointManager.js
@@ -27,7 +27,8 @@
WebInspector.BreakpointManager = function()
{
this._breakpoints = {};
- this._xhrBreakpoints = {};
+ this._nativeBreakpoints = {};
+ this._domBreakpoints = {};
}
WebInspector.BreakpointManager.prototype = {
@@ -87,6 +88,7 @@ WebInspector.BreakpointManager.prototype = {
{
this._breakpoints = {};
delete this._oneTimeBreakpoint;
+ this._nativeBreakpoints = {};
},
_setBreakpoint: function(sourceID, url, line, enabled, condition)
@@ -127,20 +129,144 @@ WebInspector.BreakpointManager.prototype = {
InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition, didSetBreakpoint.bind(this));
},
- createXHRBreakpoint: function(url)
+ createDOMBreakpoint: function(nodeId, domEventType, disabled)
{
- if (url in this._xhrBreakpoints)
+ var frontendId = "dom:" + nodeId + ":" + domEventType;
+ if (frontendId in this._nativeBreakpoints)
return;
- this._xhrBreakpoints[url] = true;
- var breakpoint = new WebInspector.XHRBreakpoint(url);
- breakpoint.addEventListener("removed", this._xhrBreakpointRemoved.bind(this));
+ var breakpoint = new WebInspector.DOMBreakpoint(this, frontendId, nodeId, domEventType);
+ this._nativeBreakpoints[frontendId] = breakpoint;
+ this._domBreakpoints[frontendId] = breakpoint;
+ this.dispatchEventToListeners("dom-breakpoint-added", breakpoint);
+ breakpoint.enabled = !disabled;
+ return breakpoint;
+ },
+
+ createEventListenerBreakpoint: function(eventName, disabled)
+ {
+ var frontendId = eventName;
+ if (frontendId in this._nativeBreakpoints)
+ return;
+
+ var breakpoint = new WebInspector.EventListenerBreakpoint(this, frontendId, eventName);
+ this._nativeBreakpoints[frontendId] = breakpoint;
+ breakpoint.enabled = !disabled;
+ return breakpoint;
+ },
+
+ createXHRBreakpoint: function(url, disabled)
+ {
+ var frontendId = url;
+ if (frontendId in this._nativeBreakpoints)
+ return;
+
+ var breakpoint = new WebInspector.XHRBreakpoint(this, frontendId, url);
+ this._nativeBreakpoints[frontendId] = breakpoint;
this.dispatchEventToListeners("xhr-breakpoint-added", breakpoint);
+ breakpoint.enabled = !disabled
+ return breakpoint;
},
- _xhrBreakpointRemoved: function(event)
+ _removeNativeBreakpoint: function(breakpoint)
{
- delete this._xhrBreakpoints[event.target.url];
+ if (breakpoint._beingSetOnBackend)
+ return;
+ if (breakpoint.enabled)
+ this._removeNativeBreakpointFromBackend(breakpoint);
+ delete this._nativeBreakpoints[breakpoint._frontendId];
+ if (breakpoint._type === "DOM")
+ delete this._domBreakpoints[breakpoint._frontendId];
+ breakpoint.dispatchEventToListeners("removed");
+ },
+
+ _setNativeBreakpointEnabled: function(breakpoint, enabled)
+ {
+ if (breakpoint._beingSetOnBackend)
+ return;
+ if (breakpoint.enabled === enabled)
+ return;
+ if (enabled)
+ this._setNativeBreakpointOnBackend(breakpoint);
+ else
+ this._removeNativeBreakpointFromBackend(breakpoint);
+ },
+
+ _setNativeBreakpointOnBackend: function(breakpoint)
+ {
+ breakpoint._beingSetOnBackend = true;
+ var data = { type: breakpoint._type, condition: breakpoint._condition() };
+ InspectorBackend.setNativeBreakpoint(data, didSetNativeBreakpoint.bind(this));
+
+ function didSetNativeBreakpoint(backendBreakpointId)
+ {
+ breakpoint._beingSetOnBackend = false;
+ if (backendBreakpointId !== "") {
+ breakpoint._backendId = backendBreakpointId;
+ this._breakpoints[backendBreakpointId] = breakpoint;
+ }
+ breakpoint.dispatchEventToListeners("enable-changed");
+ }
+ },
+
+ _removeNativeBreakpointFromBackend: function(breakpoint)
+ {
+ InspectorBackend.removeNativeBreakpoint(breakpoint._backendId);
+ delete this._breakpoints[breakpoint._backendId]
+ delete breakpoint._backendId;
+ breakpoint.dispatchEventToListeners("enable-changed");
+ },
+
+ debuggerPaused: function(details)
+ {
+ if (details.eventType !== WebInspector.DebuggerEventTypes.NativeBreakpoint)
+ return;
+
+ var breakpoint = this._breakpoints[details.eventData.breakpointId];
+ if (!breakpoint)
+ return;
+
+ breakpoint.hit = true;
+ breakpoint.dispatchEventToListeners("hit-state-changed");
+ this._lastHitBreakpoint = breakpoint;
+
+ this.dispatchEventToListeners("breakpoint-hit", { breakpoint: breakpoint, eventData: details.eventData });
+ },
+
+ debuggerResumed: function()
+ {
+ if (!this._lastHitBreakpoint)
+ return;
+ this._lastHitBreakpoint.hit = false;
+ this._lastHitBreakpoint.dispatchEventToListeners("hit-state-changed");
+ delete this._lastHitBreakpoint;
+ },
+
+ restoreDOMBreakpoints: function()
+ {
+ var domBreakpoints = this._domBreakpoints;
+ this._domBreakpoints = {};
+
+ var breakpointsToRestore = {};
+ for (var frontendId in domBreakpoints) {
+ var breakpoint = domBreakpoints[frontendId];
+ var path = breakpoint._path;
+ if (!path)
+ continue;
+ if (!breakpointsToRestore[path]) {
+ breakpointsToRestore[path] = [];
+ InspectorBackend.pushNodeByPathToFrontend(path, restoreBreakpointsForNode.bind(this, breakpointsToRestore[path]));
+ }
+ breakpointsToRestore[path].push(breakpoint);
+ }
+
+ function restoreBreakpointsForNode(breakpoints, nodeId)
+ {
+ if (!nodeId)
+ return;
+ for (var i = 0; i < breakpoints.length; ++i)
+ this.createDOMBreakpoint(nodeId, breakpoints[i]._domEventType, !breakpoints[i].enabled);
+ }
}
}
@@ -226,82 +352,237 @@ WebInspector.Breakpoint.prototype = {
WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype;
-WebInspector.XHRBreakpoint = function(url)
+WebInspector.NativeBreakpoint = function(manager, frontendId, type)
{
- this._url = url;
- this._locked = false;
- this.enabled = true;
+ this._manager = manager;
+ this.__frontendId = frontendId;
+ this.__type = type;
}
-WebInspector.XHRBreakpoint.prototype = {
+WebInspector.NativeBreakpoint.prototype = {
get enabled()
{
- return "_id" in this;
+ return "_backendId" in this;
},
set enabled(enabled)
{
- if (this._locked)
- return;
- if (this.enabled === enabled)
- return;
- if (enabled)
- this._setOnBackend();
- else
- this._removeFromBackend();
+ this._manager._setNativeBreakpointEnabled(this, enabled);
},
- get url()
+ remove: function()
{
- return this._url;
+ this._manager._removeNativeBreakpoint(this);
+ this._onRemove();
},
- formatLabel: function()
+ get _frontendId()
{
- var label = "";
- if (!this.url.length)
- label = WebInspector.UIString("Any XHR");
- else
- label = WebInspector.UIString("URL contains \"%s\"", this.url);
- return label;
+ return this.__frontendId;
},
- compareTo: function(other)
+ get _type()
{
- if (this.url != other.url)
- return this.url < other.url ? -1 : 1;
+ return this.__type;
+ },
+
+ _compare: function(x, y)
+ {
+ if (x !== y)
+ return x < y ? -1 : 1;
return 0;
},
- remove: function()
+ _onRemove: function()
{
- if (this._locked)
- return;
- if (this.enabled)
- this._removeFromBackend();
- this.dispatchEventToListeners("removed");
+ }
+}
+
+WebInspector.NativeBreakpoint.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DOMBreakpoint = function(manager, frontendId, nodeId, domEventType)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "DOM");
+ this._nodeId = nodeId;
+ this._domEventType = domEventType;
+
+ var node = WebInspector.domAgent.nodeForId(this._nodeId);
+ if (node) {
+ node.breakpoints[this._domEventType] = this;
+ this._path = node.path();
+ }
+}
+
+WebInspector.DOMBreakpoint.prototype = {
+ click: function()
+ {
+ WebInspector.updateFocusedNode(this._nodeId);
},
- _setOnBackend: function()
+ compareTo: function(other)
{
- this._locked = true;
- var data = { type: "XHR", condition: { url: this.url } };
- InspectorBackend.setNativeBreakpoint(data, didSet.bind(this));
+ return this._compare(this._domEventType, other._domEventType);
+ },
- function didSet(breakpointId)
+ populateLabelElement: function(element)
+ {
+ element.appendChild(WebInspector.panels.elements.linkifyNodeById(this._nodeId));
+ element.appendChild(document.createTextNode(" - "));
+ element.appendChild(document.createTextNode(WebInspector.domBreakpointTypeLabel(this._domEventType)));
+ },
+
+ populateStatusMessageElement: function(element, eventData)
+ {
+ var substitutions = [WebInspector.domBreakpointTypeLabel(this._domEventType), WebInspector.panels.elements.linkifyNodeById(this._nodeId)];
+ var formatters = {
+ s: function(substitution)
+ {
+ return substitution;
+ }
+ };
+ function append(a, b)
{
- this._locked = false;
- this._id = breakpointId;
- this.dispatchEventToListeners("enable-changed");
+ if (typeof b === "string")
+ b = document.createTextNode(b);
+ element.appendChild(b);
}
+ if (this._domEventType === 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);
},
- _removeFromBackend: function()
+ _condition: function()
{
- InspectorBackend.removeNativeBreakpoint(this._id);
- delete this._id;
- this.dispatchEventToListeners("enable-changed");
+ return { nodeId: this._nodeId, type: this._domEventType };
+ },
+
+ _onRemove: function()
+ {
+ var node = WebInspector.domAgent.nodeForId(this._nodeId);
+ if (node)
+ delete node.breakpoints[this._domEventType];
}
}
-WebInspector.XHRBreakpoint.prototype.__proto__ = WebInspector.Object.prototype;
+WebInspector.DOMBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.EventListenerBreakpoint = function(manager, frontendId, eventName)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "EventListener");
+ this._eventName = eventName;
+}
+
+WebInspector.EventListenerBreakpoint.prototype = {
+ compareTo: function(other)
+ {
+ return this._compare(this._eventName, other._eventName);
+ },
+
+ populateLabelElement: function(element)
+ {
+ element.appendChild(document.createTextNode(this._uiEventName()));
+ },
+
+ populateStatusMessageElement: function(element, eventData)
+ {
+ var status = WebInspector.UIString("Paused on a \"%s\" Event Listener.", this._uiEventName());
+ element.appendChild(document.createTextNode(status));
+ },
+
+ _condition: function()
+ {
+ return { eventName: this._eventName };
+ },
+
+ _uiEventName: function()
+ {
+ if (!WebInspector.EventListenerBreakpoint._uiEventNames) {
+ WebInspector.EventListenerBreakpoint._uiEventNames = {
+ "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
+ "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
+ "instrumentation:timerFired": WebInspector.UIString("Timer Fired")
+ };
+ }
+ return WebInspector.EventListenerBreakpoint._uiEventNames[this._eventName] || this._eventName.substring(this._eventName.indexOf(":") + 1);
+ }
+}
+
+WebInspector.EventListenerBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.XHRBreakpoint = function(manager, frontendId, url)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "XHR");
+ this._url = url;
+}
+
+WebInspector.XHRBreakpoint.prototype = {
+ compareTo: function(other)
+ {
+ return this._compare(this._url, other._url);
+ },
+
+ populateLabelElement: function(element)
+ {
+ var label;
+ if (!this._url.length)
+ label = WebInspector.UIString("Any XHR");
+ else
+ label = WebInspector.UIString("URL contains \"%s\"", this._url);
+ element.appendChild(document.createTextNode(label));
+ },
+
+ populateStatusMessageElement: function(element)
+ {
+ var status = WebInspector.UIString("Paused on a XMLHttpRequest.");
+ element.appendChild(document.createTextNode(status));
+ },
+
+ _condition: function()
+ {
+ return { url: this._url };
+ }
+}
+
+WebInspector.XHRBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.DebuggerEventTypes = {
+ JavaScriptPause: 0,
+ JavaScriptBreakpoint: 1,
+ NativeBreakpoint: 2
+};
+
+WebInspector.DOMBreakpointTypes = {
+ SubtreeModified: 0,
+ AttributeModified: 1,
+ NodeRemoved: 2
+};
+
+WebInspector.domBreakpointTypeLabel = function(type)
+{
+ if (!WebInspector._DOMBreakpointTypeLabels) {
+ WebInspector._DOMBreakpointTypeLabels = {};
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified");
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified");
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed");
+ }
+ return WebInspector._DOMBreakpointTypeLabels[type];
+}
+
+WebInspector.domBreakpointTypeContextMenuLabel = function(type)
+{
+ if (!WebInspector._DOMBreakpointTypeContextMenuLabels) {
+ WebInspector._DOMBreakpointTypeContextMenuLabels = {};
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications");
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications");
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Break on Node Removal");
+ }
+ return WebInspector._DOMBreakpointTypeContextMenuLabels[type];
+}
diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 16ab041..2151137 100644
--- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -113,6 +113,9 @@ WebInspector.XHRBreakpointsSidebarPane.prototype = {
if (this.urlInputElement.parentElement)
return;
+ if (!this.expanded)
+ this.expanded = true;
+
this.urlInputElement.textContent = "";
this.bodyElement.insertBefore(this.urlInputElement, this.bodyElement.firstChild);
WebInspector.startEditing(this.urlInputElement, this._hideEditBreakpointDialog.bind(this, false), this._hideEditBreakpointDialog.bind(this, true));
@@ -142,7 +145,11 @@ WebInspector.BreakpointItem = function(breakpoint)
checkboxElement.addEventListener("click", this._checkboxClicked.bind(this), false);
this._element.appendChild(checkboxElement);
+ if ("populateLabelElement" in this._breakpoint)
+ this._breakpoint.populateLabelElement(this._element);
+
this._breakpoint.addEventListener("enable-changed", this._enableChanged, this);
+ this._breakpoint.addEventListener("hit-state-changed", this._hitStateChanged, this);
this._breakpoint.addEventListener("removed", this.dispatchEventToListeners.bind(this, "removed"));
}
@@ -162,6 +169,12 @@ WebInspector.BreakpointItem.prototype = {
this._breakpoint.remove();
},
+ _breakpointClicked: function(event)
+ {
+ if ("click" in this._breakpoint)
+ this._breakpoint.click();
+ },
+
_checkboxClicked: function(event)
{
this._breakpoint.enabled = !this._breakpoint.enabled;
@@ -176,8 +189,12 @@ WebInspector.BreakpointItem.prototype = {
checkbox.checked = this._breakpoint.enabled;
},
- _breakpointClicked: function(event)
+ _hitStateChanged: function(event)
{
+ if (event.target.hit)
+ this._element.addStyleClass("breakpoint-hit");
+ else
+ this._element.removeStyleClass("breakpoint-hit");
}
}
@@ -214,33 +231,119 @@ WebInspector.JSBreakpointItem.prototype = {
WebInspector.JSBreakpointItem.prototype.__proto__ = WebInspector.BreakpointItem.prototype;
-WebInspector.DOMBreakpointItem = function(breakpoint)
+WebInspector.EventListenerBreakpointsSidebarPane = function()
{
- WebInspector.BreakpointItem.call(this, breakpoint);
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
- var link = WebInspector.panels.elements.linkifyNodeById(this._breakpoint.nodeId);
- this._element.appendChild(link);
-
- var type = WebInspector.DOMBreakpoint.labelForType(this._breakpoint.type);
- var typeElement = document.createTextNode(" - " + type);
- this._element.appendChild(typeElement);
+ this.categoriesElement = document.createElement("ol");
+ this.categoriesElement.tabIndex = 0;
+ this.categoriesElement.addStyleClass("properties-tree event-listener-breakpoints");
+ this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
+ this.bodyElement.appendChild(this.categoriesElement);
}
-WebInspector.DOMBreakpointItem.prototype = {
- _breakpointClicked: function()
+WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
+ _populate: function()
{
- WebInspector.updateFocusedNode(this._breakpoint.nodeId);
- }
-}
+ var categories = {
+ "Mouse": { type: "listener", eventNames: ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"] },
+ "Keyboard": { type: "listener", eventNames: ["keydown", "keypress", "keyup"] },
+ "HTML frame/object": { type: "listener", eventNames: ["load", "error", "resize", "scroll"] },
+ "Timer": { type: "instrumentation", eventNames: ["setTimer", "clearTimer", "timerFired"] }
+ };
+
+ for (var category in categories) {
+ var categoryTreeElement = new TreeElement(WebInspector.UIString(category));
+ this.categoriesTreeOutline.appendChild(categoryTreeElement);
+ categoryTreeElement.listItemElement.addStyleClass("event-category");
+ categoryTreeElement.selectable = true;
+
+ var categoryItem = {};
+ categoryItem.checkbox = this._createCheckbox(categoryTreeElement, this._categoryCheckboxClicked.bind(this, categoryItem));
+ categoryItem.children = {};
+
+ var categoryType = categories[category].type;
+ var eventNames = categories[category].eventNames;
+ for (var i = 0; i < eventNames.length; ++i) {
+ var eventName = categoryType + ":" + eventNames[i];
+
+ var breakpoint = WebInspector.breakpointManager.createEventListenerBreakpoint(eventName, true);
+ if (!breakpoint)
+ continue;
+
+ var labelElement = document.createElement("div");
+ breakpoint.populateLabelElement(labelElement);
+ var eventNameTreeElement = new TreeElement(labelElement);
+ categoryTreeElement.appendChild(eventNameTreeElement);
+ eventNameTreeElement.listItemElement.addStyleClass("source-code");
+ eventNameTreeElement.selectable = true;
+
+ var eventNameItem = {};
+ eventNameItem.checkbox = this._createCheckbox(eventNameTreeElement, this._eventNameCheckboxClicked.bind(this, categoryItem, eventNameItem));
+ eventNameItem.breakpoint = breakpoint;
+
+ breakpoint.addEventListener("enable-changed", this._breakpointEnableChanged.bind(this, categoryItem, eventNameItem), true);
+
+ categoryItem.children[eventName] = eventNameItem;
+ }
+ }
+ },
-WebInspector.DOMBreakpointItem.prototype.__proto__ = WebInspector.BreakpointItem.prototype;
+ _createCheckbox: function(treeElement, checkboxClickedDelegate)
+ {
+ var checkbox = document.createElement("input");
+ checkbox.className = "checkbox-elem";
+ checkbox.type = "checkbox";
+ checkbox.addEventListener("click", checkboxClickedDelegate, true);
+ treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild);
+ return checkbox;
+ },
-WebInspector.XHRBreakpointItem = function(breakpoint)
-{
- WebInspector.BreakpointItem.call(this, breakpoint);
+ _categoryCheckboxClicked: function(categoryItem)
+ {
+ var checkbox = categoryItem.checkbox;
+ checkbox.indeterminate = false;
+ for (var eventName in categoryItem.children) {
+ var eventNameItem = categoryItem.children[eventName];
+ eventNameItem.checkbox.checked = checkbox.checked;
+ eventNameItem.breakpoint.enabled = checkbox.checked;
+ }
+ },
+
+ _eventNameCheckboxClicked: function(categoryItem, eventNameItem)
+ {
+ this._updateCategoryCheckbox(categoryItem);
+ eventNameItem.breakpoint.enabled = eventNameItem.checkbox.checked;
+ },
+
+ _breakpointEnableChanged: function(categoryItem, eventNameItem)
+ {
+ if (eventNameItem.checkbox.checked === eventNameItem.breakpoint.enabled)
+ return;
- var label = document.createTextNode(this._breakpoint.formatLabel());
- this._element.appendChild(label);
+ eventNameItem.checkbox.checked = eventNameItem.breakpoint.enabled;
+ this._updateCategoryCheckbox(categoryItem);
+ },
+
+ _updateCategoryCheckbox: function(categoryItem)
+ {
+ var hasEnabled = false, hasDisabled = false;
+ for (var eventName in categoryItem.children) {
+ var eventNameItem = categoryItem.children[eventName];
+ if (eventNameItem.checkbox.checked)
+ hasEnabled = true;
+ else
+ hasDisabled = true;
+ }
+ categoryItem.checkbox.checked = hasEnabled;
+ categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
+ },
+
+ reset: function()
+ {
+ this.categoriesTreeOutline.removeChildren();
+ this._populate();
+ }
}
-WebInspector.XHRBreakpointItem.prototype.__proto__ = WebInspector.BreakpointItem.prototype;
+WebInspector.EventListenerBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/WebCore/inspector/front-end/CSSStyleModel.js b/WebCore/inspector/front-end/CSSStyleModel.js
index bda4064..e3e9b4f 100644
--- a/WebCore/inspector/front-end/CSSStyleModel.js
+++ b/WebCore/inspector/front-end/CSSStyleModel.js
@@ -96,13 +96,13 @@ WebInspector.CSSStyleModel.prototype = {
applyStyleText: function(styleId, styleText, propertyName, successCallback, failureCallback)
{
- function callback(success, newPayload, changedProperties)
+ function callback(success, newPayload)
{
if (!success)
failureCallback();
else {
var newStyle = newPayload ? WebInspector.CSSStyleDeclaration.parseStyle(newPayload) : null;
- successCallback(newStyle, changedProperties);
+ successCallback(newStyle);
}
}
diff --git a/WebCore/inspector/front-end/CallStackSidebarPane.js b/WebCore/inspector/front-end/CallStackSidebarPane.js
index 6212ea1..08c1942 100644
--- a/WebCore/inspector/front-end/CallStackSidebarPane.js
+++ b/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -26,13 +26,9 @@
WebInspector.CallStackSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+ WebInspector.breakpointManager.addEventListener("breakpoint-hit", this._breakpointHit, this);
}
-WebInspector.CallStackSidebarPane.DebuggerEventType = {
- DOMBreakpoint: 0,
- NativeBreakpoint: 1
-};
-
WebInspector.CallStackSidebarPane.prototype = {
update: function(callFrames, sourceIDMap)
{
@@ -87,44 +83,6 @@ WebInspector.CallStackSidebarPane.prototype = {
}
},
- updateStatus: function(eventType, eventData)
- {
- var statusElement = document.createElement("div");
- if (eventType === WebInspector.CallStackSidebarPane.DebuggerEventType.DOMBreakpoint) {
- var breakpoint = eventData.breakpoint;
- var substitutions = [WebInspector.DOMBreakpoint.labelForType(breakpoint.type), WebInspector.panels.elements.linkifyNodeById(breakpoint.nodeId)];
- var formatters = {
- s: function(substitution)
- {
- return substitution;
- }
- };
- function append(a, b)
- {
- if (typeof b === "string")
- b = document.createTextNode(b);
- statusElement.appendChild(b);
- }
- if (breakpoint.type === WebInspector.DOMBreakpoint.Types.SubtreeModified) {
- var targetNode = WebInspector.panels.elements.linkifyNodeById(eventData.targetNodeId);
- if (eventData.insertion) {
- if (eventData.targetNodeId !== breakpoint.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);
- } else if (eventType === WebInspector.CallStackSidebarPane.DebuggerEventType.NativeBreakpoint && eventData.type === "XHR")
- statusElement.appendChild(document.createTextNode(WebInspector.UIString("Paused on XMLHttpRequest.")));
- else
- return;
-
- statusElement.className = "info";
- this.bodyElement.appendChild(statusElement);
- },
-
get selectedCallFrame()
{
return this._selectedCallFrame;
@@ -210,6 +168,16 @@ WebInspector.CallStackSidebarPane.prototype = {
this._shortcuts[prevCallFrame.key] = this._selectPreviousCallFrameOnStack.bind(this);
section.addRelatedKeys([ nextCallFrame.name, prevCallFrame.name ], WebInspector.UIString("Next/previous call frame"));
+ },
+
+ _breakpointHit: function(event)
+ {
+ var breakpoint = event.data.breakpoint;
+
+ var statusMessageElement = document.createElement("div");
+ statusMessageElement.className = "info";
+ breakpoint.populateStatusMessageElement(statusMessageElement, event.data.eventData);
+ this.bodyElement.appendChild(statusMessageElement);
}
}
diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js
index 6f8bd8b..8cd5d52 100644
--- a/WebCore/inspector/front-end/ConsoleView.js
+++ b/WebCore/inspector/front-end/ConsoleView.js
@@ -64,7 +64,7 @@ WebInspector.ConsoleView = function(drawer)
function createDividerElement() {
var dividerElement = document.createElement("div");
- dividerElement.addStyleClass("divider");
+ dividerElement.addStyleClass("scope-bar-divider");
this.filterBarElement.appendChild(dividerElement);
}
@@ -360,7 +360,7 @@ WebInspector.ConsoleView.prototype = {
}
var results = [];
- var properties = Object.sortedProperties(result);
+ var properties = Object.keys(result).sort();
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
@@ -679,25 +679,22 @@ WebInspector.ConsoleMessage.prototype = {
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
var ol = document.createElement("ol");
ol.addStyleClass("stack-trace");
- if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
- ol.addStyleClass("trace-message");
var treeOutline = new TreeOutline(ol);
+ var messageText;
+ if (this.type === WebInspector.ConsoleMessage.MessageType.Assert)
+ messageText = this._format(this._parameters);
+ else if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
+ messageText = document.createTextNode("console.trace()");
+ else
+ messageText = document.createTextNode(this._messageText);
- var root = treeOutline;
- if (this.type === WebInspector.ConsoleMessage.MessageType.UncaughtException ||
- this.type === WebInspector.ConsoleMessage.MessageType.Assert) {
- var messageText;
- if (this.type === WebInspector.ConsoleMessage.MessageType.Assert)
- messageText = this._format(this._parameters);
- else
- messageText = document.createTextNode(this._messageText);
-
- var content = document.createElement("div");
- this._addMessageHeader(content, messageText);
- root = new TreeElement(content, null, true);
- content.treeElementForTest = root;
- treeOutline.appendChild(root);
- }
+ var content = document.createElement("div");
+ this._addMessageHeader(content, messageText);
+ var root = new TreeElement(content, null, true);
+ content.treeElementForTest = root;
+ treeOutline.appendChild(root);
+ if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
+ root.expand();
this._populateStackTraceTreeElement(root);
this.formattedMessage = ol;
diff --git a/WebCore/inspector/front-end/CookieItemsView.js b/WebCore/inspector/front-end/CookieItemsView.js
index 1baf4a6..88cbe05 100644
--- a/WebCore/inspector/front-end/CookieItemsView.js
+++ b/WebCore/inspector/front-end/CookieItemsView.js
@@ -122,8 +122,8 @@ WebInspector.CookieItemsView.prototype = {
for (var id in WebInspector.resources) {
var resource = WebInspector.resources[id];
- var match = resource.documentURL.match(WebInspector.GenericURLRegExp);
- if (match && match[2] === this._cookieDomain)
+ var url = resource.documentURL.asParsedURL();
+ if (url && url.host == this._cookieDomain)
resourceURLsForDocumentURL.push(resource.url);
}
diff --git a/WebCore/inspector/front-end/CookieParser.js b/WebCore/inspector/front-end/CookieParser.js
new file mode 100755
index 0000000..2be5df7
--- /dev/null
+++ b/WebCore/inspector/front-end/CookieParser.js
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+// Ideally, we would rely on platform support for parsing a cookie, since
+// this would save us from any potential inconsistency. However, exposing
+// platform cookie parsing logic would require quite a bit of additional
+// plumbing, and at least some platforms lack support for parsing Cookie,
+// which is in a format slightly different from Set-Cookie and is normally
+// only required on the server side.
+
+WebInspector.CookieParser = function()
+{
+}
+
+WebInspector.CookieParser.prototype = {
+ get cookies()
+ {
+ return this._cookies;
+ },
+
+ parseCookie: function(cookieHeader)
+ {
+ if (!this._initialize(cookieHeader))
+ return;
+
+ for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
+ if (kv.key.charAt(0) === "$" && this._lastCookie)
+ this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
+ else if (kv.key.toLowerCase() !== "$version" && typeof kv.value === "string")
+ this._addCookie(kv);
+ this._advanceAndCheckCookieDelimiter();
+ }
+ this._flushCookie();
+ return this._cookies;
+ },
+
+ parseSetCookie: function(setCookieHeader)
+ {
+ if (!this._initialize(setCookieHeader))
+ return;
+ for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
+ if (this._lastCookie)
+ this._lastCookie.addAttribute(kv.key, kv.value);
+ else
+ this._addCookie(kv);
+ if (this._advanceAndCheckCookieDelimiter())
+ this._flushCookie();
+ }
+ this._flushCookie();
+ return this._cookies;
+ },
+
+ _initialize: function(headerValue)
+ {
+ this._input = headerValue;
+ if (typeof headerValue !== "string")
+ return false;
+ this._cookies = [];
+ this._lastCookie = null;
+ this._originalInputLength = this._input.length;
+ return true;
+ },
+
+ _flushCookie: function()
+ {
+ if (this._lastCookie)
+ this._lastCookie.size = this._originalInputLength - this._input.length - this._lastCookiePosition;
+ this._lastCookie = null;
+ },
+
+ _extractKeyValue: function()
+ {
+ if (!this._input || !this._input.length)
+ return null;
+ // Note: RFCs offer an option for quoted values that may contain commas and semicolons.
+ // Many browsers/platforms do not support this, however (see http://webkit.org/b/16699
+ // and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox,
+ // Chrome and Safari on some old platforms. The latest version of Safari supports quoted
+ // cookie values, though.
+ var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input);
+ if (!keyValueMatch) {
+ console.log("Failed parsing cookie header before: " + this._input);
+ return null;
+ }
+
+ var result = {
+ key: keyValueMatch[1],
+ value: keyValueMatch[2] && keyValueMatch[2].trim(),
+ position: this._originalInputLength - this._input.length
+ };
+ this._input = this._input.slice(keyValueMatch[0].length);
+ return result;
+ },
+
+ _advanceAndCheckCookieDelimiter: function()
+ {
+ var match = /^\s*[\n;]\s*/.exec(this._input);
+ if (!match)
+ return false;
+ this._input = this._input.slice(match[0].length);
+ return match[0].match("\n") !== null;
+ },
+
+ _addCookie: function(keyValue)
+ {
+ if (this._lastCookie)
+ this._lastCookie.size = keyValue.position - this._lastCookiePosition;
+ // Mozilla bug 169091: Mozilla, IE and Chrome treat signle token (w/o "=") as
+ // specifying a value for a cookie with empty name.
+ this._lastCookie = keyValue.value ? new WebInspector.Cookie(keyValue.key, keyValue.value) :
+ new WebInspector.Cookie("", keyValue.key);
+ this._lastCookiePosition = keyValue.position;
+ this._cookies.push(this._lastCookie);
+ }
+};
+
+WebInspector.CookieParser.parseCookie = function(header)
+{
+ return (new WebInspector.CookieParser()).parseCookie(header);
+}
+
+WebInspector.CookieParser.parseSetCookie = function(header)
+{
+ return (new WebInspector.CookieParser()).parseSetCookie(header);
+}
+
+WebInspector.Cookie = function(name, value)
+{
+ this.name = name;
+ this.value = value;
+ this._attributes = {};
+}
+
+WebInspector.Cookie.prototype = {
+ get httpOnly()
+ {
+ return "httponly" in this._attributes;
+ },
+
+ get secure()
+ {
+ return "secure" in this._attributes;
+ },
+
+ get session()
+ {
+ // RFC 2965 suggests using Discard attribute to mark session cookies, but this does not seem to be widely used.
+ // Check for absence of explicity max-age or expiry date instead.
+ return !("expries" in this._attributes || "max-age" in this._attributes);
+ },
+
+ get path()
+ {
+ return this._attributes.path;
+ },
+
+ get domain()
+ {
+ return this._attributes.domain;
+ },
+
+ expires: function(requestDate)
+ {
+ return this._attributes.expires ? new Date(this._attributes.expires) :
+ (this._attributes["max-age"] ? new Date(requestDate.getTime() + 1000 * this._attributes["max-age"]) : null);
+ },
+
+ get attributes()
+ {
+ return this._attributes;
+ },
+
+ addAttribute: function(key, value)
+ {
+ this._attributes[key.toLowerCase()] = value;
+ }
+}
diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js
index 279852e..5153fb1 100644
--- a/WebCore/inspector/front-end/DOMAgent.js
+++ b/WebCore/inspector/front-end/DOMAgent.js
@@ -60,6 +60,8 @@ WebInspector.DOMNode = function(doc, payload) {
this.style = null;
this._matchedCSSRules = [];
+ this.breakpoints = {};
+
if (this.nodeType === Node.ELEMENT_NODE) {
// HTML and BODY from internal iframes should not overwrite top-level ones.
if (!this.ownerDocument.documentElement && this.nodeName === "HTML")
@@ -149,28 +151,6 @@ WebInspector.DOMNode.prototype = {
return path.join(",");
},
- setBreakpoint: function(type)
- {
- return WebInspector.domBreakpointManager.setBreakpoint(this.id, type, true, this.path());
- },
-
- hasBreakpoint: function(type)
- {
- return !!WebInspector.domBreakpointManager.findBreakpoint(this.id, type);
- },
-
- removeBreakpoint: function(type)
- {
- var breakpoint = WebInspector.domBreakpointManager.findBreakpoint(this.id, type);
- if (breakpoint)
- breakpoint.remove();
- },
-
- removeBreakpoints: function()
- {
- WebInspector.domBreakpointManager.removeBreakpointsForNode(this.id);
- },
-
_setAttributesPayload: function(attrs)
{
this.attributes = [];
@@ -399,7 +379,7 @@ WebInspector.DOMAgent.prototype = {
this.document = new WebInspector.DOMDocument(this, this._window, payload);
this._idToDOMNode[payload.id] = this.document;
this._bindNodes(this.document.children);
- WebInspector.domBreakpointManager.restoreBreakpoints();
+ WebInspector.breakpointManager.restoreDOMBreakpoints();
} else
this.document = null;
WebInspector.panels.elements.setDocument(this.document);
@@ -461,12 +441,13 @@ WebInspector.DOMAgent.prototype = {
_removeBreakpoints: function(node)
{
- node.removeBreakpoints();
+ for (var type in node.breakpoints)
+ node.breakpoints[type].remove();
if (!node.children)
return;
for (var i = 0; i < node.children.length; ++i)
this._removeBreakpoints(node.children[i]);
- }
+ }
}
WebInspector.ApplicationCache = {}
@@ -519,17 +500,12 @@ WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
{
- var match = resourceURL.match(WebInspector.GenericURLRegExp);
- if (!match)
+ var url = resourceURL.asParsedURL();
+ if (!url || !this.cookieDomainMatchesResourceDomain(cookie.domain, url.host))
return false;
- // See WebInspector.URLRegExp for definitions of the group index constants.
- if (!this.cookieDomainMatchesResourceDomain(cookie.domain, match[2]))
- return false;
- var resourcePort = match[3] ? match[3] : undefined;
- var resourcePath = match[4] ? match[4] : '/';
- return (resourcePath.indexOf(cookie.path) === 0
- && (!cookie.port || resourcePort == cookie.port)
- && (!cookie.secure || match[1].toLowerCase() === 'https'));
+ return (url.path.indexOf(cookie.path) === 0
+ && (!cookie.port || url.port == cookie.port)
+ && (!cookie.secure || url.scheme === "https"));
}
WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
@@ -728,166 +704,3 @@ WebInspector.childNodeRemoved = function()
{
this.domAgent._childNodeRemoved.apply(this.domAgent, arguments);
}
-
-WebInspector.DOMBreakpointManager = function()
-{
- this._breakpoints = {};
- this._pathCache = {};
-}
-
-WebInspector.DOMBreakpointManager.prototype = {
- setBreakpoint: function(nodeId, type, enabled, path)
- {
- if (!(nodeId in this._breakpoints))
- this._breakpoints[nodeId] = {};
- else if (type in this._breakpoints[nodeId])
- return;
-
- var breakpoint = new WebInspector.DOMBreakpoint(nodeId, type, enabled);
- this._breakpoints[nodeId][type] = breakpoint;
- breakpoint.addEventListener("removed", this._breakpointRemoved, this);
-
- if (!(nodeId in this._pathCache))
- this._pathCache[nodeId] = path;
-
- this.dispatchEventToListeners("dom-breakpoint-added", breakpoint);
- },
-
- findBreakpoint: function(nodeId, type)
- {
- var nodeBreakpoints = this._breakpoints[nodeId];
- if (nodeBreakpoints && type in nodeBreakpoints)
- return nodeBreakpoints[type];
- },
-
- removeBreakpointsForNode: function(nodeId)
- {
- var nodeBreakpoints = this._breakpoints[nodeId];
- for (var type in nodeBreakpoints)
- nodeBreakpoints[type].remove();
- },
-
- _breakpointRemoved: function(event)
- {
- var breakpoint = event.target;
-
- var nodeBreakpoints = this._breakpoints[breakpoint.nodeId];
- delete nodeBreakpoints[breakpoint.type];
- for (var type in nodeBreakpoints)
- return;
-
- delete this._breakpoints[breakpoint.nodeId];
- delete this._pathCache[breakpoint.nodeId];
- },
-
- restoreBreakpoints: function()
- {
- var breakpoints = this._breakpoints;
- this._breakpoints = {};
- var pathCache = this._pathCache;
- this._pathCache = {};
-
- for (var oldNodeId in breakpoints) {
- var path = pathCache[oldNodeId];
- InspectorBackend.pushNodeByPathToFrontend(path, restoreBreakpointsForNode.bind(this, breakpoints[oldNodeId], path));
- }
-
- function restoreBreakpointsForNode(nodeBreakpoints, path, nodeId)
- {
- if (!nodeId)
- return;
- for (var type in nodeBreakpoints) {
- var breakpoint = nodeBreakpoints[type];
- this.setBreakpoint(nodeId, breakpoint.type, breakpoint.enabled, path);
- }
- }
- }
-}
-
-WebInspector.DOMBreakpointManager.prototype.__proto__ = WebInspector.Object.prototype;
-
-WebInspector.DOMBreakpoint = function(nodeId, type, enabled)
-{
- this._nodeId = nodeId;
- this._type = type;
- this._enabled = enabled;
-
- if (this.enabled)
- InspectorBackend.setDOMBreakpoint(this.nodeId, this.type);
-}
-
-WebInspector.DOMBreakpoint.Types = {
- SubtreeModified: 0,
- AttributeModified: 1,
- NodeRemoved: 2
-};
-
-WebInspector.DOMBreakpoint.labelForType = function(type)
-{
- if (!WebInspector.DOMBreakpoint._labels) {
- WebInspector.DOMBreakpoint._labels = {};
- WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.SubtreeModified] = WebInspector.UIString("Subtree Modified");
- WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.AttributeModified] = WebInspector.UIString("Attribute Modified");
- WebInspector.DOMBreakpoint._labels[WebInspector.DOMBreakpoint.Types.NodeRemoved] = WebInspector.UIString("Node Removed");
- }
- return WebInspector.DOMBreakpoint._labels[type];
-}
-
-WebInspector.DOMBreakpoint.contextMenuLabelForType = function(type)
-{
- if (!WebInspector.DOMBreakpoint._contextMenuLabels) {
- WebInspector.DOMBreakpoint._contextMenuLabels = {};
- WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications");
- WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications");
- WebInspector.DOMBreakpoint._contextMenuLabels[WebInspector.DOMBreakpoint.Types.NodeRemoved] = WebInspector.UIString("Break on Node Removal");
- }
- return WebInspector.DOMBreakpoint._contextMenuLabels[type];
-}
-
-WebInspector.DOMBreakpoint.prototype = {
- get nodeId()
- {
- return this._nodeId;
- },
-
- get type()
- {
- return this._type;
- },
-
- get enabled()
- {
- return this._enabled;
- },
-
- set enabled(enabled)
- {
- if (this._enabled === enabled)
- return;
-
- this._enabled = enabled;
- if (this.enabled)
- InspectorBackend.setDOMBreakpoint(this.nodeId, this.type);
- else
- InspectorBackend.removeDOMBreakpoint(this.nodeId, this.type);
-
- this.dispatchEventToListeners("enable-changed");
- },
-
- compareTo: function(other)
- {
- if (this.type != other.type)
- return this.type < other.type ? -1 : 1;
- return 0;
- },
-
- remove: function()
- {
- if (this.enabled)
- InspectorBackend.removeDOMBreakpoint(this.nodeId, this.type);
- this.dispatchEventToListeners("removed");
- }
-}
-
-WebInspector.DOMBreakpoint.prototype.__proto__ = WebInspector.Object.prototype;
-
diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js
index f68fe48..3007497 100644
--- a/WebCore/inspector/front-end/DataGrid.js
+++ b/WebCore/inspector/front-end/DataGrid.js
@@ -32,6 +32,7 @@ WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
this._headerTable = document.createElement("table");
this._headerTable.className = "header";
+ this._headerTableHeaders = {};
this._dataTable = document.createElement("table");
this._dataTable.className = "data";
@@ -77,9 +78,13 @@ WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
var cell = document.createElement("th");
cell.className = columnIdentifier + "-column";
cell.columnIdentifier = columnIdentifier;
+ this._headerTableHeaders[columnIdentifier] = cell;
var div = document.createElement("div");
- div.textContent = column.title;
+ if (column.titleDOMFragment)
+ div.appendChild(column.titleDOMFragment);
+ else
+ div.textContent = column.title;
cell.appendChild(div);
if (column.sort) {
@@ -113,16 +118,27 @@ WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
var fillerRow = document.createElement("tr");
fillerRow.className = "filler";
- for (var i = 0; i < this._columnCount; ++i) {
+ for (var columnIdentifier in columns) {
+ var column = columns[columnIdentifier];
var cell = document.createElement("td");
+ cell.className = columnIdentifier + "-column";
fillerRow.appendChild(cell);
}
-
+
this._dataTableColumnGroup = columnGroup.cloneNode(true);
this._dataTable.appendChild(this._dataTableColumnGroup);
this.dataTableBody.appendChild(fillerRow);
this.columns = columns || {};
+ this._columnsArray = [];
+ for (var columnIdentifier in columns) {
+ columns[columnIdentifier].ordinal = this._columnsArray.length;
+ this._columnsArray.push(columns[columnIdentifier]);
+ }
+
+ for (var i = 0; i < this._columnsArray.length; ++i)
+ this._columnsArray[i].bodyElement = this._dataTableColumnGroup.children[i];
+
this.children = [];
this.selectedNode = null;
this.expandNodesWhenArrowing = false;
@@ -134,7 +150,7 @@ WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
this.dataGrid = this;
this.indentWidth = 15;
this.resizers = [];
- this.columnWidthsInitialized = false;
+ this._columnWidthsInitialized = false;
}
WebInspector.DataGrid.prototype = {
@@ -351,7 +367,7 @@ WebInspector.DataGrid.prototype = {
for (var columnIdentifier in columns)
columns[columnIdentifier].element.style.width = widths[columnIdentifier] + "%";
- this.columnWidthsInitialized = false;
+ this._columnWidthsInitialized = false;
this.updateWidths();
},
@@ -369,11 +385,10 @@ WebInspector.DataGrid.prototype = {
{
var headerTableColumns = this._headerTableColumnGroup.children;
- var left = 0;
var tableWidth = this._dataTable.offsetWidth;
var numColumns = headerTableColumns.length;
- if (!this.columnWidthsInitialized) {
+ if (!this._columnWidthsInitialized) {
// Give all the columns initial widths now so that during a resize,
// when the two columns that get resized get a percent value for
// their widths, all the other columns already have percent values
@@ -384,9 +399,86 @@ WebInspector.DataGrid.prototype = {
this._headerTableColumnGroup.children[i].style.width = percentWidth;
this._dataTableColumnGroup.children[i].style.width = percentWidth;
}
- this.columnWidthsInitialized = true;
+ this._columnWidthsInitialized = true;
}
-
+ this._positionResizers();
+ this.dispatchEventToListeners("width changed");
+ },
+
+ columnWidthsMap: function()
+ {
+ var result = {};
+ for (var i = 0; i < this._columnsArray.length; ++i) {
+ var width = this._headerTableColumnGroup.children[i].style.width;
+ result[this._columnsArray[i].columnIdentifier] = parseFloat(width);
+ }
+ return result;
+ },
+
+ applyColumnWidthsMap: function(columnWidthsMap)
+ {
+ for (var columnIdentifier in this.columns) {
+ var column = this.columns[columnIdentifier];
+ var width = (columnWidthsMap[columnIdentifier] || 0) + "%";
+ this._headerTableColumnGroup.children[column.ordinal].style.width = width;
+ this._dataTableColumnGroup.children[column.ordinal].style.width = width;
+ }
+
+ // Normalize widths
+ delete this._columnWidthsInitialized;
+ this.updateWidths();
+ },
+
+ isColumnVisible: function(columnIdentifier)
+ {
+ var column = this.columns[columnIdentifier];
+ var columnElement = column.element;
+ return !columnElement.hidden;
+ },
+
+ showColumn: function(columnIdentifier)
+ {
+ var column = this.columns[columnIdentifier];
+ var columnElement = column.element;
+ if (!columnElement.hidden)
+ return;
+
+ columnElement.hidden = false;
+ columnElement.removeStyleClass("hidden");
+
+ var columnBodyElement = column.bodyElement;
+ columnBodyElement.hidden = false;
+ columnBodyElement.removeStyleClass("hidden");
+ },
+
+ hideColumn: function(columnIdentifier)
+ {
+ var column = this.columns[columnIdentifier];
+ var columnElement = column.element;
+ if (columnElement.hidden)
+ return;
+
+ var oldWidth = parseFloat(columnElement.style.width);
+
+ columnElement.hidden = true;
+ columnElement.addStyleClass("hidden");
+ columnElement.style.width = 0;
+
+ var columnBodyElement = column.bodyElement;
+ columnBodyElement.hidden = true;
+ columnBodyElement.addStyleClass("hidden");
+ columnBodyElement.style.width = 0;
+
+ this._columnWidthsInitialized = false;
+ },
+
+ _positionResizers: function()
+ {
+ var headerTableColumns = this._headerTableColumnGroup.children;
+ var numColumns = headerTableColumns.length;
+ var left = 0;
+ var previousResizer = null;
+
// Make n - 1 resizers for n columns.
for (var i = 0; i < numColumns - 1; i++) {
var resizer = this.resizers[i];
@@ -397,7 +489,6 @@ WebInspector.DataGrid.prototype = {
resizer = document.createElement("div");
resizer.addStyleClass("data-grid-resizer");
// This resizer is associated with the column to its right.
- resizer.rightNeighboringColumnID = i + 1;
resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
this.element.appendChild(resizer);
this.resizers[i] = resizer;
@@ -407,10 +498,23 @@ WebInspector.DataGrid.prototype = {
// header table in order to determine the width of the column, since
// it is not possible to query a column for its width.
left += this.headerTableBody.rows[0].cells[i].offsetWidth;
-
- resizer.style.left = left + "px";
+
+ var columnIsVisible = !this._headerTableColumnGroup.children[i].hidden;
+ if (columnIsVisible) {
+ resizer.style.removeProperty("display");
+ resizer.style.left = left + "px";
+ resizer.leftNeighboringColumnID = i;
+ if (previousResizer)
+ previousResizer.rightNeighboringColumnID = i;
+ previousResizer = resizer;
+ } else {
+ resizer.style.setProperty("display", "none");
+ resizer.leftNeighboringColumnID = 0;
+ resizer.rightNeighboringColumnID = 0;
+ }
}
- this.dispatchEventToListeners("width changed");
+ if (previousResizer)
+ previousResizer.rightNeighboringColumnID = numColumns - 1;
},
addCreationNode: function(hasChildren)
@@ -474,6 +578,7 @@ WebInspector.DataGrid.prototype = {
throw("removeChild: Node is not a child of this node.");
child.deselect();
+ child._detach();
this.children.remove(child, true);
@@ -534,17 +639,18 @@ WebInspector.DataGrid.prototype = {
this.children = [];
},
- sortNodes: function(comparator, descending)
+ sortNodes: function(comparator, reverseMode)
{
function comparatorWrapper(a, b)
{
+ if (a._dataGridNode._data.summaryRow)
+ return 1;
+ if (b._dataGridNode._data.summaryRow)
+ return -1;
+
var aDataGirdNode = a._dataGridNode;
var bDataGirdNode = b._dataGridNode;
- if (!aDataGirdNode)
- return 1; // Filler row.
- if (!bDataGirdNode)
- return -1; // Filler row.
- return descending ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode);
+ return reverseMode ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode);
}
var tbody = this.dataTableBody;
@@ -552,15 +658,27 @@ WebInspector.DataGrid.prototype = {
tbodyParent.removeChild(tbody);
var childNodes = tbody.childNodes;
- var sortedNodes = Array.prototype.slice.call(childNodes);
- sortedNodes.sort(comparatorWrapper.bind(this));
+ var fillerRow = childNodes[childNodes.length - 1];
+
+ var sortedRows = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1);
+ sortedRows.sort(comparatorWrapper);
+ var sortedRowsLength = sortedRows.length;
- var sortedNodesLength = sortedNodes.length;
tbody.removeChildren();
- for (var i = 0; i < sortedNodesLength; ++i) {
- var node = sortedNodes[i];
- tbody.appendChild(node);
+ var previousSiblingNode = null;
+ for (var i = 0; i < sortedRowsLength; ++i) {
+ var row = sortedRows[i];
+ var node = row._dataGridNode;
+ node.previousSibling = previousSiblingNode;
+ if (previousSiblingNode)
+ previousSiblingNode.nextSibling = node;
+ tbody.appendChild(row);
+ previousSiblingNode = node;
}
+ if (previousSiblingNode)
+ previousSiblingNode.nextSibling = null;
+
+ tbody.appendChild(fillerRow);
tbodyParent.appendChild(tbody);
},
@@ -673,13 +791,11 @@ WebInspector.DataGrid.prototype = {
var sortOrder = this.sortOrder;
- if (this._sortColumnCell) {
- this._sortColumnCell.removeStyleClass("sort-ascending");
- this._sortColumnCell.removeStyleClass("sort-descending");
- }
+ if (this._sortColumnCell)
+ this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");
if (cell == this._sortColumnCell) {
- if (sortOrder == "ascending")
+ if (sortOrder === "ascending")
sortOrder = "descending";
else
sortOrder = "ascending";
@@ -692,6 +808,19 @@ WebInspector.DataGrid.prototype = {
this.dispatchEventToListeners("sorting changed");
},
+ markColumnAsSortedBy: function(columnIdentifier, sortOrder)
+ {
+ if (this._sortColumnCell)
+ this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");
+ this._sortColumnCell = this._headerTableHeaders[columnIdentifier];
+ this._sortColumnCell.addStyleClass("sort-" + sortOrder);
+ },
+
+ headerTableHeader: function(columnIdentifier)
+ {
+ return this._headerTableHeaders[columnIdentifier];
+ },
+
_mouseDownInDataTable: function(event)
{
var gridNode = this.dataGridNodeFromNode(event.target);
@@ -778,27 +907,28 @@ WebInspector.DataGrid.prototype = {
// column directly to the left and the column directly to the right.
var leftEdgeOfPreviousColumn = 0;
var firstRowCells = this.headerTableBody.rows[0].cells;
- for (var i = 0; i < resizer.rightNeighboringColumnID - 1; i++)
+ for (var i = 0; i < resizer.leftNeighboringColumnID; i++)
leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
- var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.rightNeighboringColumnID - 1].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth;
-
- // Give each column some padding so that they don't disappear.
+ var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.leftNeighboringColumnID].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth;
+
+ // Give each column some padding so that they don't disappear.
var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding;
var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding;
-
+
dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
-
+
resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
-
+
var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%";
- this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
- this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
-
+ this._headerTableColumnGroup.children[resizer.leftNeighboringColumnID].style.width = percentLeftColumn;
+ this._dataTableColumnGroup.children[resizer.leftNeighboringColumnID].style.width = percentLeftColumn;
+
var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%";
this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
-
+
+ this._positionResizers();
event.preventDefault();
this.dispatchEventToListeners("width changed");
},
diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js
index d6437fc..76c22c5 100644
--- a/WebCore/inspector/front-end/ElementsPanel.js
+++ b/WebCore/inspector/front-end/ElementsPanel.js
@@ -107,7 +107,6 @@ WebInspector.ElementsPanel = function()
this.element.appendChild(this.sidebarResizeElement);
this._registerShortcuts();
- this._changedStyles = {};
this.reset();
}
@@ -346,115 +345,6 @@ WebInspector.ElementsPanel.prototype = {
// TODO: Implement Shifting the oldSelector, and its contents to a newSelector
},
- addStyleChange: function(identifier, style, property)
- {
- if (!style.parentRule)
- return;
-
- var selector = style.parentRule.selectorText;
- if (!this._changedStyles[identifier])
- this._changedStyles[identifier] = {};
-
- if (!this._changedStyles[identifier][selector])
- this._changedStyles[identifier][selector] = {};
-
- if (!this._changedStyles[identifier][selector][property])
- WebInspector.styleChanges += 1;
-
- this._changedStyles[identifier][selector][property] = style.getPropertyValue(property);
- },
-
- removeStyleChange: function(identifier, style, property)
- {
- if (!style.parentRule)
- return;
-
- var selector = style.parentRule.selectorText;
- if (!this._changedStyles[identifier] || !this._changedStyles[identifier][selector])
- return;
-
- if (this._changedStyles[identifier][selector][property]) {
- delete this._changedStyles[identifier][selector][property];
- WebInspector.styleChanges -= 1;
- }
- },
-
- generateStylesheet: function()
- {
- if (!WebInspector.styleChanges)
- return;
-
- // Merge Down to Just Selectors
- var mergedSelectors = {};
- for (var identifier in this._changedStyles) {
- for (var selector in this._changedStyles[identifier]) {
- if (!mergedSelectors[selector])
- mergedSelectors[selector] = this._changedStyles[identifier][selector];
- else { // merge on selector
- var merge = {};
- for (var property in mergedSelectors[selector])
- merge[property] = mergedSelectors[selector][property];
- for (var property in this._changedStyles[identifier][selector]) {
- if (!merge[property])
- merge[property] = this._changedStyles[identifier][selector][property];
- else { // merge on property within a selector, include comment to notify user
- var value1 = merge[property];
- var value2 = this._changedStyles[identifier][selector][property];
-
- if (value1 === value2)
- merge[property] = [value1];
- else if (value1 instanceof Array)
- merge[property].push(value2);
- else
- merge[property] = [value1, value2];
- }
- }
- mergedSelectors[selector] = merge;
- }
- }
- }
-
- var builder = [];
- builder.push("/**");
- builder.push(" * Inspector Generated Stylesheet"); // UIString?
- builder.push(" */\n");
-
- var indent = " ";
- function displayProperty(property, value, comment) {
- if (comment)
- return indent + "/* " + property + ": " + value + "; */";
- else
- return indent + property + ": " + value + ";";
- }
-
- for (var selector in mergedSelectors) {
- var psuedoStyle = mergedSelectors[selector];
- var properties = Object.properties(psuedoStyle);
- if (properties.length) {
- builder.push(selector + " {");
- for (var i = 0; i < properties.length; ++i) {
- var property = properties[i];
- var value = psuedoStyle[property];
- if (!(value instanceof Array))
- builder.push(displayProperty(property, value));
- else {
- if (value.length === 1)
- builder.push(displayProperty(property, value) + " /* merged from equivalent edits */"); // UIString?
- else {
- builder.push(indent + "/* There was a Conflict... There were Multiple Edits for '" + property + "' */"); // UIString?
- for (var j = 0; j < value.length; ++j)
- builder.push(displayProperty(property, value, true));
- }
- }
- }
- builder.push("}\n");
- }
- }
-
- WebInspector.showConsole();
- WebInspector.console.addMessage(WebInspector.ConsoleMessage.createTextMessage(builder.join("\n")));
- },
-
get rootDOMNode()
{
return this.treeOutline.rootDOMNode;
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index 1479c9a..1d546c2 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -759,15 +759,15 @@ WebInspector.ElementsTreeElement.prototype = {
contextMenu.appendSeparator();
var node = this.representedObject;
- for (var key in WebInspector.DOMBreakpoint.Types) {
- var type = WebInspector.DOMBreakpoint.Types[key];
- var label = WebInspector.DOMBreakpoint.contextMenuLabelForType(type);
- var hasBreakpoint = node.hasBreakpoint(type);
- if (!hasBreakpoint)
- var handler = node.setBreakpoint.bind(node, type);
+ for (var key in WebInspector.DOMBreakpointTypes) {
+ var type = WebInspector.DOMBreakpointTypes[key];
+ var label = WebInspector.domBreakpointTypeContextMenuLabel(type);
+ var breakpoint = node.breakpoints[type];
+ if (!breakpoint)
+ var handler = WebInspector.breakpointManager.createDOMBreakpoint.bind(WebInspector.breakpointManager, node.id, type);
else
- var handler = node.removeBreakpoint.bind(node, type);
- contextMenu.appendCheckboxItem(label, handler, hasBreakpoint);
+ var handler = breakpoint.remove.bind(breakpoint);
+ contextMenu.appendCheckboxItem(label, handler, !!breakpoint);
}
}
},
diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js
index 34dea00..e2ad259 100644
--- a/WebCore/inspector/front-end/EventListenersSidebarPane.js
+++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js
@@ -183,7 +183,7 @@ WebInspector.EventListenerBar = function(eventListener, nodeId)
this._setFunctionSubtitle();
this.editable = false;
this.element.className = "event-bar"; /* Changed from "section" */
- this.propertiesElement.className = "event-properties source-code"; /* Changed from "properties" */
+ this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */
}
WebInspector.EventListenerBar.prototype = {
diff --git a/WebCore/inspector/front-end/ExtensionAPI.js b/WebCore/inspector/front-end/ExtensionAPI.js
index 64f5482..5d090b0 100644
--- a/WebCore/inspector/front-end/ExtensionAPI.js
+++ b/WebCore/inspector/front-end/ExtensionAPI.js
@@ -123,6 +123,16 @@ Resources.prototype = {
get: function(id, callback)
{
return extensionServer.sendRequest({ command: "getResources", id: id }, callback);
+ },
+
+ getPageTimings: function(callback)
+ {
+ return extensionServer.sendRequest({ command: "getPageTimings" }, callback);
+ },
+
+ getContent: function(ids, callback)
+ {
+ return extensionServer.sendRequest({ command: "getResourceContent", ids: ids }, callback);
}
}
diff --git a/WebCore/inspector/front-end/ExtensionServer.js b/WebCore/inspector/front-end/ExtensionServer.js
index bdf3a25..9ab4c0c 100644
--- a/WebCore/inspector/front-end/ExtensionServer.js
+++ b/WebCore/inspector/front-end/ExtensionServer.js
@@ -38,6 +38,8 @@ WebInspector.ExtensionServer = function()
this._registerHandler("subscribe", this._onSubscribe.bind(this));
this._registerHandler("unsubscribe", this._onUnsubscribe.bind(this));
this._registerHandler("getResources", this._onGetResources.bind(this));
+ this._registerHandler("getResourceContent", this._onGetResourceContent.bind(this));
+ this._registerHandler("getPageTimings", this._onGetPageTimings.bind(this));
this._registerHandler("createPanel", this._onCreatePanel.bind(this));
this._registerHandler("createSidebarPane", this._onCreateSidebar.bind(this));
this._registerHandler("log", this._onLog.bind(this));
@@ -238,7 +240,7 @@ WebInspector.ExtensionServer.prototype = {
var id = message.id;
var resource = null;
- resource = typeof id === "number" ? WebInspector.resources[id] : WebInspector.resourceForURL(id);
+ resource = WebInspector.resources[id] || WebInspector.resourceForURL(id);
if (!resource)
return this._status.E_NOTFOUND(typeof id + ": " + id);
WebInspector.panels.resources.showResource(resource, message.line);
@@ -261,10 +263,53 @@ WebInspector.ExtensionServer.prototype = {
if (request.id)
response = WebInspector.resources[request.id] ? resourceWrapper(request.id) : this._status.E_NOTFOUND(request.id);
else
- response = Object.properties(WebInspector.resources).map(resourceWrapper);
+ response = Object.keys(WebInspector.resources).map(resourceWrapper);
return response;
},
+ _onGetResourceContent: function(message, port)
+ {
+ var ids;
+ var response = [];
+
+ function onContentAvailable(id, encoded, content)
+ {
+ var resourceContent = {
+ id: id,
+ encoding: encoded ? "base64" : "",
+ content: content
+ };
+ response.push(resourceContent);
+ if (response.length === ids.length)
+ this._dispatchCallback(message.requestId, port, response);
+ }
+
+ if (typeof message.ids === "number")
+ ids = [ message.ids ];
+ else if (message.ids instanceof Array)
+ ids = message.ids;
+ else
+ return this._status.E_BADARGTYPE("message.ids", "Array", typeof message.ids);
+
+ for (var i = 0; i < ids.length; ++i) {
+ var id = ids[i];
+ var resource = WebInspector.resources[id];
+ if (!resource)
+ response.push(this._status.E_NOTFOUND(id));
+ else {
+ var encode = !WebInspector.Resource.Type.isTextType(resource.type);
+ WebInspector.getEncodedResourceContent(id, encode, onContentAvailable.bind(this, id, encode));
+ }
+ }
+ if (response.length === ids.length)
+ this._dispatchCallback(message.requestId, port, response);
+ },
+
+ _onGetPageTimings: function()
+ {
+ return (new WebInspector.HARLog()).buildMainResourceTimings();
+ },
+
_onAddAuditCategory: function(request)
{
var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.ruleCount);
@@ -329,12 +374,13 @@ WebInspector.ExtensionServer.prototype = {
if (typeof propValue === "number")
resourceTypes[propName] = WebInspector.Resource.Type.toString(propValue);
}
-
+ var platformAPI = WebInspector.buildPlatformExtensionAPI ? WebInspector.buildPlatformExtensionAPI() : "";
return "(function(){ " +
"var private = {};" +
"(" + WebInspector.commonExtensionSymbols.toString() + ")(private);" +
"(" + WebInspector.injectedExtensionAPI.toString() + ").apply(this, arguments);" +
"webInspector.resources.Types = " + JSON.stringify(resourceTypes) + ";" +
+ platformAPI +
"})";
},
@@ -400,3 +446,8 @@ WebInspector.addExtensions = function(extensions)
}
WebInspector.extensionServer = new WebInspector.ExtensionServer();
+
+WebInspector.getEncodedResourceContent = function(identifier, encode, callback)
+{
+ InspectorBackend.getResourceContent(identifier, encode, callback);
+}
diff --git a/WebCore/inspector/front-end/HAREntry.js b/WebCore/inspector/front-end/HAREntry.js
index 85e4f59..2b8f41b 100644
--- a/WebCore/inspector/front-end/HAREntry.js
+++ b/WebCore/inspector/front-end/HAREntry.js
@@ -56,7 +56,6 @@ WebInspector.HAREntry.prototype = {
method: this._resource.requestMethod,
url: this._resource.url,
// httpVersion: "HTTP/1.1" -- Not available.
- // cookies: [] -- Not available.
headers: this._buildHeaders(this._resource.requestHeaders),
headersSize: -1, // Not available.
bodySize: -1 // Not available.
@@ -65,22 +64,26 @@ WebInspector.HAREntry.prototype = {
res.queryString = this._buildParameters(this._resource.queryParameters);
if (this._resource.requestFormData)
res.postData = this._buildPostData();
+ if (this._resource.requestCookies)
+ res.cookies = this._buildCookies(this._resource.requestCookies);
return res;
},
_buildResponse: function()
{
- return {
+ var res = {
status: this._resource.statusCode,
statusText: this._resource.statusText,
// "httpVersion": "HTTP/1.1" -- Not available.
- // "cookies": [], -- Not available.
headers: this._buildHeaders(this._resource.responseHeaders),
content: this._buildContent(),
redirectURL: this._resource.responseHeaderValue("Location") || "",
headersSize: -1, // Not available.
bodySize: this._resource.resourceSize
};
+ if (this._resource.responseCookies)
+ res.cookies = this._buildCookies(this._resource.responseCookies);
+ return res;
},
_buildContent: function()
@@ -150,6 +153,25 @@ WebInspector.HAREntry.prototype = {
return parameters.slice();
},
+ _buildCookies: function(cookies)
+ {
+ return cookies.map(this._buildCookie.bind(this));
+ },
+
+ _buildCookie: function(cookie)
+ {
+
+ return {
+ name: cookie.name,
+ value: cookie.value,
+ path: cookie.path,
+ domain: cookie.domain,
+ expires: cookie.expires(new Date(this._resource.startTime * 1000)),
+ httpOnly: cookie.httpOnly,
+ secure: cookie.secure
+ };
+ },
+
_interval: function(start, end)
{
var timing = this._resource.timing;
@@ -181,7 +203,7 @@ WebInspector.HARLog.prototype = {
version: webKitVersion ? webKitVersion[1] : "n/a"
},
pages: this._buildPages(),
- entries: Object.properties(WebInspector.resources).map(this._convertResource)
+ entries: Object.keys(WebInspector.resources).map(this._convertResource)
}
},
@@ -192,23 +214,31 @@ WebInspector.HARLog.prototype = {
startedDateTime: new Date(WebInspector.mainResource.startTime * 1000),
id: WebInspector.mainResource.documentURL,
title: "",
- pageTimings: this._buildMainResourceTimings()
+ pageTimings: this.buildMainResourceTimings()
}
];
},
- _buildMainResourceTimings: function()
+ buildMainResourceTimings: function()
{
var resourcesPanel = WebInspector.panels.resources;
var startTime = WebInspector.mainResource.startTime;
return {
- onContentLoad: WebInspector.HAREntry._toMilliseconds(resourcesPanel.mainResourceDOMContentTime - startTime),
- onLoad: WebInspector.HAREntry._toMilliseconds(resourcesPanel.mainResourceLoadTime - startTime),
+ onContentLoad: this._pageEventTime(resourcesPanel.mainResourceDOMContentTime),
+ onLoad: this._pageEventTime(resourcesPanel.mainResourceLoadTime),
}
},
_convertResource: function(id)
{
return (new WebInspector.HAREntry(WebInspector.resources[id])).build();
+ },
+
+ _pageEventTime: function(time)
+ {
+ var startTime = WebInspector.mainResource.startTime;
+ if (time === -1 || startTime === -1)
+ return -1;
+ return WebInspector.HAREntry._toMilliseconds(time - startTime);
}
};
diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js
index 5544ed5..24b270b 100644
--- a/WebCore/inspector/front-end/InjectedScript.js
+++ b/WebCore/inspector/front-end/InjectedScript.js
@@ -220,7 +220,7 @@ InjectedScript.prototype = {
if (!callFrame)
return props;
if (expression)
- expressionResult = this._evaluateOn(callFrame.evaluate, callFrame, expression);
+ expressionResult = this._evaluateOn(callFrame.evaluate, callFrame, expression, true);
else {
// Evaluate into properties in scope of the selected call frame.
var scopeChain = callFrame.scopeChain;
@@ -230,7 +230,7 @@ InjectedScript.prototype = {
} else {
if (!expression)
expression = "this";
- expressionResult = this._evaluateOn(inspectedWindow.eval, inspectedWindow, expression);
+ expressionResult = this._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false);
}
if (typeof expressionResult === "object")
this._populatePropertyNames(expressionResult, props);
@@ -246,26 +246,29 @@ InjectedScript.prototype = {
evaluate: function(expression, objectGroup)
{
- return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup);
+ return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup, false);
},
- _evaluateAndWrap: function(evalFunction, object, expression, objectGroup)
+ _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame)
{
try {
- return this._wrapObject(this._evaluateOn(evalFunction, object, expression), objectGroup);
+ return this._wrapObject(this._evaluateOn(evalFunction, object, expression, isEvalOnCallFrame), objectGroup);
} catch (e) {
return InjectedScript.RemoteObject.fromException(e);
}
},
- _evaluateOn: function(evalFunction, object, expression)
+ _evaluateOn: function(evalFunction, object, expression, isEvalOnCallFrame)
{
// Only install command line api object for the time of evaluation.
// Surround the expression in with statements to inject our command line API so that
// the window object properties still take more precedent than our API functions.
inspectedWindow.console._commandLineAPI = this._commandLineAPI;
- expression = "with (window.console._commandLineAPI) { with (window) {\n" + expression + "\n} }";
+ // We don't want local variables to be shadowed by global ones when evaluating on CallFrame.
+ if (!isEvalOnCallFrame)
+ expression = "with (window) {\n" + expression + "\n} ";
+ expression = "with (window.console._commandLineAPI) {\n" + expression + "\n}";
var value = evalFunction.call(object, expression);
delete inspectedWindow.console._commandLineAPI;
@@ -303,7 +306,7 @@ InjectedScript.prototype = {
var callFrame = this._callFrameForId(callFrameId);
if (!callFrame)
return false;
- return this._evaluateAndWrap(callFrame.evaluate, callFrame, code, objectGroup);
+ return this._evaluateAndWrap(callFrame.evaluate, callFrame, code, objectGroup, true);
},
_callFrameForId: function(id)
diff --git a/WebCore/inspector/front-end/NetworkPanel.js b/WebCore/inspector/front-end/NetworkPanel.js
index f07b3b0..8eed425 100644
--- a/WebCore/inspector/front-end/NetworkPanel.js
+++ b/WebCore/inspector/front-end/NetworkPanel.js
@@ -32,25 +32,41 @@ WebInspector.NetworkPanel = function()
{
WebInspector.Panel.call(this, "network");
+ this.createSidebar();
+ this.sidebarElement.className = "network-sidebar";
+
this._resources = [];
this._staleResources = [];
this._resourceGridNodes = {};
this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;
+ this._hiddenCategories = {};
+
+ this._categories = WebInspector.resourceCategories;
+
+ this.containerElement = document.createElement("div");
+ this.containerElement.id = "network-container";
+ this.sidebarElement.appendChild(this.containerElement);
this._viewsContainerElement = document.createElement("div");
this._viewsContainerElement.id = "network-views";
+ this._viewsContainerElement.className = "hidden";
+
this.element.appendChild(this._viewsContainerElement);
this._createSortingFunctions();
- this._createTimelineGrid();
this._createTable();
+ this._createTimelineGrid();
this._createStatusbarButtons();
+ this._createFilterStatusBarItems();
+ this._createSummaryBar();
this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);
this.calculator = new WebInspector.NetworkTransferTimeCalculator();
- this.filter(this.filterAllElement, false);
+ this._filter(this._filterAllElement, false);
+
+ this._toggleGridMode();
}
WebInspector.NetworkPanel.prototype = {
@@ -61,7 +77,7 @@ WebInspector.NetworkPanel.prototype = {
get statusBarItems()
{
- return [this._largerResourcesButton.element, this._clearButton.element];
+ return [this._largerResourcesButton.element, this._clearButton.element, this._filterBarElement];
},
isCategoryVisible: function(categoryName)
@@ -78,32 +94,87 @@ WebInspector.NetworkPanel.prototype = {
{
WebInspector.Panel.prototype.resize.call(this);
this._dataGrid.updateWidths();
+ this._positionSummaryBar();
+ },
+
+ updateSidebarWidth: function()
+ {
+ if (!this._viewingResourceMode)
+ return;
+ WebInspector.Panel.prototype.updateSidebarWidth.apply(this, arguments);
+ },
+
+ updateMainViewWidth: function(width)
+ {
+ this._viewsContainerElement.style.left = width + "px";
+ },
+
+ handleShortcut: function(event)
+ {
+ if (this._viewingResourceMode && event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+ this._toggleGridMode();
+ event.handled = true;
+ }
+ },
+
+ _positionSummaryBar: function()
+ {
+ // Position the total bar.
+ const rowHeight = 22;
+ const summaryBarHeight = 22;
+ var offsetHeight = this.element.offsetHeight;
+
+ var parentElement = this._summaryBarElement.parentElement;
+
+ if (this._summaryBarElement.parentElement !== this.element && offsetHeight > (this._dataGrid.children.length - 1) * rowHeight + summaryBarHeight) {
+ // 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 && offsetHeight - summaryBarHeight < this._dataGrid.children.length * rowHeight) {
+ // 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();
+ }
+ },
+
+ _resetSummaryBar: function()
+ {
+ delete this._summaryBarRowNode;
+ this._summaryBarElement.parentElement.removeChild(this._summaryBarElement);
+ this._updateSummaryBar();
},
_createTimelineGrid: function()
{
this._timelineGrid = new WebInspector.TimelineGrid();
this._timelineGrid.element.addStyleClass("network-timeline-grid");
- this.element.appendChild(this._timelineGrid.element);
+ this._dataGrid.element.appendChild(this._timelineGrid.element);
},
_createTable: function()
{
- this.containerElement = document.createElement("div");
- this.containerElement.id = "network-container";
- this.element.appendChild(this.containerElement);
+ var columns = {name: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}};
+ columns.name.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path"));
+ columns.name.sortable = true;
+ columns.name.width = "20%";
+ columns.name.disclosure = true;
- var columns = {url: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}};
- columns.url.title = WebInspector.UIString("URL");
- columns.url.sortable = true;
- columns.url.width = "20%";
- columns.url.disclosure = true;
-
columns.method.title = WebInspector.UIString("Method");
columns.method.sortable = true;
columns.method.width = "7%";
- columns.status.title = WebInspector.UIString("Status");
+ columns.status.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text"));
columns.status.sortable = true;
columns.status.width = "8%";
@@ -111,41 +182,233 @@ WebInspector.NetworkPanel.prototype = {
columns.type.sortable = true;
columns.type.width = "7%";
- columns.size.title = WebInspector.UIString("Size");
+ columns.size.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Transfer"));
columns.size.sortable = true;
columns.size.width = "10%";
columns.size.aligned = "right";
- columns.time.title = WebInspector.UIString("Time");
+ columns.time.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Duration"));
columns.time.sortable = true;
columns.time.width = "10%";
columns.time.aligned = "right";
columns.timeline.title = "";
- columns.timeline.sortable = true;
+ columns.timeline.sortable = false;
columns.timeline.width = "40%";
- columns.timeline.sort = true;
+ columns.timeline.sort = "ascending";
this._dataGrid = new WebInspector.DataGrid(columns);
- this.element.appendChild(this._dataGrid.element);
+ this.containerElement.appendChild(this._dataGrid.element);
this._dataGrid.addEventListener("sorting changed", this._sortItems, this);
this._dataGrid.addEventListener("width changed", this._updateDividersIfNeeded, this);
+
+ this._patchTimelineHeader();
+ },
+
+ _makeHeaderFragment: function(title, subtitle)
+ {
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(document.createTextNode(title));
+ var subtitleDiv = document.createElement("div");
+ subtitleDiv.className = "network-header-subtitle";
+ subtitleDiv.textContent = subtitle;
+ fragment.appendChild(subtitleDiv);
+ return fragment;
+ },
+
+ _patchTimelineHeader: function()
+ {
+ var timelineSorting = document.createElement("select");
+
+ var option = document.createElement("option");
+ option.value = "startTime";
+ option.label = WebInspector.UIString("Timeline");
+ timelineSorting.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "startTime";
+ option.label = WebInspector.UIString("Start Time");
+ timelineSorting.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "responseTime";
+ option.label = WebInspector.UIString("Response Time");
+ timelineSorting.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "endTime";
+ option.label = WebInspector.UIString("End Time");
+ timelineSorting.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "duration";
+ option.label = WebInspector.UIString("Duration");
+ timelineSorting.appendChild(option);
+
+ option = document.createElement("option");
+ option.value = "latency";
+ option.label = WebInspector.UIString("Latency");
+ timelineSorting.appendChild(option);
+
+ var header = this._dataGrid.headerTableHeader("timeline");
+ header.firstChild.appendChild(timelineSorting);
+
+ timelineSorting.addEventListener("click", function(event) { event.stopPropagation() }, false);
+ timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false);
+ this._timelineSortSelector = timelineSorting;
},
_createSortingFunctions: function()
{
this._sortingFunctions = {};
- this._sortingFunctions.url = WebInspector.NetworkDataGridNode.URLComparator;
- this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method");
- this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode");
- this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType");
- this._sortingFunctions.size = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "resourceSize");
- this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration");
- this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime");
+ this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator;
+ this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method", false);
+ this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode", false);
+ this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType", false);
+ this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator;
+ this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", false);
+ this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+ this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
+ this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "endTime", false);
+ this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "responseReceivedTime", false);
+ this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", true);
+ this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "latency", true);
+
+ var timeCalculator = new WebInspector.NetworkTransferTimeCalculator();
+ var durationCalculator = new WebInspector.NetworkTransferDurationCalculator();
+
+ this._calculators = {};
+ this._calculators.timeline = timeCalculator;
+ this._calculators.startTime = timeCalculator;
+ this._calculators.endTime = timeCalculator;
+ this._calculators.responseTime = timeCalculator;
+ this._calculators.duration = durationCalculator;
+ this._calculators.latency = durationCalculator;
},
- filter: function(target, selectMultiple)
+ _sortItems: function()
{
+ var columnIdentifier = this._dataGrid.sortColumnIdentifier;
+ if (columnIdentifier === "timeline") {
+ this._sortByTimeline();
+ return;
+ }
+ var sortingFunction = this._sortingFunctions[columnIdentifier];
+ if (!sortingFunction)
+ return;
+
+ this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
+ this._timelineSortSelector.selectedIndex = 0;
+ },
+
+ _sortByTimeline: function()
+ {
+ var selectedIndex = this._timelineSortSelector.selectedIndex;
+ if (!selectedIndex)
+ selectedIndex = 1; // Sort by start time by default.
+ var selectedOption = this._timelineSortSelector[selectedIndex];
+ var value = selectedOption.value;
+
+ var sortingFunction = this._sortingFunctions[value];
+ this._dataGrid.sortNodes(sortingFunction);
+ this.calculator = this._calculators[value];
+ if (this.calculator.startAtZero)
+ this._timelineGrid.hideEventDividers();
+ else
+ this._timelineGrid.showEventDividers();
+ this._dataGrid.markColumnAsSortedBy("timeline", "ascending");
+ },
+
+ _createFilterStatusBarItems: function()
+ {
+ var filterBarElement = document.createElement("div");
+ filterBarElement.className = "scope-bar status-bar-item";
+ filterBarElement.id = "network-filter";
+
+ function createFilterElement(category, label)
+ {
+ var categoryElement = document.createElement("li");
+ categoryElement.category = category;
+ categoryElement.className = category;
+ categoryElement.appendChild(document.createTextNode(label));
+ categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
+ filterBarElement.appendChild(categoryElement);
+
+ return categoryElement;
+ }
+
+ this._filterAllElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));
+
+ // Add a divider
+ var dividerElement = document.createElement("div");
+ dividerElement.addStyleClass("scope-bar-divider");
+ filterBarElement.appendChild(dividerElement);
+
+ for (var category in this._categories)
+ createFilterElement.call(this, category, this._categories[category].title);
+ this._filterBarElement = filterBarElement;
+ },
+
+ _createSummaryBar: function()
+ {
+ this._summaryBarElement = document.createElement("div");
+ this._summaryBarElement.className = "network-summary-bar";
+ this.containerElement.appendChild(this._summaryBarElement);
+ },
+
+ _updateSummaryBar: function()
+ {
+ this._positionSummaryBar(); // Grid is growing.
+ var numRequests = this._resources.length;
+
+ if (!numRequests) {
+ if (this._summaryBarElement._isDisplayingWarning)
+ return;
+ this._summaryBarElement._isDisplayingWarning = true;
+
+ var img = document.createElement("img");
+ 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;
+ }
+ delete this._summaryBarElement._isDisplayingWarning;
+
+ var transferSize = 0;
+ var baseTime = -1;
+ var maxTime = -1;
+ for (var i = 0; i < this._resources.length; ++i) {
+ var resource = this._resources[i];
+ transferSize += resource.cached ? 0 : resource.transferSize;
+ if (resource.isMainResource)
+ baseTime = resource.startTime;
+ if (resource.endTime > maxTime)
+ maxTime = resource.endTime;
+ }
+ var text = String.sprintf(WebInspector.UIString("%d requests"), numRequests);
+ text += " \u2758 " + String.sprintf(WebInspector.UIString("%s transferred"), Number.bytesToString(transferSize));
+ if (baseTime !== -1 && this._mainResourceLoadTime !== -1 && this._mainResourceDOMContentTime !== -1 && this._mainResourceDOMContentTime > baseTime) {
+ text += " \u2758 " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"),
+ Number.secondsToString(maxTime - baseTime),
+ Number.secondsToString(this._mainResourceLoadTime - baseTime),
+ Number.secondsToString(this._mainResourceDOMContentTime - baseTime));
+ }
+ this._summaryBarElement.textContent = text;
+ },
+
+ _showCategory: function(category)
+ {
+ this._dataGrid.element.addStyleClass("filter-" + category);
+ delete this._hiddenCategories[category];
+ },
+
+ _hideCategory: function(category)
+ {
+ this._dataGrid.element.removeStyleClass("filter-" + category);
+ this._hiddenCategories[category] = true;
},
_updateFilter: function(e)
@@ -157,16 +420,65 @@ WebInspector.NetworkPanel.prototype = {
if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
selectMultiple = true;
- this.filter(e.target, selectMultiple);
-
- // When we are updating our filtering, scroll to the top so we don't end up
- // in blank graph under all the resources.
- this.containerElement.scrollTop = 0;
+ this._filter(e.target, selectMultiple);
var searchField = document.getElementById("search");
WebInspector.doPerformSearch(searchField.value, WebInspector.shortSearchWasForcedByKeyEvent, false, true);
},
+ _filter: function(target, selectMultiple)
+ {
+ function unselectAll()
+ {
+ for (var i = 0; i < this._filterBarElement.childNodes.length; ++i) {
+ var child = this._filterBarElement.childNodes[i];
+ if (!child.category)
+ continue;
+
+ child.removeStyleClass("selected");
+ this._hideCategory(child.category);
+ }
+ }
+
+ if (target.category === this._filterAllElement) {
+ if (target.hasStyleClass("selected")) {
+ // We can't unselect All, so we break early here
+ return;
+ }
+
+ // If All wasn't selected, and now is, unselect everything else.
+ unselectAll.call(this);
+ } else {
+ // Something other than All is being selected, so we want to unselect All.
+ if (this._filterAllElement.hasStyleClass("selected")) {
+ this._filterAllElement.removeStyleClass("selected");
+ this._hideCategory("all");
+ }
+ }
+
+ if (!selectMultiple) {
+ // If multiple selection is off, we want to unselect everything else
+ // and just select ourselves.
+ unselectAll.call(this);
+
+ target.addStyleClass("selected");
+ this._showCategory(target.category);
+ return;
+ }
+
+ if (target.hasStyleClass("selected")) {
+ // If selectMultiple is turned on, and we were selected, we just
+ // want to unselect ourselves.
+ target.removeStyleClass("selected");
+ this._hideCategory(target.category);
+ } else {
+ // If selectMultiple is turned on, and we weren't selected, we just
+ // want to select ourselves.
+ target.addStyleClass("selected");
+ this._showCategory(target.category);
+ }
+ },
+
_scheduleRefresh: function()
{
if (this._needsRefresh)
@@ -178,18 +490,16 @@ WebInspector.NetworkPanel.prototype = {
this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
},
- _sortItems: function()
- {
- var columnIdentifier = this._dataGrid.sortColumnIdentifier;
- var sortingFunction = this._sortingFunctions[columnIdentifier];
- if (!sortingFunction)
- return;
- this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
- },
-
_updateDividersIfNeeded: function(force)
{
- this._timelineGrid.element.style.left = this._dataGrid.resizers[this._dataGrid.resizers.length - 1].style.left;
+ var timelineColumn = this._dataGrid.columns.timeline;
+ for (var i = 0; i < this._dataGrid.resizers.length; ++i) {
+ if (timelineColumn.ordinal === this._dataGrid.resizers[i].rightNeighboringColumnID) {
+ // Position timline grid location.
+ this._timelineGrid.element.style.left = this._dataGrid.resizers[i].style.left;
+ this._timelineGrid.element.style.right = "18px";
+ }
+ }
var proceed = true;
if (!this.visible) {
@@ -296,7 +606,7 @@ WebInspector.NetworkPanel.prototype = {
_createStatusbarButtons: function()
{
this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
- this._clearButton.addEventListener("click", this.reset.bind(this), false);
+ this._clearButton.addEventListener("click", this._reset.bind(this), false);
this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
WebInspector.applicationSettings.addEventListener("loaded", this._settingsLoaded, this);
@@ -354,27 +664,18 @@ WebInspector.NetworkPanel.prototype = {
view.visible = false;
}
this._dataGrid.updateWidths();
+ this._positionSummaryBar();
+ },
+
+ hide: function()
+ {
+ WebInspector.Panel.prototype.hide.call(this);
+ this._popoverHelper.hidePopup();
},
get searchableViews()
{
var views = [];
-
- const visibleView = this.visibleView;
- if (visibleView && visibleView.performSearch)
- views.push(visibleView);
-
- var resourcesLength = this._resources.length;
- for (var i = 0; i < resourcesLength; ++i) {
- var resource = this._resources[i];
- if (!this._resourceGridNode(resource) || !this._resourceGridNode(resource).selectable)
- continue;
- var resourceView = this.resourceViewForResource(resource);
- if (!resourceView.performSearch || resourceView === visibleView)
- continue;
- views.push(resourceView);
- }
-
return views;
},
@@ -420,7 +721,7 @@ WebInspector.NetworkPanel.prototype = {
var node = this._resourceGridNode(resource);
if (!node) {
// Create the timeline tree element and graph.
- node = new WebInspector.NetworkDataGridNode(resource);
+ node = new WebInspector.NetworkDataGridNode(this, resource);
this._resourceGridNodes[resource.identifier] = node;
this._dataGrid.appendChild(node);
}
@@ -441,54 +742,35 @@ WebInspector.NetworkPanel.prototype = {
this._staleResources = [];
this._sortItems();
+ this._updateSummaryBar();
this._dataGrid.updateWidths();
},
- reset: function()
+ _reset: function()
{
this._popoverHelper.hidePopup();
- this.closeVisibleResource();
+ this._closeVisibleResource();
- delete this.currentQuery;
- this.searchCanceled();
-
- if (this._resources) {
- var resourcesLength = this._resources.length;
- for (var i = 0; i < resourcesLength; ++i) {
- var resource = this._resources[i];
-
- resource.warnings = 0;
- resource.errors = 0;
-
- delete resource._resourcesView;
- }
- }
+ this._toggleGridMode();
// Begin reset timeline
- this.containerElement.scrollTop = 0;
-
if (this._calculator)
this._calculator.reset();
- if (this._resources) {
- var itemsLength = this._resources.length;
- for (var i = 0; i < itemsLength; ++i) {
- var item = this._resources[i];
- }
- }
-
this._resources = [];
this._staleResources = [];
this._resourceGridNodes = {};
this._dataGrid.removeChildren();
+ delete this._summaryBarRowNode;
this._updateDividersIfNeeded(true);
// End reset timeline.
-
+
this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;
this._viewsContainerElement.removeChildren();
+ this._resetSummaryBar();
},
addResource: function(resource)
@@ -501,20 +783,17 @@ WebInspector.NetworkPanel.prototype = {
{
this._staleResources.push(resource);
this._scheduleRefresh();
- },
- recreateViewForResourceIfNeeded: function(resource)
- {
if (!resource || !resource._resourcesView)
return;
+ if (this._resourceViewTypeMatchesResource(resource, resource._resourcesView))
+ return;
+
var newView = this._createResourceView(resource);
if (newView.__proto__ === resource._resourcesView.__proto__)
return;
- if (!this.currentQuery && this._resourceGridNode(resource))
- this._resourceGridNode(resource).updateErrorsAndWarnings();
-
var oldView = resource._resourcesView;
var oldViewParentNode = oldView.visible ? oldView.element.parentNode : null;
@@ -533,27 +812,26 @@ WebInspector.NetworkPanel.prototype = {
canShowSourceLine: function(url, line)
{
- return this._resourceTrackingEnabled && !!WebInspector.resourceForURL(url);
+ return false;
},
showSourceLine: function(url, line)
{
- this.showResource(WebInspector.resourceForURL(url), line);
},
- showResource: function(resource, line)
+ _showResource: function(resource, line)
{
if (!resource)
return;
this._popoverHelper.hidePopup();
- this.containerElement.addStyleClass("viewing-resource");
+ this._toggleViewingResourceMode();
if (this.visibleResource && this.visibleResource._resourcesView)
this.visibleResource._resourcesView.hide();
- var view = this.resourceViewForResource(resource);
+ var view = this._resourceViewForResource(resource);
view.headersVisible = true;
view.show(this._viewsContainerElement);
@@ -565,23 +843,13 @@ WebInspector.NetworkPanel.prototype = {
view.highlightLine(line);
}
- this.revealAndSelectItem(resource);
-
this.visibleResource = resource;
-
this.updateSidebarWidth();
},
- showView: function(view)
- {
- if (!view)
- return;
- this.showResource(view.resource);
- },
-
- closeVisibleResource: function()
+ _closeVisibleResource: function()
{
- this.containerElement.removeStyleClass("viewing-resource");
+ this.element.removeStyleClass("viewing-resource");
if (this.visibleResource && this.visibleResource._resourcesView)
this.visibleResource._resourcesView.hide();
@@ -593,7 +861,7 @@ WebInspector.NetworkPanel.prototype = {
this.updateSidebarWidth();
},
- resourceViewForResource: function(resource)
+ _resourceViewForResource: function(resource)
{
if (!resource)
return null;
@@ -602,23 +870,6 @@ WebInspector.NetworkPanel.prototype = {
return resource._resourcesView;
},
- sourceFrameForResource: function(resource)
- {
- var view = this.resourceViewForResource(resource);
- if (!view)
- return null;
-
- if (!view.setupSourceFrameIfNeeded)
- return null;
-
- // Setting up the source frame requires that we be attached.
- if (!this.element.parentNode)
- this.attach();
-
- view.setupSourceFrameIfNeeded();
- return view.sourceFrame;
- },
-
_toggleLargerResources: function()
{
WebInspector.applicationSettings.resourcesLargeRows = !WebInspector.applicationSettings.resourcesLargeRows;
@@ -631,9 +882,11 @@ WebInspector.NetworkPanel.prototype = {
if (!enabled) {
this._largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
this._dataGrid.element.addStyleClass("small");
+ this._timelineGrid.element.addStyleClass("small");
} else {
this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
this._dataGrid.element.removeStyleClass("small");
+ this._timelineGrid.element.removeStyleClass("small");
}
},
@@ -654,6 +907,24 @@ WebInspector.NetworkPanel.prototype = {
}
},
+ _resourceViewTypeMatchesResource: function(resource, resourceView)
+ {
+ switch (resource.category) {
+ case WebInspector.resourceCategories.documents:
+ case WebInspector.resourceCategories.stylesheets:
+ case WebInspector.resourceCategories.scripts:
+ case WebInspector.resourceCategories.xhr:
+ return resourceView instanceof WebInspector.SourceView;
+ case WebInspector.resourceCategories.images:
+ return resourceView instanceof WebInspector.ImageView;
+ case WebInspector.resourceCategories.fonts:
+ return resourceView instanceof WebInspector.FontView;
+ default:
+ return resourceView instanceof WebInspector.ResourceView;
+ }
+ return false;
+ },
+
_getPopoverAnchor: function(element)
{
var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label");
@@ -751,20 +1022,85 @@ WebInspector.NetworkPanel.prototype = {
return popover;
},
- hide: function()
+ _toggleGridMode: function()
{
- WebInspector.Panel.prototype.hide.call(this);
- this._popoverHelper.hidePopup();
+ if (this._viewingResourceMode) {
+ this._viewingResourceMode = false;
+ this.element.removeStyleClass("viewing-resource");
+ this._dataGrid.element.removeStyleClass("viewing-resource-mode");
+ this._viewsContainerElement.addStyleClass("hidden");
+ this.sidebarElement.style.right = 0;
+ this.sidebarElement.style.removeProperty("width");
+ }
+
+ if (this._briefGrid) {
+ this._dataGrid.element.removeStyleClass("full-grid-mode");
+ this._dataGrid.element.addStyleClass("brief-grid-mode");
+
+ this._dataGrid.hideColumn("method");
+ this._dataGrid.hideColumn("status");
+ this._dataGrid.hideColumn("type");
+ this._dataGrid.hideColumn("size");
+ this._dataGrid.hideColumn("time");
+
+ var widths = {};
+ widths.name = 20;
+ widths.timeline = 80;
+ } else {
+ this._dataGrid.element.addStyleClass("full-grid-mode");
+ this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+ this._dataGrid.showColumn("method");
+ this._dataGrid.showColumn("status");
+ this._dataGrid.showColumn("type");
+ this._dataGrid.showColumn("size");
+ this._dataGrid.showColumn("time");
+
+ var widths = {};
+ widths.name = 20;
+ widths.method = 7;
+ widths.status = 8;
+ widths.type = 7;
+ widths.size = 10;
+ widths.time = 10;
+ widths.timeline = 40;
+ }
+
+ this._dataGrid.showColumn("timeline");
+ this._dataGrid.applyColumnWidthsMap(widths);
+
+ },
+
+ _toggleViewingResourceMode: function()
+ {
+ if (this._viewingResourceMode)
+ return;
+ this._viewingResourceMode = true;
+ this._preservedColumnWidths = this._dataGrid.columnWidthsMap();
+
+ this.element.addStyleClass("viewing-resource");
+ this._dataGrid.element.addStyleClass("viewing-resource-mode");
+ this._dataGrid.element.removeStyleClass("full-grid-mode");
+ this._dataGrid.element.removeStyleClass("brief-grid-mode");
+
+ this._dataGrid.hideColumn("method");
+ this._dataGrid.hideColumn("status");
+ this._dataGrid.hideColumn("type");
+ this._dataGrid.hideColumn("size");
+ this._dataGrid.hideColumn("time");
+ this._dataGrid.hideColumn("timeline");
+
+ this._viewsContainerElement.removeStyleClass("hidden");
+ this.updateSidebarWidth(200);
+
+ var widths = {};
+ widths.name = 100;
+ this._dataGrid.applyColumnWidthsMap(widths);
}
}
WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.getResourceContent = function(identifier, callback)
-{
- InspectorBackend.getResourceContent(identifier, callback);
-}
-
WebInspector.NetworkBaseCalculator = function()
{
}
@@ -1047,86 +1383,50 @@ WebInspector.NetworkTransferDurationCalculator.prototype = {
WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;
-WebInspector.NetworkTransferSizeCalculator = function()
+WebInspector.NetworkDataGridNode = function(panel, resource)
{
- WebInspector.NetworkBaseCalculator.call(this);
+ WebInspector.DataGridNode.call(this, {});
+ this._panel = panel;
+ this._resource = resource;
}
-WebInspector.NetworkTransferSizeCalculator.prototype = {
- computeBarGraphLabels: function(resource)
- {
- var networkBytes = this._networkBytes(resource);
- var resourceBytes = this._value(resource);
- if (networkBytes && networkBytes !== resourceBytes) {
- // Transferred size is not the same as reported resource length.
- var networkBytesString = this.formatValue(networkBytes);
- var left = networkBytesString;
- var right = this.formatValue(resourceBytes);
- var tooltip = right ? WebInspector.UIString("%s (%s transferred)", right, networkBytesString) : right;
- } else {
- var left = this.formatValue(resourceBytes);
- var right = left;
- var tooltip = left;
- }
- if (resource.cached)
- tooltip = WebInspector.UIString("%s (from cache)", tooltip);
- return {left: left, right: right, tooltip: tooltip};
- },
-
- computeBarGraphPercentages: function(item)
+WebInspector.NetworkDataGridNode.prototype = {
+ createCells: function()
{
- const resourceBytesAsPercent = (this._value(item) / this.boundarySpan) * 100;
- const networkBytesAsPercent = this._networkBytes(item) ? (this._networkBytes(item) / this.boundarySpan) * 100 : resourceBytesAsPercent;
- return {start: 0, middle: networkBytesAsPercent, end: resourceBytesAsPercent};
+ this._nameCell = this._createDivInTD("name");
+ this._methodCell = this._createDivInTD("method");
+ this._statusCell = this._createDivInTD("status");
+ this._typeCell = this._createDivInTD("type");
+ this._sizeCell = this._createDivInTD("size");
+ this._timeCell = this._createDivInTD("time");
+ this._createTimelineCell();
},
- _value: function(resource)
+ select: function()
{
- return resource.resourceSize;
+ WebInspector.DataGridNode.prototype.select.apply(this, arguments);
+ this._panel._showResource(this._resource);
},
- _networkBytes: function(resource)
+ get selectable()
{
- return resource.transferSize;
+ if (!this._panel._hiddenCategories.all)
+ return true;
+ if (this._panel._hiddenCategories[this._resource.category.name])
+ return false;
+ return true;
},
- formatValue: function(value)
- {
- return Number.bytesToString(value, WebInspector.UIString);
- }
-}
-
-WebInspector.NetworkTransferSizeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype;
-
-WebInspector.NetworkDataGridNode = function(resource)
-{
- WebInspector.DataGridNode.call(this, {});
- this._resource = resource;
-}
-
-WebInspector.NetworkDataGridNode.prototype = {
- createCells: function()
+ _createDivInTD: function(columnIdentifier)
{
- this._urlCell = this._createDivInTD("url-column");
- this._methodCell = this._createDivInTD("optional-column");
- this._statusCell = this._createDivInTD("optional-column");
- this._typeCell = this._createDivInTD("optional-column");
- this._sizeCell = this._createDivInTD("optional-column right");
- this._timeCell = this._createDivInTD("optional-column right");
- this._createTimelineCell();
- },
-
- _createDivInTD: function(className) {
var td = document.createElement("td");
- if (className)
- td.className = className;
+ td.className = columnIdentifier + "-column";
var div = document.createElement("div");
td.appendChild(div);
this._element.appendChild(td);
return div;
},
-
_createTimelineCell: function()
{
this._graphElement = document.createElement("div");
@@ -1156,13 +1456,14 @@ WebInspector.NetworkDataGridNode.prototype = {
this._barAreaElement.appendChild(this._labelRightElement);
this._timelineCell = document.createElement("td");
+ this._timelineCell.className = "timeline-column";
this._element.appendChild(this._timelineCell);
this._timelineCell.appendChild(this._graphElement);
},
refreshResource: function()
{
- this._refreshURLCell();
+ this._refreshNameCell();
this._methodCell.textContent = this._resource.requestMethod;
@@ -1188,9 +1489,9 @@ WebInspector.NetworkDataGridNode.prototype = {
}
},
- _refreshURLCell: function()
+ _refreshNameCell: function()
{
- this._urlCell.removeChildren();
+ this._nameCell.removeChildren();
if (this._resource.category === WebInspector.resourceCategories.images) {
var previewImage = document.createElement("img");
@@ -1204,8 +1505,8 @@ WebInspector.NetworkDataGridNode.prototype = {
var iconElement = document.createElement("img");
iconElement.className = "icon";
}
- this._urlCell.appendChild(iconElement);
- this._urlCell.appendChild(document.createTextNode(this._fileName()));
+ this._nameCell.appendChild(iconElement);
+ this._nameCell.appendChild(document.createTextNode(this._fileName()));
var subtitle = this._resource.displayDomain;
@@ -1216,13 +1517,8 @@ WebInspector.NetworkDataGridNode.prototype = {
subtitle += this._resource.path.substring(0, lastPathComponentIndex);
}
- var subtitleElement = document.createElement("div");
- subtitleElement.className = "network-grid-subtitle";
- subtitleElement.textContent = subtitle;
- this._urlCell.appendChild(subtitleElement);
-
-
- this._urlCell.title = this._resource.url;
+ this._appendSubtitle(this._nameCell, subtitle);
+ this._nameCell.title = this._resource.url;
},
_fileName: function()
@@ -1238,16 +1534,6 @@ WebInspector.NetworkDataGridNode.prototype = {
this._statusCell.removeChildren();
if (this._resource.statusCode) {
- var img = document.createElement("img");
- if (this._resource.statusCode < 300)
- img.src = "Images/successGreenDot.png";
- else if (this._resource.statusCode < 400)
- img.src = "Images/warningOrangeDot.png";
- else
- img.src = "Images/errorRedDot.png";
-
- img.className = "resource-status-image";
- this._statusCell.appendChild(img);
this._statusCell.appendChild(document.createTextNode(this._resource.statusCode));
this._statusCell.removeStyleClass("network-dim-cell");
this._appendSubtitle(this._statusCell, this._resource.statusText);
@@ -1287,7 +1573,7 @@ WebInspector.NetworkDataGridNode.prototype = {
_appendSubtitle: function(cellElement, subtitleText)
{
var subtitleElement = document.createElement("div");
- subtitleElement.className = "network-grid-subtitle";
+ subtitleElement.className = "network-cell-subtitle";
subtitleElement.textContent = subtitleText;
cellElement.appendChild(subtitleElement);
},
@@ -1324,6 +1610,8 @@ WebInspector.NetworkDataGridNode.prototype = {
_refreshLabelPositions: function()
{
+ if (!this._percentages)
+ return;
this._labelLeftElement.style.removeProperty("left");
this._labelLeftElement.style.removeProperty("right");
this._labelLeftElement.removeStyleClass("before");
@@ -1389,7 +1677,7 @@ WebInspector.NetworkDataGridNode.prototype = {
}
}
-WebInspector.NetworkDataGridNode.URLComparator = function(a, b)
+WebInspector.NetworkDataGridNode.NameComparator = function(a, b)
{
var aFileName = a._resource.displayName + (a._resource.queryString ? a._resource.queryString : "");
var bFileName = b._resource.displayName + (b._resource.queryString ? b._resource.queryString : "");
@@ -1400,15 +1688,47 @@ WebInspector.NetworkDataGridNode.URLComparator = function(a, b)
return 0;
}
-WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, a, b)
+WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
+{
+ if (b._resource.cached && !a._resource.cached)
+ return 1;
+ if (a._resource.cached && !b._resource.cached)
+ return -1;
+
+ if (a._resource.resourceSize === b._resource.resourceSize)
+ return 0;
+
+ return a._resource.resourceSize - b._resource.resourceSize;
+}
+
+WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, revert, a, b)
{
var aValue = a._resource[propertyName];
var bValue = b._resource[propertyName];
if (aValue > bValue)
- return 1;
+ return revert ? -1 : 1;
if (bValue > aValue)
- return -1;
+ return revert ? 1 : -1;
return 0;
}
WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.NetworkTotalGridNode = function(element)
+{
+ this._summaryBarElement = element;
+ WebInspector.DataGridNode.call(this, {summaryRow: true});
+}
+
+WebInspector.NetworkTotalGridNode.prototype = {
+ 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/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js
index 2bd76f9..ca02f9e 100644
--- a/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/WebCore/inspector/front-end/ProfilesPanel.js
@@ -116,7 +116,7 @@ WebInspector.ProfilesPanel = function()
this.clearResultsButton.addEventListener("click", this._clearProfiles.bind(this), false);
this.profileViewStatusBarItemsContainer = document.createElement("div");
- this.profileViewStatusBarItemsContainer.id = "profile-view-status-bar-items";
+ this.profileViewStatusBarItemsContainer.className = "status-bar-items";
this.welcomeView = new WebInspector.WelcomeView("profiles", WebInspector.UIString("Welcome to the Profiles panel"));
this.element.appendChild(this.welcomeView.element);
@@ -550,7 +550,7 @@ WebInspector.ProfilesPanel.prototype = {
{
this.welcomeView.element.style.left = width + "px";
this.profileViews.style.left = width + "px";
- this.profileViewStatusBarItemsContainer.style.left = width + "px";
+ this.profileViewStatusBarItemsContainer.style.left = Math.max(155, width) + "px";
this.resize();
}
}
diff --git a/WebCore/inspector/front-end/PropertiesSection.js b/WebCore/inspector/front-end/PropertiesSection.js
index 5ced9ef..1ca52ce 100644
--- a/WebCore/inspector/front-end/PropertiesSection.js
+++ b/WebCore/inspector/front-end/PropertiesSection.js
@@ -32,7 +32,7 @@ WebInspector.PropertiesSection = function(title, subtitle)
WebInspector.Section.call(this, title, subtitle);
this.propertiesElement = document.createElement("ol");
- this.propertiesElement.className = "properties source-code";
+ this.propertiesElement.className = "properties properties-tree source-code";
this.propertiesElement.tabIndex = 0;
this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
this.propertiesTreeOutline.section = this;
diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js
index ea9052d..fe2f7d2 100644
--- a/WebCore/inspector/front-end/Resource.js
+++ b/WebCore/inspector/front-end/Resource.js
@@ -29,7 +29,7 @@
WebInspector.Resource = function(identifier, url)
{
this.identifier = identifier;
- this._url = url;
+ this.url = url;
this._startTime = -1;
this._endTime = -1;
this._requestMethod = "";
@@ -97,14 +97,19 @@ WebInspector.Resource.prototype = {
if (this._url === x)
return;
- var oldURL = this._url;
this._url = x;
delete this._parsedQueryParameters;
- // FIXME: We should make the WebInspector object listen for the "url changed" event.
- // Then resourceURLChanged can be removed.
- WebInspector.resourceURLChanged(this, oldURL);
- this.dispatchEventToListeners("url changed");
+ var parsedURL = x.asParsedURL();
+ this.domain = parsedURL ? parsedURL.host : "";
+ this.path = parsedURL ? parsedURL.path : "";
+ this.lastPathComponent = "";
+ if (parsedURL && parsedURL.path) {
+ var lastSlashIndex = parsedURL.path.lastIndexOf("/");
+ if (lastSlashIndex !== -1)
+ this.lastPathComponent = parsedURL.path.substring(lastSlashIndex + 1);
+ }
+ this.lastPathComponentLowerCase = this.lastPathComponent.toLowerCase();
},
get documentURL()
@@ -114,46 +119,21 @@ WebInspector.Resource.prototype = {
set documentURL(x)
{
- if (this._documentURL === x)
- return;
this._documentURL = x;
},
- get domain()
- {
- return this._domain;
- },
-
- set domain(x)
- {
- if (this._domain === x)
- return;
- this._domain = x;
- },
-
- get lastPathComponent()
- {
- return this._lastPathComponent;
- },
-
- set lastPathComponent(x)
- {
- if (this._lastPathComponent === x)
- return;
- this._lastPathComponent = x;
- this._lastPathComponentLowerCase = x ? x.toLowerCase() : null;
- },
-
get displayName()
{
- var title = this.lastPathComponent;
- if (!title)
- title = this.displayDomain;
- if (!title && this.url)
- title = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
- if (title === "/")
- title = this.url;
- return title;
+ if (this._displayName)
+ return this._displayName;
+ this._displayName = this.lastPathComponent;
+ if (!this._displayName)
+ this._displayName = this.displayDomain;
+ if (!this._displayName && this.url)
+ this._displayName = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+ if (this._displayName === "/")
+ this._displayName = this.url;
+ return this._displayName;
},
get displayDomain()
@@ -171,29 +151,22 @@ WebInspector.Resource.prototype = {
set startTime(x)
{
- if (this._startTime === x)
- return;
-
this._startTime = x;
-
- if (WebInspector.panels.resources)
- WebInspector.panels.resources.refreshResource(this);
},
get responseReceivedTime()
{
+ if (this.timing && this.timing.requestTime) {
+ // Calculate responseReceivedTime from timing data for better accuracy.
+ // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis.
+ return this.timing.requestTime + this.timing.receiveHeadersEnd / 1000.0;
+ }
return this._responseReceivedTime || -1;
},
set responseReceivedTime(x)
{
- if (this._responseReceivedTime === x)
- return;
-
this._responseReceivedTime = x;
-
- if (WebInspector.panels.resources)
- WebInspector.panels.resources.refreshResource(this);
},
get endTime()
@@ -203,13 +176,13 @@ WebInspector.Resource.prototype = {
set endTime(x)
{
- if (this._endTime === x)
- return;
+ // In case of fast load (or in case of cached resources), endTime on network stack
+ // can be less then m_responseReceivedTime measured in WebCore. Normalize it here,
+ // prefer actualEndTime to m_responseReceivedTime.
+ if (x < this.responseReceivedTime)
+ this.responseReceivedTime = x;
this._endTime = x;
-
- if (WebInspector.panels.resources)
- WebInspector.panels.resources.refreshResource(this);
},
get duration()
@@ -240,13 +213,7 @@ WebInspector.Resource.prototype = {
set resourceSize(x)
{
- if (this._resourceSize === x)
- return;
-
this._resourceSize = x;
-
- if (WebInspector.panels.resources)
- WebInspector.panels.resources.refreshResource(this);
},
get transferSize()
@@ -262,8 +229,6 @@ WebInspector.Resource.prototype = {
set expectedContentLength(x)
{
- if (this._expectedContentLength === x)
- return;
this._expectedContentLength = x;
},
@@ -313,11 +278,6 @@ WebInspector.Resource.prototype = {
if (this._category)
this._category.addResource(this);
-
- if (WebInspector.panels.resources) {
- WebInspector.panels.resources.refreshResource(this);
- WebInspector.panels.resources.recreateViewForResourceIfNeeded(this);
- }
},
get cached()
@@ -328,7 +288,6 @@ WebInspector.Resource.prototype = {
set cached(x)
{
this._cached = x;
- this.dispatchEventToListeners("cached changed");
},
get mimeType()
@@ -338,9 +297,6 @@ WebInspector.Resource.prototype = {
set mimeType(x)
{
- if (this._mimeType === x)
- return;
-
this._mimeType = x;
},
@@ -387,18 +343,14 @@ WebInspector.Resource.prototype = {
get requestHeaders()
{
- if (this._requestHeaders === undefined)
- this._requestHeaders = {};
- return this._requestHeaders;
+ return this._requestHeaders || {};
},
set requestHeaders(x)
{
- if (this._requestHeaders === x)
- return;
-
this._requestHeaders = x;
delete this._sortedRequestHeaders;
+ delete this._requestCookies;
this.dispatchEventToListeners("requestHeaders changed");
},
@@ -421,6 +373,13 @@ WebInspector.Resource.prototype = {
return this._headerValue(this.requestHeaders, headerName);
},
+ get requestCookies()
+ {
+ if (!this._requestCookies)
+ this._requestCookies = WebInspector.CookieParser.parseCookie(this.requestHeaderValue("Cookie"));
+ return this._requestCookies;
+ },
+
get requestFormData()
{
return this._requestFormData;
@@ -434,18 +393,14 @@ WebInspector.Resource.prototype = {
get responseHeaders()
{
- if (this._responseHeaders === undefined)
- this._responseHeaders = {};
- return this._responseHeaders;
+ return this._responseHeaders || {};
},
set responseHeaders(x)
{
- if (this._responseHeaders === x)
- return;
-
this._responseHeaders = x;
delete this._sortedResponseHeaders;
+ delete this._responseCookies;
this.dispatchEventToListeners("responseHeaders changed");
},
@@ -468,6 +423,13 @@ WebInspector.Resource.prototype = {
return this._headerValue(this.responseHeaders, headerName);
},
+ get responseCookies()
+ {
+ if (!this._responseCookies)
+ this._responseCookies = WebInspector.CookieParser.parseSetCookie(this.responseHeaderValue("Set-Cookie"));
+ return this._responseCookies;
+ },
+
get queryParameters()
{
if (this._parsedQueryParameters)
@@ -627,6 +589,15 @@ WebInspector.Resource.prototype = {
if (msg)
WebInspector.console.addMessage(msg);
+ },
+
+ getContents: function(callback)
+ {
+ // FIXME: eventually, cached resources will have no identifiers.
+ if (this.frameID)
+ InspectorBackend.resourceContent(this.frameID, this.url, callback);
+ else
+ InspectorBackend.getResourceContent(this.identifier, false, callback);
}
}
diff --git a/WebCore/inspector/front-end/ResourceCategory.js b/WebCore/inspector/front-end/ResourceCategory.js
index 84f2cf9..7d95a1f 100644
--- a/WebCore/inspector/front-end/ResourceCategory.js
+++ b/WebCore/inspector/front-end/ResourceCategory.js
@@ -47,8 +47,8 @@ WebInspector.ResourceCategory.prototype = {
var resourcesLength = this.resources.length;
for (var i = 0; i < resourcesLength; ++i) {
var b = this.resources[i];
- if (a._lastPathComponentLowerCase && b._lastPathComponentLowerCase)
- if (a._lastPathComponentLowerCase < b._lastPathComponentLowerCase)
+ if (a.lastPathComponentLowerCase && b.lastPathComponentLowerCase)
+ if (a.lastPathComponentLowerCase < b.lastPathComponentLowerCase)
break;
else if (a.name && b.name)
if (a.name < b.name)
diff --git a/WebCore/inspector/front-end/ResourceManager.js b/WebCore/inspector/front-end/ResourceManager.js
new file mode 100644
index 0000000..7244cea
--- /dev/null
+++ b/WebCore/inspector/front-end/ResourceManager.js
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2009, 2010 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.ResourceManager = function()
+{
+ this._registerNotifyHandlers(
+ "identifierForInitialRequest",
+ "willSendRequest",
+ "markResourceAsCached",
+ "didReceiveResponse",
+ "didReceiveContentLength",
+ "didFinishLoading",
+ "didFailLoading",
+ "didLoadResourceFromMemoryCache",
+ "setOverrideContent",
+ "didCommitLoad",
+ "frameDetachedFromParent",
+ "didCreateWebSocket",
+ "willSendWebSocketHandshakeRequest",
+ "didReceiveWebSocketHandshakeResponse",
+ "didCloseWebSocket");
+
+ this._resources = {};
+ this._resourcesByFrame = {};
+ this._lastCachedId = 0;
+}
+
+WebInspector.ResourceManager.prototype = {
+ _registerNotifyHandlers: function()
+ {
+ for (var i = 0; i < arguments.length; ++i)
+ WebInspector[arguments[i]] = this[arguments[i]].bind(this);
+ },
+
+ identifierForInitialRequest: function(identifier, url, frameID, isMainResource)
+ {
+ var resource = new WebInspector.Resource(identifier, url);
+ if (isMainResource)
+ resource.isMainResource = true;
+ this._resources[identifier] = resource;
+
+ if (frameID) {
+ resource.frameID = frameID;
+ var resourcesForFrame = this._resourcesByFrame[frameID];
+ if (!resourcesForFrame) {
+ resourcesForFrame = [];
+ this._resourcesByFrame[frameID] = resourcesForFrame;
+ }
+ resourcesForFrame.push(resource);
+ }
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.addResource(resource);
+ },
+
+ willSendRequest: function(identifier, time, request, redirectResponse)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ // Redirect may have empty URL and we'd like to not crash with invalid HashMap entry.
+ // See http/tests/misc/will-send-request-returns-null-on-redirect.html
+ if (!redirectResponse.isNull && request.url.length) {
+ resource.endTime = time;
+ this.didReceiveResponse(identifier, time, "Other", redirectResponse);
+ resource = this._appendRedirect(resource.identifier, request.url);
+ }
+
+ resource.requestMethod = request.httpMethod;
+ resource.requestHeaders = request.httpHeaderFields;
+ resource.requestFormData = request.requestFormData;
+ resource.startTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ _appendRedirect: function(identifier, redirectURL)
+ {
+ // We always store last redirect by the original id key. Rest of the redirects are referenced from within the last one.
+
+ var originalResource = this._resources[identifier];
+ var redirectIdentifier = originalResource.identifier + ":" + (originalResource.redirects ? originalResource.redirects.length : 0);
+ originalResource.identifier = redirectIdentifier;
+ this._resources[redirectIdentifier] = originalResource;
+
+ this.identifierForInitialRequest(identifier, redirectURL, originalResource.frameID);
+
+ var newResource = this._resources[identifier];
+ newResource.redirects = originalResource.redirects || [];
+ delete originalResource.redirects;
+ newResource.redirects.push(originalResource);
+ return newResource;
+ },
+
+ markResourceAsCached: function(identifier)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.cached = true;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didReceiveResponse: function(identifier, time, resourceType, response)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.type = WebInspector.Resource.Type[resourceType];
+ resource.mimeType = response.mimeType;
+ resource.expectedContentLength = response.expectedContentLength;
+ resource.textEncodingName = response.textEncodingName;
+ resource.suggestedFilename = response.suggestedFilename;
+ resource.statusCode = response.httpStatusCode;
+ resource.statusText = response.httpStatusText;
+
+ resource.responseHeaders = response.httpHeaderFields;
+ resource.connectionReused = response.connectionReused;
+ resource.connectionID = response.connectionID;
+ resource.responseReceivedTime = time;
+
+ if (response.wasCached)
+ resource.cached = true;
+ else
+ resource.timing = response.timing;
+
+ if (response.rawHeaders) {
+ resource.requestHeaders = response.rawHeaders.requestHeaders;
+ resource.responseHeaders = response.rawHeaders.responseHeaders;
+ }
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didReceiveContentLength: function(identifier, time, lengthReceived)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.resourceSize += lengthReceived;
+ resource.endTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didFinishLoading: function(identifier, finishTime)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.finished = true;
+ resource.endTime = finishTime;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didFailLoading: function(identifier, time, localizedDescription)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.failed = true;
+ resource.endTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didLoadResourceFromMemoryCache: function(time, frameID, cachedResource)
+ {
+ var identifier = "cached:" + this._lastCachedId++;
+ this.identifierForInitialRequest(identifier, cachedResource.url, frameID);
+
+ var resource = this._resources[identifier];
+ resource.cached = true;
+ resource.startTime = resource.responseReceivedTime = time;
+ resource.resourceSize = cachedResource.encodedSize();
+
+ this.didReceiveResponse(identifier, time, cachedResource.response);
+ },
+
+ setOverrideContent: function(identifier, sourceString, type)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.type = WebInspector.Resource.Type[type];
+ resource.overridenContent = sourceString;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.addResource(resource);
+ },
+
+ didCommitLoad: function(frameID)
+ {
+ },
+
+ frameDetachedFromParent: function(frameID)
+ {
+ var resourcesForFrame = this._resourcesByFrame[frameID];
+ for (var i = 0; resourcesForFrame && i < resourcesForFrame.length; ++i)
+ delete this._resources[resourcesForFrame[i].identifier];
+ delete this._resourcesByFrame[frameID];
+ },
+
+ didCreateWebSocket: function(identifier, requestURL)
+ {
+ this.identifierForInitialRequest(identifier, requestURL);
+ var resource = this._resources[identifier];
+ resource.type = WebInspector.Resource.Type.WebSocket;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.addResource(resource);
+ },
+
+ willSendWebSocketHandshakeRequest: function(identifier, time, request)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.requestMethod = "GET";
+ resource.requestHeaders = request.webSocketHeaderFields;
+ resource.webSocketRequestKey3 = request.webSocketRequestKey3;
+ resource.startTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didReceiveWebSocketHandshakeResponse: function(identifier, time, response)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+
+ resource.statusCode = response.statusCode;
+ resource.statusText = response.statusText;
+ resource.responseHeaders = response.webSocketHeaderFields;
+ resource.webSocketChallengeResponse = response.webSocketChallengeResponse;
+ resource.responseReceivedTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ },
+
+ didCloseWebSocket: function(identifier, time)
+ {
+ var resource = this._resources[identifier];
+ if (!resource)
+ return;
+ resource.endTime = time;
+
+ if (WebInspector.panels.network)
+ WebInspector.panels.network.refreshResource(resource);
+ }
+}
diff --git a/WebCore/inspector/front-end/ResourceView.js b/WebCore/inspector/front-end/ResourceView.js
index 1c2574f..862569f 100644
--- a/WebCore/inspector/front-end/ResourceView.js
+++ b/WebCore/inspector/front-end/ResourceView.js
@@ -99,7 +99,6 @@ WebInspector.ResourceView = function(resource)
this.headersVisible = true;
- resource.addEventListener("url changed", this._refreshURL, this);
resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
resource.addEventListener("finished", this._refreshHTTPInformation, this);
diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js
index aa021ff..ae67bef 100644
--- a/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/WebCore/inspector/front-end/ResourcesPanel.js
@@ -142,7 +142,7 @@ WebInspector.ResourcesPanel.prototype = {
// Add a divider
var dividerElement = document.createElement("div");
- dividerElement.addStyleClass("divider");
+ dividerElement.addStyleClass("scope-bar-divider");
this.filterBarElement.appendChild(dividerElement);
for (var category in this.categories)
@@ -757,7 +757,6 @@ WebInspector.ResourcesPanel.prototype = {
addResource: function(resource)
{
this._resources.push(resource);
- this.refreshResource(resource);
},
removeResource: function(resource)
@@ -815,18 +814,19 @@ WebInspector.ResourcesPanel.prototype = {
refreshResource: function(resource)
{
+ this._recreateViewForResourceIfNeeded(resource);
this.refreshItem(resource);
},
- recreateViewForResourceIfNeeded: function(resource)
+ _recreateViewForResourceIfNeeded: function(resource)
{
if (!resource || !resource._resourcesView)
return;
- var newView = this._createResourceView(resource);
- if (newView.__proto__ === resource._resourcesView.__proto__)
+ if (this._resourceViewIsConsistentWithCategory(resource, resource._resourcesView))
return;
+ var newView = this._createResourceView(resource);
if (!this.currentQuery && resource._itemsTreeElement)
resource._itemsTreeElement.updateErrorsAndWarnings();
@@ -1068,6 +1068,23 @@ WebInspector.ResourcesPanel.prototype = {
this.calculator = this.summaryBar.calculator = selectedOption.calculator;
},
+ _resourceViewIsConsistentWithCategory: function(resource, resourceView)
+ {
+ switch (resource.category) {
+ case WebInspector.resourceCategories.documents:
+ case WebInspector.resourceCategories.stylesheets:
+ case WebInspector.resourceCategories.scripts:
+ case WebInspector.resourceCategories.xhr:
+ return resourceView.__proto__ === WebInspector.SourceView.prototype;
+ case WebInspector.resourceCategories.images:
+ return resourceView.__proto__ === WebInspector.ImageView.prototype;
+ case WebInspector.resourceCategories.fonts:
+ return resourceView.__proto__ === WebInspector.FontView.prototype;
+ default:
+ return resourceView.__proto__ === WebInspector.ResourceView.prototype;
+ }
+ },
+
_createResourceView: function(resource)
{
switch (resource.category) {
@@ -1250,17 +1267,27 @@ WebInspector.ResourcesPanel.prototype = {
_contextMenu: function(event)
{
- // createBlobURL is enabled conditionally, do not expose resource export if it's not available.
- if (typeof window.createBlobURL !== "function" || !Preferences.resourceExportEnabled)
- return;
-
var contextMenu = new WebInspector.ContextMenu();
var resourceTreeItem = event.target.enclosingNodeOrSelfWithClass("resource-sidebar-tree-item");
- if (resourceTreeItem && resourceTreeItem.treeElement) {
- var resource = resourceTreeItem.treeElement.representedObject;
- contextMenu.appendItem(WebInspector.UIString("Export to HAR"), this._exportResource.bind(this, resource));
+ var resource;
+ if (resourceTreeItem && resourceTreeItem.treeElement)
+ resource = resourceTreeItem.treeElement.representedObject;
+
+ var needSeparator = false;
+ // createObjectURL is enabled conditionally, do not expose resource export if it's not available.
+ if (typeof window.createObjectURL === "function" && Preferences.resourceExportEnabled) {
+ if (resource)
+ contextMenu.appendItem(WebInspector.UIString("Export to HAR"), this._exportResource.bind(this, resource));
+ contextMenu.appendItem(WebInspector.UIString("Export all to HAR"), this._exportAll.bind(this));
+ needSeparator = true;
}
- contextMenu.appendItem(WebInspector.UIString("Export all to HAR"), this._exportAll.bind(this));
+
+ if (resource && resource.category === WebInspector.resourceCategories.xhr) {
+ if (needSeparator)
+ contextMenu.appendSeparator();
+ contextMenu.appendItem(WebInspector.UIString("Set XHR Breakpoint"), WebInspector.breakpointManager.createXHRBreakpoint.bind(WebInspector.breakpointManager, resource.url));
+ }
+
contextMenu.show(event);
},
@@ -1281,11 +1308,6 @@ WebInspector.ResourcesPanel.prototype = {
WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.getResourceContent = function(identifier, callback)
-{
- InspectorBackend.getResourceContent(identifier, callback);
-}
-
WebInspector.ResourceBaseCalculator = function()
{
}
@@ -1814,7 +1836,8 @@ WebInspector.ResourceGraph = function(resource)
this._graphElement.className = "resources-graph-side";
this._graphElement.addEventListener("mouseover", this.refreshLabelPositions.bind(this), false);
- this._cachedChanged();
+ if (this.resource.cached)
+ this._graphElement.addStyleClass("resource-cached");
this._barAreaElement = document.createElement("div");
this._barAreaElement.className = "resources-graph-bar-area hidden";
@@ -1838,8 +1861,6 @@ WebInspector.ResourceGraph = function(resource)
this._barAreaElement.appendChild(this._labelRightElement);
this._graphElement.addStyleClass("resources-category-" + resource.category.name);
-
- resource.addEventListener("cached changed", this._cachedChanged, this);
}
WebInspector.ResourceGraph.prototype = {
@@ -1963,11 +1984,8 @@ WebInspector.ResourceGraph.prototype = {
this._labelLeftElement.title = tooltip;
this._labelRightElement.title = tooltip;
this._barRightElement.title = tooltip;
- },
- _cachedChanged: function()
- {
- if (this.resource.cached)
+ if (this.resource.cached && !this._graphElement.hasStyleClass("resource-cached"))
this._graphElement.addStyleClass("resource-cached");
}
}
diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js
index 8283528..0a653c9 100644
--- a/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/WebCore/inspector/front-end/ScriptsPanel.js
@@ -134,10 +134,9 @@ WebInspector.ScriptsPanel = function()
this.sidebarPanes.jsBreakpoints = WebInspector.createJSBreakpointsSidebarPane();
if (Preferences.nativeInstrumentationEnabled) {
this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane();
- this.sidebarPanes.domBreakpoints.expanded = true;
this.sidebarPanes.xhrBreakpoints = WebInspector.createXHRBreakpointsSidebarPane();
- this.sidebarPanes.xhrBreakpoints.expanded = true;
}
+ this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
@@ -389,9 +388,6 @@ WebInspector.ScriptsPanel.prototype = {
this.sidebarPanes.callstack.update(details.callFrames, this._sourceIDMap);
this.sidebarPanes.callstack.selectedCallFrame = details.callFrames[0];
- if ("eventType" in details)
- this.sidebarPanes.callstack.updateStatus(details.eventType, details.eventData);
-
WebInspector.currentPanel = this;
window.focus();
},
@@ -439,13 +435,7 @@ WebInspector.ScriptsPanel.prototype = {
delete this.currentQuery;
this.searchCanceled();
- if (!this._debuggerEnabled) {
- this._paused = false;
- this._waitingToPause = false;
- this._stepping = false;
- }
-
- this._clearInterface();
+ this.debuggerResumed();
this._backForwardList = [];
this._currentBackForwardIndex = -1;
@@ -473,6 +463,7 @@ WebInspector.ScriptsPanel.prototype = {
this.sidebarPanes.domBreakpoints.reset();
this.sidebarPanes.xhrBreakpoints.reset();
}
+ this.sidebarPanes.eventListenerBreakpoints.reset();
this.sidebarPanes.workers.reset();
}
},
diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js
index aecd57b..4b391ac 100644
--- a/WebCore/inspector/front-end/SourceFrame.js
+++ b/WebCore/inspector/front-end/SourceFrame.js
@@ -169,6 +169,14 @@ WebInspector.SourceFrame.prototype = {
this._lineToHighlight = line;
},
+ clearLineHighlight: function()
+ {
+ if (this._textViewer)
+ this._textViewer.clearLineHighlight();
+ else
+ delete this._lineToHighlight;
+ },
+
_createViewerIfNeeded: function()
{
if (!this._visible || !this._loaded || this._textViewer)
diff --git a/WebCore/inspector/front-end/SourceView.js b/WebCore/inspector/front-end/SourceView.js
index 3f762cc..8092505 100644
--- a/WebCore/inspector/front-end/SourceView.js
+++ b/WebCore/inspector/front-end/SourceView.js
@@ -59,6 +59,8 @@ WebInspector.SourceView.prototype = {
hide: function()
{
this.sourceFrame.visible = false;
+ if (!this._frameNeedsSetup)
+ this.sourceFrame.clearLineHighlight();
WebInspector.View.prototype.hide.call(this);
if (this.localSourceFrame)
this.localSourceFrame.visible = false;
@@ -81,7 +83,7 @@ WebInspector.SourceView.prototype = {
this.attach();
delete this._frameNeedsSetup;
- WebInspector.getResourceContent(this.resource.identifier, this._contentLoaded.bind(this));
+ this.resource.getContents(this._contentLoaded.bind(this));
},
hasContentTab: function()
diff --git a/WebCore/inspector/front-end/StoragePanel.js b/WebCore/inspector/front-end/StoragePanel.js
index 2d17989..e033b57 100644
--- a/WebCore/inspector/front-end/StoragePanel.js
+++ b/WebCore/inspector/front-end/StoragePanel.js
@@ -59,7 +59,7 @@ WebInspector.StoragePanel = function(database)
this.element.appendChild(this.storageViews);
this.storageViewStatusBarItemsContainer = document.createElement("div");
- this.storageViewStatusBarItemsContainer.id = "storage-view-status-bar-items";
+ this.storageViewStatusBarItemsContainer.className = "status-bar-items";
this.reset();
}
diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js
index 6aff37d..36d854c 100644
--- a/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -1695,17 +1695,13 @@ WebInspector.StylePropertyTreeElement.prototype = {
self.updateTitle();
}
- function successCallback(newStyle, changedProperties)
+ function successCallback(newStyle)
{
- elementsPanel.removeStyleChange(section.identifier, self.style, self.name);
-
if (!styleTextLength) {
// Do remove ourselves from UI when the property removal is confirmed.
self.parent.removeChild(self);
} else {
self.style = newStyle;
- for (var i = 0; i < changedProperties.length; ++i)
- elementsPanel.addStyleChange(section.identifier, self.style, changedProperties[i]);
self._styleRule.style = self.style;
}
diff --git a/WebCore/inspector/front-end/TabbedPane.js b/WebCore/inspector/front-end/TabbedPane.js
index 6acd163..dec3a0b 100644
--- a/WebCore/inspector/front-end/TabbedPane.js
+++ b/WebCore/inspector/front-end/TabbedPane.js
@@ -33,7 +33,7 @@ WebInspector.TabbedPane = function(element)
this.element = element || document.createElement("div");
this.tabsElement = document.createElement("div");
- this.tabsElement.className = "scope-bar";
+ this.tabsElement.className = "tabbed-pane-header";
this.element.appendChild(this.tabsElement);
this._tabObjects = {};
diff --git a/WebCore/inspector/front-end/TextViewer.js b/WebCore/inspector/front-end/TextViewer.js
index 13b2836..9ad5e49 100644
--- a/WebCore/inspector/front-end/TextViewer.js
+++ b/WebCore/inspector/front-end/TextViewer.js
@@ -117,16 +117,22 @@ WebInspector.TextViewer.prototype = {
highlightLine: function(lineNumber)
{
- if (typeof this._highlightedLine === "number") {
- var chunk = this._makeLineAChunk(this._highlightedLine);
- chunk.removeDecoration("webkit-highlighted-line");
- }
+ this.clearLineHighlight();
this._highlightedLine = lineNumber;
this.revealLine(lineNumber);
var chunk = this._makeLineAChunk(lineNumber);
chunk.addDecoration("webkit-highlighted-line");
},
+ clearLineHighlight: function()
+ {
+ if (typeof this._highlightedLine === "number") {
+ var chunk = this._makeLineAChunk(this._highlightedLine);
+ chunk.removeDecoration("webkit-highlighted-line");
+ delete this._highlightedLine;
+ }
+ },
+
freeCachedElements: function()
{
this._cachedSpans = [];
diff --git a/WebCore/inspector/front-end/TimelineGrid.js b/WebCore/inspector/front-end/TimelineGrid.js
index ad7e769..adc8e47 100644
--- a/WebCore/inspector/front-end/TimelineGrid.js
+++ b/WebCore/inspector/front-end/TimelineGrid.js
@@ -55,6 +55,7 @@ WebInspector.TimelineGrid.prototype = {
return this._itemsGraphsElement;
},
+
updateDividers: function(force, calculator, paddingLeft)
{
var dividerCount = Math.round(this._dividersElement.offsetWidth / 64);
@@ -88,10 +89,21 @@ WebInspector.TimelineGrid.prototype = {
dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth;
}
- if (i === dividerCount)
+ if (i === (paddingLeft ? 0 : 1)) {
+ divider.addStyleClass("first");
+ dividerLabelBar.addStyleClass("first");
+ } else {
+ divider.removeStyleClass("first");
+ dividerLabelBar.removeStyleClass("first");
+ }
+
+ if (i === dividerCount) {
divider.addStyleClass("last");
- else
+ dividerLabelBar.addStyleClass("last");
+ } else {
divider.removeStyleClass("last");
+ dividerLabelBar.removeStyleClass("last");
+ }
var left = paddingLeft + clientWidth * (i / dividerCount);
var percentLeft = 100 * left / dividersLabelBarElementClientWidth;
diff --git a/WebCore/inspector/front-end/TimelineOverviewPane.js b/WebCore/inspector/front-end/TimelineOverviewPane.js
index 3e83f62..55e24c5 100644
--- a/WebCore/inspector/front-end/TimelineOverviewPane.js
+++ b/WebCore/inspector/front-end/TimelineOverviewPane.js
@@ -33,8 +33,7 @@ WebInspector.TimelineOverviewPane = function(categories)
this._categories = categories;
this.statusBarFilters = document.createElement("div");
- this.statusBarFilters.id = "timeline-view-status-bar-items";
- this.statusBarFilters.addStyleClass("status-bar-item");
+ this.statusBarFilters.className = "status-bar-items";
for (var categoryName in this._categories) {
var category = this._categories[categoryName];
this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCheckboxClicked.bind(this, category)));
@@ -197,6 +196,7 @@ WebInspector.TimelineOverviewPane.prototype = {
updateMainViewWidth: function(width, records)
{
this._overviewGrid.element.style.left = width + "px";
+ this.statusBarFilters.style.left = Math.max(155, width) + "px";
},
reset: function()
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index 11382cd..1e5a508 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -20,6 +20,7 @@
<file>ConsoleView.js</file>
<file>ContextMenu.js</file>
<file>CookieItemsView.js</file>
+ <file>CookieParser.js</file>
<file>CSSCompletions.js</file>
<file>CSSStyleModel.js</file>
<file>Database.js</file>
@@ -68,6 +69,7 @@
<file>RemoteObject.js</file>
<file>Resource.js</file>
<file>ResourceCategory.js</file>
+ <file>ResourceManager.js</file>
<file>ResourcesPanel.js</file>
<file>ResourceView.js</file>
<file>ScopeChainSidebarPane.js</file>
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 848afdc..0662954 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -810,6 +810,7 @@ body.platform-linux .monospace, body.platform-linux .source-code {
.resource-view {
display: none;
position: absolute;
+ background: white;
top: 0;
left: 0;
right: 0;
@@ -820,7 +821,7 @@ body.platform-linux .monospace, body.platform-linux .source-code {
display: block;
}
-.resource-view .scope-bar {
+.resource-view .tabbed-pane-header {
display: none;
position: absolute;
height: 20px;
@@ -831,7 +832,7 @@ body.platform-linux .monospace, body.platform-linux .source-code {
border-bottom: 1px solid rgb(163, 163, 163);
}
-.resource-view.headers-visible .scope-bar {
+.resource-view.headers-visible .tabbed-pane-header {
display: block;
}
@@ -1373,10 +1374,10 @@ body.inactive .placard.selected {
.section .properties, .event-bar .event-properties {
display: none;
- margin: 0;
- padding: 2px 6px 3px;
- list-style: none;
- min-height: 18px;
+}
+
+.section.expanded .properties, .event-bar.expanded .event-properties {
+ display: block;
}
.section.no-affect .properties li {
@@ -1387,11 +1388,14 @@ body.inactive .placard.selected {
opacity: 1.0;
}
-.section.expanded .properties, .event-bar.expanded .event-properties {
- display: block;
+.properties-tree {
+ margin: 0;
+ padding: 2px 6px 3px;
+ list-style: none;
+ min-height: 18px;
}
-.section .properties li, .event-properties li {
+.properties-tree li {
margin-left: 12px;
white-space: nowrap;
text-overflow: ellipsis;
@@ -1400,26 +1404,11 @@ body.inactive .placard.selected {
cursor: auto;
}
-.section .properties li.parent, .event-properties li.parent {
+.properties-tree li.parent {
margin-left: 1px;
}
-.section .properties ol, .event-properties ol, .stack-trace ol, ol.stack-trace {
- display: none;
- margin: 0;
- -webkit-padding-start: 12px;
- list-style: none;
-}
-
-ol.stack-trace {
- -webkit-padding-start: 0px;
-}
-
-.section .properties ol.expanded, .event-properties ol.expanded, .stack-trace ol, ol.stack-trace {
- display: block;
-}
-
-.section .properties li.parent::before, .event-properties li.parent::before {
+.properties-tree li.parent::before {
content: url(Images/treeRightTriangleBlack.png);
opacity: 0.75;
float: left;
@@ -1431,16 +1420,47 @@ ol.stack-trace {
cursor: default;
}
-.section .properties li.parent.expanded::before, .event-properties li.parent.expanded::before {
+.properties-tree li.parent.expanded::before {
content: url(Images/treeDownTriangleBlack.png);
margin-top: 1px;
}
-.section .properties li .info, .event-properties li .info {
+.properties-tree li .info {
padding-top: 4px;
padding-bottom: 3px;
}
+.properties-tree ol, .stack-trace ol, ol.stack-trace {
+ display: none;
+ margin: 0;
+ -webkit-padding-start: 12px;
+ list-style: none;
+}
+
+.properties-tree ol.expanded, .stack-trace ol, ol.stack-trace {
+ display: block;
+}
+
+ol.stack-trace {
+ -webkit-padding-start: 0px;
+}
+
+.event-listener-breakpoints .event-category {
+ font-size: 12px;
+ font-weight: bold;
+ color: rgb(110, 110, 110);
+}
+
+.event-listener-breakpoints.properties-tree .children li {
+ margin-left: 17px;
+}
+
+.event-listener-breakpoints .checkbox-elem {
+ float: left;
+ margin-top: 1px;
+ margin-left: 0px;
+}
+
.section .event-bars {
display: none;
}
@@ -2086,22 +2106,27 @@ body.inactive .sidebar {
background-image: url(Images/glossyHeaderSelectedPressed.png);
}
-.data-grid th.sort-ascending div::after {
+.data-grid th.sort-ascending > div::after {
position: absolute;
top: 0;
+ bottom: 0;
right: 0;
+ height: 12px;
+ margin-bottom: auto;
+ margin-top: auto;
width: 8px;
- height: 8px;
content: url(Images/treeUpTriangleBlack.png);
}
-.data-grid th.sort-descending div::after {
+.data-grid th.sort-descending > div::after {
position: absolute;
top: 0;
+ bottom: 0;
right: 0;
- margin-top: 1px;
- width: 8px;
height: 8px;
+ margin-bottom: auto;
+ margin-top: auto;
+ width: 8px;
content: url(Images/treeDownTriangleBlack.png);
}
@@ -2560,6 +2585,33 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
margin-top: 1px;
}
+.tabbed-pane-header {
+ height: 23px;
+ padding: 0 10px;
+ border-bottom: 1px solid rgb(163, 163, 163);
+}
+
+.tabbed-pane-header li {
+ display: inline-block;
+ margin-top: 2px;
+ font-size: 11px;
+ font-weight: bold;
+ color: rgb(46, 46, 46);
+ background: transparent;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+ vertical-align: middle;
+ padding: 1px 7px 2px;
+ height: 18px;
+ border: 1px solid transparent;
+ border-bottom: none;
+}
+
+.tabbed-pane-header li.selected {
+ background-color: white;
+ border: 1px solid rgb(163, 163, 163);
+ border-bottom: none;
+}
+
.scope-bar {
height: 23px;
padding: 2px 10px 0;
@@ -2580,7 +2632,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
vertical-align: middle;
}
-.scope-bar .divider {
+.scope-bar-divider {
margin: 1px 9px 0 8px;
background-color: rgba(0, 0, 0, 0.4);
height: 16px;
@@ -2718,7 +2770,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph {
.resources-event-dividers {
position: absolute;
left: 0;
- right: 0;
+ right: 5px;
height: 100%;
top: 0;
z-index: 300;
@@ -3837,8 +3889,7 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
bottom: 0;
}
-#timeline-view-status-bar-items,
-#profile-view-status-bar-items {
+.status-bar-items {
position: absolute;
top: 0;
bottom: 0;
@@ -3962,30 +4013,10 @@ button.enable-toggle-status-bar-item .glyph {
-webkit-mask-image: url(Images/excludeButtonGlyph.png);
}
-#storage-view-status-bar-items {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 200px;
- overflow: hidden;
- border-left: 1px solid rgb(184, 184, 184);
- margin-left: -1px;
-}
-
.refresh-storage-status-bar-item .glyph {
-webkit-mask-image: url(Images/reloadButtonGlyph.png);
}
-#storage-view-status-bar-items {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 200px;
- overflow: hidden;
- border-left: 1px solid rgb(184, 184, 184);
- margin-left: -1px;
-}
-
ol.breakpoint-list {
-webkit-padding-start: 2px;
list-style: none;
@@ -4020,6 +4051,10 @@ ol.breakpoint-list {
margin: 2px 0 0px 20px;
}
+.breakpoint-list .breakpoint-hit {
+ background-color: yellow;
+}
+
.webkit-html-js-node, .webkit-html-css-node {
white-space: pre;
}
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index 949b18f..96d0cfe 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -61,6 +61,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="Panel.js"></script>
<script type="text/javascript" src="TimelineGrid.js"></script>
<script type="text/javascript" src="Resource.js"></script>
+ <script type="text/javascript" src="ResourceManager.js"></script>
<script type="text/javascript" src="ResourceCategory.js"></script>
<script type="text/javascript" src="Database.js"></script>
<script type="text/javascript" src="DOMStorage.js"></script>
@@ -143,6 +144,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="GoToLineDialog.js"></script>
<script type="text/javascript" src="ShortcutsHelp.js"></script>
<script type="text/javascript" src="HAREntry.js"></script>
+ <script type="text/javascript" src="CookieParser.js"></script>
</head>
<body class="detached">
<div id="toolbar">
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index 3edae8f..9bd88d6 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -56,15 +56,6 @@ var WebInspector = {
missingLocalizedStrings: {},
pendingDispatches: 0,
- // RegExp groups:
- // 1 - scheme
- // 2 - hostname
- // 3 - ?port
- // 4 - ?path
- // 5 - ?fragment
- URLRegExp: /^(http[s]?|file):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i,
- GenericURLRegExp: /^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i,
-
get platform()
{
if (!("_platform" in this))
@@ -213,9 +204,9 @@ var WebInspector = {
var pane = new WebInspector.BreakpointsSidebarPane(WebInspector.UIString("DOM Breakpoints"));
function breakpointAdded(event)
{
- pane.addBreakpoint(new WebInspector.DOMBreakpointItem(event.data));
+ pane.addBreakpoint(new WebInspector.BreakpointItem(event.data));
}
- WebInspector.domBreakpointManager.addEventListener("dom-breakpoint-added", breakpointAdded);
+ WebInspector.breakpointManager.addEventListener("dom-breakpoint-added", breakpointAdded);
return pane;
},
@@ -224,7 +215,7 @@ var WebInspector = {
var pane = new WebInspector.XHRBreakpointsSidebarPane();
function breakpointAdded(event)
{
- pane.addBreakpoint(new WebInspector.XHRBreakpointItem(event.data));
+ pane.addBreakpoint(new WebInspector.BreakpointItem(event.data));
}
WebInspector.breakpointManager.addEventListener("xhr-breakpoint-added", breakpointAdded);
return pane;
@@ -516,6 +507,8 @@ WebInspector.doLoadedDone = function()
// this.changes = new WebInspector.ChangesView(this.drawer);
// TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item
this.drawer.visibleView = this.console;
+ // FIXME: uncomment when ready.
+ // this.resourceManager = new WebInspector.ResourceManager();
this.domAgent = new WebInspector.DOMAgent();
this.resourceCategories = {
@@ -530,7 +523,6 @@ WebInspector.doLoadedDone = function()
};
this.breakpointManager = new WebInspector.BreakpointManager();
- this.domBreakpointManager = new WebInspector.DOMBreakpointManager();
this.cssModel = new WebInspector.CSSStyleModel();
this.panels = {};
@@ -604,6 +596,7 @@ WebInspector.doLoadedDone = function()
InspectorBackend.getInspectorState(populateInspectorState);
InspectorBackend.populateScriptObjects();
+ InspectorBackend.setConsoleMessagesEnabled(true);
// As a DOMAgent method, this needs to happen after the frontend has loaded and the agent is available.
InspectorBackend.getSupportedCSSProperties(WebInspector.CSSCompletions._load);
@@ -770,10 +763,10 @@ WebInspector.documentClick = function(event)
return;
}
- const urlMatch = WebInspector.GenericURLRegExp.exec(anchor.href);
- if (urlMatch && urlMatch[1] === "webkit-link-action") {
- if (urlMatch[2] === "show-panel") {
- const panel = urlMatch[4].substring(1);
+ var parsedURL = anchor.href.asParsedURL();
+ if (parsedURL && parsedURL.scheme === "webkit-link-action") {
+ if (parsedURL.host === "show-panel") {
+ var panel = parsedURL.path.substring(1);
if (WebInspector.panels[panel])
WebInspector.currentPanel = WebInspector.panels[panel];
}
@@ -1229,14 +1222,9 @@ WebInspector.updateResource = function(payload)
this.resourceURLMap[resource.url] = resource;
this.panels.resources.addResource(resource);
this.panels.audits.resourceStarted(resource);
- if (this.panels.network)
- this.panels.network.addResource(resource);
}
if (payload.didRequestChange) {
- resource.domain = payload.host;
- resource.path = payload.path;
- resource.lastPathComponent = payload.lastPathComponent;
resource.requestHeaders = payload.requestHeaders;
resource.mainResource = payload.mainResource;
resource.requestMethod = payload.requestMethod;
@@ -1248,11 +1236,10 @@ WebInspector.updateResource = function(payload)
if (resource.mainResource)
this.mainResource = resource;
- var match = payload.documentURL.match(WebInspector.GenericURLRegExp);
- if (match) {
- var protocol = match[1].toLowerCase();
- this._addCookieDomain(match[2]);
- this._addAppCacheDomain(match[2]);
+ var parsedURL = payload.documentURL.asParsedURL();
+ if (parsedURL) {
+ this._addCookieDomain(parsedURL.host);
+ this._addAppCacheDomain(parsedURL.host);
}
}
@@ -1293,29 +1280,24 @@ WebInspector.updateResource = function(payload)
resource.responseReceivedTime = payload.responseReceivedTime;
if (payload.endTime)
resource.endTime = payload.endTime;
-
- if (payload.loadEventTime) {
- // This loadEventTime is for the main resource, and we want to show it
- // for all resources on this page. This means we want to set it as a member
- // of the resources panel instead of the individual resource.
- this.panels.resources.mainResourceLoadTime = payload.loadEventTime;
- this.panels.audits.mainResourceLoadTime = payload.loadEventTime;
- if (this.panels.network)
- this.panels.network.mainResourceLoadTime = payload.loadEventTime;
- }
-
- if (payload.domContentEventTime) {
- // This domContentEventTime is for the main resource, so it should go in
- // the resources panel for the same reasons as above.
- this.panels.resources.mainResourceDOMContentTime = payload.domContentEventTime;
- this.panels.audits.mainResourceDOMContentTime = payload.domContentEventTime;
- if (this.panels.network)
- this.panels.network.mainResourceDOMContentTime = payload.domContentEventTime;
- }
}
+ this.panels.resources.refreshResource(resource);
+}
+WebInspector.domContentEventFired = function(time)
+{
+ this.panels.resources.mainResourceDOMContentTime = time;
+ this.panels.audits.mainResourceDOMContentTime = time;
if (this.panels.network)
- this.panels.network.refreshResource(resource);
+ this.panels.network.mainResourceDOMContentTime = time;
+}
+
+WebInspector.loadEventFired = function(time)
+{
+ this.panels.resources.mainResourceLoadTime = time;
+ this.panels.audits.mainResourceLoadTime = time;
+ if (this.panels.network)
+ this.panels.network.mainResourceLoadTime = time;
}
WebInspector.removeResource = function(identifier)
@@ -1447,16 +1429,20 @@ WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLin
WebInspector.pausedScript = function(details)
{
this.panels.scripts.debuggerPaused(details);
+ this.breakpointManager.debuggerPaused(details);
InspectorFrontendHost.bringToFront();
}
WebInspector.resumedScript = function()
{
+ this.breakpointManager.debuggerResumed();
this.panels.scripts.debuggerResumed();
}
WebInspector.reset = function()
{
+ this.breakpointManager.reset();
+
for (var panelName in this.panels) {
var panel = this.panels[panelName];
if ("reset" in panel)
@@ -1464,7 +1450,6 @@ WebInspector.reset = function()
}
this.sessionSettings.reset();
- this.breakpointManager.reset();
for (var category in this.resourceCategories)
this.resourceCategories[category].removeAllResources();
@@ -1498,12 +1483,6 @@ WebInspector.inspectedURLChanged = function(url)
this.extensionServer.notifyInspectedURLChanged();
}
-WebInspector.resourceURLChanged = function(resource, oldURL)
-{
- delete this.resourceURLMap[oldURL];
- this.resourceURLMap[resource.url] = resource;
-}
-
WebInspector.didCommitLoad = function()
{
// Cleanup elements panel early on inspected page refresh.
@@ -1837,8 +1816,8 @@ WebInspector.resourceURLForRelatedNode = function(node, url)
// documentURL not found or has bad value
for (var resourceURL in WebInspector.resourceURLMap) {
- var match = resourceURL.match(WebInspector.URLRegExp);
- if (match && match[4] === url)
+ var parsedURL = resourceURL.asParsedURL();
+ if (parsedURL && parsedURL.path === url)
return resourceURL;
}
return url;
@@ -1846,17 +1825,17 @@ WebInspector.resourceURLForRelatedNode = function(node, url)
WebInspector.completeURL = function(baseURL, href)
{
- var match = baseURL.match(WebInspector.URLRegExp);
- if (match) {
+ var parsedURL = baseURL.asParsedURL();
+ if (parsedURL) {
var path = href;
if (path.charAt(0) !== "/") {
- var basePath = match[4] || "/";
+ var basePath = parsedURL.path;
path = basePath.substring(0, basePath.lastIndexOf("/")) + "/" + path;
} else if (path.length > 1 && path.charAt(1) === "/") {
// href starts with "//" which is a full URL with the protocol dropped (use the baseURL protocol).
- return match[1] + ":" + path;
+ return parsedURL.scheme + ":" + path;
}
- return match[1] + "://" + match[2] + (match[3] ? (":" + match[3]) : "") + path;
+ return parsedURL.scheme + "://" + parsedURL.host + (parsedURL.port ? (":" + parsedURL.port) : "") + path;
}
return null;
}
diff --git a/WebCore/inspector/front-end/networkPanel.css b/WebCore/inspector/front-end/networkPanel.css
index cdea7fe..773fe99 100644
--- a/WebCore/inspector/front-end/networkPanel.css
+++ b/WebCore/inspector/front-end/networkPanel.css
@@ -1,383 +1,601 @@
-.network-larger-resources-status-bar-item .glyph {
- -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
-}
-
-.network.panel .data-grid {
- border: none;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- font-size: 11px;
-}
-
-.network.panel .data-grid table.data {
- -webkit-background-size: 1px 82px;
- background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0.05)), to(rgba(0, 0, 0, 0.05)));
- font-size: 11px;
-}
-
-.network.panel .data-grid.small table.data {
- -webkit-background-size: 1px 42px;
-}
-
-.network.panel .data-grid td {
- line-height: 17px;
- border-right: 1px solid rgb(210, 210, 210);
- -webkit-user-select: none;
-}
-
-.network.panel .data-grid th {
- border-bottom: 1px solid rgb(64%, 64%, 64%);
- height: 22px;
-}
-
-.network.panel .data-grid th, .network.panel .data-grid th.sort-descending, .network.panel .data-grid th.sort-ascending {
- background: -webkit-gradient(linear, left top, left bottom, from(rgb(236, 236, 236)), to(rgb(217, 217, 217)));
-}
-
-.network.panel .data-grid .data-container {
- top: 23px;
-}
-
-.network.panel .data-grid td.url-column {
- font-weight: bold;
-}
-
-.network.panel .data-grid td.optional-column {
- background-color: rgba(0, 0, 0, 0.07);
-}
-
-.network.panel .small .network-graph-side {
- height: 14px;
-}
-
-.network.panel .data-grid th.sortable:active {
- background-image: none;
-}
-
-.network-grid-subtitle {
- font-weight: normal;
- color: grey;
-}
-
-.network.panel .data-grid.small .network-grid-subtitle {
- display: none;
-}
-
-/* Resource preview icons */
-
-.network.panel .data-grid .icon {
- content: url(Images/resourcePlainIcon.png);
-}
-
-.network.panel .data-grid.small .icon {
- content: url(Images/resourcePlainIconSmall.png);
-}
-
-.network.panel .network-category-scripts .icon {
- content: url(Images/resourceJSIcon.png);
-}
-
-.network.panel .data-grid.small .network-category-scripts .icon {
- content: url(Images/resourceDocumentIconSmall.png);
-}
-
-.network.panel .network-category-documents .icon {
- content: url(Images/resourceDocumentIcon.png);
-}
-
-.network.panel .data-grid.small .network-category-documents .icon {
- content: url(Images/resourceDocumentIconSmall.png);
-}
-
-.network.panel .network-category-stylesheets .icon {
- content: url(Images/resourceCSSIcon.png);
-}
-
-.network.panel .data-grid.small .network-category-stylesheets .icon {
- content: url(Images/resourceDocumentIconSmall.png);
-}
-
-.network.panel .network-category-images .icon {
- position: relative;
- background-image: url(Images/resourcePlainIcon.png);
- background-repeat: no-repeat;
- content: "";
-}
-
-.network.panel .network-category-images .icon {
- position: relative;
- background-image: url(Images/resourcePlainIcon.png);
- background-repeat: no-repeat;
- content: "";
-}
-
-.network.panel .data-grid.small .network-category-images .icon {
- background-image: url(Images/resourcePlainIconSmall.png);
- content: "";
-}
-
-.network.panel .data-grid .icon {
- float: left;
- width: 32px;
- height: 32px;
- margin-top: 1px;
- margin-right: 3px;
-}
-
-.network.panel .data-grid.small .icon {
- width: 16px;
- height: 16px;
-}
-
-.network.panel .image-network-icon-preview {
- position: absolute;
- margin: auto;
- top: 3px;
- bottom: 4px;
- left: 5px;
- right: 5px;
- max-width: 18px;
- max-height: 21px;
- min-width: 1px;
- min-height: 1px;
-}
-
-.network.panel .data-grid.small .image-network-icon-preview {
- top: 2px;
- bottom: 1px;
- left: 3px;
- right: 3px;
- max-width: 8px;
- max-height: 11px;
-}
-
-/* Graph styles */
-
-.network-graph-side {
- position: relative;
- height: 36px;
- padding: 0 5px;
- white-space: nowrap;
- margin-top: 1px;
- border-top: 1px solid transparent;
- overflow: hidden;
-}
-
-.network-graph-bar-area {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 8px;
- left: 9px;
-}
-
-.network-graph-label {
- position: absolute;
- top: 0;
- bottom: 0;
- margin: auto -7px;
- height: 13px;
- line-height: 13px;
- font-size: 9px;
- color: rgba(0, 0, 0, 0.75);
- text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
- z-index: 150;
- overflow: hidden;
- text-align: center;
- font-weight: bold;
- opacity: 0;
- -webkit-transition: opacity 250ms ease-in-out;
-}
-
-.network-graph-side:hover .network-graph-label {
- opacity: 1;
-}
-
-.network-graph-label:empty {
- display: none;
-}
-
-.network-graph-label.waiting {
- margin-right: 5px;
-}
-
-.network-graph-label.waiting-right {
- margin-left: 5px;
-}
-
-.network-graph-label.before {
- color: rgba(0, 0, 0, 0.7);
- text-shadow: none;
- text-align: right;
- margin-right: 2px;
-}
-
-.network-graph-label.before::after {
- padding-left: 2px;
- height: 6px;
- content: url(Images/graphLabelCalloutLeft.png);
-}
-
-.network-graph-label.after {
- color: rgba(0, 0, 0, 0.7);
- text-shadow: none;
- text-align: left;
- margin-left: 2px;
-}
-
-.network-graph-label.after::before {
- padding-right: 2px;
- height: 6px;
- content: url(Images/graphLabelCalloutRight.png);
-}
-
-.network-graph-bar {
- position: absolute;
- top: 0;
- bottom: 0;
- margin: auto -7px;
- border-width: 6px 7px;
- height: 13px;
- min-width: 14px;
- opacity: 0.65;
- -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
-}
-
-.network-graph-bar.waiting, .network-graph-bar.waiting-right {
- opacity: 0.35;
-}
-
-/* Resource categories */
-
-
-.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
-}
-
-.network-category-documents .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
-}
-
-.network-category-documents.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
-}
-
-.network-category-stylesheets .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
-}
-
-.network-category-stylesheets.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
-}
-
-.network-category-images .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
-}
-
-.network-category-images.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
-}
-
-.network-category-fonts .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
-}
-
-.network-category-fonts.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
-}
-
-.network-category-scripts .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
-}
-
-.network-category-scripts.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
-}
-
-.network-category-xhr .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
-}
-
-.network-category-xhr.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
-}
-
-.network-category-websockets .network-graph-bar {
- -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
-}
-
-.network-category-websockets.resource-cached .network-graph-bar {
- -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
-}
-
-
-/* Popover */
-
-.network-timing-row {
- position: relative;
- height: 12px;
-}
-
-.network-timing-bar {
- position: absolute;
- background-color: red;
- border-left: 1px solid red;
- opacity: 0.4;
-}
-
-.network-timing-bar-title {
- position: absolute;
-}
-
-.network-dim-cell {
- color: grey;
-}
-
-/* Dividers */
-
-.network-timeline-grid {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-}
-
-.network-event-divider-padding {
- position: absolute;
- width: 8px;
- top: 0;
- bottom: 0;
- pointer-events: auto;
-}
-
-.network-event-divider {
- position: absolute;
- width: 2px;
- top: 0;
- bottom: 0;
- z-index: 300;
-}
-
-.network-red-divider {
- background-color: rgba(255, 0, 0, 0.5);
-}
-
-.network-blue-divider {
- background-color: rgba(0, 0, 255, 0.5);
-}
-
-.network.panel .resources-dividers-label-bar {
- background-color: transparent;
- border: none;
- height: 23px;
- pointer-events: none;
-}
-
-.network.panel .resources-divider-label {
- top: 6px;
- color: black;
-}
+.network-larger-resources-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
+}
+
+.network.panel .data-grid {
+ border: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ font-size: 11px;
+}
+
+.network.panel .data-grid table.data {
+ -webkit-background-size: 1px 82px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0.05)), to(rgba(0, 0, 0, 0.05)));
+ font-size: 11px;
+}
+
+.network.panel .data-grid.small table.data {
+ -webkit-background-size: 1px 42px;
+}
+
+.network.panel .data-grid td {
+ line-height: 17px;
+ border-right: 1px solid rgb(210, 210, 210);
+ -webkit-user-select: none;
+ vertical-align: middle;
+}
+
+.network.panel .data-grid th {
+ border-bottom: 1px solid rgb(64%, 64%, 64%);
+ height: 30px;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+.network.panel .data-grid.small th {
+ height: 22px;
+}
+
+.network.panel .data-grid th, .network.panel .data-grid th.sort-descending, .network.panel .data-grid th.sort-ascending {
+ background: -webkit-gradient(linear, left top, left bottom, from(rgb(236, 236, 236)), to(rgb(217, 217, 217)));
+}
+
+.network.panel .data-grid .data-container {
+ top: 31px;
+}
+
+.network.panel .data-grid.small .data-container {
+ top: 23px;
+}
+
+.network.panel .data-grid select {
+ -webkit-appearance: none;
+ background-color: transparent;
+ border: none;
+ width: 100%;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+.network.panel .data-grid tr.filler {
+ background-color: white;
+}
+
+.network.panel .data-grid td.name-column {
+ font-weight: bold;
+}
+
+.network.panel .data-grid td.method-column,
+.network.panel .data-grid td.status-column,
+.network.panel .data-grid td.type-column,
+.network.panel .data-grid td.size-column,
+.network.panel .data-grid td.time-column {
+ background-color: rgba(0, 0, 0, 0.07);
+}
+
+.network.panel .data-grid td.size-column,
+.network.panel .data-grid td.time-column {
+ text-align: right;
+}
+
+.network.panel .small .network-graph-side {
+ height: 14px;
+}
+
+.network.panel .data-grid th.sortable:active {
+ background-image: none;
+}
+
+.network-cell-subtitle {
+ font-weight: normal;
+ color: grey;
+}
+
+.network-header-subtitle {
+ color: grey;
+}
+
+.network.panel .data-grid.small .network-cell-subtitle,
+.network.panel .data-grid.small .network-header-subtitle
+{
+ display: none;
+}
+
+/* Resource preview icons */
+
+.network.panel .data-grid .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.network.panel .data-grid.small .icon {
+ content: url(Images/resourcePlainIconSmall.png);
+}
+
+.network.panel .network-category-scripts .icon {
+ content: url(Images/resourceJSIcon.png);
+}
+
+.network.panel .data-grid.small .network-category-scripts .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network.panel .network-category-documents .icon {
+ content: url(Images/resourceDocumentIcon.png);
+}
+
+.network.panel .data-grid.small .network-category-documents .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network.panel .network-category-stylesheets .icon {
+ content: url(Images/resourceCSSIcon.png);
+}
+
+.network.panel .data-grid.small .network-category-stylesheets .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.network.panel .network-category-images .icon {
+ position: relative;
+ background-image: url(Images/resourcePlainIcon.png);
+ background-repeat: no-repeat;
+ content: "";
+}
+
+.network.panel .network-category-images .icon {
+ position: relative;
+ background-image: url(Images/resourcePlainIcon.png);
+ background-repeat: no-repeat;
+ content: "";
+}
+
+.network.panel .data-grid.small .network-category-images .icon {
+ background-image: url(Images/resourcePlainIconSmall.png);
+ content: "";
+}
+
+.network.panel .data-grid .icon {
+ float: left;
+ width: 32px;
+ height: 32px;
+ margin-top: 1px;
+ margin-right: 3px;
+}
+
+.network.panel .data-grid.small .icon {
+ width: 16px;
+ height: 16px;
+}
+
+.network.panel .image-network-icon-preview {
+ position: absolute;
+ margin: auto;
+ top: 3px;
+ bottom: 4px;
+ left: 5px;
+ right: 5px;
+ max-width: 18px;
+ max-height: 21px;
+ min-width: 1px;
+ min-height: 1px;
+}
+
+.network.panel .data-grid.small .image-network-icon-preview {
+ top: 2px;
+ bottom: 1px;
+ left: 3px;
+ right: 3px;
+ max-width: 8px;
+ max-height: 11px;
+}
+
+/* Graph styles */
+
+.network-graph-side {
+ position: relative;
+ height: 36px;
+ padding: 0 5px;
+ white-space: nowrap;
+ margin-top: 1px;
+ border-top: 1px solid transparent;
+ overflow: hidden;
+}
+
+.network-graph-bar-area {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 8px;
+ left: 9px;
+}
+
+.network-graph-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ height: 13px;
+ line-height: 13px;
+ font-size: 9px;
+ color: rgba(0, 0, 0, 0.75);
+ text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
+ z-index: 150;
+ overflow: hidden;
+ text-align: center;
+ font-weight: bold;
+ opacity: 0;
+ -webkit-transition: opacity 250ms ease-in-out;
+}
+
+.network-graph-side:hover .network-graph-label {
+ opacity: 1;
+}
+
+.network-graph-label:empty {
+ display: none;
+}
+
+.network-graph-label.waiting {
+ margin-right: 5px;
+}
+
+.network-graph-label.waiting-right {
+ margin-left: 5px;
+}
+
+.network-graph-label.before {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: right;
+ margin-right: 2px;
+}
+
+.network-graph-label.before::after {
+ padding-left: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutLeft.png);
+}
+
+.network-graph-label.after {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: left;
+ margin-left: 2px;
+}
+
+.network-graph-label.after::before {
+ padding-right: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutRight.png);
+}
+
+.network-graph-bar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ border-width: 6px 7px;
+ height: 13px;
+ min-width: 14px;
+ opacity: 0.65;
+ -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.network-graph-bar.waiting, .network-graph-bar.waiting-right {
+ opacity: 0.35;
+}
+
+/* Resource categories */
+
+
+.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+.network-category-documents .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
+}
+
+.network-category-documents.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
+}
+
+.network-category-stylesheets .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
+}
+
+.network-category-stylesheets.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
+}
+
+.network-category-images .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
+}
+
+.network-category-images.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
+}
+
+.network-category-fonts .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
+}
+
+.network-category-fonts.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
+}
+
+.network-category-scripts .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
+}
+
+.network-category-scripts.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
+}
+
+.network-category-xhr .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
+}
+
+.network-category-xhr.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
+}
+
+.network-category-websockets .network-graph-bar {
+ -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.network-category-websockets.resource-cached .network-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+
+/* Popover */
+
+.network-timing-row {
+ position: relative;
+ height: 12px;
+}
+
+.network-timing-bar {
+ position: absolute;
+ background-color: red;
+ border-left: 1px solid red;
+ opacity: 0.4;
+}
+
+.network-timing-bar-title {
+ position: absolute;
+}
+
+.network-dim-cell {
+ color: grey;
+}
+
+/* Dividers */
+
+.network-timeline-grid {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ pointer-events: none;
+}
+
+.network-event-divider-padding {
+ position: absolute;
+ width: 8px;
+ top: 0;
+ bottom: 0;
+ pointer-events: auto;
+}
+
+.network-event-divider {
+ position: absolute;
+ width: 2px;
+ top: 31px;
+ bottom: 0;
+ z-index: 300;
+}
+
+.network.panel .network-timeline-grid.small .network-event-divider {
+ top: 23px;
+}
+
+.network-red-divider {
+ background-color: rgba(255, 0, 0, 0.5);
+}
+
+.network-blue-divider {
+ background-color: rgba(0, 0, 255, 0.5);
+}
+
+.network.panel .resources-dividers-label-bar {
+ background-color: transparent;
+ border: none;
+ height: 30px;
+ pointer-events: none;
+}
+
+.network.panel .network-timeline-grid.small .resources-dividers-label-bar {
+ height: 23px;
+}
+
+.network.panel .resources-divider-label {
+ top: 0px;
+ margin-top: -4px;
+ color: black;
+}
+
+.network.panel .resources-dividers-label-bar .resources-divider {
+ top: 23px;
+}
+
+.network.panel .network-timeline-grid.small .resources-dividers-label-bar .resources-divider {
+ top: 15px;
+}
+
+.network.panel .resources-divider.first .resources-divider-label {
+ display: none;
+}
+
+.network.panel .resources-dividers-label-bar .resources-divider.first {
+ background-color: transparent;
+}
+
+/* Filters */
+#network-filter {
+ margin-top: 1px;
+}
+
+.data-grid table.data tr.revealed.network-category-documents, .data-grid table.data tr.revealed.network-category-stylesheets,
+.data-grid table.data tr.revealed.network-category-images, .data-grid table.data tr.revealed.network-category-scripts,
+.data-grid table.data tr.revealed.network-category-xhr, .data-grid table.data tr.revealed.network-category-fonts,
+.data-grid table.data tr.revealed.network-category-websockets, .data-grid table.data tr.revealed.network-category-other {
+ display: none;
+}
+
+.data-grid.filter-all table.data tr.revealed.network-category-documents, .data-grid.filter-documents table.data tr.revealed.network-category-documents,
+.data-grid.filter-all table.data tr.revealed.network-category-stylesheets, .data-grid.filter-stylesheets table.data tr.revealed.network-category-stylesheets,
+.data-grid.filter-all table.data tr.revealed.network-category-images, .data-grid.filter-images table.data tr.revealed.network-category-images,
+.data-grid.filter-all table.data tr.revealed.network-category-scripts, .data-grid.filter-scripts table.data tr.revealed.network-category-scripts,
+.data-grid.filter-all table.data tr.revealed.network-category-xhr, .data-grid.filter-xhr table.data tr.revealed.network-category-xhr,
+.data-grid.filter-all table.data tr.revealed.network-category-fonts, .data-grid.filter-fonts table.data tr.revealed.network-category-fonts,
+.data-grid.filter-all table.data tr.revealed.network-category-websockets, .data-grid.filter-websockets table.data tr.revealed.network-category-websockets,
+.data-grid.filter-all table.data tr.revealed.network-category-other, .data-grid.filter-other table.data tr.revealed.network-category-other {
+ display: table-row;
+}
+
+/* Summary */
+
+.network-summary-bar {
+ background-color: rgb(101, 111, 130);
+ color: white;
+ height: 20px;
+ font-size: 11px;
+ font-weight: bold;
+ padding-top: 1px;
+ padding-left: 10px;
+ z-index: 2000;
+ white-space: pre;
+}
+
+.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.panel .data-grid td.network-summary {
+ padding: 0;
+}
+
+/* Viewer */
+
+.network.panel.viewing-resource .data-grid td,
+.network.panel.viewing-resource .data-grid th {
+ border-right: none;
+}
+
+.network.panel.viewing-resource .data-grid th.corner {
+ display: none;
+}
+
+#network-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-right: 0 none transparent;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.network.panel.viewing-resource #network-container {
+ border-right: 1px solid rgb(163, 163, 163);
+}
+
+#network-views {
+ position: absolute;
+ background: rgb(203, 203, 203);
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.network.panel .data-grid.full-grid-mode .viewer-column {
+ display: none;
+}
+
+.network.panel .data-grid.brief-grid-mode .viewer-column,
+.network.panel .data-grid.brief-grid-mode .method-column,
+.network.panel .data-grid.brief-grid-mode .status-column,
+.network.panel .data-grid.brief-grid-mode .type-column,
+.network.panel .data-grid.brief-grid-mode .size-column,
+.network.panel .data-grid.brief-grid-mode .time-column {
+ display: none;
+}
+
+.network.panel.viewing-resource .network-timeline-grid {
+ display: none;
+}
+
+.network.panel .data-grid.viewing-resource-mode .method-column,
+.network.panel .data-grid.viewing-resource-mode .status-column,
+.network.panel .data-grid.viewing-resource-mode .type-column,
+.network.panel .data-grid.viewing-resource-mode .size-column,
+.network.panel .data-grid.viewing-resource-mode .time-column,
+.network.panel .data-grid.viewing-resource-mode .timeline-column {
+ display: none;
+}
+
+.network.panel .network-sidebar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.network.panel:not(.viewing-resource) .sidebar-resizer-vertical {
+ display: none;
+}
+
+.network.panel.viewing-resource .data-grid-resizer {
+ display: none;
+}
+
+.network.panel .scope-bar {
+ height: 23px;
+ padding-top: 5px;
+}
+
+.network.panel .resource-view.headers-visible .resource-view-content {
+ top: 23px;
+}
+
+.network.panel:not(.viewing-resource) .data-grid tr.selected {
+ background-color: transparent;
+ color: black;
+}
+
+.network.panel .resource-view .tabbed-pane-header {
+ height: 23px;
+ padding-top: 3px;
+}
+
+.network.panel.viewing-resource .data-grid .data-container {
+ padding-right: 0;
+}
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index 5e41da6..3aff6bb 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -26,19 +26,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-Object.properties = function(obj)
-{
- var properties = [];
- for (var prop in obj)
- properties.push(prop);
- return properties;
-}
-
-Object.sortedProperties = function(obj, sortFunc)
-{
- return Object.properties(obj).sort(sortFunc);
-}
-
Function.prototype.bind = function(thisObject)
{
var func = this;
@@ -393,6 +380,26 @@ String.prototype.hasSubstring = function(string, caseInsensitive)
return this.match(new RegExp(string.escapeForRegExp(), "i"));
}
+String.prototype.asParsedURL = function()
+{
+ // RegExp groups:
+ // 1 - scheme
+ // 2 - hostname
+ // 3 - ?port
+ // 4 - ?path
+ // 5 - ?fragment
+ var match = this.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
+ if (!match)
+ return null;
+ var result = {};
+ result.scheme = match[1].toLowerCase();
+ result.host = match[2];
+ result.port = match[3];
+ result.path = match[4] || "/";
+ result.fragment = match[5];
+ return result;
+}
+
String.prototype.escapeCharacters = function(chars)
{
var foundChar = false;
@@ -990,6 +997,6 @@ function offerFileForDownload(contents)
var builder = new BlobBuilder();
builder.append(contents);
var blob = builder.getBlob("application/octet-stream");
- var url = window.createBlobURL(blob);
+ var url = window.createObjectURL(blob);
window.open(url);
}