summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector')
-rw-r--r--WebCore/inspector/InjectedScriptHost.cpp8
-rw-r--r--WebCore/inspector/InjectedScriptHost.h3
-rw-r--r--WebCore/inspector/InjectedScriptHost.idl3
-rw-r--r--WebCore/inspector/InspectorBackend.cpp57
-rw-r--r--WebCore/inspector/InspectorBackend.h13
-rw-r--r--WebCore/inspector/InspectorBackend.idl13
-rw-r--r--WebCore/inspector/InspectorCSSStore.cpp4
-rw-r--r--WebCore/inspector/InspectorClient.h8
-rw-r--r--WebCore/inspector/InspectorController.cpp189
-rw-r--r--WebCore/inspector/InspectorController.h20
-rw-r--r--WebCore/inspector/InspectorDOMAgent.cpp162
-rw-r--r--WebCore/inspector/InspectorDOMAgent.h10
-rw-r--r--WebCore/inspector/InspectorFrontend.cpp51
-rw-r--r--WebCore/inspector/InspectorFrontend.h8
-rw-r--r--WebCore/inspector/InspectorFrontendClientLocal.cpp2
-rw-r--r--WebCore/inspector/InspectorValues.cpp6
-rw-r--r--WebCore/inspector/InspectorValues.h2
-rw-r--r--WebCore/inspector/ScriptBreakpoint.cpp74
-rw-r--r--WebCore/inspector/ScriptBreakpoint.h10
-rw-r--r--WebCore/inspector/front-end/BreakpointManager.js35
-rw-r--r--WebCore/inspector/front-end/CSSCompletions.js102
-rw-r--r--WebCore/inspector/front-end/ConsoleView.js12
-rw-r--r--WebCore/inspector/front-end/DOMAgent.js3
-rw-r--r--WebCore/inspector/front-end/ElementsPanel.js9
-rw-r--r--WebCore/inspector/front-end/ElementsTreeOutline.js10
-rw-r--r--WebCore/inspector/front-end/InjectedScript.js395
-rw-r--r--WebCore/inspector/front-end/InjectedScriptAccess.js5
-rw-r--r--WebCore/inspector/front-end/InspectorBackendStub.js23
-rw-r--r--WebCore/inspector/front-end/InspectorFrontendHostStub.js8
-rw-r--r--WebCore/inspector/front-end/ProfilesPanel.js18
-rw-r--r--WebCore/inspector/front-end/ScriptView.js7
-rw-r--r--WebCore/inspector/front-end/ScriptsPanel.js2
-rw-r--r--WebCore/inspector/front-end/Section.js17
-rw-r--r--WebCore/inspector/front-end/StoragePanel.js37
-rw-r--r--WebCore/inspector/front-end/StylesSidebarPane.js77
-rw-r--r--WebCore/inspector/front-end/WebKit.qrc1
-rw-r--r--WebCore/inspector/front-end/inspector.css8
-rw-r--r--WebCore/inspector/front-end/inspector.html1
-rw-r--r--WebCore/inspector/front-end/inspector.js18
-rw-r--r--WebCore/inspector/front-end/utilities.js63
40 files changed, 1127 insertions, 367 deletions
diff --git a/WebCore/inspector/InjectedScriptHost.cpp b/WebCore/inspector/InjectedScriptHost.cpp
index 4c3c7ae..e8a9fee 100644
--- a/WebCore/inspector/InjectedScriptHost.cpp
+++ b/WebCore/inspector/InjectedScriptHost.cpp
@@ -110,17 +110,13 @@ long InjectedScriptHost::pushNodePathToFrontend(Node* node, bool withChildren, b
return id;
}
-long InjectedScriptHost::pushNodeByPathToFrontend(const String& path)
+long InjectedScriptHost::inspectedNode(unsigned long num)
{
InspectorDOMAgent* domAgent = inspectorDOMAgent();
if (!domAgent)
return 0;
- Node* node = domAgent->nodeForPath(path);
- if (!node)
- return 0;
-
- return domAgent->pushNodePathToFrontend(node);
+ return domAgent->inspectedNode(num);
}
#if ENABLE(DATABASE)
diff --git a/WebCore/inspector/InjectedScriptHost.h b/WebCore/inspector/InjectedScriptHost.h
index 66cf41e..b942148 100644
--- a/WebCore/inspector/InjectedScriptHost.h
+++ b/WebCore/inspector/InjectedScriptHost.h
@@ -68,8 +68,7 @@ public:
void copyText(const String& text);
Node* nodeForId(long nodeId);
long pushNodePathToFrontend(Node* node, bool withChildren, bool selectInUI);
-
- long pushNodeByPathToFrontend(const String& path);
+ long inspectedNode(unsigned long num);
#if ENABLE(DATABASE)
Database* databaseForId(long databaseId);
diff --git a/WebCore/inspector/InjectedScriptHost.idl b/WebCore/inspector/InjectedScriptHost.idl
index 5a4ce19..21af938 100644
--- a/WebCore/inspector/InjectedScriptHost.idl
+++ b/WebCore/inspector/InjectedScriptHost.idl
@@ -37,8 +37,7 @@ module core {
void copyText(in DOMString text);
[Custom] DOMObject nodeForId(in long nodeId);
[Custom] int pushNodePathToFrontend(in DOMObject node, in boolean withChildren, in boolean selectInUI);
-
- long pushNodeByPathToFrontend(in DOMString path);
+ long inspectedNode(in unsigned long num);
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
[Custom] DOMObject currentCallFrame();
diff --git a/WebCore/inspector/InspectorBackend.cpp b/WebCore/inspector/InspectorBackend.cpp
index 1eedda1..8e9e330 100644
--- a/WebCore/inspector/InspectorBackend.cpp
+++ b/WebCore/inspector/InspectorBackend.cpp
@@ -109,6 +109,18 @@ void InspectorBackend::disableSearchingForNode()
m_inspectorController->setSearchingForNode(false);
}
+void InspectorBackend::enableMonitoringXHR()
+{
+ if (m_inspectorController)
+ m_inspectorController->setMonitoringXHR(true);
+}
+
+void InspectorBackend::disableMonitoringXHR()
+{
+ if (m_inspectorController)
+ m_inspectorController->setMonitoringXHR(false);
+}
+
void InspectorBackend::enableResourceTracking(bool always)
{
if (m_inspectorController)
@@ -280,6 +292,12 @@ void InspectorBackend::clearProfiles()
if (m_inspectorController)
m_inspectorController->clearProfiles();
}
+
+void InspectorBackend::takeHeapSnapshot()
+{
+ if (m_inspectorController)
+ m_inspectorController->takeHeapSnapshot();
+}
#endif
void InspectorBackend::setInjectedScriptSource(const String& source)
@@ -359,10 +377,28 @@ void InspectorBackend::removeNode(long callId, long nodeId)
domAgent->removeNode(callId, nodeId);
}
-void InspectorBackend::changeTagName(long callId, long nodeId, const AtomicString& tagName, bool expanded)
+void InspectorBackend::changeTagName(long callId, long nodeId, const String& tagName)
+{
+ if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
+ domAgent->changeTagName(callId, nodeId, tagName);
+}
+
+void InspectorBackend::getOuterHTML(long callId, long nodeId)
{
if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
- domAgent->changeTagName(callId, nodeId, tagName, expanded);
+ domAgent->getOuterHTML(callId, nodeId);
+}
+
+void InspectorBackend::setOuterHTML(long callId, long nodeId, const String& outerHTML)
+{
+ if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
+ domAgent->setOuterHTML(callId, nodeId, outerHTML);
+}
+
+void InspectorBackend::addInspectedNode(long nodeId)
+{
+ if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
+ domAgent->addInspectedNode(nodeId);
}
void InspectorBackend::performSearch(const String& query, bool runSynchronously)
@@ -377,6 +413,23 @@ void InspectorBackend::searchCanceled()
domAgent->searchCanceled();
}
+void InspectorBackend::pushNodeByPathToFrontend(long callId, const String& path)
+{
+ InspectorDOMAgent* domAgent = inspectorDOMAgent();
+ InspectorFrontend* frontend = inspectorFrontend();
+ if (!domAgent || !frontend)
+ return;
+
+ long id = domAgent->pushNodeByPathToFrontend(path);
+ frontend->didPushNodeByPathToFrontend(callId, id);
+}
+
+void InspectorBackend::clearConsoleMessages()
+{
+ if (m_inspectorController)
+ m_inspectorController->clearConsoleMessages();
+}
+
void InspectorBackend::getStyles(long callId, long nodeId, bool authorOnly)
{
if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
diff --git a/WebCore/inspector/InspectorBackend.h b/WebCore/inspector/InspectorBackend.h
index 61d73b8..ce5dd99 100644
--- a/WebCore/inspector/InspectorBackend.h
+++ b/WebCore/inspector/InspectorBackend.h
@@ -65,6 +65,9 @@ public:
void enableSearchingForNode();
void disableSearchingForNode();
+ void enableMonitoringXHR();
+ void disableMonitoringXHR();
+
void enableResourceTracking(bool always);
void disableResourceTracking(bool always);
void getResourceContent(long callId, unsigned long identifier);
@@ -105,6 +108,8 @@ public:
void removeProfile(unsigned uid);
void clearProfiles();
+
+ void takeHeapSnapshot();
#endif
void setInjectedScriptSource(const String& source);
@@ -119,9 +124,15 @@ public:
void getEventListenersForNode(long callId, long nodeId);
void copyNode(long nodeId);
void removeNode(long callId, long nodeId);
- void changeTagName(long callId, long nodeId, const AtomicString& tagName, bool expanded);
+ void changeTagName(long callId, long nodeId, const String& tagName);
+ void getOuterHTML(long callId, long nodeId);
+ void setOuterHTML(long callId, long nodeId, const String& outerHTML);
+ void addInspectedNode(long nodeId);
void performSearch(const String& query, bool runSynchronously);
void searchCanceled();
+ void pushNodeByPathToFrontend(long callId, const String& path);
+
+ void clearConsoleMessages();
void getStyles(long callId, long nodeId, bool authOnly);
void getAllStyles(long callId);
diff --git a/WebCore/inspector/InspectorBackend.idl b/WebCore/inspector/InspectorBackend.idl
index c0078ee..eaacaf0 100644
--- a/WebCore/inspector/InspectorBackend.idl
+++ b/WebCore/inspector/InspectorBackend.idl
@@ -40,6 +40,9 @@ module core {
void enableSearchingForNode();
void disableSearchingForNode();
+ void enableMonitoringXHR();
+ void disableMonitoringXHR();
+
void enableResourceTracking(in boolean always);
void disableResourceTracking(in boolean always);
void getResourceContent(in long callId, in unsigned long identifier);
@@ -80,6 +83,8 @@ module core {
void removeProfile(in unsigned long uid);
void clearProfiles();
+
+ void takeHeapSnapshot();
#endif
void setInjectedScriptSource(in DOMString scriptSource);
void dispatchOnInjectedScript(in long callId, in long injectedScriptId, in DOMString methodName, in DOMString arguments, in boolean async);
@@ -94,9 +99,15 @@ module core {
void getEventListenersForNode(in long callId, in long nodeId);
void copyNode(in long nodeId);
void removeNode(in long callId, in long nodeId);
- void changeTagName(in long callId, in long nodeId, in DOMString newTagName, in boolean expanded);
+ void changeTagName(in long callId, in long nodeId, in DOMString newTagName);
+ void getOuterHTML(in long callId, in long nodeId);
+ void setOuterHTML(in long callId, in long nodeId, in DOMString outerHTML);
+ void addInspectedNode(in long nodeId);
void performSearch(in DOMString query, in boolean runSynchronously);
void searchCanceled();
+ void pushNodeByPathToFrontend(in long callId, in DOMString path);
+
+ void clearConsoleMessages();
void highlightDOMNode(in long nodeId);
void hideDOMNodeHighlight();
diff --git a/WebCore/inspector/InspectorCSSStore.cpp b/WebCore/inspector/InspectorCSSStore.cpp
index a080eda..7bc947a 100644
--- a/WebCore/inspector/InspectorCSSStore.cpp
+++ b/WebCore/inspector/InspectorCSSStore.cpp
@@ -29,6 +29,8 @@
#include "config.h"
#include "InspectorCSSStore.h"
+#if ENABLE(INSPECTOR)
+
#include "CSSMutableStyleDeclaration.h"
#include "CSSParser.h"
#include "CSSRuleList.h"
@@ -220,3 +222,5 @@ long InspectorCSSStore::bindRule(CSSStyleRule* rule)
}
} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/InspectorClient.h b/WebCore/inspector/InspectorClient.h
index 2ce3a09..61900bb 100644
--- a/WebCore/inspector/InspectorClient.h
+++ b/WebCore/inspector/InspectorClient.h
@@ -50,6 +50,14 @@ public:
virtual void storeSetting(const String& key, const String& value) = 0;
virtual bool sendMessageToFrontend(const String& message) = 0;
+
+ // Navigation can cause some WebKit implementations to change the view / page / inspector controller instance.
+ // 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 resourceTrackingWasEnabled() { };
+ virtual void resourceTrackingWasDisabled() { };
+ virtual void timelineProfilerWasStarted() { };
+ virtual void timelineProfilerWasStopped() { };
};
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp
index 7916cd0..5020634 100644
--- a/WebCore/inspector/InspectorController.cpp
+++ b/WebCore/inspector/InspectorController.cpp
@@ -62,6 +62,7 @@
#include "InspectorDatabaseResource.h"
#include "InspectorFrontend.h"
#include "InspectorResource.h"
+#include "InspectorValues.h"
#include "InspectorWorkerResource.h"
#include "InspectorTimelineAgent.h"
#include "Page.h"
@@ -86,6 +87,7 @@
#include <wtf/text/CString.h>
#include <wtf/CurrentTime.h>
#include <wtf/ListHashSet.h>
+#include <wtf/MD5.h>
#include <wtf/RefCounted.h>
#include <wtf/StdLibExtras.h>
@@ -120,6 +122,7 @@ static const char* const debuggerEnabledSettingName = "debuggerEnabled";
static const char* const profilerEnabledSettingName = "profilerEnabled";
static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight";
static const char* const lastActivePanelSettingName = "lastActivePanel";
+static const char* const monitoringXHRSettingName = "xhrMonitor";
const String& InspectorController::frontendSettingsSettingName()
{
@@ -141,6 +144,27 @@ static const unsigned expireConsoleMessagesStep = 100;
static unsigned s_inspectorControllerCount;
+namespace {
+
+String md5Base16(const String& string)
+{
+ static const char digits[] = "0123456789abcdef";
+
+ MD5 md5;
+ md5.addBytes(reinterpret_cast<const uint8_t*>(string.characters()), string.length() * 2);
+ Vector<uint8_t, 16> digest;
+ md5.checksum(digest);
+
+ Vector<char, 32> result;
+ for (int i = 0; i < 16; ++i) {
+ result.append(digits[(digest[i] >> 4) & 0xf]);
+ result.append(digits[digest[i] & 0xf]);
+ }
+ return String(result.data(), result.size());
+}
+
+}
+
InspectorController::InspectorController(Page* page, InspectorClient* client)
: m_inspectedPage(page)
, m_client(client)
@@ -151,15 +175,17 @@ InspectorController::InspectorController(Page* page, InspectorClient* client)
, m_sessionSettings(InspectorObject::create())
, m_groupLevel(0)
, m_searchingForNode(false)
+ , m_monitoringXHR(false)
, m_previousMessage(0)
, m_resourceTrackingEnabled(false)
- , m_resourceTrackingSettingsLoaded(false)
+ , m_settingsLoaded(false)
, m_inspectorBackend(InspectorBackend::create(this))
, m_injectedScriptHost(InjectedScriptHost::create(this))
#if ENABLE(JAVASCRIPT_DEBUGGER)
, m_debuggerEnabled(false)
, m_attachDebuggerWhenShown(false)
, m_pausedScriptState(0)
+ , m_breakpointsLoaded(false)
, m_profilerEnabled(!WTF_USE_JSC)
, m_recordingUserInitiatedProfile(false)
, m_currentUserInitiatedProfileNumber(-1)
@@ -232,7 +258,7 @@ void InspectorController::setSetting(const String& key, const String& value)
void InspectorController::setSessionSettings(const String& settingsJSON)
{
- m_sessionSettings = InspectorValue::readJSON(settingsJSON);
+ m_sessionSettings = InspectorValue::parseJSON(settingsJSON);
}
void InspectorController::inspect(Node* node)
@@ -431,6 +457,20 @@ void InspectorController::setSearchingForNode(bool enabled)
}
}
+void InspectorController::setMonitoringXHR(bool enabled)
+{
+ if (m_monitoringXHR == enabled)
+ return;
+ m_monitoringXHR = enabled;
+ setSetting(monitoringXHRSettingName, enabled ? "true" : "false");
+ if (m_frontend) {
+ if (enabled)
+ m_frontend->monitoringXHRWasEnabled();
+ else
+ m_frontend->monitoringXHRWasDisabled();
+ }
+}
+
void InspectorController::connectFrontend(const ScriptObject& webInspector)
{
m_openingFrontend = false;
@@ -439,6 +479,12 @@ void InspectorController::connectFrontend(const ScriptObject& webInspector)
m_domAgent = InspectorDOMAgent::create(m_cssStore.get(), m_frontend.get());
if (m_timelineAgent)
m_timelineAgent->resetFrontendProxyObject(m_frontend.get());
+
+ // Initialize Web Inspector title.
+ m_frontend->inspectedURLChanged(m_inspectedPage->mainFrame()->loader()->url().string());
+
+ populateScriptObjects();
+
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (ScriptDebugServer::shared().isDebuggerAlwaysEnabled()) {
// FIXME (40364): This will force pushing script sources to frontend even if script
@@ -446,7 +492,7 @@ void InspectorController::connectFrontend(const ScriptObject& webInspector)
enableDebuggerFromFrontend(false);
} else {
String debuggerEnabled = setting(debuggerEnabledSettingName);
- if (debuggerEnabled == "true")
+ if (debuggerEnabled == "true" || m_attachDebuggerWhenShown)
enableDebugger();
String profilerEnabled = setting(profilerEnabledSettingName);
if (profilerEnabled == "true")
@@ -454,11 +500,6 @@ void InspectorController::connectFrontend(const ScriptObject& webInspector)
}
#endif
- // Initialize Web Inspector title.
- m_frontend->inspectedURLChanged(m_inspectedPage->mainFrame()->loader()->url().string());
-
- populateScriptObjects();
-
if (m_showAfterVisible == CurrentPanel) {
String lastActivePanelSetting = setting(lastActivePanelSettingName);
m_showAfterVisible = specialPanelForJSName(lastActivePanelSetting);
@@ -466,10 +507,6 @@ void InspectorController::connectFrontend(const ScriptObject& webInspector)
if (m_nodeToFocus)
focusNode();
-#if ENABLE(JAVASCRIPT_DEBUGGER)
- if (m_attachDebuggerWhenShown)
- enableDebugger();
-#endif
showPanel(m_showAfterVisible);
}
@@ -526,8 +563,7 @@ void InspectorController::disconnectFrontend()
// opening.
bool debuggerWasEnabled = m_debuggerEnabled;
disableDebugger();
- if (debuggerWasEnabled)
- m_attachDebuggerWhenShown = true;
+ m_attachDebuggerWhenShown = debuggerWasEnabled;
#endif
setSearchingForNode(false);
unbindAllResources();
@@ -567,8 +603,9 @@ void InspectorController::populateScriptObjects()
if (m_searchingForNode)
m_frontend->searchingForNodeWasEnabled();
- else
- m_frontend->searchingForNodeWasDisabled();
+
+ if (m_monitoringXHR)
+ m_frontend->monitoringXHRWasEnabled();
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (m_profilerEnabled)
@@ -674,11 +711,15 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
#if ENABLE(JAVASCRIPT_DEBUGGER)
m_sourceIDToURL.clear();
m_scriptIDToContent.clear();
+ m_stickyBreakpoints.clear();
+ m_breakpointsLoaded = false;
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
m_profiles.clear();
m_currentUserInitiatedProfileNumber = 1;
m_nextUserInitiatedProfileNumber = 1;
+ if (m_frontend)
+ m_frontend->resetProfilesPanel();
#endif
// unbindAllResources should be called before database and DOM storage
// resources are cleared so that it has a chance to unbind them.
@@ -812,7 +853,7 @@ void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader,
ASSERT(m_inspectedPage);
bool isMainResource = isMainResourceLoader(loader, KURL(ParsedURLString, cachedResource->url()));
- ensureResourceTrackingSettingsLoaded();
+ ensureSettingsLoaded();
if (!isMainResource && !m_resourceTrackingEnabled)
return;
@@ -836,7 +877,7 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier,
ASSERT(m_inspectedPage);
bool isMainResource = isMainResourceLoader(loader, request.url());
- ensureResourceTrackingSettingsLoaded();
+ ensureSettingsLoaded();
if (!isMainResource && !m_resourceTrackingEnabled)
return;
@@ -1006,9 +1047,15 @@ void InspectorController::didFailLoading(unsigned long identifier, const Resourc
resource->updateScriptObject(m_frontend.get());
}
-void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString)
+void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber)
{
- if (!enabled() || !m_resourceTrackingEnabled)
+ if (!enabled())
+ return;
+
+ if (m_monitoringXHR)
+ addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, "XHR finished loading: \"" + url + "\".", sendLineNumber, sendURL);
+
+ if (!m_resourceTrackingEnabled)
return;
InspectorResource* resource = m_resources.get(identifier).get();
@@ -1051,6 +1098,7 @@ void InspectorController::enableResourceTracking(bool always, bool reload)
m_resourceTrackingEnabled = true;
if (m_frontend)
m_frontend->resourceTrackingWasEnabled();
+ m_client->resourceTrackingWasEnabled();
if (reload)
m_inspectedPage->mainFrame()->redirectScheduler()->scheduleRefresh(true);
@@ -1068,17 +1116,23 @@ void InspectorController::disableResourceTracking(bool always)
m_resourceTrackingEnabled = false;
if (m_frontend)
m_frontend->resourceTrackingWasDisabled();
+ m_client->resourceTrackingWasDisabled();
}
-void InspectorController::ensureResourceTrackingSettingsLoaded()
+void InspectorController::ensureSettingsLoaded()
{
- if (m_resourceTrackingSettingsLoaded)
+ if (m_settingsLoaded)
return;
- m_resourceTrackingSettingsLoaded = true;
+ m_settingsLoaded = true;
String resourceTracking = setting(resourceTrackingEnabledSettingName);
if (resourceTracking == "true")
m_resourceTrackingEnabled = true;
+ m_client->resourceTrackingWasEnabled();
+
+ String monitoringXHR = setting(monitoringXHRSettingName);
+ if (monitoringXHR == "true")
+ m_monitoringXHR = true;
}
void InspectorController::startTimelineProfiler()
@@ -1092,6 +1146,7 @@ void InspectorController::startTimelineProfiler()
m_timelineAgent = new InspectorTimelineAgent(m_frontend.get());
if (m_frontend)
m_frontend->timelineProfilerWasStarted();
+ m_client->timelineProfilerWasStarted();
}
void InspectorController::stopTimelineProfiler()
@@ -1105,6 +1160,7 @@ void InspectorController::stopTimelineProfiler()
m_timelineAgent = 0;
if (m_frontend)
m_frontend->timelineProfilerWasStopped();
+ m_client->timelineProfilerWasStopped();
}
#if ENABLE(WORKERS)
@@ -1580,18 +1636,27 @@ void InspectorController::disableProfiler(bool always)
if (m_frontend)
m_frontend->profilerWasDisabled();
}
+
+void InspectorController::takeHeapSnapshot()
+{
+ if (!enabled())
+ return;
+
+ ScriptProfiler::takeHeapSnapshot();
+}
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
void InspectorController::enableDebuggerFromFrontend(bool always)
{
+ ASSERT(!m_debuggerEnabled);
if (always)
setSetting(debuggerEnabledSettingName, "true");
ASSERT(m_inspectedPage);
- ScriptDebugServer::shared().addListener(this, m_inspectedPage);
ScriptDebugServer::shared().clearBreakpoints();
+ ScriptDebugServer::shared().addListener(this, m_inspectedPage);
m_debuggerEnabled = true;
m_frontend->debuggerWasEnabled();
@@ -1678,10 +1743,12 @@ void InspectorController::setBreakpoint(const String& sourceID, unsigned lineNum
if (url.isEmpty())
return;
- HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url);
+ String key = md5Base16(url);
+ HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(key);
if (it == m_stickyBreakpoints.end())
- it = m_stickyBreakpoints.set(url, SourceBreakpoints()).first;
+ it = m_stickyBreakpoints.set(key, SourceBreakpoints()).first;
it->second.set(lineNumber, breakpoint);
+ saveBreakpoints();
}
void InspectorController::removeBreakpoint(const String& sourceID, unsigned lineNumber)
@@ -1692,9 +1759,10 @@ void InspectorController::removeBreakpoint(const String& sourceID, unsigned line
if (url.isEmpty())
return;
- HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url);
+ HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(md5Base16(url));
if (it != m_stickyBreakpoints.end())
it->second.remove(lineNumber);
+ saveBreakpoints();
}
// JavaScriptDebugListener functions
@@ -1704,10 +1772,13 @@ void InspectorController::didParseSource(const String& sourceID, const String& u
// Don't send script content to the front end until it's really needed.
m_frontend->parsedScriptSource(sourceID, url, "", firstLine, worldType);
+ m_scriptIDToContent.set(sourceID, data);
+
if (url.isEmpty())
return;
- HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url);
+ loadBreakpoints();
+ HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(md5Base16(url));
if (it != m_stickyBreakpoints.end()) {
for (SourceBreakpoints::iterator breakpointIt = it->second.begin(); breakpointIt != it->second.end(); ++breakpointIt) {
if (firstLine <= breakpointIt->first) {
@@ -1716,9 +1787,7 @@ void InspectorController::didParseSource(const String& sourceID, const String& u
}
}
}
-
m_sourceIDToURL.set(sourceID, url);
- m_scriptIDToContent.set(sourceID, data);
}
void InspectorController::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
@@ -1761,6 +1830,47 @@ void InspectorController::didEvaluateForTestInFrontend(long callId, const String
function.call();
}
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+String InspectorController::breakpointsSettingKey()
+{
+ DEFINE_STATIC_LOCAL(String, keyPrefix, ("breakpoints:"));
+ return keyPrefix + md5Base16(m_mainResource->requestURL());
+}
+
+void InspectorController::loadBreakpoints()
+{
+ if (m_breakpointsLoaded)
+ return;
+ m_breakpointsLoaded = true;
+
+ RefPtr<InspectorValue> parsedSetting = InspectorValue::parseJSON(setting(breakpointsSettingKey()));
+ if (!parsedSetting)
+ return;
+ RefPtr<InspectorObject> breakpoints = parsedSetting->asObject();
+ if (!breakpoints)
+ return;
+ for (InspectorObject::iterator it = breakpoints->begin(); it != breakpoints->end(); ++it) {
+ RefPtr<InspectorObject> breakpointsForURL = it->second->asObject();
+ if (!breakpointsForURL)
+ continue;
+ HashMap<String, SourceBreakpoints>::iterator sourceBreakpointsIt = m_stickyBreakpoints.set(it->first, SourceBreakpoints()).first;
+ ScriptBreakpoint::sourceBreakpointsFromInspectorObject(breakpointsForURL, &sourceBreakpointsIt->second);
+ }
+}
+
+void InspectorController::saveBreakpoints()
+{
+ RefPtr<InspectorObject> breakpoints = InspectorObject::create();
+ for (HashMap<String, SourceBreakpoints>::iterator it(m_stickyBreakpoints.begin()); it != m_stickyBreakpoints.end(); ++it) {
+ if (it->second.isEmpty())
+ continue;
+ RefPtr<InspectorObject> breakpointsForURL = ScriptBreakpoint::inspectorObjectFromSourceBreakpoints(it->second);
+ breakpoints->set(it->first, breakpointsForURL);
+ }
+ setSetting(breakpointsSettingKey(), breakpoints->toJSONString());
+}
+#endif
+
static Path quadToPath(const FloatQuad& quad)
{
Path quadPath;
@@ -1826,7 +1936,7 @@ static void drawHighlightForBox(GraphicsContext& context, const FloatQuad& conte
drawOutlinedQuad(context, contentQuad, contentBoxColor);
}
-static void drawHighlightForLineBoxes(GraphicsContext& context, const Vector<FloatQuad>& lineBoxQuads)
+static void drawHighlightForLineBoxesOrSVGRenderer(GraphicsContext& context, const Vector<FloatQuad>& lineBoxQuads)
{
static const Color lineBoxColor(125, 173, 217, 128);
@@ -1867,7 +1977,14 @@ void InspectorController::drawNodeHighlight(GraphicsContext& context) const
overlayRect = view->visibleContentRect();
context.translate(-overlayRect.x(), -overlayRect.y());
- if (renderer->isBox()) {
+ // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
+#if ENABLE(SVG)
+ bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
+#else
+ bool isSVGRenderer = false;
+#endif
+
+ if (renderer->isBox() && !isSVGRenderer) {
RenderBox* renderBox = toRenderBox(renderer);
IntRect contentBox = renderBox->contentBoxRect();
@@ -1890,16 +2007,14 @@ void InspectorController::drawNodeHighlight(GraphicsContext& context) const
absMarginQuad.move(mainFrameOffset);
drawHighlightForBox(context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
- } else if (renderer->isRenderInline()) {
- RenderInline* renderInline = toRenderInline(renderer);
-
+ } else if (renderer->isRenderInline() || isSVGRenderer) {
// FIXME: We should show margins/padding/border for inlines.
Vector<FloatQuad> lineBoxQuads;
- renderInline->absoluteQuads(lineBoxQuads);
+ renderer->absoluteQuads(lineBoxQuads);
for (unsigned i = 0; i < lineBoxQuads.size(); ++i)
lineBoxQuads[i] += mainFrameOffset;
- drawHighlightForLineBoxes(context, lineBoxQuads);
+ drawHighlightForLineBoxesOrSVGRenderer(context, lineBoxQuads);
}
}
diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h
index 346a8dc..b2d1d5a 100644
--- a/WebCore/inspector/InspectorController.h
+++ b/WebCore/inspector/InspectorController.h
@@ -170,13 +170,14 @@ public:
void didReceiveContentLength(unsigned long identifier, int lengthReceived);
void didFinishLoading(unsigned long identifier);
void didFailLoading(unsigned long identifier, const ResourceError&);
- void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString);
+ void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber);
void scriptImported(unsigned long identifier, const String& sourceString);
void enableResourceTracking(bool always = false, bool reload = true);
void disableResourceTracking(bool always = false);
bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; }
- void ensureResourceTrackingSettingsLoaded();
+
+ void ensureSettingsLoaded();
void startTimelineProfiler();
void stopTimelineProfiler();
@@ -240,6 +241,8 @@ public:
void enableProfiler(bool always = false, bool skipRecompile = false);
void disableProfiler(bool always = false);
bool profilerEnabled() const { return enabled() && m_profilerEnabled; }
+
+ void takeHeapSnapshot();
#endif
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -278,6 +281,7 @@ private:
// Following are used from InspectorBackend and internally.
void setSearchingForNode(bool enabled);
+ void setMonitoringXHR(bool enabled);
void storeLastActivePanel(const String& panelName);
InspectorDOMAgent* domAgent() { return m_domAgent.get(); }
void releaseDOMAgent();
@@ -325,6 +329,12 @@ private:
void didEvaluateForTestInFrontend(long callId, const String& jsonResult);
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ String breakpointsSettingKey();
+ void loadBreakpoints();
+ void saveBreakpoints();
+#endif
+
Page* m_inspectedPage;
InspectorClient* m_client;
OwnPtr<InspectorFrontendClient> m_inspectorFrontendClient;
@@ -350,12 +360,15 @@ private:
#endif
SpecialPanels m_showAfterVisible;
RefPtr<Node> m_highlightedNode;
+#if ENABLE(INSPECTOR)
RefPtr<InspectorValue> m_sessionSettings;
+#endif
unsigned m_groupLevel;
bool m_searchingForNode;
+ bool m_monitoringXHR;
ConsoleMessage* m_previousMessage;
bool m_resourceTrackingEnabled;
- bool m_resourceTrackingSettingsLoaded;
+ bool m_settingsLoaded;
RefPtr<InspectorBackend> m_inspectorBackend;
RefPtr<InjectedScriptHost> m_injectedScriptHost;
@@ -371,6 +384,7 @@ private:
HashMap<String, String> m_sourceIDToURL;
HashMap<String, String> m_scriptIDToContent;
HashMap<String, SourceBreakpoints> m_stickyBreakpoints;
+ bool m_breakpointsLoaded;
bool m_profilerEnabled;
bool m_recordingUserInitiatedProfile;
diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp
index b152dc3..a2f2e15 100644
--- a/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/WebCore/inspector/InspectorDOMAgent.cpp
@@ -53,9 +53,9 @@
#include "EventTarget.h"
#include "Frame.h"
#include "FrameTree.h"
+#include "HTMLElement.h"
#include "HTMLFrameOwnerElement.h"
#include "InspectorFrontend.h"
-#include "markup.h"
#include "MutationEvent.h"
#include "Node.h"
#include "NodeList.h"
@@ -355,12 +355,28 @@ void InspectorDOMAgent::pushChildNodesToFrontend(long nodeId)
m_frontend->setChildNodes(nodeId, children);
}
+long InspectorDOMAgent::pushNodeByPathToFrontend(const String& path)
+{
+ Node* node = nodeForPath(path);
+ if (!node)
+ return 0;
+ return pushNodePathToFrontend(node);
+}
+
+long InspectorDOMAgent::inspectedNode(unsigned long num)
+{
+ if (num < m_inspectedNodes.size())
+ return m_inspectedNodes[num];
+ return 0;
+}
+
void InspectorDOMAgent::discardBindings()
{
m_documentNodeToIdMap.clear();
m_idToNode.clear();
releaseDanglingNodes();
m_childrenRequested.clear();
+ m_inspectedNodes.clear();
}
Node* InspectorDOMAgent::nodeForId(long id)
@@ -374,35 +390,6 @@ Node* InspectorDOMAgent::nodeForId(long id)
return 0;
}
-Node* InspectorDOMAgent::nodeForPath(const String& path)
-{
- // The path is of form "1,HTML,2,BODY,1,DIV"
- Node* node = mainFrameDocument();
- if (!node)
- return 0;
-
- Vector<String> pathTokens;
- path.split(",", false, pathTokens);
- for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
- bool success = true;
- unsigned childNumber = pathTokens[i].toUInt(&success);
- if (!success)
- return 0;
- if (childNumber >= innerChildNodeCount(node))
- return 0;
-
- Node* child = innerFirstChild(node);
- String childName = pathTokens[i + 1];
- for (size_t j = 0; child && j < childNumber; ++j)
- child = innerNextSibling(child);
-
- if (!child || child->nodeName() != childName)
- return 0;
- node = child;
- }
- return node;
-}
-
void InspectorDOMAgent::getChildNodes(long callId, long nodeId)
{
pushChildNodesToFrontend(nodeId);
@@ -481,40 +468,40 @@ void InspectorDOMAgent::removeNode(long callId, long nodeId)
{
Node* node = nodeForId(nodeId);
if (!node) {
- // Use -1 to denote an error condition.
- m_frontend->didRemoveNode(callId, -1);
+ m_frontend->didRemoveNode(callId, 0);
return;
}
Node* parentNode = node->parentNode();
if (!parentNode) {
- m_frontend->didRemoveNode(callId, -1);
+ m_frontend->didRemoveNode(callId, 0);
return;
}
- ExceptionCode code;
- parentNode->removeChild(node, code);
- if (code) {
- m_frontend->didRemoveNode(callId, -1);
+ ExceptionCode ec = 0;
+ parentNode->removeChild(node, ec);
+ if (ec) {
+ m_frontend->didRemoveNode(callId, 0);
return;
}
m_frontend->didRemoveNode(callId, nodeId);
}
-void InspectorDOMAgent::changeTagName(long callId, long nodeId, const AtomicString& tagName, bool expanded)
+void InspectorDOMAgent::changeTagName(long callId, long nodeId, const String& tagName)
{
Node* oldNode = nodeForId(nodeId);
if (!oldNode || !oldNode->isElementNode()) {
- // Use -1 to denote an error condition.
- m_frontend->didChangeTagName(callId, -1);
+ m_frontend->didChangeTagName(callId, 0);
return;
}
- ExceptionCode code = 0;
- RefPtr<Element> newElem = oldNode->document()->createElement(tagName, code);
- if (code) {
- m_frontend->didChangeTagName(callId, -1);
+ bool childrenRequested = m_childrenRequested.contains(nodeId);
+
+ ExceptionCode ec = 0;
+ RefPtr<Element> newElem = oldNode->document()->createElement(tagName, ec);
+ if (ec) {
+ m_frontend->didChangeTagName(callId, 0);
return;
}
@@ -527,24 +514,63 @@ void InspectorDOMAgent::changeTagName(long callId, long nodeId, const AtomicStri
// Copy over the original node's children.
Node* child;
while ((child = oldNode->firstChild()))
- newElem->appendChild(child, code);
+ newElem->appendChild(child, ec);
// Replace the old node with the new node
Node* parent = oldNode->parentNode();
- parent->insertBefore(newElem, oldNode->nextSibling(), code);
- parent->removeChild(oldNode, code);
+ parent->insertBefore(newElem, oldNode->nextSibling(), ec);
+ parent->removeChild(oldNode, ec);
- if (code) {
- m_frontend->didChangeTagName(callId, -1);
+ if (ec) {
+ m_frontend->didChangeTagName(callId, 0);
return;
}
long newId = pushNodePathToFrontend(newElem.get());
- if (expanded)
+ if (childrenRequested)
pushChildNodesToFrontend(newId);
m_frontend->didChangeTagName(callId, newId);
}
+void InspectorDOMAgent::getOuterHTML(long callId, long nodeId)
+{
+ Node* node = nodeForId(nodeId);
+ if (!node || !node->isHTMLElement()) {
+ m_frontend->didGetOuterHTML(callId, "");
+ return;
+ }
+
+ HTMLElement* htmlElement = static_cast<HTMLElement*>(node);
+ m_frontend->didGetOuterHTML(callId, htmlElement->outerHTML());
+}
+
+void InspectorDOMAgent::setOuterHTML(long callId, long nodeId, const String& outerHTML)
+{
+ Node* node = nodeForId(nodeId);
+ if (!node || !node->isHTMLElement()) {
+ m_frontend->didSetOuterHTML(callId, 0);
+ return;
+ }
+
+ bool childrenRequested = m_childrenRequested.contains(nodeId);
+ Node* previousSibling = node->previousSibling();
+ Node* parentNode = node->parentNode();
+
+ HTMLElement* htmlElement = static_cast<HTMLElement*>(node);
+ ExceptionCode ec = 0;
+ htmlElement->setOuterHTML(outerHTML, ec);
+ if (ec)
+ m_frontend->didSetOuterHTML(callId, 0);
+
+ Node* newNode = previousSibling ? previousSibling->nextSibling() : parentNode->firstChild();
+
+ long newId = pushNodePathToFrontend(newNode);
+ if (childrenRequested)
+ pushChildNodesToFrontend(newId);
+
+ m_frontend->didSetOuterHTML(callId, newId);
+}
+
void InspectorDOMAgent::setTextNodeValue(long callId, long nodeId, const String& value)
{
Node* node = nodeForId(nodeId);
@@ -632,6 +658,13 @@ void InspectorDOMAgent::getEventListenersForNode(long callId, long nodeId)
m_frontend->didGetEventListenersForNode(callId, nodeId, listenersArray);
}
+void InspectorDOMAgent::addInspectedNode(long nodeId)
+{
+ m_inspectedNodes.prepend(nodeId);
+ while (m_inspectedNodes.size() > 5)
+ m_inspectedNodes.removeLast();
+}
+
void InspectorDOMAgent::performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously)
{
// FIXME: Few things are missing here:
@@ -1531,6 +1564,35 @@ bool InspectorDOMAgent::ruleAffectsNode(CSSStyleRule* rule, Node* node)
return false;
}
+Node* InspectorDOMAgent::nodeForPath(const String& path)
+{
+ // The path is of form "1,HTML,2,BODY,1,DIV"
+ Node* node = mainFrameDocument();
+ if (!node)
+ return 0;
+
+ Vector<String> pathTokens;
+ path.split(",", false, pathTokens);
+ for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
+ bool success = true;
+ unsigned childNumber = pathTokens[i].toUInt(&success);
+ if (!success)
+ return 0;
+ if (childNumber >= innerChildNodeCount(node))
+ return 0;
+
+ Node* child = innerFirstChild(node);
+ String childName = pathTokens[i + 1];
+ for (size_t j = 0; child && j < childNumber; ++j)
+ child = innerNextSibling(child);
+
+ if (!child || child->nodeName() != childName)
+ return 0;
+ node = child;
+ }
+ return node;
+}
+
ScriptArray InspectorDOMAgent::toArray(const Vector<String>& data)
{
ScriptArray result = m_frontend->newScriptArray();
diff --git a/WebCore/inspector/InspectorDOMAgent.h b/WebCore/inspector/InspectorDOMAgent.h
index a962569..70d5b94 100644
--- a/WebCore/inspector/InspectorDOMAgent.h
+++ b/WebCore/inspector/InspectorDOMAgent.h
@@ -102,9 +102,12 @@ namespace WebCore {
void setAttribute(long callId, long elementId, const String& name, const String& value);
void removeAttribute(long callId, long elementId, const String& name);
void removeNode(long callId, long nodeId);
- void changeTagName(long callId, long nodeId, const AtomicString& tagName, bool expanded);
+ void changeTagName(long callId, long nodeId, const String& tagName);
+ void getOuterHTML(long callId, long nodeId);
+ void setOuterHTML(long callId, long nodeId, const String& outerHTML);
void setTextNodeValue(long callId, long nodeId, const String& value);
void getEventListenersForNode(long callId, long nodeId);
+ void addInspectedNode(long nodeId);
void performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously);
void searchCanceled();
@@ -131,9 +134,10 @@ namespace WebCore {
void didModifyDOMAttr(Element*);
Node* nodeForId(long nodeId);
- Node* nodeForPath(const String& path);
long pushNodePathToFrontend(Node* node);
void pushChildNodesToFrontend(long nodeId);
+ long pushNodeByPathToFrontend(const String& path);
+ long inspectedNode(unsigned long num);
private:
static CSSStyleSheet* getParentStyleSheet(CSSStyleDeclaration*);
@@ -183,6 +187,7 @@ namespace WebCore {
String shorthandValue(CSSStyleDeclaration*, const String& shorthandProperty);
String shorthandPriority(CSSStyleDeclaration*, const String& shorthandProperty);
bool ruleAffectsNode(CSSStyleRule*, Node*);
+ Node* nodeForPath(const String& path);
ScriptArray toArray(const Vector<String>& data);
void discardBindings();
@@ -200,6 +205,7 @@ namespace WebCore {
Deque<MatchJob*> m_pendingMatchJobs;
Timer<InspectorDOMAgent> m_matchJobsTimer;
HashSet<RefPtr<Node> > m_searchResults;
+ Vector<long> m_inspectedNodes;
};
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorFrontend.cpp b/WebCore/inspector/InspectorFrontend.cpp
index c9aa730..cde5a70 100644
--- a/WebCore/inspector/InspectorFrontend.cpp
+++ b/WebCore/inspector/InspectorFrontend.cpp
@@ -184,14 +184,6 @@ void InspectorFrontend::updateFocusedNode(long nodeId)
function.call();
}
-void InspectorFrontend::setAttachedWindow(bool attached)
-{
- ScriptFunctionCall function(m_webInspector, "dispatch");
- function.appendArgument("setAttachedWindow");
- function.appendArgument(attached);
- function.call();
-}
-
void InspectorFrontend::showPanel(int panel)
{
const char* showFunctionName;
@@ -239,6 +231,11 @@ void InspectorFrontend::reset()
callSimpleFunction("reset");
}
+void InspectorFrontend::resetProfilesPanel()
+{
+ callSimpleFunction("resetProfilesPanel");
+}
+
void InspectorFrontend::bringToFront()
{
callSimpleFunction("bringToFront");
@@ -262,7 +259,6 @@ void InspectorFrontend::resourceTrackingWasDisabled()
callSimpleFunction("resourceTrackingWasDisabled");
}
-
void InspectorFrontend::searchingForNodeWasEnabled()
{
callSimpleFunction("searchingForNodeWasEnabled");
@@ -273,6 +269,16 @@ void InspectorFrontend::searchingForNodeWasDisabled()
callSimpleFunction("searchingForNodeWasDisabled");
}
+void InspectorFrontend::monitoringXHRWasEnabled()
+{
+ callSimpleFunction("monitoringXHRWasEnabled");
+}
+
+void InspectorFrontend::monitoringXHRWasDisabled()
+{
+ callSimpleFunction("monitoringXHRWasDisabled");
+}
+
void InspectorFrontend::updatePauseOnExceptionsState(long state)
{
ScriptFunctionCall function(m_webInspector, "dispatch");
@@ -514,6 +520,33 @@ void InspectorFrontend::didChangeTagName(long callId, long nodeId)
function.call();
}
+void InspectorFrontend::didGetOuterHTML(long callId, const String& outerHTML)
+{
+ ScriptFunctionCall function(m_webInspector, "dispatch");
+ function.appendArgument("didGetOuterHTML");
+ function.appendArgument(callId);
+ function.appendArgument(outerHTML);
+ function.call();
+}
+
+void InspectorFrontend::didSetOuterHTML(long callId, long nodeId)
+{
+ ScriptFunctionCall function(m_webInspector, "dispatch");
+ function.appendArgument("didSetOuterHTML");
+ function.appendArgument(callId);
+ function.appendArgument(nodeId);
+ function.call();
+}
+
+void InspectorFrontend::didPushNodeByPathToFrontend(long callId, long nodeId)
+{
+ ScriptFunctionCall function(m_webInspector, "dispatch");
+ function.appendArgument("didPushNodeByPathToFrontend");
+ function.appendArgument(callId);
+ function.appendArgument(nodeId);
+ function.call();
+}
+
void InspectorFrontend::didGetChildNodes(long callId)
{
ScriptFunctionCall function(m_webInspector, "dispatch");
diff --git a/WebCore/inspector/InspectorFrontend.h b/WebCore/inspector/InspectorFrontend.h
index 1762014..0b19983 100644
--- a/WebCore/inspector/InspectorFrontend.h
+++ b/WebCore/inspector/InspectorFrontend.h
@@ -77,10 +77,10 @@ namespace WebCore {
void didGetResourceContent(long callId, const String& content);
void updateFocusedNode(long nodeId);
- void setAttachedWindow(bool attached);
void showPanel(int panel);
void populateInterface();
void reset();
+ void resetProfilesPanel();
void bringToFront();
void inspectedURLChanged(const String&);
@@ -91,6 +91,9 @@ namespace WebCore {
void searchingForNodeWasEnabled();
void searchingForNodeWasDisabled();
+ void monitoringXHRWasEnabled();
+ void monitoringXHRWasDisabled();
+
void updatePauseOnExceptionsState(long state);
#if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -142,6 +145,9 @@ namespace WebCore {
void didGetEventListenersForNode(long callId, long nodeId, const ScriptArray& listenersArray);
void didRemoveNode(long callId, long nodeId);
void didChangeTagName(long callId, long nodeId);
+ void didGetOuterHTML(long callId, const String& outerHTML);
+ void didSetOuterHTML(long callId, long nodeId);
+ void didPushNodeByPathToFrontend(long callId, long nodeId);
void didGetStyles(long callId, const ScriptValue& styles);
void didGetAllStyles(long callId, const ScriptArray& styles);
diff --git a/WebCore/inspector/InspectorFrontendClientLocal.cpp b/WebCore/inspector/InspectorFrontendClientLocal.cpp
index 188566f..16a6a8b 100644
--- a/WebCore/inspector/InspectorFrontendClientLocal.cpp
+++ b/WebCore/inspector/InspectorFrontendClientLocal.cpp
@@ -148,7 +148,7 @@ void InspectorFrontendClientLocal::restoreAttachedWindowHeight()
String attachedHeight = m_inspectorController->setting(inspectorAttachedHeightName);
bool success = true;
int height = attachedHeight.toInt(&success);
- unsigned preferredHeight = success ? height : defaultAttachedHeight;
+ unsigned preferredHeight = success ? static_cast<unsigned>(height) : 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/InspectorValues.cpp b/WebCore/inspector/InspectorValues.cpp
index 5c7d0c8..f95116c 100644
--- a/WebCore/inspector/InspectorValues.cpp
+++ b/WebCore/inspector/InspectorValues.cpp
@@ -499,7 +499,7 @@ PassRefPtr<InspectorArray> InspectorValue::asArray()
return 0;
}
-PassRefPtr<InspectorValue> InspectorValue::readJSON(const String& json)
+PassRefPtr<InspectorValue> InspectorValue::parseJSON(const String& json)
{
const UChar* start = json.characters();
const UChar* end = json.characters() + json.length();
@@ -599,7 +599,7 @@ PassRefPtr<InspectorObject> InspectorObject::getObject(const String& name) const
{
PassRefPtr<InspectorValue> value = get(name);
if (!value)
- return false;
+ return 0;
return value->asObject();
}
@@ -607,7 +607,7 @@ PassRefPtr<InspectorArray> InspectorObject::getArray(const String& name) const
{
PassRefPtr<InspectorValue> value = get(name);
if (!value)
- return false;
+ return 0;
return value->asArray();
}
diff --git a/WebCore/inspector/InspectorValues.h b/WebCore/inspector/InspectorValues.h
index b9920c4..30ba95a 100644
--- a/WebCore/inspector/InspectorValues.h
+++ b/WebCore/inspector/InspectorValues.h
@@ -73,7 +73,7 @@ public:
virtual PassRefPtr<InspectorObject> asObject();
virtual PassRefPtr<InspectorArray> asArray();
- static PassRefPtr<InspectorValue> readJSON(const String& json);
+ static PassRefPtr<InspectorValue> parseJSON(const String& json);
String toJSONString() const;
virtual void writeJSON(Vector<UChar>* output) const;
diff --git a/WebCore/inspector/ScriptBreakpoint.cpp b/WebCore/inspector/ScriptBreakpoint.cpp
new file mode 100644
index 0000000..ce0d18a
--- /dev/null
+++ b/WebCore/inspector/ScriptBreakpoint.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScriptBreakpoint.h"
+
+#if ENABLE(INSPECTOR)
+
+#include "InspectorValues.h"
+
+namespace WebCore {
+
+void ScriptBreakpoint::sourceBreakpointsFromInspectorObject(PassRefPtr<InspectorObject> breakpoints, SourceBreakpoints* sourceBreakpoints)
+{
+ for (InspectorObject::iterator it = breakpoints->begin(); it != breakpoints->end(); ++it) {
+ bool ok;
+ int lineNumber = it->first.toInt(&ok);
+ if (!ok)
+ continue;
+ RefPtr<InspectorObject> breakpoint = it->second->asObject();
+ if (!breakpoint)
+ continue;
+ bool enabled;
+ RefPtr<InspectorValue> enabledValue = breakpoint->get("enabled");
+ if (!enabledValue || !enabledValue->asBool(&enabled))
+ continue;
+ String condition;
+ RefPtr<InspectorValue> conditionValue = breakpoint->get("condition");
+ if (!conditionValue || !conditionValue->asString(&condition))
+ continue;
+ sourceBreakpoints->set(lineNumber, ScriptBreakpoint(enabled, condition));
+ }
+}
+
+PassRefPtr<InspectorObject> ScriptBreakpoint::inspectorObjectFromSourceBreakpoints(const SourceBreakpoints& sourceBreakpoints)
+{
+ RefPtr<InspectorObject> breakpoints = InspectorObject::create();
+ for (SourceBreakpoints::const_iterator it = sourceBreakpoints.begin(); it != sourceBreakpoints.end(); ++it) {
+ RefPtr<InspectorObject> breakpoint = InspectorObject::create();
+ breakpoint->setBool("enabled", it->second.enabled);
+ breakpoint->setString("condition", it->second.condition);
+ breakpoints->set(String::number(it->first), breakpoint);
+ }
+ return breakpoints.release();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/inspector/ScriptBreakpoint.h b/WebCore/inspector/ScriptBreakpoint.h
index 8775901..b7c7a37 100644
--- a/WebCore/inspector/ScriptBreakpoint.h
+++ b/WebCore/inspector/ScriptBreakpoint.h
@@ -35,6 +35,11 @@
namespace WebCore {
+class InspectorObject;
+struct ScriptBreakpoint;
+
+typedef HashMap<int, ScriptBreakpoint> SourceBreakpoints;
+
struct ScriptBreakpoint {
ScriptBreakpoint(bool enabled, const String& condition)
: enabled(enabled)
@@ -48,9 +53,10 @@ struct ScriptBreakpoint {
bool enabled;
String condition;
-};
-typedef HashMap<int, ScriptBreakpoint> SourceBreakpoints;
+ static void sourceBreakpointsFromInspectorObject(PassRefPtr<InspectorObject>, SourceBreakpoints*);
+ static PassRefPtr<InspectorObject> inspectorObjectFromSourceBreakpoints(const SourceBreakpoints&);
+};
} // namespace WebCore
diff --git a/WebCore/inspector/front-end/BreakpointManager.js b/WebCore/inspector/front-end/BreakpointManager.js
index 3ccccac..4f6965a 100644
--- a/WebCore/inspector/front-end/BreakpointManager.js
+++ b/WebCore/inspector/front-end/BreakpointManager.js
@@ -38,6 +38,7 @@ WebInspector.BreakpointManager.prototype = {
if (this._oneTimeBreakpoint)
this._removeBreakpointFromBackend(this._oneTimeBreakpoint);
this._oneTimeBreakpoint = breakpoint;
+ // FIXME(40669): one time breakpoint will be persisted in inspector settings if not hit.
this._saveBreakpointOnBackend(breakpoint);
},
@@ -51,15 +52,15 @@ WebInspector.BreakpointManager.prototype = {
addBreakpoint: function(sourceID, sourceURL, line, enabled, condition)
{
- var breakpoint = new WebInspector.Breakpoint(this, sourceID, sourceURL, line, enabled, condition);
- if (this._breakpoints[breakpoint.id])
- return;
- if (this._oneTimeBreakpoint && (this._oneTimeBreakpoint.id == breakpoint.id))
- delete this._oneTimeBreakpoint;
- this._breakpoints[breakpoint.id] = breakpoint;
- this._saveBreakpointOnBackend(breakpoint);
- this.dispatchEventToListeners("breakpoint-added", breakpoint);
- },
+ var breakpoint = this._addBreakpoint(sourceID, sourceURL, line, enabled, condition);
+ if (breakpoint)
+ this._saveBreakpointOnBackend(breakpoint);
+ },
+
+ restoredBreakpoint: function(sourceID, sourceURL, line, enabled, condition)
+ {
+ this._addBreakpoint(sourceID, sourceURL, line, enabled, condition);
+ },
removeBreakpoint: function(breakpoint)
{
@@ -78,7 +79,7 @@ WebInspector.BreakpointManager.prototype = {
breakpoints.push(this._breakpoints[id]);
}
return breakpoints;
- },
+ },
breakpointsForURL: function(url)
{
@@ -87,7 +88,7 @@ WebInspector.BreakpointManager.prototype = {
if (this._breakpoints[id].url === url)
breakpoints.push(this._breakpoints[id]);
}
- return breakpoints;
+ return breakpoints;
},
reset: function()
@@ -96,6 +97,18 @@ WebInspector.BreakpointManager.prototype = {
delete this._oneTimeBreakpoint;
},
+ _addBreakpoint: function(sourceID, sourceURL, line, enabled, condition)
+ {
+ var breakpoint = new WebInspector.Breakpoint(this, sourceID, sourceURL, line, enabled, condition);
+ if (this._breakpoints[breakpoint.id])
+ return;
+ if (this._oneTimeBreakpoint && (this._oneTimeBreakpoint.id == breakpoint.id))
+ delete this._oneTimeBreakpoint;
+ this._breakpoints[breakpoint.id] = breakpoint;
+ this.dispatchEventToListeners("breakpoint-added", breakpoint);
+ return breakpoint;
+ },
+
_saveBreakpointOnBackend: function(breakpoint)
{
InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition);
diff --git a/WebCore/inspector/front-end/CSSCompletions.js b/WebCore/inspector/front-end/CSSCompletions.js
new file mode 100644
index 0000000..5485464
--- /dev/null
+++ b/WebCore/inspector/front-end/CSSCompletions.js
@@ -0,0 +1,102 @@
+WebInspector.CSSCompletions = (function() {
+ var used = {};
+ var properties = [];
+ var style = document.documentElement.style;
+ var list = document.defaultView.getComputedStyle(document.documentElement, "");
+ var length = list.length;
+ for (var i = 0; i < length; ++i)
+ used[properties[i] = list[i]] = true;
+
+ for (var i = 0, end = length; i < length; ++i) {
+ var propertyWords = properties[i].split("-");
+ var j = propertyWords.length;
+ while (--j) {
+ propertyWords.pop();
+ var shorthand = propertyWords.join("-");
+ if (!(shorthand in used) && style[shorthand] !== undefined) {
+ used[shorthand] = true;
+ properties[end++] = shorthand;
+ }
+ }
+ }
+
+ return properties.sort();
+})();
+
+WebInspector.CSSCompletions.startsWith = function(prefix)
+{
+ var firstIndex = this._firstIndexOfPrefix(prefix);
+ if (firstIndex === -1)
+ return [];
+
+ var results = [];
+ while (this[firstIndex].indexOf(prefix) === 0)
+ results.push(this[firstIndex++]);
+ return results;
+}
+
+WebInspector.CSSCompletions.firstStartsWith = function(prefix)
+{
+ var foundIndex = this._firstIndexOfPrefix(prefix);
+ return (foundIndex === -1 ? "" : this[foundIndex]);
+}
+
+WebInspector.CSSCompletions._firstIndexOfPrefix = function(prefix)
+{
+ if (!prefix)
+ return -1;
+
+ var maxIndex = this.length - 1;
+ var minIndex = 0;
+ var foundIndex;
+
+ do {
+ var middleIndex = (maxIndex + minIndex) >> 1;
+ if (this[middleIndex].indexOf(prefix) === 0) {
+ foundIndex = middleIndex;
+ break;
+ }
+ if (this[middleIndex] < prefix)
+ minIndex = middleIndex + 1;
+ else
+ maxIndex = middleIndex - 1;
+ } while (minIndex <= maxIndex);
+
+ if (!foundIndex)
+ return -1;
+
+ while (foundIndex && this[foundIndex - 1].indexOf(prefix) === 0)
+ foundIndex--;
+
+ return foundIndex;
+}
+
+WebInspector.CSSCompletions.next = function(str, prefix)
+{
+ return WebInspector.CSSCompletions._closest(str, prefix, 1);
+}
+
+WebInspector.CSSCompletions.previous = function(str, prefix)
+{
+ return WebInspector.CSSCompletions._closest(str, prefix, -1);
+}
+
+WebInspector.CSSCompletions._closest = function(str, prefix, shift)
+{
+ if (!str)
+ return "";
+
+ var index = this.indexOf(str);
+ if (index === -1)
+ return "";
+
+ if (!prefix) {
+ index = (index + this.length + shift) % this.length;
+ return this[index];
+ }
+
+ var propertiesWithPrefix = this.startsWith(prefix);
+ var j = propertiesWithPrefix.indexOf(str);
+ j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;
+ return propertiesWithPrefix[j];
+}
diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js
index d1f347b..8bb71e6 100644
--- a/WebCore/inspector/front-end/ConsoleView.js
+++ b/WebCore/inspector/front-end/ConsoleView.js
@@ -296,7 +296,7 @@ WebInspector.ConsoleView.prototype = {
requestClearMessages: function()
{
- InjectedScriptAccess.getDefault().clearConsoleMessages(function() {});
+ InspectorBackend.clearConsoleMessages();
},
clearMessages: function()
@@ -399,7 +399,13 @@ WebInspector.ConsoleView.prototype = {
return;
}
- this._contextMenu.show(event);
+ var contextMenu = new WebInspector.ContextMenu();
+ if (!WebInspector.monitoringXHREnabled)
+ contextMenu.appendItem(WebInspector.UIString("Enable XMLHttpRequest logging"), InspectorBackend.enableMonitoringXHR.bind(InspectorBackend));
+ else
+ contextMenu.appendItem(WebInspector.UIString("Disable XMLHttpRequest logging"), InspectorBackend.disableMonitoringXHR.bind(InspectorBackend));
+ contextMenu.appendItem(WebInspector.UIString("Clear Console"), this.requestClearMessages.bind(this));
+ contextMenu.show(event);
},
_messagesSelectStart: function(event)
@@ -444,8 +450,6 @@ WebInspector.ConsoleView.prototype = {
var clearConsoleHandler = this.requestClearMessages.bind(this);
var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
this._shortcuts[shortcutL.key] = clearConsoleHandler;
- this._contextMenu = new WebInspector.ContextMenu();
- this._contextMenu.appendItem(WebInspector.UIString("Clear Console"), clearConsoleHandler);
var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Console"));
var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ];
diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js
index 5bde12f..ee85d1c 100644
--- a/WebCore/inspector/front-end/DOMAgent.js
+++ b/WebCore/inspector/front-end/DOMAgent.js
@@ -669,6 +669,9 @@ WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback;
WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback;
WebInspector.didRemoveNode = WebInspector.Callback.processCallback;
WebInspector.didChangeTagName = WebInspector.Callback.processCallback;
+WebInspector.didGetOuterHTML = WebInspector.Callback.processCallback;
+WebInspector.didSetOuterHTML = WebInspector.Callback.processCallback;
+WebInspector.didPushNodeByPathToFrontend = WebInspector.Callback.processCallback;
WebInspector.didGetEventListenersForNode = WebInspector.Callback.processCallback;
WebInspector.didGetStyles = WebInspector.Callback.processCallback;
diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js
index 55ba82d..c8eb3dd 100644
--- a/WebCore/inspector/front-end/ElementsPanel.js
+++ b/WebCore/inspector/front-end/ElementsPanel.js
@@ -59,7 +59,7 @@ WebInspector.ElementsPanel = function()
this.panel.updateEventListeners();
if (this._focusedDOMNode)
- InjectedScriptAccess.get(this._focusedDOMNode.injectedScriptId).addInspectedNode(this._focusedDOMNode.id, function() {});
+ InspectorBackend.addInspectedNode(this._focusedDOMNode.id);
};
this.contentElement.appendChild(this.treeOutline.element);
@@ -224,9 +224,10 @@ WebInspector.ElementsPanel.prototype = {
selectNode.call(this, node);
}
- if (this._selectedPathOnReset)
- InjectedScriptAccess.getDefault().nodeByPath(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
- else
+ if (this._selectedPathOnReset) {
+ var callId = WebInspector.Callback.wrap(selectLastSelectedNode.bind(this));
+ InspectorBackend.pushNodeByPathToFrontend(callId, this._selectedPathOnReset);
+ } else
selectNode.call(this);
delete this._selectedPathOnReset;
},
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index e8fecb0..1b84b83 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -1094,7 +1094,7 @@ WebInspector.ElementsTreeElement.prototype = {
function changeTagNameCallback(nodeId)
{
- if (nodeId === -1) {
+ if (!nodeId) {
cancel();
return;
}
@@ -1111,7 +1111,7 @@ WebInspector.ElementsTreeElement.prototype = {
}
var callId = WebInspector.Callback.wrap(changeTagNameCallback);
- InspectorBackend.changeTagName(callId, this.representedObject.id, newText, wasExpanded);
+ InspectorBackend.changeTagName(callId, this.representedObject.id, newText);
},
_textNodeEditingCommitted: function(element, newText)
@@ -1382,10 +1382,12 @@ WebInspector.ElementsTreeElement.prototype = {
function commitChange(value)
{
- InjectedScriptAccess.get(node.injectedScriptId).setOuterHTML(node.id, value, wasExpanded, selectNode.bind(this));
+ var setCallId = WebInspector.Callback.wrap(selectNode);
+ InspectorBackend.setOuterHTML(setCallId, node.id, value);
}
- InjectedScriptAccess.get(node.injectedScriptId).getNodePropertyValue(node.id, "outerHTML", this._startEditingAsHTML.bind(this, commitChange));
+ var getCallId = WebInspector.Callback.wrap(this._startEditingAsHTML.bind(this, commitChange));
+ InspectorBackend.getOuterHTML(getCallId, node.id);
},
_copyHTML: function()
diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js
index e62a916..26495e8 100644
--- a/WebCore/inspector/front-end/InjectedScript.js
+++ b/WebCore/inspector/front-end/InjectedScript.js
@@ -80,13 +80,6 @@ InjectedScript.releaseWrapperObjectGroup = function(objectGroupName) {
delete InjectedScript.objectGroups[objectGroupName];
};
-// Called from within InspectorController on the 'inspected page' side.
-InjectedScript.reset = function()
-{
-}
-
-InjectedScript.reset();
-
InjectedScript.dispatch = function(methodName, args, callId)
{
var argsArray = eval("(" + args + ")");
@@ -218,29 +211,6 @@ InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression
}
}
-InjectedScript.getNodePropertyValue = function(nodeId, propertyName)
-{
- var node = InjectedScript._nodeForId(nodeId);
- if (!node)
- return false;
- var result = node[propertyName];
- return result !== undefined ? result : false;
-}
-
-InjectedScript.setOuterHTML = function(nodeId, value, expanded)
-{
- var node = InjectedScript._nodeForId(nodeId);
- if (!node)
- return false;
-
- var parent = node.parentNode;
- var prevSibling = node.previousSibling;
- node.outerHTML = value;
- var newNode = prevSibling ? prevSibling.nextSibling : parent.firstChild;
-
- return InjectedScriptHost.pushNodePathToFrontend(newNode, expanded, false);
-}
-
InjectedScript._populatePropertyNames = function(object, resultSet)
{
for (var o = object; o; o = o.__proto__) {
@@ -281,14 +251,15 @@ InjectedScript.getCompletions = function(expression, includeInspectorCommandLine
} else {
if (!expression)
expression = "this";
- expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression);
+ expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false);
}
- if (typeof expressionResult == "object")
+ if (typeof expressionResult === "object")
InjectedScript._populatePropertyNames(expressionResult, props);
- if (includeInspectorCommandLineAPI)
- for (var prop in inspectedWindow.console._inspectorCommandLineAPI)
- if (prop.charAt(0) !== '_')
- props[prop] = true;
+
+ if (includeInspectorCommandLineAPI) {
+ for (var prop in InjectedScript._commandLineAPI)
+ props[prop] = true;
+ }
} catch(e) {
}
return props;
@@ -319,14 +290,21 @@ InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, obj
InjectedScript._evaluateOn = function(evalFunction, object, expression, dontUseCommandLineAPI)
{
- InjectedScript._ensureCommandLineAPIInstalled(evalFunction, object);
- // 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.
- if (!dontUseCommandLineAPI)
- expression = "with (window.console._inspectorCommandLineAPI) { with (window) {\n" + expression + "\n} }";
+ if (!dontUseCommandLineAPI) {
+ // 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 = InjectedScript._commandLineAPI;
+
+ expression = "with (window.console._commandLineAPI) { with (window) {\n" + expression + "\n} }";
+ }
var value = evalFunction.call(object, expression);
+ if (!dontUseCommandLineAPI)
+ delete inspectedWindow.console._commandLineAPI;
+
// When evaluating on call frame error is not thrown, but returned as a value.
if (InjectedScript._type(value) === "error")
throw value.toString();
@@ -334,20 +312,6 @@ InjectedScript._evaluateOn = function(evalFunction, object, expression, dontUseC
return value;
}
-InjectedScript.addInspectedNode = function(nodeId)
-{
- var node = InjectedScript._nodeForId(nodeId);
- if (!node)
- return false;
-
- InjectedScript._ensureCommandLineAPIInstalled(inspectedWindow.eval, inspectedWindow);
- var inspectedNodes = inspectedWindow.console._inspectorCommandLineAPI._inspectedNodes;
- inspectedNodes.unshift(node);
- if (inspectedNodes.length >= 5)
- inspectedNodes.pop();
- return true;
-}
-
InjectedScript.getNodeId = function(node)
{
return InjectedScriptHost.pushNodePathToFrontend(node, false, false);
@@ -392,125 +356,10 @@ InjectedScript._callFrameForId = function(id)
return callFrame;
}
-InjectedScript.clearConsoleMessages = function()
-{
- InjectedScriptHost.clearConsoleMessages();
- return true;
-}
-
-InjectedScript._inspectObject = function(o)
-{
- if (arguments.length === 0)
- return;
-
- inspectedWindow.console.log(o);
- if (InjectedScript._type(o) === "node") {
- InjectedScriptHost.pushNodePathToFrontend(o, false, true);
- } else {
- switch (InjectedScript._describe(o)) {
- case "Database":
- InjectedScriptHost.selectDatabase(o);
- break;
- case "Storage":
- InjectedScriptHost.selectDOMStorage(o);
- break;
- }
- }
-}
-
-InjectedScript._copy = function(o)
-{
- if (InjectedScript._type(o) === "node") {
- var nodeId = InjectedScriptHost.pushNodePathToFrontend(o, false, false);
- InjectedScriptHost.copyNode(nodeId);
- } else {
- InjectedScriptHost.copyText(o);
- }
-}
-
-InjectedScript._ensureCommandLineAPIInstalled = function(evalFunction, evalObject)
-{
- if (evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI"))
- return;
- var inspectorCommandLineAPI = evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI = { \n\
- $: function() { return document.getElementById.apply(document, arguments) }, \n\
- $$: function() { return document.querySelectorAll.apply(document, arguments) }, \n\
- $x: function(xpath, context) \n\
- { \n\
- var nodes = []; \n\
- try { \n\
- var doc = context || document; \n\
- var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \n\
- var node; \n\
- while (node = results.iterateNext()) nodes.push(node); \n\
- } catch (e) {} \n\
- return nodes; \n\
- }, \n\
- dir: function() { return console.dir.apply(console, arguments) }, \n\
- dirxml: function() { return console.dirxml.apply(console, arguments) }, \n\
- keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \n\
- values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \n\
- profile: function() { return console.profile.apply(console, arguments) }, \n\
- profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \n\
- _logEvent: function _inspectorCommandLineAPI_logEvent(e) { console.log(e.type, e); }, \n\
- _allEventTypes: [\"mouse\", \"key\", \"load\", \"unload\", \"abort\", \"error\", \n\
- \"select\", \"change\", \"submit\", \"reset\", \"focus\", \"blur\", \n\
- \"resize\", \"scroll\"], \n\
- _normalizeEventTypes: function(t) \n\
- { \n\
- if (typeof t === \"undefined\") \n\
- t = console._inspectorCommandLineAPI._allEventTypes; \n\
- else if (typeof t === \"string\") \n\
- t = [t]; \n\
- var i, te = []; \n\
- for (i = 0; i < t.length; i++) { \n\
- if (t[i] === \"mouse\") \n\
- te.splice(0, 0, \"mousedown\", \"mouseup\", \"click\", \"dblclick\", \n\
- \"mousemove\", \"mouseover\", \"mouseout\"); \n\
- else if (t[i] === \"key\") \n\
- te.splice(0, 0, \"keydown\", \"keyup\", \"keypress\"); \n\
- else \n\
- te.push(t[i]); \n\
- } \n\
- return te; \n\
- }, \n\
- monitorEvents: function(o, t) \n\
- { \n\
- if (!o || !o.addEventListener || !o.removeEventListener) \n\
- return; \n\
- t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\
- for (i = 0; i < t.length; i++) { \n\
- o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\
- o.addEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\
- } \n\
- }, \n\
- unmonitorEvents: function(o, t) \n\
- { \n\
- if (!o || !o.removeEventListener) \n\
- return; \n\
- t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\
- for (i = 0; i < t.length; i++) { \n\
- o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\
- } \n\
- }, \n\
- _inspectedNodes: [], \n\
- get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] }, \n\
- get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] }, \n\
- get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] }, \n\
- get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] }, \n\
- get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] }, \n\
- };");
-
- inspectorCommandLineAPI.clear = InjectedScript.clearConsoleMessages;
- inspectorCommandLineAPI.inspect = InjectedScript._inspectObject;
- inspectorCommandLineAPI.copy = InjectedScript._copy;
-}
-
InjectedScript._resolveObject = function(objectProxy)
{
var object = InjectedScript._objectForId(objectProxy.objectId);
var path = objectProxy.path;
- var protoDepth = objectProxy.protoDepth;
// Follow the property path.
for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length; ++i)
@@ -532,11 +381,11 @@ InjectedScript._objectForId = function(objectId)
// - numbers point to DOM Node via the InspectorDOMAgent mapping
// - strings point to console objects cached in InspectorController for lazy evaluation upon them
// - objects contain complex ids and are currently used for scoped objects
- if (typeof objectId === "number") {
+ if (typeof objectId === "number")
return InjectedScript._nodeForId(objectId);
- } else if (typeof objectId === "string") {
+ else if (typeof objectId === "string")
return InjectedScript.unwrapObject(objectId);
- } else if (typeof objectId === "object") {
+ else if (typeof objectId === "object") {
var callFrame = InjectedScript._callFrameForId(objectId.callFrame);
if (objectId.thisObject)
return callFrame.thisObject;
@@ -554,13 +403,6 @@ InjectedScript.pushNodeToFrontend = function(objectProxy)
return InjectedScriptHost.pushNodePathToFrontend(object, false, false);
}
-InjectedScript.nodeByPath = function(path)
-{
- // We make this call through the injected script only to get a nice
- // callback for it.
- return InjectedScriptHost.pushNodeByPathToFrontend(path.join(","));
-}
-
// Called from within InspectorController on the 'inspected page' side.
InjectedScript.createProxyObject = function(object, objectId, abbreviate)
{
@@ -736,14 +578,13 @@ InjectedScript._type = function(obj)
InjectedScript._describe = function(obj, abbreviated)
{
- var type1 = InjectedScript._type(obj);
- var type2 = InjectedScript._className(obj);
+ var type = InjectedScript._type(obj);
- switch (type1) {
+ switch (type) {
case "object":
case "node":
case "array":
- return type2;
+ return InjectedScript._className(obj);
case "string":
if (!abbreviated)
return obj;
@@ -752,10 +593,8 @@ InjectedScript._describe = function(obj, abbreviated)
return "\"" + obj + "\"";
case "function":
var objectText = InjectedScript._toString(obj);
- if (!/^function /.test(objectText))
- objectText = (type2 == "object") ? type1 : type2;
- else if (abbreviated)
- objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
+ if (abbreviated)
+ objectText = /.*/.exec(objectText)[0].replace(/ +$/g, "");
return objectText;
default:
return InjectedScript._toString(obj);
@@ -779,11 +618,185 @@ InjectedScript._className = function(obj)
return str.replace(/^\[object (.*)\]$/i, "$1");
} else {
// V8
- if (typeof obj !== "object")
- return "null";
- return obj.constructor.name || "Object";
+ return obj.constructor && obj.constructor.name || "Object";
+ }
+}
+
+InjectedScript._logEvent = function(event)
+{
+ console.log(event.type, event);
+}
+
+InjectedScript._normalizeEventTypes = function(types)
+{
+ if (typeof types === "undefined")
+ types = [ "mouse", "key", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll" ];
+ else if (typeof types === "string")
+ types = [ types ];
+
+ var result = [];
+ for (var i = 0; i < types.length; i++) {
+ if (types[i] === "mouse")
+ result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout");
+ else if (types[i] === "key")
+ result.splice(0, 0, "keydown", "keyup", "keypress");
+ else
+ result.push(types[i]);
+ }
+ return result;
+}
+
+InjectedScript._inspectedNode = function(num)
+{
+ var nodeId = InjectedScriptHost.inspectedNode(num);
+ return InjectedScript._nodeForId(nodeId);
+}
+
+function CommandLineAPI()
+{
+}
+
+CommandLineAPI.prototype = {
+ // Only add API functions here, private stuff should go to
+ // InjectedScript so that it is not suggested by the completion.
+ $: function()
+ {
+ return document.getElementById.apply(document, arguments)
+ },
+
+ $$: function()
+ {
+ return document.querySelectorAll.apply(document, arguments)
+ },
+
+ $x: function(xpath, context)
+ {
+ var nodes = [];
+ try {
+ var doc = context || document;
+ var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
+ var node;
+ while (node = results.iterateNext())
+ nodes.push(node);
+ } catch (e) {
+ }
+ return nodes;
+ },
+
+ dir: function()
+ {
+ return console.dir.apply(console, arguments)
+ },
+
+ dirxml: function()
+ {
+ return console.dirxml.apply(console, arguments)
+ },
+
+ keys: function(object)
+ {
+ return Object.keys(object);
+ },
+
+ values: function(object)
+ {
+ var result = [];
+ for (var key in object)
+ result.push(object[key]);
+ return result;
+ },
+
+ profile: function()
+ {
+ return console.profile.apply(console, arguments)
+ },
+
+ profileEnd: function()
+ {
+ return console.profileEnd.apply(console, arguments)
+ },
+
+ monitorEvents: function(object, types)
+ {
+ if (!object || !object.addEventListener || !object.removeEventListener)
+ return;
+ types = InjectedScript._normalizeEventTypes(types);
+ for (var i = 0; i < types.length; ++i) {
+ object.removeEventListener(types[i], InjectedScript._logEvent, false);
+ object.addEventListener(types[i], InjectedScript._logEvent, false);
+ }
+ },
+
+ unmonitorEvents: function(object, types)
+ {
+ if (!object || !object.addEventListener || !object.removeEventListener)
+ return;
+ types = InjectedScript._normalizeEventTypes(types);
+ for (var i = 0; i < types.length; ++i)
+ object.removeEventListener(types[i], InjectedScript._logEvent, false);
+ },
+
+ inspect: function(object)
+ {
+ if (arguments.length === 0)
+ return;
+
+ inspectedWindow.console.log(object);
+ if (InjectedScript._type(object) === "node")
+ InjectedScriptHost.pushNodePathToFrontend(object, false, true);
+ else {
+ switch (InjectedScript._describe(object)) {
+ case "Database":
+ InjectedScriptHost.selectDatabase(object);
+ break;
+ case "Storage":
+ InjectedScriptHost.selectDOMStorage(object);
+ break;
+ }
+ }
+ },
+
+ copy: function(object)
+ {
+ if (InjectedScript._type(object) === "node") {
+ var nodeId = InjectedScriptHost.pushNodePathToFrontend(object, false, false);
+ InjectedScriptHost.copyNode(nodeId);
+ } else
+ InjectedScriptHost.copyText(object);
+ },
+
+ clear: function()
+ {
+ InjectedScriptHost.clearConsoleMessages();
+ },
+
+ get $0()
+ {
+ return InjectedScript._inspectedNode(0);
+ },
+
+ get $1()
+ {
+ return InjectedScript._inspectedNode(1);
+ },
+
+ get $2()
+ {
+ return InjectedScript._inspectedNode(2);
+ },
+
+ get $3()
+ {
+ return InjectedScript._inspectedNode(3);
+ },
+
+ get $4()
+ {
+ return InjectedScript._inspectedNode(4);
}
}
+InjectedScript._commandLineAPI = new CommandLineAPI();
+
return InjectedScript;
});
diff --git a/WebCore/inspector/front-end/InjectedScriptAccess.js b/WebCore/inspector/front-end/InjectedScriptAccess.js
index c388213..90daab7 100644
--- a/WebCore/inspector/front-end/InjectedScriptAccess.js
+++ b/WebCore/inspector/front-end/InjectedScriptAccess.js
@@ -70,18 +70,13 @@ InjectedScriptAccess._installHandler = function(methodName, async)
// - Make sure corresponding methods in InjectedScript return non-null and non-undefined values,
// - Make sure last parameter of all the InjectedSriptAccess.* calls is a callback function.
// We keep these sorted.
-InjectedScriptAccess._installHandler("addInspectedNode");
-InjectedScriptAccess._installHandler("clearConsoleMessages");
InjectedScriptAccess._installHandler("evaluate");
InjectedScriptAccess._installHandler("evaluateInCallFrame");
InjectedScriptAccess._installHandler("getCompletions");
-InjectedScriptAccess._installHandler("getNodePropertyValue");
InjectedScriptAccess._installHandler("getProperties");
InjectedScriptAccess._installHandler("getPrototypes");
InjectedScriptAccess._installHandler("openInInspectedWindow");
InjectedScriptAccess._installHandler("pushNodeToFrontend");
-InjectedScriptAccess._installHandler("nodeByPath");
-InjectedScriptAccess._installHandler("setOuterHTML");
InjectedScriptAccess._installHandler("setPropertyValue");
InjectedScriptAccess._installHandler("evaluateOnSelf");
diff --git a/WebCore/inspector/front-end/InspectorBackendStub.js b/WebCore/inspector/front-end/InspectorBackendStub.js
index 492bf87..1ae32b5 100644
--- a/WebCore/inspector/front-end/InspectorBackendStub.js
+++ b/WebCore/inspector/front-end/InspectorBackendStub.js
@@ -32,7 +32,6 @@ if (!window.InspectorBackend) {
WebInspector.InspectorBackendStub = function()
{
- this._searchingForNode = false;
this._attachedWindowHeight = 0;
this._timelineEnabled = false;
}
@@ -60,25 +59,23 @@ WebInspector.InspectorBackendStub.prototype = {
{
},
- clearMessages: function()
+ clearConsoleMessages: function()
{
},
- searchingForNode: function()
+ getOuterHTML: function()
{
- return this._searchingForNode;
},
- search: function(sourceRow, query)
+ setOuterHTML: function()
{
},
- toggleNodeSearch: function()
+ addInspectedNode: function()
{
- this._searchingForNode = !this._searchingForNode;
},
- setAttachedWindowHeight: function(height)
+ search: function(sourceRow, query)
{
},
@@ -144,6 +141,16 @@ WebInspector.InspectorBackendStub.prototype = {
WebInspector.searchingForNodeWasDisabled();
},
+ enableMonitoringXHR: function()
+ {
+ WebInspector.monitoringXHRWasEnabled();
+ },
+
+ disableMonitoringXHR: function()
+ {
+ WebInspector.monitoringXHRWasDisabled();
+ },
+
reloadPage: function()
{
},
diff --git a/WebCore/inspector/front-end/InspectorFrontendHostStub.js b/WebCore/inspector/front-end/InspectorFrontendHostStub.js
index 5456069..39bbe02 100644
--- a/WebCore/inspector/front-end/InspectorFrontendHostStub.js
+++ b/WebCore/inspector/front-end/InspectorFrontendHostStub.js
@@ -40,7 +40,13 @@ WebInspector._platformFlavor = WebInspector.PlatformFlavor.MacLeopard;
WebInspector.InspectorFrontendHostStub.prototype = {
platform: function()
{
- return "mac";
+ var match = navigator.userAgent.match(/Windows NT/);
+ if (match)
+ return "windows";
+ match = navigator.userAgent.match(/Mac OS X/);
+ if (match)
+ return "mac";
+ return "linux";
},
port: function()
diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js
index 1980fa5..b5122af 100644
--- a/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/WebCore/inspector/front-end/ProfilesPanel.js
@@ -124,7 +124,7 @@ WebInspector.ProfilesPanel = function()
this._profiles = [];
this._profilerEnabled = Preferences.profilerAlwaysEnabled;
- this.reset();
+ this._reset();
}
WebInspector.ProfilesPanel.prototype = {
@@ -167,7 +167,7 @@ WebInspector.ProfilesPanel.prototype = {
populateInterface: function()
{
- this.reset();
+ this._reset();
if (this.visible)
this._populateProfiles();
else
@@ -189,10 +189,15 @@ WebInspector.ProfilesPanel.prototype = {
return;
this._profilerEnabled = false;
- this.reset();
+ this._reset();
},
- reset: function()
+ resetProfiles: function()
+ {
+ this._reset();
+ },
+
+ _reset: function()
{
for (var i = 0; i < this._profiles.length; ++i)
delete this._profiles[i]._profileView;
@@ -222,7 +227,7 @@ WebInspector.ProfilesPanel.prototype = {
_clearProfiles: function()
{
InspectorBackend.clearProfiles();
- this.reset();
+ this._reset();
},
registerProfileType: function(profileType)
@@ -618,7 +623,8 @@ WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
WebInspector.ProfileGroupSidebarTreeElement.prototype = {
onselect: function()
{
- WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
+ if (this.children.length > 0)
+ WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
}
}
diff --git a/WebCore/inspector/front-end/ScriptView.js b/WebCore/inspector/front-end/ScriptView.js
index fb0bb4b..1883fb3 100644
--- a/WebCore/inspector/front-end/ScriptView.js
+++ b/WebCore/inspector/front-end/ScriptView.js
@@ -105,7 +105,12 @@ WebInspector.ScriptView.prototype = {
this.sourceFrame.updateContent(this._prependWhitespace(newBody));
},
- // The follow methods are pulled from SourceView, since they are
+ _sourceIDForLine: function(line)
+ {
+ return this.script.sourceID;
+ },
+
+ // The following methods are pulled from SourceView, since they are
// generic and work with ScriptView just fine.
hide: WebInspector.SourceView.prototype.hide,
diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js
index 4504d57..c23db14 100644
--- a/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/WebCore/inspector/front-end/ScriptsPanel.js
@@ -169,8 +169,6 @@ WebInspector.ScriptsPanel = function()
this._registerShortcuts();
this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;
- if (Preferences.debuggerAlwaysEnabled)
- this._attachDebuggerWhenShown = true;
WebInspector.breakpointManager.addEventListener("breakpoint-added", this._breakpointAdded, this);
WebInspector.breakpointManager.addEventListener("breakpoint-removed", this._breakpointRemoved, this);
diff --git a/WebCore/inspector/front-end/Section.js b/WebCore/inspector/front-end/Section.js
index 7710192..913d495 100644
--- a/WebCore/inspector/front-end/Section.js
+++ b/WebCore/inspector/front-end/Section.js
@@ -82,7 +82,22 @@ WebInspector.Section.prototype = {
if (this._subtitle === x)
return;
this._subtitle = x;
- this.subtitleElement.innerHTML = x;
+ this.subtitleElement.setAttribute("data-uncopyable", x);
+ },
+
+ get subtitleAsText()
+ {
+ var result = "";
+ var data = this.subtitleElement.getAttribute("data-uncopyable");
+ if (data)
+ result += data;
+ var child = this.subtitleElement.querySelector("[data-uncopyable]");
+ if (child) {
+ var linkData = child.getAttribute("data-uncopyable");
+ if (linkData)
+ result += linkData;
+ }
+ return result;
},
get expanded()
diff --git a/WebCore/inspector/front-end/StoragePanel.js b/WebCore/inspector/front-end/StoragePanel.js
index ca1b276..fef7802 100644
--- a/WebCore/inspector/front-end/StoragePanel.js
+++ b/WebCore/inspector/front-end/StoragePanel.js
@@ -289,6 +289,7 @@ WebInspector.StoragePanel.prototype = {
var column = {};
column.width = columnIdentifier.length;
column.title = columnIdentifier;
+ column.sortable = true;
columns[columnIdentifier] = column;
++numColumns;
@@ -313,9 +314,45 @@ WebInspector.StoragePanel.prototype = {
for (var i = 0; i < length; ++i)
dataGrid.appendChild(nodes[i]);
+ dataGrid.addEventListener("sorting changed", this._sortDataGrid.bind(this, dataGrid), this);
return dataGrid;
},
+ _sortDataGrid: function(dataGrid)
+ {
+ var nodes = dataGrid.children.slice();
+ var sortColumnIdentifier = dataGrid.sortColumnIdentifier;
+ var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1;
+ var columnIsNumeric = true;
+
+ for (var i = 0; i < nodes.length; i++) {
+ if (isNaN(Number(nodes[i].data[sortColumnIdentifier])))
+ columnIsNumeric = false;
+ }
+
+ function comparator(dataGridNode1, dataGridNode2)
+ {
+ var item1 = dataGridNode1.data[sortColumnIdentifier];
+ var item2 = dataGridNode2.data[sortColumnIdentifier];
+
+ var comparison;
+ if (columnIsNumeric) {
+ // Sort numbers based on comparing their values rather than a lexicographical comparison.
+ var number1 = parseFloat(item1);
+ var number2 = parseFloat(item2);
+ comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0);
+ } else
+ comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0);
+
+ return sortDirection * comparison;
+ }
+
+ nodes.sort(comparator);
+ dataGrid.removeChildren();
+ for (var i = 0; i < nodes.length; i++)
+ dataGrid.appendChild(nodes[i]);
+ },
+
updateDOMStorage: function(storageId)
{
var domStorage = this._domStorageForId(storageId);
diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js
index 18b7f0f..649b9d0 100644
--- a/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -651,7 +651,10 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
if (!subtitle) {
if (this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.href) {
var url = this.styleRule.parentStyleSheet.href;
- this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(url, "resources", this.rule.sourceLine + 1));
+ var link = WebInspector.linkifyResourceAsNode(url, "resources", this.rule.sourceLine + 1);
+ link.setAttribute("data-uncopyable", link.textContent);
+ link.textContent = "";
+ this.subtitleElement.appendChild(link);
} else if (isUserAgent)
subtitle = WebInspector.UIString("user agent stylesheet");
else if (isUser)
@@ -669,7 +672,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
this.identifier = styleRule.selectorText;
if (this.subtitle)
- this.identifier += ":" + this.subtitleElement.textContent;
+ this.identifier += ":" + this.subtitle;
}
WebInspector.StylePropertiesSection.prototype = {
@@ -1315,6 +1318,18 @@ WebInspector.StylePropertyTreeElement.prototype = {
event.stopPropagation();
},
+ restoreNameElement: function()
+ {
+ // Restore <span class="webkit-css-property"> if it doesn't yet exist or was accidentally deleted.
+ if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property"))
+ return;
+
+ this.nameElement = document.createElement("span");
+ this.nameElement.className = "webkit-css-property";
+ this.nameElement.textContent = "";
+ this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild);
+ },
+
startEditing: function(selectElement)
{
// FIXME: we don't allow editing of longhand properties under a shorthand right now.
@@ -1324,7 +1339,12 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable))
return;
- var context = { expanded: this.expanded, hasChildren: this.hasChildren, keyDownListener: this.editingKeyDown.bind(this) };
+ var context = {
+ expanded: this.expanded,
+ hasChildren: this.hasChildren,
+ keyDownListener: this.editingKeyDown.bind(this),
+ keyPressListener: this.editingKeyPress.bind(this)
+ };
// Lie about our children to prevent expanding on double click and to collapse shorthands.
this.hasChildren = false;
@@ -1333,11 +1353,42 @@ WebInspector.StylePropertyTreeElement.prototype = {
selectElement = this.listItemElement;
this.listItemElement.addEventListener("keydown", context.keyDownListener, false);
+ this.listItemElement.addEventListener("keypress", context.keyPressListener, false);
WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
},
+ editingKeyPress: function(event)
+ {
+ var selection = window.getSelection();
+ var colonIndex = this.listItemElement.textContent.indexOf(":");
+ var selectionLeftOffset = event.target.selectionLeftOffset;
+
+ if (colonIndex < 0 || selectionLeftOffset <= colonIndex) {
+ // Complete property names.
+ var character = event.data.toLowerCase();
+ if (character && /[a-z-]/.test(character)) {
+ var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset);
+ var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character);
+
+ if (!selection.isCollapsed)
+ selection.deleteFromDocument();
+
+ this.restoreNameElement();
+
+ if (property) {
+ if (property !== this.nameElement.textContent)
+ this.nameElement.textContent = property;
+ this.nameElement.firstChild.select(prefix.length + 1);
+ event.preventDefault();
+ }
+ }
+ } else {
+ // FIXME: This should complete property values.
+ }
+ },
+
editingKeyDown: function(event)
{
var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
@@ -1396,9 +1447,24 @@ WebInspector.StylePropertyTreeElement.prototype = {
}
replacementString = prefix + number + suffix;
- } else {
- // FIXME: this should cycle through known keywords for the current property name.
+ } else if (selection.containsNode(this.nameElement, true)) {
+ var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset);
+ var property;
+
+ if (event.keyIdentifier === "Up")
+ property = WebInspector.CSSCompletions.previous(wordString, prefix);
+ else if (event.keyIdentifier === "Down")
+ property = WebInspector.CSSCompletions.next(wordString, prefix);
+
+ var startOffset = selectionRange.startOffset;
+ if (property) {
+ this.nameElement.textContent = property;
+ this.nameElement.firstChild.select(startOffset);
+ }
+ event.preventDefault();
return;
+ } else {
+ // FIXME: this should cycle through known keywords for the current property value.
}
var replacementTextNode = document.createTextNode(replacementString);
@@ -1434,6 +1500,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (context.expanded)
this.expand();
this.listItemElement.removeEventListener("keydown", context.keyDownListener, false);
+ this.listItemElement.removeEventListener("keypress", context.keyPressListener, false);
delete this.originalCSSText;
},
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index fd84586..add50e1 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -19,6 +19,7 @@
<file>ConsoleView.js</file>
<file>ContextMenu.js</file>
<file>CookieItemsView.js</file>
+ <file>CSSCompletions.js</file>
<file>CSSStyleModel.js</file>
<file>Database.js</file>
<file>DatabaseQueryView.js</file>
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 52b85bc..b92672a 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -27,6 +27,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+html {
+ height: 100%;
+}
+
body {
cursor: default;
position: absolute;
@@ -4038,6 +4042,10 @@ a.worker-item {
color: inherit;
}
+.styles-section .subtitle::before, .styles-section .subtitle a::before {
+ content: attr(data-uncopyable);
+}
+
.styles-section .properties {
display: none;
margin: 0;
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index 4c51634..8a8b7d5 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -82,6 +82,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="PropertiesSidebarPane.js"></script>
<script type="text/javascript" src="EventListenersSidebarPane.js"></script>
<script type="text/javascript" src="Color.js"></script>
+ <script type="text/javascript" src="CSSCompletions.js"></script>
<script type="text/javascript" src="StylesSidebarPane.js"></script>
<script type="text/javascript" src="PanelEnablerView.js"></script>
<script type="text/javascript" src="WelcomeView.js"></script>
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index e8108af..3bb4180 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -1297,6 +1297,16 @@ WebInspector.searchingForNodeWasDisabled = function()
this.panels.elements.searchingForNodeWasDisabled();
}
+WebInspector.monitoringXHRWasEnabled = function()
+{
+ this.monitoringXHREnabled = true;
+}
+
+WebInspector.monitoringXHRWasDisabled = function()
+{
+ this.monitoringXHREnabled = false;
+}
+
WebInspector.attachDebuggerWhenShown = function()
{
this.panels.scripts.attachDebuggerWhenShown();
@@ -1334,7 +1344,7 @@ WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, starting
WebInspector.restoredBreakpoint = function(sourceID, sourceURL, line, enabled, condition)
{
- this.breakpointManager.addBreakpoint(sourceID, sourceURL, line, enabled, condition);
+ this.breakpointManager.restoredBreakpoint(sourceID, sourceURL, line, enabled, condition);
}
WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage)
@@ -1385,6 +1395,12 @@ WebInspector.reset = function()
this.console.clearMessages();
}
+WebInspector.resetProfilesPanel = function()
+{
+ if (WebInspector.panels.profiles)
+ WebInspector.panels.profiles.resetProfiles();
+}
+
WebInspector.bringToFront = function()
{
InspectorFrontendHost.bringToFront();
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index bb19dbd..1312e5b 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -328,6 +328,63 @@ Element.prototype.offsetRelativeToWindow = function(targetWindow)
return elementOffset;
}
+KeyboardEvent.prototype.__defineGetter__("data", function()
+{
+ // Emulate "data" attribute from DOM 3 TextInput event.
+ // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data
+ switch (this.type) {
+ case "keypress":
+ if (!this.ctrlKey && !this.metaKey)
+ return String.fromCharCode(this.charCode);
+ else
+ return "";
+ case "keydown":
+ case "keyup":
+ if (!this.ctrlKey && !this.metaKey && !this.altKey)
+ return String.fromCharCode(this.which);
+ else
+ return "";
+ }
+});
+
+Text.prototype.select = function(start, end)
+{
+ start = start || 0;
+ end = end || this.textContent.length;
+
+ if (start < 0)
+ start = end + start;
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(this, start);
+ range.setEnd(this, end);
+ selection.addRange(range);
+ return this;
+}
+
+Element.prototype.__defineGetter__("selectionLeftOffset", function() {
+ // Calculate selection offset relative to the current element.
+
+ var selection = window.getSelection();
+ if (!selection.containsNode(this, true))
+ return null;
+
+ var leftOffset = selection.anchorOffset;
+ var node = selection.anchorNode;
+
+ while (node !== this) {
+ while (node.previousSibling) {
+ node = node.previousSibling;
+ leftOffset += node.textContent.length;
+ }
+ node = node.parentNode;
+ }
+
+ return leftOffset;
+});
+
Node.prototype.isWhitespace = isNodeWhitespace;
Node.prototype.displayName = nodeDisplayName;
Node.prototype.isAncestor = function(node)
@@ -672,6 +729,12 @@ Array.prototype.keySet = function()
return keys;
}
+Array.convert = function(list)
+{
+ // Cast array-like object to an array.
+ return Array.prototype.slice.call(list);
+}
+
function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
{
// indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound.