summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/inspector
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/inspector')
-rw-r--r--WebCore/inspector/ConsoleMessage.cpp12
-rw-r--r--WebCore/inspector/ConsoleMessage.h8
-rw-r--r--WebCore/inspector/InspectorBackend.cpp388
-rw-r--r--WebCore/inspector/InspectorBackend.h146
-rw-r--r--WebCore/inspector/InspectorBackend.idl (renamed from WebCore/inspector/InspectorController.idl)51
-rw-r--r--WebCore/inspector/InspectorClient.h2
-rw-r--r--WebCore/inspector/InspectorController.cpp355
-rw-r--r--WebCore/inspector/InspectorController.h93
-rw-r--r--WebCore/inspector/InspectorDOMAgent.cpp471
-rw-r--r--WebCore/inspector/InspectorDOMAgent.h111
-rw-r--r--WebCore/inspector/InspectorDOMStorageResource.cpp4
-rw-r--r--WebCore/inspector/InspectorDatabaseResource.cpp4
-rw-r--r--WebCore/inspector/InspectorFrontend.cpp96
-rw-r--r--WebCore/inspector/InspectorFrontend.h26
-rw-r--r--WebCore/inspector/InspectorResource.cpp14
-rw-r--r--WebCore/inspector/JSONObject.cpp95
-rw-r--r--WebCore/inspector/JSONObject.h60
-rw-r--r--WebCore/inspector/JavaScriptCallFrame.cpp10
-rw-r--r--WebCore/inspector/JavaScriptCallFrame.h1
-rw-r--r--WebCore/inspector/JavaScriptDebugServer.cpp23
-rw-r--r--WebCore/inspector/JavaScriptDebugServer.h3
-rw-r--r--WebCore/inspector/JavaScriptProfileNode.cpp20
-rw-r--r--WebCore/inspector/front-end/Breakpoint.js23
-rw-r--r--WebCore/inspector/front-end/BreakpointsSidebarPane.js94
-rw-r--r--WebCore/inspector/front-end/CallStackSidebarPane.js57
-rw-r--r--WebCore/inspector/front-end/Callback.js56
-rw-r--r--WebCore/inspector/front-end/ChangesView.js80
-rw-r--r--WebCore/inspector/front-end/Color.js671
-rw-r--r--WebCore/inspector/front-end/ConsoleView.js (renamed from WebCore/inspector/front-end/Console.js)380
-rw-r--r--WebCore/inspector/front-end/DOMAgent.js724
-rw-r--r--WebCore/inspector/front-end/DOMStorageDataGrid.js92
-rw-r--r--WebCore/inspector/front-end/DOMStorageItemsView.js7
-rw-r--r--WebCore/inspector/front-end/DataGrid.js153
-rw-r--r--WebCore/inspector/front-end/DatabaseQueryView.js6
-rw-r--r--WebCore/inspector/front-end/DatabasesPanel.js86
-rw-r--r--WebCore/inspector/front-end/Drawer.js196
-rw-r--r--WebCore/inspector/front-end/ElementsPanel.js126
-rw-r--r--WebCore/inspector/front-end/ElementsTreeOutline.js146
-rw-r--r--WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.pngbin0 -> 396 bytes
-rw-r--r--WebCore/inspector/front-end/Images/clearConsoleButtons.pngbin5224 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/consoleButtonGlyph.pngbin0 -> 183 bytes
-rw-r--r--WebCore/inspector/front-end/Images/consoleButtons.pngbin5197 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/dockButtonGlyph.pngbin0 -> 164 bytes
-rw-r--r--WebCore/inspector/front-end/Images/dockButtons.pngbin1274 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/enableButtons.pngbin5543 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.pngbin0 -> 363 bytes
-rw-r--r--WebCore/inspector/front-end/Images/enableSolidButtonGlyph.pngbin0 -> 302 bytes
-rw-r--r--WebCore/inspector/front-end/Images/excludeButtonGlyph.pngbin0 -> 212 bytes
-rw-r--r--WebCore/inspector/front-end/Images/excludeButtons.pngbin4562 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/focusButtonGlyph.pngbin0 -> 285 bytes
-rw-r--r--WebCore/inspector/front-end/Images/focusButtons.pngbin4919 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.pngbin0 -> 192 bytes
-rw-r--r--WebCore/inspector/front-end/Images/largerResourcesButtons.pngbin1596 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.pngbin0 -> 283 bytes
-rw-r--r--WebCore/inspector/front-end/Images/nodeSearchButtons.pngbin5708 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.pngbin0 -> 331 bytes
-rw-r--r--WebCore/inspector/front-end/Images/pauseOnExceptionButtons.pngbin2305 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/percentButtonGlyph.pngbin0 -> 357 bytes
-rw-r--r--WebCore/inspector/front-end/Images/percentButtons.pngbin5771 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/recordButtonGlyph.pngbin0 -> 213 bytes
-rw-r--r--WebCore/inspector/front-end/Images/recordButtons.pngbin5716 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/recordToggledButtonGlyph.pngbin0 -> 510 bytes
-rw-r--r--WebCore/inspector/front-end/Images/reloadButtonGlyph.pngbin0 -> 267 bytes
-rw-r--r--WebCore/inspector/front-end/Images/reloadButtons.pngbin4544 -> 0 bytes
-rw-r--r--WebCore/inspector/front-end/Images/resourcesSilhouette.pngbin0 -> 42925 bytes
-rw-r--r--WebCore/inspector/front-end/Images/undockButtonGlyph.pngbin0 -> 179 bytes
-rw-r--r--WebCore/inspector/front-end/InjectedScript.js516
-rw-r--r--WebCore/inspector/front-end/KeyboardShortcut.js108
-rw-r--r--WebCore/inspector/front-end/MetricsSidebarPane.js38
-rw-r--r--WebCore/inspector/front-end/ObjectPropertiesSection.js202
-rw-r--r--WebCore/inspector/front-end/ObjectProxy.js45
-rw-r--r--WebCore/inspector/front-end/Panel.js12
-rw-r--r--WebCore/inspector/front-end/ProfileView.js86
-rw-r--r--WebCore/inspector/front-end/ProfilesPanel.js21
-rw-r--r--WebCore/inspector/front-end/PropertiesSidebarPane.js20
-rw-r--r--WebCore/inspector/front-end/Resource.js10
-rw-r--r--WebCore/inspector/front-end/ResourcesPanel.js71
-rw-r--r--WebCore/inspector/front-end/ScopeChainSidebarPane.js10
-rw-r--r--WebCore/inspector/front-end/Script.js13
-rw-r--r--WebCore/inspector/front-end/ScriptsPanel.js108
-rw-r--r--WebCore/inspector/front-end/SourceFrame.js41
-rw-r--r--WebCore/inspector/front-end/SourceView.js7
-rw-r--r--WebCore/inspector/front-end/StylesSidebarPane.js600
-rw-r--r--WebCore/inspector/front-end/TextPrompt.js17
-rw-r--r--WebCore/inspector/front-end/WebKit.qrc38
-rw-r--r--WebCore/inspector/front-end/inspector.css381
-rw-r--r--WebCore/inspector/front-end/inspector.html20
-rw-r--r--WebCore/inspector/front-end/inspector.js174
-rw-r--r--WebCore/inspector/front-end/utilities.js117
89 files changed, 6190 insertions, 1355 deletions
diff --git a/WebCore/inspector/ConsoleMessage.cpp b/WebCore/inspector/ConsoleMessage.cpp
index 62a9ab7..f9d8708 100644
--- a/WebCore/inspector/ConsoleMessage.cpp
+++ b/WebCore/inspector/ConsoleMessage.cpp
@@ -32,14 +32,15 @@
#include "ConsoleMessage.h"
#include "InspectorFrontend.h"
-#include "JSONObject.h"
#include "ScriptCallStack.h"
+#include "ScriptObject.h"
#include "ScriptObjectQuarantine.h"
namespace WebCore {
-ConsoleMessage::ConsoleMessage(MessageSource s, MessageLevel l, const String& m, unsigned li, const String& u, unsigned g)
+ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, const String& m, unsigned li, const String& u, unsigned g)
: m_source(s)
+ , m_type(t)
, m_level(l)
, m_message(m)
, m_line(li)
@@ -49,8 +50,9 @@ ConsoleMessage::ConsoleMessage(MessageSource s, MessageLevel l, const String& m,
{
}
-ConsoleMessage::ConsoleMessage(MessageSource s, MessageLevel l, ScriptCallStack* callStack, unsigned g, bool storeTrace)
+ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, ScriptCallStack* callStack, unsigned g, bool storeTrace)
: m_source(s)
+ , m_type(t)
, m_level(l)
, m_wrappedArguments(callStack->at(0).argumentCount())
, m_frames(storeTrace ? callStack->size() : 0)
@@ -75,8 +77,9 @@ ConsoleMessage::ConsoleMessage(MessageSource s, MessageLevel l, ScriptCallStack*
void ConsoleMessage::addToConsole(InspectorFrontend* frontend)
{
- JSONObject jsonObj = frontend->newJSONObject();
+ ScriptObject jsonObj = frontend->newScriptObject();
jsonObj.set("source", static_cast<int>(m_source));
+ jsonObj.set("type", static_cast<int>(m_type));
jsonObj.set("level", static_cast<int>(m_level));
jsonObj.set("line", static_cast<int>(m_line));
jsonObj.set("url", m_url);
@@ -109,6 +112,7 @@ bool ConsoleMessage::isEqual(ScriptState* state, ConsoleMessage* msg) const
}
return msg->m_source == m_source
+ && msg->m_type == m_type
&& msg->m_level == m_level
&& msg->m_message == m_message
&& msg->m_line == m_line
diff --git a/WebCore/inspector/ConsoleMessage.h b/WebCore/inspector/ConsoleMessage.h
index 15e6e7e..910a007 100644
--- a/WebCore/inspector/ConsoleMessage.h
+++ b/WebCore/inspector/ConsoleMessage.h
@@ -44,15 +44,19 @@ namespace WebCore {
class ConsoleMessage {
public:
- ConsoleMessage(MessageSource, MessageLevel, const String& m, unsigned li, const String& u, unsigned g);
- ConsoleMessage(MessageSource, MessageLevel, ScriptCallStack*, unsigned g, bool storeTrace = false);
+ ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& m, unsigned li, const String& u, unsigned g);
+ ConsoleMessage(MessageSource, MessageType, MessageLevel, ScriptCallStack*, unsigned g, bool storeTrace = false);
void addToConsole(InspectorFrontend* frontend);
void incrementCount() { ++m_repeatCount; };
bool isEqual(ScriptState*, ConsoleMessage* msg) const;
+ MessageSource source() const { return m_source; }
+ const String& message() const { return m_message; }
+
private:
MessageSource m_source;
+ MessageType m_type;
MessageLevel m_level;
String m_message;
Vector<ScriptValue> m_wrappedArguments;
diff --git a/WebCore/inspector/InspectorBackend.cpp b/WebCore/inspector/InspectorBackend.cpp
new file mode 100644
index 0000000..1eb10e8
--- /dev/null
+++ b/WebCore/inspector/InspectorBackend.cpp
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * 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 "InspectorBackend.h"
+
+#include "Element.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTMLFrameOwnerElement.h"
+#include "InspectorClient.h"
+#include "InspectorController.h"
+#include "InspectorDOMAgent.h"
+#include "InspectorResource.h"
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+#include "JavaScriptCallFrame.h"
+#include "JavaScriptDebugServer.h"
+using namespace JSC;
+#endif
+
+#include <wtf/RefPtr.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+InspectorBackend::InspectorBackend(InspectorController* inspectorController, InspectorClient* client)
+ : m_inspectorController(inspectorController)
+ , m_client(client)
+{
+}
+
+InspectorBackend::~InspectorBackend()
+{
+}
+
+void InspectorBackend::hideDOMNodeHighlight()
+{
+ if (m_inspectorController)
+ m_inspectorController->hideHighlight();
+}
+
+String InspectorBackend::localizedStringsURL()
+{
+ return m_client->localizedStringsURL();
+}
+
+String InspectorBackend::hiddenPanels()
+{
+ return m_client->hiddenPanels();
+}
+
+void InspectorBackend::windowUnloading()
+{
+ if (m_inspectorController)
+ m_inspectorController->close();
+}
+
+bool InspectorBackend::isWindowVisible()
+{
+ if (m_inspectorController)
+ return m_inspectorController->windowVisible();
+ return false;
+}
+
+void InspectorBackend::addResourceSourceToFrame(long identifier, Node* frame)
+{
+ if (!m_inspectorController)
+ return;
+ RefPtr<InspectorResource> resource = m_inspectorController->resources().get(identifier);
+ if (resource) {
+ String sourceString = resource->sourceString();
+ if (!sourceString.isEmpty())
+ addSourceToFrame(resource->mimeType(), sourceString, frame);
+ }
+}
+
+bool InspectorBackend::addSourceToFrame(const String& mimeType, const String& source, Node* frameNode)
+{
+ ASSERT_ARG(frameNode, frameNode);
+
+ if (!frameNode)
+ return false;
+
+ if (!frameNode->attached()) {
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ ASSERT(frameNode->isElementNode());
+ if (!frameNode->isElementNode())
+ return false;
+
+ Element* element = static_cast<Element*>(frameNode);
+ ASSERT(element->isFrameOwnerElement());
+ if (!element->isFrameOwnerElement())
+ return false;
+
+ HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
+ ASSERT(frameOwner->contentFrame());
+ if (!frameOwner->contentFrame())
+ return false;
+
+ FrameLoader* loader = frameOwner->contentFrame()->loader();
+
+ loader->setResponseMIMEType(mimeType);
+ loader->begin();
+ loader->write(source);
+ loader->end();
+
+ return true;
+}
+
+void InspectorBackend::clearMessages()
+{
+ if (m_inspectorController)
+ m_inspectorController->clearConsoleMessages();
+}
+
+void InspectorBackend::toggleNodeSearch()
+{
+ if (m_inspectorController)
+ m_inspectorController->toggleSearchForNodeInPage();
+}
+
+void InspectorBackend::attach()
+{
+ if (m_inspectorController)
+ m_inspectorController->attachWindow();
+}
+
+void InspectorBackend::detach()
+{
+ if (m_inspectorController)
+ m_inspectorController->detachWindow();
+}
+
+void InspectorBackend::setAttachedWindowHeight(unsigned height)
+{
+ if (m_inspectorController)
+ m_inspectorController->setAttachedWindowHeight(height);
+}
+
+void InspectorBackend::storeLastActivePanel(const String& panelName)
+{
+ if (m_inspectorController)
+ m_inspectorController->storeLastActivePanel(panelName);
+}
+
+bool InspectorBackend::searchingForNode()
+{
+ if (m_inspectorController)
+ return m_inspectorController->searchingForNodeInPage();
+ return false;
+}
+
+void InspectorBackend::loaded(bool enableDOMAgent)
+{
+ if (m_inspectorController)
+ m_inspectorController->scriptObjectReady(enableDOMAgent);
+}
+
+void InspectorBackend::enableResourceTracking(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->enableResourceTracking(always);
+}
+
+void InspectorBackend::disableResourceTracking(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->disableResourceTracking(always);
+}
+
+bool InspectorBackend::resourceTrackingEnabled() const
+{
+ if (m_inspectorController)
+ return m_inspectorController->resourceTrackingEnabled();
+ return false;
+}
+
+void InspectorBackend::moveWindowBy(float x, float y) const
+{
+ if (m_inspectorController)
+ m_inspectorController->moveWindowBy(x, y);
+}
+
+void InspectorBackend::closeWindow()
+{
+ if (m_inspectorController)
+ m_inspectorController->closeWindow();
+}
+
+const String& InspectorBackend::platform() const
+{
+#if PLATFORM(MAC)
+#ifdef BUILDING_ON_TIGER
+ DEFINE_STATIC_LOCAL(const String, platform, ("mac-tiger"));
+#else
+ DEFINE_STATIC_LOCAL(const String, platform, ("mac-leopard"));
+#endif
+#elif PLATFORM(WIN_OS)
+ DEFINE_STATIC_LOCAL(const String, platform, ("windows"));
+#elif PLATFORM(QT)
+ DEFINE_STATIC_LOCAL(const String, platform, ("qt"));
+#elif PLATFORM(GTK)
+ DEFINE_STATIC_LOCAL(const String, platform, ("gtk"));
+#elif PLATFORM(WX)
+ DEFINE_STATIC_LOCAL(const String, platform, ("wx"));
+#else
+ DEFINE_STATIC_LOCAL(const String, platform, ("unknown"));
+#endif
+
+ return platform;
+}
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+const ProfilesArray& InspectorBackend::profiles() const
+{
+ if (m_inspectorController)
+ return m_inspectorController->profiles();
+ return m_emptyProfiles;
+}
+
+void InspectorBackend::startProfiling()
+{
+ if (m_inspectorController)
+ m_inspectorController->startUserInitiatedProfiling();
+}
+
+void InspectorBackend::stopProfiling()
+{
+ if (m_inspectorController)
+ m_inspectorController->stopUserInitiatedProfiling();
+}
+
+void InspectorBackend::enableProfiler(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->enableProfiler(always);
+}
+
+void InspectorBackend::disableProfiler(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->disableProfiler(always);
+}
+
+bool InspectorBackend::profilerEnabled()
+{
+ if (m_inspectorController)
+ return m_inspectorController->profilerEnabled();
+ return false;
+}
+
+void InspectorBackend::enableDebugger(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->enableDebuggerFromFrontend(always);
+}
+
+void InspectorBackend::disableDebugger(bool always)
+{
+ if (m_inspectorController)
+ m_inspectorController->disableDebugger(always);
+}
+
+bool InspectorBackend::debuggerEnabled() const
+{
+ if (m_inspectorController)
+ return m_inspectorController->debuggerEnabled();
+ return false;
+}
+
+JavaScriptCallFrame* InspectorBackend::currentCallFrame() const
+{
+ return JavaScriptDebugServer::shared().currentCallFrame();
+}
+
+void InspectorBackend::addBreakpoint(const String& sourceID, unsigned lineNumber)
+{
+ intptr_t sourceIDValue = sourceID.toIntPtr();
+ JavaScriptDebugServer::shared().addBreakpoint(sourceIDValue, lineNumber);
+}
+
+void InspectorBackend::removeBreakpoint(const String& sourceID, unsigned lineNumber)
+{
+ intptr_t sourceIDValue = sourceID.toIntPtr();
+ JavaScriptDebugServer::shared().removeBreakpoint(sourceIDValue, lineNumber);
+}
+
+bool InspectorBackend::pauseOnExceptions()
+{
+ return JavaScriptDebugServer::shared().pauseOnExceptions();
+}
+
+void InspectorBackend::setPauseOnExceptions(bool pause)
+{
+ JavaScriptDebugServer::shared().setPauseOnExceptions(pause);
+}
+
+void InspectorBackend::pauseInDebugger()
+{
+ JavaScriptDebugServer::shared().pauseProgram();
+}
+
+void InspectorBackend::resumeDebugger()
+{
+ if (m_inspectorController)
+ m_inspectorController->resumeDebugger();
+}
+
+void InspectorBackend::stepOverStatementInDebugger()
+{
+ JavaScriptDebugServer::shared().stepOverStatement();
+}
+
+void InspectorBackend::stepIntoStatementInDebugger()
+{
+ JavaScriptDebugServer::shared().stepIntoStatement();
+}
+
+void InspectorBackend::stepOutOfFunctionInDebugger()
+{
+ JavaScriptDebugServer::shared().stepOutOfFunction();
+}
+
+#endif
+
+void InspectorBackend::getChildNodes(long callId, long elementId)
+{
+ if (m_inspectorController)
+ m_inspectorController->domAgent()->getChildNodes(callId, elementId);
+}
+
+void InspectorBackend::setAttribute(long callId, long elementId, const String& name, const String& value)
+{
+ if (m_inspectorController)
+ m_inspectorController->domAgent()->setAttribute(callId, elementId, name, value);
+}
+
+void InspectorBackend::removeAttribute(long callId, long elementId, const String& name)
+{
+ if (m_inspectorController)
+ m_inspectorController->domAgent()->removeAttribute(callId, elementId, name);
+}
+
+void InspectorBackend::setTextNodeValue(long callId, long elementId, const String& value)
+{
+ if (m_inspectorController)
+ m_inspectorController->domAgent()->setTextNodeValue(callId, elementId, value);
+}
+
+void InspectorBackend::highlight(Node* node)
+{
+ if (m_inspectorController)
+ m_inspectorController->highlight(node);
+}
+
+} // namespace WebCore
diff --git a/WebCore/inspector/InspectorBackend.h b/WebCore/inspector/InspectorBackend.h
new file mode 100644
index 0000000..daa16b4
--- /dev/null
+++ b/WebCore/inspector/InspectorBackend.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2007 Apple 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.
+ */
+
+#ifndef InspectorBackend_h
+#define InspectorBackend_h
+
+#include "Console.h"
+#include "InspectorController.h"
+#include "PlatformString.h"
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CachedResource;
+class InspectorClient;
+class InspectorDOMAgent;
+class JavaScriptCallFrame;
+class Node;
+
+class InspectorBackend : public RefCounted<InspectorBackend>
+{
+public:
+ static PassRefPtr<InspectorBackend> create(InspectorController* inspectorController, InspectorClient* client)
+ {
+ return adoptRef(new InspectorBackend(inspectorController, client));
+ }
+
+ ~InspectorBackend();
+
+ InspectorController* inspectorController() { return m_inspectorController; }
+
+ void disconnectController() { m_inspectorController = 0; }
+
+ void hideDOMNodeHighlight();
+
+ String localizedStringsURL();
+ String hiddenPanels();
+
+ void windowUnloading();
+
+ bool isWindowVisible();
+
+ void addResourceSourceToFrame(long identifier, Node* frame);
+ bool addSourceToFrame(const String& mimeType, const String& source, Node* frame);
+
+ void clearMessages();
+
+ void toggleNodeSearch();
+
+ void attach();
+ void detach();
+
+ void setAttachedWindowHeight(unsigned height);
+
+ void storeLastActivePanel(const String& panelName);
+
+ bool searchingForNode();
+
+ void loaded(bool enableDOMAgent);
+
+ void enableResourceTracking(bool always);
+ void disableResourceTracking(bool always);
+ bool resourceTrackingEnabled() const;
+
+ void moveWindowBy(float x, float y) const;
+ void closeWindow();
+
+ const String& platform() const;
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ const ProfilesArray& profiles() const;
+
+ void startProfiling();
+ void stopProfiling();
+
+ void enableProfiler(bool always);
+ void disableProfiler(bool always);
+ bool profilerEnabled();
+
+ void enableDebugger(bool always);
+ void disableDebugger(bool always);
+ bool debuggerEnabled() const;
+
+ JavaScriptCallFrame* currentCallFrame() const;
+
+ void addBreakpoint(const String& sourceID, unsigned lineNumber);
+ void removeBreakpoint(const String& sourceID, unsigned lineNumber);
+
+ bool pauseOnExceptions();
+ void setPauseOnExceptions(bool pause);
+
+ void pauseInDebugger();
+ void resumeDebugger();
+
+ void stepOverStatementInDebugger();
+ void stepIntoStatementInDebugger();
+ void stepOutOfFunctionInDebugger();
+#endif
+
+ void getChildNodes(long callId, long elementId);
+ void setAttribute(long callId, long elementId, const String& name, const String& value);
+ void removeAttribute(long callId, long elementId, const String& name);
+ void setTextNodeValue(long callId, long elementId, const String& value);
+
+ // Generic code called from custom implementations.
+ void highlight(Node* node);
+
+private:
+ InspectorBackend(InspectorController* inspectorController, InspectorClient* client);
+
+ InspectorController* m_inspectorController;
+ InspectorClient* m_client;
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ ProfilesArray m_emptyProfiles;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorBackend_h)
diff --git a/WebCore/inspector/InspectorController.idl b/WebCore/inspector/InspectorBackend.idl
index 920786a..bae1f26 100644
--- a/WebCore/inspector/InspectorController.idl
+++ b/WebCore/inspector/InspectorBackend.idl
@@ -33,24 +33,23 @@
module core {
interface [
GenerateConstructor
- ] InspectorController {
- [ImplementationFunction=hideHighlight] void hideDOMNodeHighlight();
+ ] InspectorBackend {
+ void hideDOMNodeHighlight();
[Custom] void highlightDOMNode(in Node node);
- [ImplementationFunction=scriptObjectReady] void loaded();
- [ImplementationFunction=close] void windowUnloading();
- [ImplementationFunction=attachWindow] void attach();
- [ImplementationFunction=detachWindow] void detach();
+ void loaded(in boolean enableDOMAgent);
+ void windowUnloading();
+ void attach();
+ void detach();
void closeWindow();
- [ImplementationFunction=clearConsoleMessages] void clearMessages();
- [ImplementationFunction=toggleSearchForNodeInPage] void toggleNodeSearch();
+ void clearMessages();
+ void toggleNodeSearch();
- [ImplementationFunction=windowVisible] boolean isWindowVisible();
- [ImplementationFunction=searchingForNodeInPage] boolean searchingForNode();
+ boolean isWindowVisible();
+ boolean searchingForNode();
void addResourceSourceToFrame(in long identifier, in Node frame);
boolean addSourceToFrame(in DOMString mimeType, in DOMString sourceValue, in Node frame);
- [Custom] Node getResourceDocumentNode(in long long identifier);
[Custom] void search(in Node node, in DOMString query);
#if defined(ENABLE_DATABASE) && ENABLE_DATABASE
[Custom] DOMObject databaseTableNames(in Database database);
@@ -67,28 +66,40 @@ module core {
boolean resourceTrackingEnabled();
void enableResourceTracking(in boolean always);
void disableResourceTracking(in boolean always);
+ void storeLastActivePanel(in DOMString panelName);
#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
- void enableDebuggerFromFrontend(in boolean always);
+ boolean debuggerEnabled();
+ void enableDebugger(in boolean always);
void disableDebugger(in boolean always);
+
+ void addBreakpoint(in DOMString sourceID, in unsigned long lineNumber);
+ void removeBreakpoint(in DOMString sourceID, in unsigned long lineNumber);
+
void pauseInDebugger();
void resumeDebugger();
+
void stepOverStatementInDebugger();
void stepIntoStatementInDebugger();
void stepOutOfFunctionInDebugger();
- boolean debuggerEnabled();
+
+ [Custom] DOMObject currentCallFrame();
+
boolean pauseOnExceptions();
+ void setPauseOnExceptions(in boolean pauseOnExceptions);
+
boolean profilerEnabled();
- [ImplementationFunction=startUserInitiatedProfiling] void startProfiling();
- [ImplementationFunction=stopUserInitiatedProfiling] void stopProfiling();
void enableProfiler(in boolean always);
void disableProfiler(in boolean always);
- [Custom] DOMObject currentCallFrame();
- void setPauseOnExceptions(in boolean pauseOnExceptions);
- void addBreakpoint(in unsigned long sourceID, in unsigned long lineNumber);
- void removeBreakpoint(in unsigned long sourceID, in unsigned long lineNumber);
+
+ void startProfiling();
+ void stopProfiling();
[Custom] Array profiles();
#endif
- };
+ void getChildNodes(in long callId, in long elementId);
+ void setAttribute(in long callId, in long elementId, in DOMString name, in DOMString value);
+ void removeAttribute(in long callId, in long elementId, in DOMString name);
+ void setTextNodeValue(in long callId, in long elementId, in DOMString value);
+ };
}
diff --git a/WebCore/inspector/InspectorClient.h b/WebCore/inspector/InspectorClient.h
index 2508536..f96662a 100644
--- a/WebCore/inspector/InspectorClient.h
+++ b/WebCore/inspector/InspectorClient.h
@@ -62,6 +62,8 @@ public:
virtual void populateSetting(const String& key, InspectorController::Setting&) = 0;
virtual void storeSetting(const String& key, const InspectorController::Setting&) = 0;
virtual void removeSetting(const String& key) = 0;
+
+ virtual void inspectorWindowObjectCleared() = 0;
};
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp
index 170c4e3..c3351e5 100644
--- a/WebCore/inspector/InspectorController.cpp
+++ b/WebCore/inspector/InspectorController.cpp
@@ -47,9 +47,11 @@
#include "GraphicsContext.h"
#include "HTMLFrameOwnerElement.h"
#include "HitTestResult.h"
+#include "InspectorBackend.h"
#include "InspectorClient.h"
#include "InspectorFrontend.h"
#include "InspectorDatabaseResource.h"
+#include "InspectorDOMAgent.h"
#include "InspectorDOMStorageResource.h"
#include "InspectorResource.h"
#include "JavaScriptProfile.h"
@@ -99,65 +101,12 @@ static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-in
static const char* const resourceTrackingEnabledSettingName = "resourceTrackingEnabled";
static const char* const debuggerEnabledSettingName = "debuggerEnabled";
static const char* const profilerEnabledSettingName = "profilerEnabled";
+static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight";
+static const char* const lastActivePanelSettingName = "lastActivePanel";
-bool InspectorController::addSourceToFrame(const String& mimeType, const String& source, Node* frameNode)
-{
- ASSERT_ARG(frameNode, frameNode);
-
- if (!frameNode)
- return false;
-
- if (!frameNode->attached()) {
- ASSERT_NOT_REACHED();
- return false;
- }
-
- ASSERT(frameNode->isElementNode());
- if (!frameNode->isElementNode())
- return false;
-
- Element* element = static_cast<Element*>(frameNode);
- ASSERT(element->isFrameOwnerElement());
- if (!element->isFrameOwnerElement())
- return false;
-
- HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
- ASSERT(frameOwner->contentFrame());
- if (!frameOwner->contentFrame())
- return false;
-
- FrameLoader* loader = frameOwner->contentFrame()->loader();
-
- loader->setResponseMIMEType(mimeType);
- loader->begin();
- loader->write(source);
- loader->end();
-
- return true;
-}
-
-const String& InspectorController::platform() const
-{
-#if PLATFORM(MAC)
-#ifdef BUILDING_ON_TIGER
- DEFINE_STATIC_LOCAL(const String, platform, ("mac-tiger"));
-#else
- DEFINE_STATIC_LOCAL(const String, platform, ("mac-leopard"));
-#endif
-#elif PLATFORM(WIN_OS)
- DEFINE_STATIC_LOCAL(const String, platform, ("windows"));
-#elif PLATFORM(QT)
- DEFINE_STATIC_LOCAL(const String, platform, ("qt"));
-#elif PLATFORM(GTK)
- DEFINE_STATIC_LOCAL(const String, platform, ("gtk"));
-#elif PLATFORM(WX)
- DEFINE_STATIC_LOCAL(const String, platform, ("wx"));
-#else
- DEFINE_STATIC_LOCAL(const String, platform, ("unknown"));
-#endif
-
- return platform;
-}
+static const unsigned defaultAttachedHeight = 300;
+static const float minimumAttachedHeight = 250.0f;
+static const float maximumAttachedHeightRatio = 0.75f;
static unsigned s_inspectorControllerCount;
static HashMap<String, InspectorController::Setting*>* s_settingCache;
@@ -168,13 +117,14 @@ InspectorController::InspectorController(Page* page, InspectorClient* client)
, m_page(0)
, m_scriptState(0)
, m_windowVisible(false)
- , m_showAfterVisible(ElementsPanel)
+ , m_showAfterVisible(CurrentPanel)
, m_nextIdentifier(-2)
, m_groupLevel(0)
, m_searchingForNode(false)
, m_previousMessage(0)
, m_resourceTrackingEnabled(false)
, m_resourceTrackingSettingsLoaded(false)
+ , m_inspectorBackend(InspectorBackend::create(this, client))
#if ENABLE(JAVASCRIPT_DEBUGGER)
, m_debuggerEnabled(false)
, m_attachDebuggerWhenShown(false)
@@ -209,6 +159,8 @@ InspectorController::~InspectorController()
delete s_settingCache;
s_settingCache = 0;
}
+
+ m_inspectorBackend->disconnectController();
}
void InspectorController::inspectedPageDestroyed()
@@ -279,20 +231,6 @@ void InspectorController::setSetting(const String& key, const Setting& setting)
m_client->storeSetting(key, setting);
}
-String InspectorController::localizedStringsURL()
-{
- if (!enabled())
- return String();
- return m_client->localizedStringsURL();
-}
-
-String InspectorController::hiddenPanels()
-{
- if (!enabled())
- return String();
- return m_client->hiddenPanels();
-}
-
// Trying to inspect something in a frame with JavaScript disabled would later lead to
// crashes trying to create JavaScript wrappers. Some day we could fix this issue, but
// for now prevent crashes here by never targeting a node in such a frame.
@@ -371,14 +309,27 @@ void InspectorController::setWindowVisible(bool visible, bool attached)
if (m_windowVisible) {
setAttachedWindow(attached);
populateScriptObjects();
+
+ // Console panel is implemented as a 'fast view', so there should be
+ // real panel opened along with it.
+ bool showConsole = m_showAfterVisible == ConsolePanel;
+ if (m_showAfterVisible == CurrentPanel || showConsole) {
+ Setting lastActivePanelSetting = setting(lastActivePanelSettingName);
+ if (lastActivePanelSetting.type() == Setting::StringType)
+ m_showAfterVisible = specialPanelForJSName(lastActivePanelSetting.string());
+ else
+ m_showAfterVisible = ElementsPanel;
+ }
+
if (m_nodeToFocus)
focusNode();
#if ENABLE(JAVASCRIPT_DEBUGGER)
if (m_attachDebuggerWhenShown)
enableDebugger();
#endif
- if (m_showAfterVisible != CurrentPanel)
- showPanel(m_showAfterVisible);
+ showPanel(m_showAfterVisible);
+ if (showConsole)
+ showPanel(ConsolePanel);
} else {
#if ENABLE(JAVASCRIPT_DEBUGGER)
// If the window is being closed with the debugger enabled,
@@ -391,24 +342,23 @@ void InspectorController::setWindowVisible(bool visible, bool attached)
#endif
resetScriptObjects();
}
-
m_showAfterVisible = CurrentPanel;
}
-void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, ScriptCallStack* callStack)
+void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, ScriptCallStack* callStack)
{
if (!enabled())
return;
- addConsoleMessage(callStack->state(), new ConsoleMessage(source, level, callStack, m_groupLevel, level == TraceMessageLevel));
+ addConsoleMessage(callStack->state(), new ConsoleMessage(source, type, level, callStack, m_groupLevel, type == TraceMessageType));
}
-void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
+void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
{
if (!enabled())
return;
- addConsoleMessage(0, new ConsoleMessage(source, level, message, lineNumber, sourceID, m_groupLevel));
+ addConsoleMessage(0, new ConsoleMessage(source, type, level, message, lineNumber, sourceID, m_groupLevel));
}
void InspectorController::addConsoleMessage(ScriptState* scriptState, ConsoleMessage* consoleMessage)
@@ -440,7 +390,7 @@ void InspectorController::startGroup(MessageSource source, ScriptCallStack* call
{
++m_groupLevel;
- addConsoleMessage(callStack->state(), new ConsoleMessage(source, StartGroupMessageLevel, callStack, m_groupLevel));
+ addConsoleMessage(callStack->state(), new ConsoleMessage(source, StartGroupMessageType, LogMessageLevel, callStack, m_groupLevel));
}
void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL)
@@ -450,14 +400,29 @@ void InspectorController::endGroup(MessageSource source, unsigned lineNumber, co
--m_groupLevel;
- addConsoleMessage(0, new ConsoleMessage(source, EndGroupMessageLevel, String(), lineNumber, sourceURL, m_groupLevel));
+ addConsoleMessage(0, new ConsoleMessage(source, EndGroupMessageType, LogMessageLevel, String(), lineNumber, sourceURL, m_groupLevel));
+}
+
+static unsigned constrainedAttachedWindowHeight(unsigned preferredHeight, unsigned totalWindowHeight)
+{
+ return roundf(max(minimumAttachedHeight, min<float>(preferredHeight, totalWindowHeight * maximumAttachedHeightRatio)));
}
void InspectorController::attachWindow()
{
if (!enabled())
return;
+
+ unsigned inspectedPageHeight = m_inspectedPage->mainFrame()->view()->visibleHeight();
+
m_client->attachWindow();
+
+ Setting attachedHeight = setting(inspectorAttachedHeightName);
+ unsigned preferredHeight = attachedHeight.type() == Setting::IntegerType ? attachedHeight.integerValue() : defaultAttachedHeight;
+
+ // We need to constrain the window height here in case the user has resized the inspected page's window so that
+ // the user's preferred height would be too big to display.
+ m_client->setAttachedWindowHeight(constrainedAttachedWindowHeight(preferredHeight, inspectedPageHeight));
}
void InspectorController::detachWindow()
@@ -479,7 +444,18 @@ void InspectorController::setAttachedWindowHeight(unsigned height)
{
if (!enabled())
return;
- m_client->setAttachedWindowHeight(height);
+
+ unsigned totalHeight = m_page->mainFrame()->view()->visibleHeight() + m_inspectedPage->mainFrame()->view()->visibleHeight();
+ unsigned attachedHeight = constrainedAttachedWindowHeight(height, totalHeight);
+
+ setSetting(inspectorAttachedHeightName, Setting(attachedHeight));
+
+ m_client->setAttachedWindowHeight(attachedHeight);
+}
+
+void InspectorController::storeLastActivePanel(const String& panelName)
+{
+ setSetting(lastActivePanelSettingName, Setting(panelName));
}
void InspectorController::toggleSearchForNodeInPage()
@@ -492,19 +468,6 @@ void InspectorController::toggleSearchForNodeInPage()
hideHighlight();
}
-void InspectorController::addResourceSourceToFrame(long identifier, Node* frame)
-{
- if (!enabled() || !m_frontend)
- return;
-
- RefPtr<InspectorResource> resource = resources().get(identifier);
- if (resource) {
- String sourceString = resource->sourceString();
- if (!sourceString.isEmpty())
- addSourceToFrame(resource->mimeType(), sourceString, frame);
- }
-}
-
void InspectorController::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
{
if (!enabled() || !m_searchingForNode)
@@ -544,12 +507,11 @@ void InspectorController::windowScriptObjectAvailable()
// Grant the inspector the ability to script the inspected page.
m_page->mainFrame()->document()->securityOrigin()->grantUniversalAccess();
-
m_scriptState = scriptStateFromPage(m_page);
- ScriptGlobalObject::set(m_scriptState, "InspectorController", this);
+ ScriptGlobalObject::set(m_scriptState, "InspectorController", m_inspectorBackend.get());
}
-void InspectorController::scriptObjectReady()
+void InspectorController::scriptObjectReady(bool enableDOMAgent)
{
ASSERT(m_scriptState);
if (!m_scriptState)
@@ -559,6 +521,8 @@ void InspectorController::scriptObjectReady()
if (!ScriptGlobalObject::get(m_scriptState, "WebInspector", webInspectorObj))
return;
setFrontendProxyObject(m_scriptState, webInspectorObj);
+ if (enableDOMAgent)
+ m_domAgent = new InspectorDOMAgent(m_frontend.get());
#if ENABLE(JAVASCRIPT_DEBUGGER)
Setting debuggerEnabled = setting(debuggerEnabledSettingName);
@@ -571,6 +535,8 @@ void InspectorController::scriptObjectReady()
// Make sure our window is visible now that the page loaded
showWindow();
+
+ m_client->inspectorWindowObjectCleared();
}
void InspectorController::setFrontendProxyObject(ScriptState* scriptState, ScriptObject webInspectorObj)
@@ -629,13 +595,28 @@ void InspectorController::close()
closeWindow();
m_frontend.set(0);
+ if (m_domAgent) {
+ m_domAgent->setDocument(0);
+ m_domAgent = 0;
+ }
m_scriptState = 0;
}
void InspectorController::showWindow()
{
ASSERT(enabled());
+
+ unsigned inspectedPageHeight = m_inspectedPage->mainFrame()->view()->visibleHeight();
+
m_client->showWindow();
+
+ Setting attachedHeight = setting(inspectorAttachedHeightName);
+ unsigned preferredHeight = attachedHeight.type() == Setting::IntegerType ? attachedHeight.integerValue() : 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.
+ // FIXME: Clean up code so we only have to call setAttachedWindowHeight in InspectorController::attachWindow
+ m_client->setAttachedWindowHeight(constrainedAttachedWindowHeight(preferredHeight, inspectedPageHeight));
}
void InspectorController::closeWindow()
@@ -668,6 +649,8 @@ void InspectorController::populateScriptObjects()
(*it)->bind(m_frontend.get());
#endif
+ if (m_domAgent)
+ m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
m_frontend->populateInterface();
}
@@ -729,6 +712,8 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
m_counts.clear();
#if ENABLE(JAVASCRIPT_DEBUGGER)
m_profiles.clear();
+ m_currentUserInitiatedProfileNumber = 1;
+ m_nextUserInitiatedProfileNumber = 1;
#endif
#if ENABLE(DATABASE)
m_databaseResources.clear();
@@ -754,6 +739,9 @@ void InspectorController::didCommitLoad(DocumentLoader* loader)
m_mainResource = 0;
}
}
+
+ if (m_domAgent)
+ m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
}
for (Frame* frame = loader->frame(); frame; frame = frame->tree()->traverseNext(loader->frame()))
@@ -788,7 +776,9 @@ void InspectorController::addResource(InspectorResource* resource)
void InspectorController::removeResource(InspectorResource* resource)
{
m_resources.remove(resource->identifier());
- m_knownResources.remove(resource->requestURL());
+ String requestURL = resource->requestURL();
+ if (!requestURL.isNull())
+ m_knownResources.remove(requestURL);
Frame* frame = resource->frame();
ResourcesMap* resourceMap = m_frameResources.get(frame);
@@ -804,6 +794,21 @@ void InspectorController::removeResource(InspectorResource* resource)
}
}
+InspectorResource* InspectorController::getTrackedResource(long long identifier)
+{
+ if (!enabled())
+ return 0;
+
+ if (m_resourceTrackingEnabled)
+ return m_resources.get(identifier).get();
+
+ bool isMainResource = m_mainResource && m_mainResource->identifier() == identifier;
+ if (isMainResource)
+ return m_mainResource.get();
+
+ return 0;
+}
+
void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader, const CachedResource* cachedResource)
{
if (!enabled())
@@ -814,7 +819,7 @@ void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader,
return;
ASSERT(m_inspectedPage);
- bool isMainResource = loader->frame() == m_inspectedPage->mainFrame() && cachedResource->url() == loader->requestURL();
+ bool isMainResource = isMainResourceLoader(loader, KURL(cachedResource->url()));
ensureResourceTrackingSettingsLoaded();
if (!isMainResource && !m_resourceTrackingEnabled)
return;
@@ -838,7 +843,7 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier,
return;
ASSERT(m_inspectedPage);
- bool isMainResource = m_inspectedPage->mainFrame() && request.url() == loader->requestURL();
+ bool isMainResource = isMainResourceLoader(loader, request.url());
ensureResourceTrackingSettingsLoaded();
if (!isMainResource && !m_resourceTrackingEnabled)
return;
@@ -858,12 +863,14 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier,
resource->createScriptObject(m_frontend.get());
}
-void InspectorController::willSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
+bool InspectorController::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
{
- if (!enabled() || !m_resourceTrackingEnabled)
- return;
+ return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
+}
- InspectorResource* resource = m_resources.get(identifier).get();
+void InspectorController::willSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+ RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -880,10 +887,7 @@ void InspectorController::willSendRequest(DocumentLoader*, unsigned long identif
void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
{
- if (!enabled() || !m_resourceTrackingEnabled)
- return;
-
- InspectorResource* resource = m_resources.get(identifier).get();
+ RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -896,10 +900,7 @@ void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long iden
void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived)
{
- if (!enabled() || !m_resourceTrackingEnabled)
- return;
-
- InspectorResource* resource = m_resources.get(identifier).get();
+ RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -911,10 +912,7 @@ void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long
void InspectorController::didFinishLoading(DocumentLoader*, unsigned long identifier)
{
- if (!enabled() || !m_resourceTrackingEnabled)
- return;
-
- RefPtr<InspectorResource> resource = m_resources.get(identifier);
+ RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -930,10 +928,7 @@ void InspectorController::didFinishLoading(DocumentLoader*, unsigned long identi
void InspectorController::didFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& /*error*/)
{
- if (!enabled() || !m_resourceTrackingEnabled)
- return;
-
- RefPtr<InspectorResource> resource = m_resources.get(identifier);
+ RefPtr<InspectorResource> resource = getTrackedResource(identifier);
if (!resource)
return;
@@ -980,7 +975,8 @@ void InspectorController::scriptImported(unsigned long identifier, const String&
resource->updateScriptObject(m_frontend.get());
}
-void InspectorController::enableResourceTracking(bool always) {
+void InspectorController::enableResourceTracking(bool always)
+{
if (!enabled())
return;
@@ -998,7 +994,8 @@ void InspectorController::enableResourceTracking(bool always) {
m_inspectedPage->mainFrame()->loader()->reload();
}
-void InspectorController::disableResourceTracking(bool always) {
+void InspectorController::disableResourceTracking(bool always)
+{
if (!enabled())
return;
@@ -1079,10 +1076,10 @@ void InspectorController::addProfile(PassRefPtr<Profile> prpProfile, unsigned li
if (windowVisible())
addScriptProfile(profile.get());
- addProfileMessageToConsole(profile, lineNumber, sourceURL);
+ addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL);
}
-void InspectorController::addProfileMessageToConsole(PassRefPtr<Profile> prpProfile, unsigned lineNumber, const UString& sourceURL)
+void InspectorController::addProfileFinishedMessageToConsole(PassRefPtr<Profile> prpProfile, unsigned lineNumber, const UString& sourceURL)
{
RefPtr<Profile> profile = prpProfile;
@@ -1091,7 +1088,15 @@ void InspectorController::addProfileMessageToConsole(PassRefPtr<Profile> prpProf
message += "/";
message += UString::from(profile->uid());
message += "\" finished.";
- addMessageToConsole(JSMessageSource, LogMessageLevel, message, lineNumber, sourceURL);
+ addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
+}
+
+void InspectorController::addStartProfilingMessageToConsole(const UString& title, unsigned lineNumber, const UString& sourceURL)
+{
+ UString message = "Profile \"webkit-profile://";
+ message += encodeWithURLEscapeSequences(title);
+ message += "/0\" started.";
+ addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
}
void InspectorController::addScriptProfile(Profile* profile)
@@ -1099,10 +1104,22 @@ void InspectorController::addScriptProfile(Profile* profile)
if (!m_frontend)
return;
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
m_frontend->addProfile(toJS(m_scriptState, profile));
}
+UString InspectorController::getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false)
+{
+ if (incrementProfileNumber)
+ m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
+
+ UString title = UserInitiatedProfileName;
+ title += ".";
+ title += UString::from(m_currentUserInitiatedProfileNumber);
+
+ return title;
+}
+
void InspectorController::startUserInitiatedProfilingSoon()
{
m_startProfiling.startOneShot(0);
@@ -1119,15 +1136,14 @@ void InspectorController::startUserInitiatedProfiling(Timer<InspectorController>
}
m_recordingUserInitiatedProfile = true;
- m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
- UString title = UserInitiatedProfileName;
- title += ".";
- title += UString::from(m_currentUserInitiatedProfileNumber);
+ UString title = getCurrentUserInitiatedProfileName(true);
ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame())->globalExec();
Profiler::profiler()->startProfiling(scriptState, title);
+ addStartProfilingMessageToConsole(title, 0, UString());
+
toggleRecordButton(true);
}
@@ -1138,9 +1154,7 @@ void InspectorController::stopUserInitiatedProfiling()
m_recordingUserInitiatedProfile = false;
- UString title = UserInitiatedProfileName;
- title += ".";
- title += UString::from(m_currentUserInitiatedProfileNumber);
+ UString title = getCurrentUserInitiatedProfileName();
ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame())->globalExec();
RefPtr<Profile> profile = Profiler::profiler()->stopProfiling(scriptState, title);
@@ -1239,28 +1253,6 @@ void InspectorController::disableDebugger(bool always)
m_frontend->debuggerWasDisabled();
}
-JavaScriptCallFrame* InspectorController::currentCallFrame() const
-{
- return JavaScriptDebugServer::shared().currentCallFrame();
-}
-
-bool InspectorController::pauseOnExceptions()
-{
- return JavaScriptDebugServer::shared().pauseOnExceptions();
-}
-
-void InspectorController::setPauseOnExceptions(bool pause)
-{
- JavaScriptDebugServer::shared().setPauseOnExceptions(pause);
-}
-
-void InspectorController::pauseInDebugger()
-{
- if (!m_debuggerEnabled)
- return;
- JavaScriptDebugServer::shared().pauseProgram();
-}
-
void InspectorController::resumeDebugger()
{
if (!m_debuggerEnabled)
@@ -1268,37 +1260,6 @@ void InspectorController::resumeDebugger()
JavaScriptDebugServer::shared().continueProgram();
}
-void InspectorController::stepOverStatementInDebugger()
-{
- if (!m_debuggerEnabled)
- return;
- JavaScriptDebugServer::shared().stepOverStatement();
-}
-
-void InspectorController::stepIntoStatementInDebugger()
-{
- if (!m_debuggerEnabled)
- return;
- JavaScriptDebugServer::shared().stepIntoStatement();
-}
-
-void InspectorController::stepOutOfFunctionInDebugger()
-{
- if (!m_debuggerEnabled)
- return;
- JavaScriptDebugServer::shared().stepOutOfFunction();
-}
-
-void InspectorController::addBreakpoint(intptr_t sourceID, unsigned lineNumber)
-{
- JavaScriptDebugServer::shared().addBreakpoint(sourceID, lineNumber);
-}
-
-void InspectorController::removeBreakpoint(intptr_t sourceID, unsigned lineNumber)
-{
- JavaScriptDebugServer::shared().removeBreakpoint(sourceID, lineNumber);
-}
-
// JavaScriptDebugListener functions
void InspectorController::didParseSource(ExecState*, const SourceCode& source)
@@ -1480,7 +1441,7 @@ void InspectorController::count(const String& title, unsigned lineNumber, const
m_counts.add(identifier, count);
String message = String::format("%s: %d", title.utf8().data(), count);
- addMessageToConsole(JSMessageSource, LogMessageLevel, message, lineNumber, sourceID);
+ addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceID);
}
void InspectorController::startTiming(const String& title)
@@ -1501,4 +1462,20 @@ bool InspectorController::stopTiming(const String& title, double& elapsed)
return true;
}
+InspectorController::SpecialPanels InspectorController::specialPanelForJSName(const String& panelName)
+{
+ if (panelName == "elements")
+ return ElementsPanel;
+ else if (panelName == "resources")
+ return ResourcesPanel;
+ else if (panelName == "scripts")
+ return ScriptsPanel;
+ else if (panelName == "profiles")
+ return ProfilesPanel;
+ else if (panelName == "databases")
+ return DatabasesPanel;
+ else
+ return ElementsPanel;
+}
+
} // namespace WebCore
diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h
index e3aa643..05d9652 100644
--- a/WebCore/inspector/InspectorController.h
+++ b/WebCore/inspector/InspectorController.h
@@ -53,13 +53,17 @@ namespace WebCore {
class CachedResource;
class Database;
+class Document;
class DocumentLoader;
class GraphicsContext;
class HitTestResult;
+class InspectorBackend;
class InspectorClient;
+class InspectorDOMAgent;
class InspectorFrontend;
class JavaScriptCallFrame;
class StorageArea;
+class KURL;
class Node;
class Page;
struct ResourceRequest;
@@ -75,9 +79,9 @@ class InspectorDatabaseResource;
class InspectorDOMStorageResource;
class InspectorResource;
-class InspectorController : public RefCounted<InspectorController>
+class InspectorController
#if ENABLE(JAVASCRIPT_DEBUGGER)
- , JavaScriptDebugListener
+ : JavaScriptDebugListener
#endif
{
public:
@@ -112,6 +116,18 @@ public:
m_simpleContent.m_boolean = value;
}
+ explicit Setting(unsigned value)
+ : m_type(IntegerType)
+ {
+ m_simpleContent.m_integer = value;
+ }
+
+ explicit Setting(const String& value)
+ : m_type(StringType)
+ {
+ m_string = value;
+ }
+
Type type() const { return m_type; }
String string() const { ASSERT(m_type == StringType); return m_string; }
@@ -138,14 +154,11 @@ public:
bool m_boolean;
} m_simpleContent;
};
-
- static PassRefPtr<InspectorController> create(Page* page, InspectorClient* inspectorClient)
- {
- return adoptRef(new InspectorController(page, inspectorClient));
- }
-
+ InspectorController(Page*, InspectorClient*);
~InspectorController();
+ InspectorBackend* inspectorBackend() { return m_inspectorBackend.get(); }
+
void inspectedPageDestroyed();
void pageDestroyed() { m_page = 0; }
@@ -156,9 +169,6 @@ public:
const Setting& setting(const String& key) const;
void setSetting(const String& key, const Setting&);
- String localizedStringsURL();
- String hiddenPanels();
-
void inspect(Node*);
void highlight(Node*);
void hideHighlight();
@@ -170,18 +180,14 @@ public:
bool windowVisible();
void setWindowVisible(bool visible = true, bool attached = false);
- void addResourceSourceToFrame(long identifier, Node* frame);
- bool addSourceToFrame(const String& mimeType, const String& source, Node*);
- void addMessageToConsole(MessageSource, MessageLevel, ScriptCallStack*);
- void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
+ void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*);
+ void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
void clearConsoleMessages();
+ const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; }
void attachWindow();
void detachWindow();
- void setAttachedWindow(bool);
- void setAttachedWindowHeight(unsigned height);
-
void toggleSearchForNodeInPage();
bool searchingForNodeInPage() { return m_searchingForNode; };
void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
@@ -190,7 +196,6 @@ public:
void inspectedWindowScriptObjectCleared(Frame*);
void windowScriptObjectAvailable();
- void scriptObjectReady();
void setFrontendProxyObject(ScriptState* state, ScriptObject object);
void populateScriptObjects();
@@ -224,9 +229,6 @@ public:
const ResourcesMap& resources() const { return m_resources; }
- void moveWindowBy(float x, float y) const;
- void closeWindow();
-
void drawNodeHighlight(GraphicsContext&) const;
void count(const String& title, unsigned lineNumber, const String& sourceID);
@@ -237,45 +239,29 @@ public:
void startGroup(MessageSource source, ScriptCallStack* callFrame);
void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL);
- const String& platform() const;
-
#if ENABLE(JAVASCRIPT_DEBUGGER)
void addProfile(PassRefPtr<JSC::Profile>, unsigned lineNumber, const JSC::UString& sourceURL);
- void addProfileMessageToConsole(PassRefPtr<JSC::Profile> prpProfile, unsigned lineNumber, const JSC::UString& sourceURL);
- void addScriptProfile(JSC::Profile* profile);
+ void addProfileFinishedMessageToConsole(PassRefPtr<JSC::Profile>, unsigned lineNumber, const JSC::UString& sourceURL);
+ void addStartProfilingMessageToConsole(const JSC::UString& title, unsigned lineNumber, const JSC::UString& sourceURL);
+ void addScriptProfile(JSC::Profile*);
const ProfilesArray& profiles() const { return m_profiles; }
bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; }
- void startUserInitiatedProfilingSoon();
+ JSC::UString getCurrentUserInitiatedProfileName(bool incrementProfileNumber);
void startUserInitiatedProfiling(Timer<InspectorController>* = 0);
void stopUserInitiatedProfiling();
- void toggleRecordButton(bool);
void enableProfiler(bool always = false, bool skipRecompile = false);
void disableProfiler(bool always = false);
bool profilerEnabled() const { return enabled() && m_profilerEnabled; }
- void enableDebuggerFromFrontend(bool always);
void enableDebugger();
void disableDebugger(bool always = false);
bool debuggerEnabled() const { return m_debuggerEnabled; }
- JavaScriptCallFrame* currentCallFrame() const;
-
- void addBreakpoint(intptr_t sourceID, unsigned lineNumber);
- void removeBreakpoint(intptr_t sourceID, unsigned lineNumber);
-
- bool pauseOnExceptions();
- void setPauseOnExceptions(bool pause);
-
- void pauseInDebugger();
void resumeDebugger();
- void stepOverStatementInDebugger();
- void stepIntoStatementInDebugger();
- void stepOutOfFunctionInDebugger();
-
virtual void didParseSource(JSC::ExecState*, const JSC::SourceCode&);
virtual void failedToParseSource(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMessage);
virtual void didPause();
@@ -283,7 +269,22 @@ public:
#endif
private:
- InspectorController(Page*, InspectorClient*);
+ friend class InspectorBackend;
+
+ // Following are used from InspectorBackend and internally.
+ void scriptObjectReady(bool enableDOMAgent);
+ void moveWindowBy(float x, float y) const;
+ void setAttachedWindow(bool);
+ void setAttachedWindowHeight(unsigned height);
+ void storeLastActivePanel(const String& panelName);
+ void closeWindow();
+ InspectorDOMAgent* domAgent() { return m_domAgent.get(); }
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ void startUserInitiatedProfilingSoon();
+ void toggleRecordButton(bool);
+ void enableDebuggerFromFrontend(bool always);
+#endif
void focusNode();
@@ -291,16 +292,21 @@ private:
void addResource(InspectorResource*);
void removeResource(InspectorResource*);
+ InspectorResource* getTrackedResource(long long identifier);
void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0);
void removeAllResources(ResourcesMap* map) { pruneResources(map); }
void showWindow();
+ bool isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl);
+
+ SpecialPanels specialPanelForJSName(const String& panelName);
Page* m_inspectedPage;
InspectorClient* m_client;
OwnPtr<InspectorFrontend> m_frontend;
+ RefPtr<InspectorDOMAgent> m_domAgent;
Page* m_page;
RefPtr<Node> m_nodeToFocus;
RefPtr<InspectorResource> m_mainResource;
@@ -326,6 +332,7 @@ private:
ConsoleMessage* m_previousMessage;
bool m_resourceTrackingEnabled;
bool m_resourceTrackingSettingsLoaded;
+ RefPtr<InspectorBackend> m_inspectorBackend;
#if ENABLE(JAVASCRIPT_DEBUGGER)
bool m_debuggerEnabled;
bool m_attachDebuggerWhenShown;
diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp
new file mode 100644
index 0000000..f222239
--- /dev/null
+++ b/WebCore/inspector/InspectorDOMAgent.cpp
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 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 "InspectorDOMAgent.h"
+
+#include "AtomicString.h"
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Event.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "EventTarget.h"
+#include "HTMLFrameOwnerElement.h"
+#include "InspectorFrontend.h"
+#include "markup.h"
+#include "MutationEvent.h"
+#include "Node.h"
+#include "NodeList.h"
+#include "PlatformString.h"
+#include "ScriptObject.h"
+#include "Text.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+InspectorDOMAgent::InspectorDOMAgent(InspectorFrontend* frontend)
+ : m_frontend(frontend)
+ , m_lastNodeId(1)
+{
+}
+
+InspectorDOMAgent::~InspectorDOMAgent()
+{
+ setDocument(0);
+}
+
+void InspectorDOMAgent::setDocument(Document* doc)
+{
+ if (doc == mainFrameDocument())
+ return;
+
+ ListHashSet<RefPtr<Document> > copy = m_documents;
+ for (ListHashSet<RefPtr<Document> >::iterator it = copy.begin(); it != copy.end(); ++it)
+ stopListening((*it).get());
+
+ ASSERT(!m_documents.size());
+
+ if (doc) {
+ startListening(doc);
+ if (doc->documentElement()) {
+ pushDocumentElementToFrontend();
+ }
+ } else {
+ discardBindings();
+ }
+}
+
+void InspectorDOMAgent::startListening(Document* doc)
+{
+ if (m_documents.contains(doc))
+ return;
+
+ doc->addEventListener(eventNames().DOMContentLoadedEvent, this, false);
+ doc->addEventListener(eventNames().DOMNodeInsertedEvent, this, false);
+ doc->addEventListener(eventNames().DOMNodeRemovedEvent, this, false);
+ doc->addEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, true);
+ doc->addEventListener(eventNames().DOMAttrModifiedEvent, this, false);
+ m_documents.add(doc);
+}
+
+void InspectorDOMAgent::stopListening(Document* doc)
+{
+ if (!m_documents.contains(doc))
+ return;
+
+ doc->removeEventListener(eventNames().DOMContentLoadedEvent, this, false);
+ doc->removeEventListener(eventNames().DOMNodeInsertedEvent, this, false);
+ doc->removeEventListener(eventNames().DOMNodeRemovedEvent, this, false);
+ doc->removeEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, true);
+ doc->removeEventListener(eventNames().DOMAttrModifiedEvent, this, false);
+ m_documents.remove(doc);
+}
+
+void InspectorDOMAgent::handleEvent(Event* event, bool)
+{
+ AtomicString type = event->type();
+ Node* node = event->target()->toNode();
+
+ // Remove mapping entry if necessary.
+ if (type == eventNames().DOMNodeRemovedFromDocumentEvent) {
+ unbind(node);
+ return;
+ }
+
+ if (type == eventNames().DOMAttrModifiedEvent) {
+ long id = idForNode(node);
+ // If node is not mapped yet -> ignore the event.
+ if (!id)
+ return;
+
+ Element* element = static_cast<Element*>(node);
+ m_frontend->attributesUpdated(id, buildArrayForElementAttributes(element));
+ } else if (type == eventNames().DOMNodeInsertedEvent) {
+ if (isWhitespace(node))
+ return;
+
+ Node* parent = static_cast<MutationEvent*>(event)->relatedNode();
+ long parentId = idForNode(parent);
+ // Return if parent is not mapped yet.
+ if (!parentId)
+ return;
+
+ if (!m_childrenRequested.contains(parentId)) {
+ // No children are mapped yet -> only notify on changes of hasChildren.
+ m_frontend->hasChildrenUpdated(parentId, true);
+ } else {
+ // Children have been requested -> return value of a new child.
+ long prevId = idForNode(innerPreviousSibling(node));
+
+ ScriptObject value = buildObjectForNode(node, 0);
+ m_frontend->childNodeInserted(parentId, prevId, value);
+ }
+ } else if (type == eventNames().DOMNodeRemovedEvent) {
+ if (isWhitespace(node))
+ return;
+
+ Node* parent = static_cast<MutationEvent*>(event)->relatedNode();
+ long parentId = idForNode(parent);
+ // If parent is not mapped yet -> ignore the event.
+ if (!parentId)
+ return;
+
+ if (!m_childrenRequested.contains(parentId)) {
+ // No children are mapped yet -> only notify on changes of hasChildren.
+ if (innerChildNodeCount(parent) == 1)
+ m_frontend->hasChildrenUpdated(parentId, false);
+ } else {
+ m_frontend->childNodeRemoved(parentId, idForNode(node));
+ }
+ } else if (type == eventNames().DOMContentLoadedEvent) {
+ // Re-push document once it is loaded.
+ discardBindings();
+ pushDocumentElementToFrontend();
+ }
+}
+
+long InspectorDOMAgent::bind(Node* node)
+{
+ HashMap<Node*, long>::iterator it = m_nodeToId.find(node);
+ if (it != m_nodeToId.end())
+ return it->second;
+ long id = m_lastNodeId++;
+ m_nodeToId.set(node, id);
+ m_idToNode.set(id, node);
+ return id;
+}
+
+void InspectorDOMAgent::unbind(Node* node)
+{
+ if (node->isFrameOwnerElement()) {
+ const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
+ stopListening(frameOwner->contentDocument());
+ }
+
+ HashMap<Node*, long>::iterator it = m_nodeToId.find(node);
+ if (it != m_nodeToId.end()) {
+ m_idToNode.remove(m_idToNode.find(it->second));
+ m_childrenRequested.remove(m_childrenRequested.find(it->second));
+ m_nodeToId.remove(it);
+ }
+}
+
+void InspectorDOMAgent::pushDocumentElementToFrontend()
+{
+ Element* docElem = mainFrameDocument()->documentElement();
+ if (!m_nodeToId.contains(docElem))
+ m_frontend->setDocumentElement(buildObjectForNode(docElem, 0));
+}
+
+void InspectorDOMAgent::pushChildNodesToFrontend(long elementId)
+{
+ Node* node = nodeForId(elementId);
+ if (!node || (node->nodeType() != Node::ELEMENT_NODE))
+ return;
+ if (m_childrenRequested.contains(elementId))
+ return;
+
+ Element* element = static_cast<Element*>(node);
+ ScriptArray children = buildArrayForElementChildren(element, 1);
+ m_childrenRequested.add(elementId);
+ m_frontend->setChildNodes(elementId, children);
+}
+
+void InspectorDOMAgent::discardBindings()
+{
+ m_nodeToId.clear();
+ m_idToNode.clear();
+ m_childrenRequested.clear();
+}
+
+Node* InspectorDOMAgent::nodeForId(long id)
+{
+ HashMap<long, Node*>::iterator it = m_idToNode.find(id);
+ if (it != m_idToNode.end())
+ return it->second;
+ return 0;
+}
+
+long InspectorDOMAgent::idForNode(Node* node)
+{
+ if (!node)
+ return 0;
+ HashMap<Node*, long>::iterator it = m_nodeToId.find(node);
+ if (it != m_nodeToId.end())
+ return it->second;
+ return 0;
+}
+
+void InspectorDOMAgent::getChildNodes(long callId, long elementId)
+{
+ pushChildNodesToFrontend(elementId);
+ m_frontend->didGetChildNodes(callId);
+}
+
+long InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
+{
+ ASSERT(nodeToPush); // Invalid input
+
+ // If we are sending information to the client that is currently being created. Send root node first.
+ pushDocumentElementToFrontend();
+
+ // Return id in case the node is known.
+ long result = idForNode(nodeToPush);
+ if (result)
+ return result;
+
+ Element* element = innerParentElement(nodeToPush);
+ ASSERT(element); // Node is detached or is a document itself
+
+ Vector<Element*> path;
+ while (element && !idForNode(element)) {
+ path.append(element);
+ element = innerParentElement(element);
+ }
+
+ // element is known to the client
+ ASSERT(element);
+ path.append(element);
+ for (int i = path.size() - 1; i >= 0; --i) {
+ long nodeId = idForNode(path.at(i));
+ ASSERT(nodeId);
+ pushChildNodesToFrontend(nodeId);
+ }
+ return idForNode(nodeToPush);
+}
+
+void InspectorDOMAgent::setAttribute(long callId, long elementId, const String& name, const String& value)
+{
+ Node* node = nodeForId(elementId);
+ if (node && (node->nodeType() == Node::ELEMENT_NODE)) {
+ Element* element = static_cast<Element*>(node);
+ ExceptionCode ec = 0;
+ element->setAttribute(name, value, ec);
+ m_frontend->didApplyDomChange(callId, ec == 0);
+ } else {
+ m_frontend->didApplyDomChange(callId, false);
+ }
+}
+
+void InspectorDOMAgent::removeAttribute(long callId, long elementId, const String& name)
+{
+ Node* node = nodeForId(elementId);
+ if (node && (node->nodeType() == Node::ELEMENT_NODE)) {
+ Element* element = static_cast<Element*>(node);
+ ExceptionCode ec = 0;
+ element->removeAttribute(name, ec);
+ m_frontend->didApplyDomChange(callId, ec == 0);
+ } else {
+ m_frontend->didApplyDomChange(callId, false);
+ }
+}
+
+void InspectorDOMAgent::setTextNodeValue(long callId, long elementId, const String& value)
+{
+ Node* node = nodeForId(elementId);
+ if (node && (node->nodeType() == Node::TEXT_NODE)) {
+ Text* text_node = static_cast<Text*>(node);
+ ExceptionCode ec = 0;
+ text_node->replaceWholeText(value, ec);
+ m_frontend->didApplyDomChange(callId, ec == 0);
+ } else {
+ m_frontend->didApplyDomChange(callId, false);
+ }
+}
+
+ScriptObject InspectorDOMAgent::buildObjectForNode(Node* node, int depth)
+{
+ ScriptObject value = m_frontend->newScriptObject();
+
+ long id = bind(node);
+ String nodeName;
+ String nodeValue;
+
+ switch (node->nodeType()) {
+ case Node::TEXT_NODE:
+ case Node::COMMENT_NODE:
+ nodeValue = node->nodeValue();
+ break;
+ case Node::ATTRIBUTE_NODE:
+ case Node::DOCUMENT_NODE:
+ case Node::DOCUMENT_FRAGMENT_NODE:
+ break;
+ case Node::ELEMENT_NODE:
+ default:
+ nodeName = node->nodeName();
+ break;
+ }
+
+ value.set("id", static_cast<int>(id));
+ value.set("nodeType", node->nodeType());
+ value.set("nodeName", nodeName);
+ value.set("nodeValue", nodeValue);
+
+ if (node->nodeType() == Node::ELEMENT_NODE) {
+ Element* element = static_cast<Element*>(node);
+ value.set("attributes", buildArrayForElementAttributes(element));
+ int nodeCount = innerChildNodeCount(element);
+ value.set("childNodeCount", nodeCount);
+
+ ScriptArray children = buildArrayForElementChildren(element, depth);
+ if (children.length() > 0)
+ value.set("children", children);
+ }
+ return value;
+}
+
+ScriptArray InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
+{
+ ScriptArray attributesValue = m_frontend->newScriptArray();
+ // Go through all attributes and serialize them.
+ const NamedNodeMap* attrMap = element->attributes(true);
+ if (!attrMap)
+ return attributesValue;
+ unsigned numAttrs = attrMap->length();
+ int index = 0;
+ for (unsigned i = 0; i < numAttrs; ++i) {
+ // Add attribute pair
+ const Attribute *attribute = attrMap->attributeItem(i);
+ attributesValue.set(index++, attribute->name().toString());
+ attributesValue.set(index++, attribute->value());
+ }
+ return attributesValue;
+}
+
+ScriptArray InspectorDOMAgent::buildArrayForElementChildren(Element* element, int depth)
+{
+ ScriptArray children = m_frontend->newScriptArray();
+ if (depth == 0) {
+ int index = 0;
+ // Special case the_only text child.
+ if (innerChildNodeCount(element) == 1) {
+ Node *child = innerFirstChild(element);
+ if (child->nodeType() == Node::TEXT_NODE)
+ children.set(index++, buildObjectForNode(child, 0));
+ }
+ return children;
+ } else if (depth > 0) {
+ depth--;
+ }
+
+ int index = 0;
+ for (Node *child = innerFirstChild(element); child; child = innerNextSibling(child))
+ children.set(index++, buildObjectForNode(child, depth));
+ return children;
+}
+
+Node* InspectorDOMAgent::innerFirstChild(Node* node)
+{
+ if (node->isFrameOwnerElement()) {
+ HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
+ Document* doc = frameOwner->contentDocument();
+ if (doc) {
+ startListening(doc);
+ return doc->firstChild();
+ }
+ }
+ node = node->firstChild();
+ while (isWhitespace(node))
+ node = node->nextSibling();
+ return node;
+}
+
+Node* InspectorDOMAgent::innerNextSibling(Node* node)
+{
+ do {
+ node = node->nextSibling();
+ } while (isWhitespace(node));
+ return node;
+}
+
+Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
+{
+ do {
+ node = node->previousSibling();
+ } while (isWhitespace(node));
+ return node;
+}
+
+int InspectorDOMAgent::innerChildNodeCount(Node* node)
+{
+ int count = 0;
+ Node* child = innerFirstChild(node);
+ while (child) {
+ count++;
+ child = innerNextSibling(child);
+ }
+ return count;
+}
+
+Element* InspectorDOMAgent::innerParentElement(Node* node)
+{
+ Element* element = node->parentElement();
+ if (!element)
+ return node->ownerDocument()->ownerElement();
+ return element;
+}
+
+bool InspectorDOMAgent::isWhitespace(Node* node)
+{
+ //TODO: pull ignoreWhitespace setting from the frontend and use here.
+ return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
+}
+
+Document* InspectorDOMAgent::mainFrameDocument()
+{
+ ListHashSet<RefPtr<Document> >::iterator it = m_documents.begin();
+ if (it != m_documents.end())
+ return it->get();
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/inspector/InspectorDOMAgent.h b/WebCore/inspector/InspectorDOMAgent.h
new file mode 100644
index 0000000..28c3a22
--- /dev/null
+++ b/WebCore/inspector/InspectorDOMAgent.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef InspectorDOMAgent_h
+#define InspectorDOMAgent_h
+
+#include "EventListener.h"
+#include "ScriptArray.h"
+#include "ScriptObject.h"
+#include "ScriptState.h"
+
+#include <wtf/ListHashSet.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+ class Element;
+ class Event;
+ class Document;
+ class InspectorFrontend;
+ class NameNodeMap;
+ class Node;
+ class Page;
+
+ class InspectorDOMAgent : public EventListener {
+ public:
+ InspectorDOMAgent(InspectorFrontend* frontend);
+ ~InspectorDOMAgent();
+
+ // Methods called from the frontend.
+ void getChildNodes(long callId, long elementId);
+ void setAttribute(long callId, long elementId, const String& name, const String& value);
+ void removeAttribute(long callId, long elementId, const String& name);
+ void setTextNodeValue(long callId, long elementId, const String& value);
+
+ // Methods called from the InspectorController.
+ void setDocument(Document* document);
+
+ Node* nodeForId(long nodeId);
+ long idForNode(Node* node);
+ long pushNodePathToFrontend(Node* node);
+
+ private:
+ void startListening(Document* document);
+ void stopListening(Document* document);
+
+ virtual void handleEvent(Event* event, bool isWindowEvent);
+
+ long bind(Node* node);
+ void unbind(Node* node);
+
+ void pushDocumentElementToFrontend();
+ void pushChildNodesToFrontend(long elementId);
+
+ ScriptObject buildObjectForNode(Node* node, int depth);
+ ScriptArray buildArrayForElementAttributes(Element* elemen);
+ ScriptArray buildArrayForElementChildren(Element* element, int depth);
+
+ // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
+ // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
+ Node* innerFirstChild(Node* node);
+ Node* innerNextSibling(Node* node);
+ Node* innerPreviousSibling(Node* node);
+ int innerChildNodeCount(Node* node);
+ Element* innerParentElement(Node* node);
+ bool isWhitespace(Node* node);
+
+ Document* mainFrameDocument();
+ void discardBindings();
+
+ InspectorFrontend* m_frontend;
+ HashMap<Node*, long> m_nodeToId;
+ HashMap<long, Node*> m_idToNode;
+ HashSet<long> m_childrenRequested;
+ long m_lastNodeId;
+ ListHashSet<RefPtr<Document> > m_documents;
+ RefPtr<EventListener> m_eventListener;
+ };
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorDOMAgent_h)
diff --git a/WebCore/inspector/InspectorDOMStorageResource.cpp b/WebCore/inspector/InspectorDOMStorageResource.cpp
index 1f3522e..03db649 100644
--- a/WebCore/inspector/InspectorDOMStorageResource.cpp
+++ b/WebCore/inspector/InspectorDOMStorageResource.cpp
@@ -36,7 +36,7 @@
#include "Document.h"
#include "Frame.h"
#include "InspectorFrontend.h"
-#include "JSONObject.h"
+#include "ScriptObject.h"
#include "ScriptObjectQuarantine.h"
#include "Storage.h"
@@ -62,7 +62,7 @@ void InspectorDOMStorageResource::bind(InspectorFrontend* frontend)
if (m_scriptObjectCreated)
return;
- JSONObject jsonObject = frontend->newJSONObject();
+ ScriptObject jsonObject = frontend->newScriptObject();
ScriptObject domStorage;
if (!getQuarantinedScriptObject(m_frame.get(), m_domStorage.get(), domStorage))
return;
diff --git a/WebCore/inspector/InspectorDatabaseResource.cpp b/WebCore/inspector/InspectorDatabaseResource.cpp
index b61344c..fba50a5 100644
--- a/WebCore/inspector/InspectorDatabaseResource.cpp
+++ b/WebCore/inspector/InspectorDatabaseResource.cpp
@@ -36,7 +36,7 @@
#include "Document.h"
#include "Frame.h"
#include "InspectorFrontend.h"
-#include "JSONObject.h"
+#include "ScriptObject.h"
#include "ScriptObjectQuarantine.h"
@@ -56,7 +56,7 @@ void InspectorDatabaseResource::bind(InspectorFrontend* frontend)
if (m_scriptObjectCreated)
return;
- JSONObject jsonObject = frontend->newJSONObject();
+ ScriptObject jsonObject = frontend->newScriptObject();
ScriptObject database;
if (!getQuarantinedScriptObject(m_database.get(), database))
return;
diff --git a/WebCore/inspector/InspectorFrontend.cpp b/WebCore/inspector/InspectorFrontend.cpp
index aacbb90..af65fb4 100644
--- a/WebCore/inspector/InspectorFrontend.cpp
+++ b/WebCore/inspector/InspectorFrontend.cpp
@@ -33,7 +33,6 @@
#include "ConsoleMessage.h"
#include "Frame.h"
#include "InspectorController.h" // TODO(pfeldman): Extract SpecialPanels to remove include.
-#include "JSONObject.h"
#include "Node.h"
#include "ScriptFunctionCall.h"
#include "ScriptObject.h"
@@ -61,14 +60,20 @@ InspectorFrontend::~InspectorFrontend()
m_webInspector = ScriptObject();
}
-JSONObject InspectorFrontend::newJSONObject() {
- return JSONObject::createNew(m_scriptState);
+ScriptArray InspectorFrontend::newScriptArray()
+{
+ return ScriptArray::createNew(m_scriptState);
}
-void InspectorFrontend::addMessageToConsole(const JSONObject& messageObj, const Vector<ScriptString>& frames, const Vector<ScriptValue> wrappedArguments, const String& message)
+ScriptObject InspectorFrontend::newScriptObject()
+{
+ return ScriptObject::createNew(m_scriptState);
+}
+
+void InspectorFrontend::addMessageToConsole(const ScriptObject& messageObj, const Vector<ScriptString>& frames, const Vector<ScriptValue> wrappedArguments, const String& message)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("addMessageToConsole"));
- function->appendArgument(messageObj.scriptObject());
+ function->appendArgument(messageObj);
if (!frames.isEmpty()) {
for (unsigned i = 0; i < frames.size(); ++i)
function->appendArgument(frames[i]);
@@ -80,21 +85,21 @@ void InspectorFrontend::addMessageToConsole(const JSONObject& messageObj, const
function->call();
}
-bool InspectorFrontend::addResource(long long identifier, const JSONObject& resourceObj)
+bool InspectorFrontend::addResource(long long identifier, const ScriptObject& resourceObj)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("addResource"));
function->appendArgument(identifier);
- function->appendArgument(resourceObj.scriptObject());
+ function->appendArgument(resourceObj);
bool hadException = false;
function->call(hadException);
return !hadException;
}
-bool InspectorFrontend::updateResource(long long identifier, const JSONObject& resourceObj)
+bool InspectorFrontend::updateResource(long long identifier, const ScriptObject& resourceObj)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("updateResource"));
function->appendArgument(identifier);
- function->appendArgument(resourceObj.scriptObject());
+ function->appendArgument(resourceObj);
bool hadException = false;
function->call(hadException);
return !hadException;
@@ -216,7 +221,7 @@ void InspectorFrontend::profilerWasDisabled()
void InspectorFrontend::parsedScriptSource(const JSC::SourceCode& source)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("parsedScriptSource"));
- function->appendArgument(static_cast<long long>(source.provider()->asID()));
+ function->appendArgument(JSC::UString(JSC::UString::from(source.provider()->asID())));
function->appendArgument(source.provider()->url());
function->appendArgument(JSC::UString(source.data(), source.length()));
function->appendArgument(source.firstLine());
@@ -260,10 +265,10 @@ void InspectorFrontend::resumedScript()
#endif
#if ENABLE(DATABASE)
-bool InspectorFrontend::addDatabase(const JSONObject& dbObject)
+bool InspectorFrontend::addDatabase(const ScriptObject& dbObject)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("addDatabase"));
- function->appendArgument(dbObject.scriptObject());
+ function->appendArgument(dbObject);
bool hadException = false;
function->call(hadException);
return !hadException;
@@ -271,16 +276,79 @@ bool InspectorFrontend::addDatabase(const JSONObject& dbObject)
#endif
#if ENABLE(DOM_STORAGE)
-bool InspectorFrontend::addDOMStorage(const JSONObject& domStorageObj)
+bool InspectorFrontend::addDOMStorage(const ScriptObject& domStorageObj)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("addDOMStorage"));
- function->appendArgument(domStorageObj.scriptObject());
+ function->appendArgument(domStorageObj);
bool hadException = false;
function->call(hadException);
return !hadException;
}
#endif
+void InspectorFrontend::setDocumentElement(const ScriptObject& root)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("setDocumentElement"));
+ function->appendArgument(root);
+ function->call();
+}
+
+void InspectorFrontend::setChildNodes(int parentId, const ScriptArray& nodes)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("setChildNodes"));
+ function->appendArgument(parentId);
+ function->appendArgument(nodes);
+ function->call();
+}
+
+void InspectorFrontend::hasChildrenUpdated(int id, bool newValue)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("hasChildrenUpdated"));
+ function->appendArgument(id);
+ function->appendArgument(newValue);
+ function->call();
+}
+
+void InspectorFrontend::childNodeInserted(int parentId, int prevId, const ScriptObject& node)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("childNodeInserted"));
+ function->appendArgument(parentId);
+ function->appendArgument(prevId);
+ function->appendArgument(node);
+ function->call();
+}
+
+void InspectorFrontend::childNodeRemoved(int parentId, int id)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("childNodeRemoved"));
+ function->appendArgument(parentId);
+ function->appendArgument(id);
+ function->call();
+}
+
+void InspectorFrontend::attributesUpdated(int id, const ScriptArray& attributes)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("attributesUpdated"));
+ function->appendArgument(id);
+ function->appendArgument(attributes);
+ function->call();
+}
+
+void InspectorFrontend::didGetChildNodes(int callId)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("didGetChildNodes"));
+ function->appendArgument(callId);
+ function->call();
+}
+
+void InspectorFrontend::didApplyDomChange(int callId, bool success)
+{
+ OwnPtr<ScriptFunctionCall> function(newFunctionCall("didApplyDomChange"));
+ function->appendArgument(callId);
+ function->appendArgument(success);
+ function->call();
+}
+
PassOwnPtr<ScriptFunctionCall> InspectorFrontend::newFunctionCall(const String& functionName)
{
ScriptFunctionCall* function = new ScriptFunctionCall(m_scriptState, m_webInspector, "dispatch");
diff --git a/WebCore/inspector/InspectorFrontend.h b/WebCore/inspector/InspectorFrontend.h
index d596b3f..7a48b62 100644
--- a/WebCore/inspector/InspectorFrontend.h
+++ b/WebCore/inspector/InspectorFrontend.h
@@ -30,7 +30,8 @@
#ifndef InspectorFrontend_h
#define InspectorFrontend_h
-#include "JSONObject.h"
+#include "ScriptArray.h"
+#include "ScriptObject.h"
#include "ScriptState.h"
#include <wtf/PassOwnPtr.h>
@@ -53,12 +54,14 @@ namespace WebCore {
public:
InspectorFrontend(ScriptState*, ScriptObject webInspector);
~InspectorFrontend();
- JSONObject newJSONObject();
- void addMessageToConsole(const JSONObject& messageObj, const Vector<ScriptString>& frames, const Vector<ScriptValue> wrappedArguments, const String& message);
+ ScriptArray newScriptArray();
+ ScriptObject newScriptObject();
+
+ void addMessageToConsole(const ScriptObject& messageObj, const Vector<ScriptString>& frames, const Vector<ScriptValue> wrappedArguments, const String& message);
- bool addResource(long long identifier, const JSONObject& resourceObj);
- bool updateResource(long long identifier, const JSONObject& resourceObj);
+ bool addResource(long long identifier, const ScriptObject& resourceObj);
+ bool updateResource(long long identifier, const ScriptObject& resourceObj);
void removeResource(long long identifier);
void updateFocusedNode(Node* node);
@@ -86,13 +89,22 @@ namespace WebCore {
#endif
#if ENABLE(DATABASE)
- bool addDatabase(const JSONObject& dbObj);
+ bool addDatabase(const ScriptObject& dbObj);
#endif
#if ENABLE(DOM_STORAGE)
- bool addDOMStorage(const JSONObject& domStorageObj);
+ bool addDOMStorage(const ScriptObject& domStorageObj);
#endif
+ void setDocumentElement(const ScriptObject& root);
+ void setChildNodes(int parentId, const ScriptArray& nodes);
+ void hasChildrenUpdated(int id, bool newValue);
+ void childNodeInserted(int parentId, int prevId, const ScriptObject& node);
+ void childNodeRemoved(int parentId, int id);
+ void attributesUpdated(int id, const ScriptArray& attributes);
+ void didGetChildNodes(int callId);
+ void didApplyDomChange(int callId, bool success);
+
private:
PassOwnPtr<ScriptFunctionCall> newFunctionCall(const String& functionName);
void callSimpleFunction(const String& functionName);
diff --git a/WebCore/inspector/InspectorResource.cpp b/WebCore/inspector/InspectorResource.cpp
index 6184119..8e6e9b1 100644
--- a/WebCore/inspector/InspectorResource.cpp
+++ b/WebCore/inspector/InspectorResource.cpp
@@ -36,10 +36,10 @@
#include "DocumentLoader.h"
#include "Frame.h"
#include "InspectorFrontend.h"
-#include "JSONObject.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "TextEncoding.h"
+#include "ScriptObject.h"
namespace WebCore {
@@ -105,7 +105,7 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
m_changes.set(TypeChange);
}
-static void populateHeadersObject(JSONObject* object, const HTTPHeaderMap& headers)
+static void populateHeadersObject(ScriptObject* object, const HTTPHeaderMap& headers)
{
HTTPHeaderMap::const_iterator end = headers.end();
for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) {
@@ -116,8 +116,8 @@ static void populateHeadersObject(JSONObject* object, const HTTPHeaderMap& heade
void InspectorResource::createScriptObject(InspectorFrontend* frontend)
{
if (!m_scriptObjectCreated) {
- JSONObject jsonObject = frontend->newJSONObject();
- JSONObject requestHeaders = frontend->newJSONObject();
+ ScriptObject jsonObject = frontend->newScriptObject();
+ ScriptObject requestHeaders = frontend->newScriptObject();
populateHeadersObject(&requestHeaders, m_requestHeaderFields);
jsonObject.set("requestHeaders", requestHeaders);
jsonObject.set("requestURL", requestURL());
@@ -143,13 +143,13 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
if (m_changes.hasChange(NoChange))
return;
- JSONObject jsonObject = frontend->newJSONObject();
+ ScriptObject jsonObject = frontend->newScriptObject();
if (m_changes.hasChange(RequestChange)) {
jsonObject.set("url", requestURL());
jsonObject.set("domain", m_requestURL.host());
jsonObject.set("path", m_requestURL.path());
jsonObject.set("lastPathComponent", m_requestURL.lastPathComponent());
- JSONObject requestHeaders = frontend->newJSONObject();
+ ScriptObject requestHeaders = frontend->newScriptObject();
populateHeadersObject(&requestHeaders, m_requestHeaderFields);
jsonObject.set("requestHeaders", requestHeaders);
jsonObject.set("mainResource", m_isMainResource);
@@ -162,7 +162,7 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
jsonObject.set("expectedContentLength", m_expectedContentLength);
jsonObject.set("statusCode", m_responseStatusCode);
jsonObject.set("suggestedFilename", m_suggestedFilename);
- JSONObject responseHeaders = frontend->newJSONObject();
+ ScriptObject responseHeaders = frontend->newScriptObject();
populateHeadersObject(&responseHeaders, m_responseHeaderFields);
jsonObject.set("responseHeaders", responseHeaders);
jsonObject.set("didResponseChange", true);
diff --git a/WebCore/inspector/JSONObject.cpp b/WebCore/inspector/JSONObject.cpp
deleted file mode 100644
index b13ddee..0000000
--- a/WebCore/inspector/JSONObject.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 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 "JSONObject.h"
-
-#include "PlatformString.h"
-#include "ScriptObject.h"
-#include "ScriptState.h"
-
-namespace WebCore {
-
-JSONObject::JSONObject(ScriptState* scriptState)
- : m_scriptState(scriptState)
-{
- m_scriptObject = ScriptObject::createNew(scriptState);
-}
-
-bool JSONObject::set(const String& name, const String& value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, const ScriptObject& value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, const JSONObject& value)
-{
- return set(name, value.scriptObject());
-}
-
-bool JSONObject::set(const char* name, const String& value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, double value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, long long value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, int value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-bool JSONObject::set(const char* name, bool value)
-{
- return m_scriptObject.set(m_scriptState, name, value);
-}
-
-ScriptObject JSONObject::scriptObject() const
-{
- return m_scriptObject;
-}
-
-JSONObject JSONObject::createNew(ScriptState* scriptState)
-{
- return JSONObject(scriptState);
-}
-
-} // namespace WebCore
diff --git a/WebCore/inspector/JSONObject.h b/WebCore/inspector/JSONObject.h
deleted file mode 100644
index 39e64f0..0000000
--- a/WebCore/inspector/JSONObject.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 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.
- */
-
-
-#ifndef JSONObject_h
-#define JSONObject_h
-
-#include "ScriptObject.h"
-#include "ScriptState.h"
-
-namespace WebCore {
- class String;
-
- class JSONObject {
- public:
- bool set(const String& name, const String&);
- bool set(const char* name, const JSONObject&);
- bool set(const char* name, const ScriptObject&);
- bool set(const char* name, const String&);
- bool set(const char* name, double);
- bool set(const char* name, long long);
- bool set(const char* name, int);
- bool set(const char* name, bool);
- ScriptObject scriptObject() const;
-
- static JSONObject createNew(ScriptState* scriptState);
- private:
- JSONObject(ScriptState* scriptState);
- ScriptState* m_scriptState;
- ScriptObject m_scriptObject;
- };
-}
-
-#endif // JSONObject_h
diff --git a/WebCore/inspector/JavaScriptCallFrame.cpp b/WebCore/inspector/JavaScriptCallFrame.cpp
index 6e8fce9..9225a03 100644
--- a/WebCore/inspector/JavaScriptCallFrame.cpp
+++ b/WebCore/inspector/JavaScriptCallFrame.cpp
@@ -62,6 +62,14 @@ const JSC::ScopeChainNode* JavaScriptCallFrame::scopeChain() const
return m_debuggerCallFrame.scopeChain();
}
+JSC::JSGlobalObject* JavaScriptCallFrame::dynamicGlobalObject() const
+{
+ ASSERT(m_isValid);
+ if (!m_isValid)
+ return 0;
+ return m_debuggerCallFrame.dynamicGlobalObject();
+}
+
String JavaScriptCallFrame::functionName() const
{
ASSERT(m_isValid);
@@ -96,7 +104,7 @@ JSValue JavaScriptCallFrame::evaluate(const UString& script, JSValue& exception)
if (!m_isValid)
return jsNull();
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
return m_debuggerCallFrame.evaluate(script, exception);
}
diff --git a/WebCore/inspector/JavaScriptCallFrame.h b/WebCore/inspector/JavaScriptCallFrame.h
index 9f193d8..e86b0eb 100644
--- a/WebCore/inspector/JavaScriptCallFrame.h
+++ b/WebCore/inspector/JavaScriptCallFrame.h
@@ -61,6 +61,7 @@ namespace WebCore {
String functionName() const;
JSC::DebuggerCallFrame::Type type() const;
const JSC::ScopeChainNode* scopeChain() const;
+ JSC::JSGlobalObject* dynamicGlobalObject() const;
JSC::JSObject* thisObject() const;
JSC::JSValue evaluate(const JSC::UString& script, JSC::JSValue& exception) const;
diff --git a/WebCore/inspector/JavaScriptDebugServer.cpp b/WebCore/inspector/JavaScriptDebugServer.cpp
index bb6358c..10eff26 100644
--- a/WebCore/inspector/JavaScriptDebugServer.cpp
+++ b/WebCore/inspector/JavaScriptDebugServer.cpp
@@ -275,6 +275,19 @@ static Page* toPage(JSGlobalObject* globalObject)
return frame ? frame->page() : 0;
}
+void JavaScriptDebugServer::detach(JSGlobalObject* globalObject)
+{
+ // If we're detaching from the currently executing global object, manually tear down our
+ // stack, since we won't get further debugger callbacks to do so. Also, resume execution,
+ // since there's no point in staying paused once a window closes.
+ if (m_currentCallFrame && m_currentCallFrame->dynamicGlobalObject() == globalObject) {
+ m_currentCallFrame = 0;
+ m_pauseOnCallFrame = 0;
+ continueProgram();
+ }
+ Debugger::detach(globalObject);
+}
+
void JavaScriptDebugServer::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMessage)
{
if (m_callingListeners)
@@ -387,12 +400,12 @@ void JavaScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused)
if (!view)
return;
- const HashSet<Widget*>* children = view->children();
+ const HashSet<RefPtr<Widget> >* children = view->children();
ASSERT(children);
- HashSet<Widget*>::const_iterator end = children->end();
- for (HashSet<Widget*>::const_iterator it = children->begin(); it != end; ++it) {
- Widget* widget = *it;
+ HashSet<RefPtr<Widget> >::const_iterator end = children->end();
+ for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
+ Widget* widget = (*it).get();
if (!widget->isPluginView())
continue;
static_cast<PluginView*>(widget)->setJavaScriptPaused(paused);
@@ -541,7 +554,7 @@ void JavaScriptDebugServer::recompileAllJSFunctionsSoon()
void JavaScriptDebugServer::recompileAllJSFunctions(Timer<JavaScriptDebugServer>*)
{
- JSLock lock(false);
+ JSLock lock(SilenceAssertionsOnly);
JSGlobalData* globalData = JSDOMWindow::commonJSGlobalData();
// If JavaScript is running, it's not safe to recompile, since we'll end
diff --git a/WebCore/inspector/JavaScriptDebugServer.h b/WebCore/inspector/JavaScriptDebugServer.h
index 4ec3e33..baa6699 100644
--- a/WebCore/inspector/JavaScriptDebugServer.h
+++ b/WebCore/inspector/JavaScriptDebugServer.h
@@ -39,6 +39,7 @@
namespace JSC {
class DebuggerCallFrame;
+ class JSGlobalObject;
}
namespace WebCore {
@@ -99,6 +100,8 @@ namespace WebCore {
void dispatchFunctionToListeners(JavaScriptExecutionCallback, Page*);
void pauseIfNeeded(Page*);
+
+ virtual void detach(JSC::JSGlobalObject*);
virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMsg);
virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber);
diff --git a/WebCore/inspector/JavaScriptProfileNode.cpp b/WebCore/inspector/JavaScriptProfileNode.cpp
index 5b5c340..3c3e279 100644
--- a/WebCore/inspector/JavaScriptProfileNode.cpp
+++ b/WebCore/inspector/JavaScriptProfileNode.cpp
@@ -84,7 +84,7 @@ static JSValueRef getLineNumber(JSContextRef ctx, JSObjectRef thisObject, JSStri
static JSValueRef getTotalTime(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -95,7 +95,7 @@ static JSValueRef getTotalTime(JSContextRef ctx, JSObjectRef thisObject, JSStrin
static JSValueRef getSelfTime(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -106,7 +106,7 @@ static JSValueRef getSelfTime(JSContextRef ctx, JSObjectRef thisObject, JSString
static JSValueRef getTotalPercent(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -117,7 +117,7 @@ static JSValueRef getTotalPercent(JSContextRef ctx, JSObjectRef thisObject, JSSt
static JSValueRef getSelfPercent(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -128,7 +128,7 @@ static JSValueRef getSelfPercent(JSContextRef ctx, JSObjectRef thisObject, JSStr
static JSValueRef getNumberOfCalls(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -139,7 +139,7 @@ static JSValueRef getNumberOfCalls(JSContextRef ctx, JSObjectRef thisObject, JSS
static JSValueRef getChildren(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef* exception)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -186,7 +186,7 @@ static JSValueRef getChildren(JSContextRef ctx, JSObjectRef thisObject, JSString
static JSValueRef getParent(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -198,7 +198,7 @@ static JSValueRef getParent(JSContextRef ctx, JSObjectRef thisObject, JSStringRe
static JSValueRef getHead(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -210,7 +210,7 @@ static JSValueRef getHead(JSContextRef ctx, JSObjectRef thisObject, JSStringRef,
static JSValueRef getVisible(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
@@ -221,7 +221,7 @@ static JSValueRef getVisible(JSContextRef ctx, JSObjectRef thisObject, JSStringR
static JSValueRef getCallUID(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- JSC::JSLock lock(false);
+ JSC::JSLock lock(SilenceAssertionsOnly);
if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
return JSValueMakeUndefined(ctx);
diff --git a/WebCore/inspector/front-end/Breakpoint.js b/WebCore/inspector/front-end/Breakpoint.js
index 8611cf5..347df60 100644
--- a/WebCore/inspector/front-end/Breakpoint.js
+++ b/WebCore/inspector/front-end/Breakpoint.js
@@ -29,6 +29,7 @@ WebInspector.Breakpoint = function(url, line, sourceID)
this.line = line;
this.sourceID = sourceID;
this._enabled = true;
+ this._sourceText = "";
}
WebInspector.Breakpoint.prototype = {
@@ -48,6 +49,28 @@ WebInspector.Breakpoint.prototype = {
this.dispatchEventToListeners("enabled");
else
this.dispatchEventToListeners("disabled");
+ },
+
+ get sourceText()
+ {
+ return this._sourceText;
+ },
+
+ set sourceText(text)
+ {
+ this._sourceText = text;
+ this.dispatchEventToListeners("text-changed");
+ },
+
+ get label()
+ {
+ var displayName = (this.url ? WebInspector.displayNameForURL(this.url) : WebInspector.UIString("(program)"));
+ return displayName + ":" + this.line;
+ },
+
+ get id()
+ {
+ return this.sourceID + ":" + this.line;
}
}
diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 2b8f3cd..14f8c06 100644
--- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -27,7 +27,10 @@ WebInspector.BreakpointsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
- this.breakpoints = [];
+ this.breakpoints = {};
+
+ this.listElement = document.createElement("ol");
+ this.listElement.className = "breakpoint-list";
this.emptyElement = document.createElement("div");
this.emptyElement.className = "info";
@@ -39,11 +42,21 @@ WebInspector.BreakpointsSidebarPane = function()
WebInspector.BreakpointsSidebarPane.prototype = {
addBreakpoint: function(breakpoint)
{
- this.breakpoints.push(breakpoint);
+ if (this.breakpoints[breakpoint.id])
+ return;
+
+ this.breakpoints[breakpoint.id] = breakpoint;
+
breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
+ breakpoint.addEventListener("text-changed", this._breakpointTextChanged, this);
- // FIXME: add to the breakpoints UI.
+ this._appendBreakpointElement(breakpoint);
+
+ if (this.emptyElement.parentElement) {
+ this.bodyElement.removeChild(this.emptyElement);
+ this.bodyElement.appendChild(this.listElement);
+ }
if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
return;
@@ -52,13 +65,73 @@ WebInspector.BreakpointsSidebarPane.prototype = {
InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
},
+ _appendBreakpointElement: function(breakpoint)
+ {
+ function checkboxClicked()
+ {
+ breakpoint.enabled = !breakpoint.enabled;
+ }
+
+ function labelClicked()
+ {
+ var script = WebInspector.panels.scripts.scriptOrResourceForID(breakpoint.sourceID);
+ if (script)
+ WebInspector.panels.scripts.showScript(script, breakpoint.line);
+ }
+
+ var breakpointElement = document.createElement("li");
+ breakpoint._breakpointListElement = breakpointElement;
+ breakpointElement._breakpointObject = breakpoint;
+
+ var checkboxElement = document.createElement("input");
+ checkboxElement.className = "checkbox-elem";
+ checkboxElement.type = "checkbox";
+ checkboxElement.checked = breakpoint.enabled;
+ checkboxElement.addEventListener("click", checkboxClicked, false);
+ breakpointElement.appendChild(checkboxElement);
+
+ var labelElement = document.createElement("a");
+ labelElement.textContent = breakpoint.label;
+ labelElement.addEventListener("click", labelClicked, false);
+ breakpointElement.appendChild(labelElement);
+
+ var sourceTextElement = document.createElement("div");
+ sourceTextElement.textContent = breakpoint.sourceText;
+ sourceTextElement.className = "source-text";
+ breakpointElement.appendChild(sourceTextElement);
+
+ var currentElement = this.listElement.firstChild;
+ while (currentElement) {
+ var currentBreak = currentElement._breakpointObject;
+ if (currentBreak.url > breakpoint.url) {
+ this.listElement.insertBefore(breakpointElement, currentElement);
+ return;
+ } else if (currentBreak.url == breakpoint.url && currentBreak.line > breakpoint.line) {
+ this.listElement.insertBefore(breakpointElement, currentElement);
+ return;
+ }
+ currentElement = currentElement.nextSibling;
+ }
+ this.listElement.appendChild(breakpointElement);
+ },
+
removeBreakpoint: function(breakpoint)
{
- this.breakpoints.remove(breakpoint);
+ if (!this.breakpoints[breakpoint.id])
+ return;
+ delete this.breakpoints[breakpoint.id];
+
breakpoint.removeEventListener("enabled", null, this);
breakpoint.removeEventListener("disabled", null, this);
+ breakpoint.removeEventListener("text-changed", null, this);
- // FIXME: remove from the breakpoints UI.
+ var element = breakpoint._breakpointListElement;
+ element.parentElement.removeChild(element);
+
+ if (!this.listElement.firstChild) {
+ this.bodyElement.removeChild(this.listElement);
+ this.bodyElement.appendChild(this.emptyElement);
+ }
if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
return;
@@ -70,7 +143,8 @@ WebInspector.BreakpointsSidebarPane.prototype = {
{
var breakpoint = event.target;
- // FIXME: change the breakpoint checkbox state in the UI.
+ var checkbox = breakpoint._breakpointListElement.firstChild;
+ checkbox.checked = breakpoint.enabled;
if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
return;
@@ -79,6 +153,14 @@ WebInspector.BreakpointsSidebarPane.prototype = {
InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
else
InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
+ },
+
+ _breakpointTextChanged: function(event)
+ {
+ var breakpoint = event.target;
+
+ var sourceTextElement = breakpoint._breakpointListElement.firstChild.nextSibling.nextSibling;
+ sourceTextElement.textContent = breakpoint.sourceText;
}
}
diff --git a/WebCore/inspector/front-end/CallStackSidebarPane.js b/WebCore/inspector/front-end/CallStackSidebarPane.js
index a2c8bed..c08cc7a 100644
--- a/WebCore/inspector/front-end/CallStackSidebarPane.js
+++ b/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -26,6 +26,16 @@
WebInspector.CallStackSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+
+ this._shortcuts = {};
+
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Period,
+ WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+ this._shortcuts[shortcut] = this._selectNextCallFrameOnStack.bind(this);
+
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Comma,
+ WebInspector.KeyboardShortcut.Modifiers.Ctrl);
+ this._shortcuts[shortcut] = this._selectPreviousCallFrameOnStack.bind(this);
}
WebInspector.CallStackSidebarPane.prototype = {
@@ -100,6 +110,53 @@ WebInspector.CallStackSidebarPane.prototype = {
this.dispatchEventToListeners("call frame selected");
},
+ handleKeyEvent: function(event)
+ {
+ var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+ var handler = this._shortcuts[shortcut];
+ if (handler) {
+ handler(event);
+ event.preventDefault();
+ event.handled = true;
+ }
+ },
+
+ _selectNextCallFrameOnStack: function()
+ {
+ var index = this._selectedCallFrameIndex();
+ if (index == -1)
+ return;
+ this._selectedPlacardByIndex(index + 1);
+ },
+
+ _selectPreviousCallFrameOnStack: function()
+ {
+ var index = this._selectedCallFrameIndex();
+ if (index == -1)
+ return;
+ this._selectedPlacardByIndex(index - 1);
+ },
+
+ _selectedPlacardByIndex: function(index)
+ {
+ if (index < 0 || index >= this.placards.length)
+ return;
+ var placard = this.placards[index];
+ this.selectedCallFrame = placard.callFrame
+ },
+
+ _selectedCallFrameIndex: function()
+ {
+ if (!this._selectedCallFrame)
+ return -1;
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ if (placard.callFrame === this._selectedCallFrame)
+ return i;
+ }
+ return -1;
+ },
+
_placardSelected: function(event)
{
var placardElement = event.target.enclosingNodeOrSelfWithClass("placard");
diff --git a/WebCore/inspector/front-end/Callback.js b/WebCore/inspector/front-end/Callback.js
new file mode 100644
index 0000000..8ae7f95
--- /dev/null
+++ b/WebCore/inspector/front-end/Callback.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Callback = function()
+{
+ this._lastCallbackId = 1;
+ this._callbacks = {};
+}
+
+WebInspector.Callback.prototype = {
+ wrap: function(callback)
+ {
+ var callbackId = this._lastCallbackId++;
+ this._callbacks[callbackId] = callback || function() {};
+ return callbackId;
+ },
+
+ processCallback: function(callbackId, opt_vararg)
+ {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var callback = this._callbacks[callbackId];
+ callback.apply(null, args);
+ delete this._callbacks[callbackId];
+ }
+}
+
+WebInspector.Callback._INSTANCE = new WebInspector.Callback();
+WebInspector.Callback.wrap = WebInspector.Callback._INSTANCE.wrap.bind(WebInspector.Callback._INSTANCE);
+WebInspector.Callback.processCallback = WebInspector.Callback._INSTANCE.processCallback.bind(WebInspector.Callback._INSTANCE);
diff --git a/WebCore/inspector/front-end/ChangesView.js b/WebCore/inspector/front-end/ChangesView.js
new file mode 100644
index 0000000..802fdba
--- /dev/null
+++ b/WebCore/inspector/front-end/ChangesView.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ChangesView = function(drawer)
+{
+ WebInspector.View.call(this);
+ this.element.innerHTML = "<div style=\"bottom:25%;color:rgb(192,192,192);font-size:12px;height:65px;left:0px;margin:auto;position:absolute;right:0px;text-align:center;top:0px;\"><h1>Not Implemented Yet</h1></div>";
+
+ this.drawer = drawer;
+
+ this.clearButton = document.createElement("button");
+ this.clearButton.id = "clear-changes-status-bar-item";
+ this.clearButton.title = WebInspector.UIString("Clear changes log.");
+ this.clearButton.className = "status-bar-item";
+ this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
+
+ this.toggleChangesButton = document.getElementById("changes-status-bar-item");
+ this.toggleChangesButton.title = WebInspector.UIString("Show changes view.");
+ this.toggleChangesButton.addEventListener("click", this._toggleChangesButtonClicked.bind(this), false);
+ var anchoredStatusBar = document.getElementById("anchored-status-bar-items");
+ anchoredStatusBar.appendChild(this.toggleChangesButton);
+}
+
+WebInspector.ChangesView.prototype = {
+ _clearButtonClicked: function()
+ {
+ // Not Implemented Yet
+ },
+
+ _toggleChangesButtonClicked: function()
+ {
+ this.drawer.visibleView = this;
+ },
+
+ attach: function(mainElement, statusBarElement)
+ {
+ mainElement.appendChild(this.element);
+ statusBarElement.appendChild(this.clearButton);
+ },
+
+ show: function()
+ {
+ this.toggleChangesButton.addStyleClass("toggled-on");
+ this.toggleChangesButton.title = WebInspector.UIString("Hide changes view.");
+ },
+
+ hide: function()
+ {
+ this.toggleChangesButton.removeStyleClass("toggled-on");
+ this.toggleChangesButton.title = WebInspector.UIString("Show changes view.");
+ }
+}
+
+WebInspector.ChangesView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/WebCore/inspector/front-end/Color.js b/WebCore/inspector/front-end/Color.js
new file mode 100644
index 0000000..7968ee4
--- /dev/null
+++ b/WebCore/inspector/front-end/Color.js
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Color = function(str)
+{
+ this.value = str;
+ this.parse();
+}
+
+WebInspector.Color.prototype = {
+ get shorthex()
+ {
+ if ("_short" in this)
+ return this._short;
+
+ if (!this.simple)
+ return null;
+
+ var hex = this.hex;
+ if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5))
+ this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4);
+ else
+ this._short = hex;
+
+ return this._short;
+ },
+
+ get hex()
+ {
+ if (!this.simple)
+ return null;
+
+ return this._hex;
+ },
+
+ set hex(x)
+ {
+ this._hex = x;
+ },
+
+ get rgb()
+ {
+ if ("_rgb" in this)
+ return this._rgb;
+
+ if (this.simple)
+ this._rgb = this.hexToRgb(this.hex);
+ else {
+ var rgba = this.rgba;
+ this._rgb = [rgba[0], rgba[1], rgba[2]];
+ }
+
+ return this._rgb;
+ },
+
+ set rgb(x)
+ {
+ this._rgb = x;
+ },
+
+ get hsl()
+ {
+ if ("_hsl" in this)
+ return this._hsl;
+
+ this._hsl = this.rgbToHsl(this.rgb);
+ return this._hsl;
+ },
+
+ set hsl(x)
+ {
+ this._hsl = x;
+ },
+
+ get nickname()
+ {
+ if (typeof this._nickname !== "undefined") // would be set on parse if there was a nickname
+ return this._nickname;
+ else
+ return null;
+ },
+
+ set nickname(x)
+ {
+ this._nickname = x;
+ },
+
+ get rgba()
+ {
+ return this._rgba;
+ },
+
+ set rgba(x)
+ {
+ this._rgba = x;
+ },
+
+ get hsla()
+ {
+ return this._hsla;
+ },
+
+ set hsla(x)
+ {
+ this._hsla = x;
+ },
+
+ hasShortHex: function()
+ {
+ var shorthex = this.shorthex;
+ return (shorthex && shorthex.length === 3);
+ },
+
+ toRgb: function()
+ {
+ return "rgb(" + this.rgb.join(", ") + ")";
+ },
+
+ toHsl: function()
+ {
+ var hsl = this.hsl;
+ return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
+ },
+
+ toShortHex: function()
+ {
+ return "#" + this.shorthex;
+ },
+
+ toHex: function()
+ {
+ return "#" + this.hex;
+ },
+
+ toRgba: function()
+ {
+ return "rgba(" + this.rgba.join(", ") + ")";
+ },
+
+ toHsla: function()
+ {
+ var hsla = this.hsla;
+ return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
+ },
+
+ toNickname: function()
+ {
+ return this.nickname;
+ },
+
+ rgbToHex: function(rgb)
+ {
+ var r = parseInt(rgb[0]).toString(16);
+ var g = parseInt(rgb[1]).toString(16);
+ var b = parseInt(rgb[2]).toString(16);
+ if (r.length === 1)
+ r = "0" + r;
+ if (g.length === 1)
+ g = "0" + g;
+ if (b.length === 1)
+ b = "0" + b;
+
+ return (r + g + b).toUpperCase();
+ },
+
+ hexToRgb: function(hex)
+ {
+ var r = parseInt(hex.substring(0,2), 16);
+ var g = parseInt(hex.substring(2,4), 16);
+ var b = parseInt(hex.substring(4,6), 16);
+
+ return [r, g, b];
+ },
+
+ rgbToHsl: function(rgb)
+ {
+ var r = parseInt(rgb[0]) / 255;
+ var g = parseInt(rgb[1]) / 255;
+ var b = parseInt(rgb[2]) / 255;
+ var max = Math.max(r, g, b);
+ var min = Math.min(r, g, b);
+ var diff = max - min;
+ var add = max + min;
+
+ if (min === max)
+ var h = 0;
+ else if (r === max)
+ var h = ((60 * (g - b) / diff) + 360) % 360;
+ else if (g === max)
+ var h = (60 * (b - r) / diff) + 120;
+ else
+ var h = (60 * (r - g) / diff) + 240;
+
+ var l = 0.5 * add;
+
+ if (l === 0)
+ var s = 0;
+ else if (l === 1)
+ var s = 1;
+ else if (l <= 0.5)
+ var s = diff / add;
+ else
+ var s = diff / (2 - add);
+
+ h = Math.round(h);
+ s = Math.round(s*100);
+ l = Math.round(l*100);
+
+ return [h, s, l];
+ },
+
+ hslToRgb: function(hsl)
+ {
+ var h = parseFloat(hsl[0]) / 360;
+ var s = parseFloat(hsl[1]) / 100;
+ var l = parseFloat(hsl[2]) / 100;
+
+ if (l <= 0.5)
+ var q = l * (1 + s);
+ else
+ var q = l + s - (l * s);
+
+ var p = 2 * l - q;
+
+ var tr = h + (1 / 3);
+ var tg = h;
+ var tb = h - (1 / 3);
+
+ var r = Math.round(hueToRgb(p, q, tr) * 255);
+ var g = Math.round(hueToRgb(p, q, tg) * 255);
+ var b = Math.round(hueToRgb(p, q, tb) * 255);
+ return [r, g, b];
+
+ function hueToRgb(p, q, h) {
+ if (h < 0)
+ h += 1;
+ else if (h > 1)
+ h -= 1;
+
+ if ((h * 6) < 1)
+ return p + (q - p) * h * 6;
+ else if ((h * 2) < 1)
+ return q;
+ else if ((h * 3) < 2)
+ return p + (q - p) * ((2 / 3) - h) * 6;
+ else
+ return p;
+ }
+ },
+
+ rgbaToHsla: function(rgba)
+ {
+ var alpha = rgba[3];
+ var hsl = this.rgbToHsl(rgba)
+ hsl.push(alpha);
+ return hsl;
+ },
+
+ hslaToRgba: function(hsla)
+ {
+ var alpha = hsla[3];
+ var rgb = this.hslToRgb(hsla);
+ rgb.push(alpha);
+ return rgb;
+ },
+
+ parse: function()
+ {
+ // Special Values - Advanced but Must Be Parsed First - transparent
+ var value = this.value.toLowerCase().replace(/%|\s+/g, "");
+ if (value in WebInspector.Color.AdvancedNickNames) {
+ this.mode = "nickname";
+ var set = WebInspector.Color.AdvancedNickNames[value];
+ this.simple = false;
+ this.rgba = set[0];
+ this.hsla = set[1];
+ this.nickname = set[2];
+ this.alpha = set[0][3];
+ return;
+ }
+
+ // Simple - #hex, rgb(), nickname, hsl()
+ var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i;
+ var match = this.value.match(simple);
+ if (match) {
+ this.simple = true;
+
+ if (match[1]) { // hex
+ var hex = match[1].toUpperCase();
+ if (hex.length === 3) {
+ this.mode = "shorthex";
+ this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
+ } else {
+ this.mode = "hex";
+ this.hex = hex;
+ }
+ } else if (match[2]) { // rgb
+ this.mode = "rgb";
+ var rgb = match[2].split(/\s*,\s*/);
+ this.rgb = rgb;
+ this.hex = this.rgbToHex(rgb);
+ } else if (match[3]) { // nickname
+ var nickname = match[3].toLowerCase();
+ if (nickname in WebInspector.Color.Nicknames) {
+ this.mode = "nickname";
+ this.hex = WebInspector.Color.Nicknames[nickname];
+ } else // unknown name
+ throw("unknown color name");
+ } else if (match[4]) { // hsl
+ this.mode = "hsl";
+ var hsl = match[4].replace(/%g/, "").split(/\s*,\s*/);
+ this.hsl = hsl;
+ this.rgb = this.hslToRgb(hsl);
+ this.hex = this.rgbToHex(this.rgb);
+ }
+
+ // Fill in the values if this is a known hex color
+ var hex = this.hex;
+ if (hex && hex in WebInspector.Color.HexTable) {
+ var set = WebInspector.Color.HexTable[hex];
+ this.rgb = set[0];
+ this.hsl = set[1];
+ this.nickname = set[2];
+ }
+
+ return;
+ }
+
+ // Advanced - rgba(), hsla()
+ var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/;
+ match = this.value.match(advanced);
+ if (match) {
+ this.simple = false;
+ if (match[1]) { // rgba
+ this.mode = "rgba";
+ this.rgba = match[1].split(/\s*,\s*/);
+ this.hsla = this.rgbaToHsla(this.rgba);
+ this.alpha = this.rgba[3];
+ } else if (match[2]) { // hsla
+ this.mode = "hsla";
+ this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/);
+ this.rgba = this.hslaToRgba(this.hsla);
+ this.alpha = this.hsla[3];
+ }
+
+ return;
+ }
+
+ // Could not parse as a valid color
+ throw("could not parse color");
+ }
+}
+
+// Simple Values: [rgb, hsl, nickname]
+WebInspector.Color.HexTable = {
+ "000000": [[0, 0, 0], [0, 0, 0], "black"],
+ "000080": [[0, 0, 128], [240, 100, 25], "navy"],
+ "00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"],
+ "0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"],
+ "0000FF": [[0, 0, 255], [240, 100, 50], "blue"],
+ "006400": [[0, 100, 0], [120, 100, 20], "darkGreen"],
+ "008000": [[0, 128, 0], [120, 100, 25], "green"],
+ "008080": [[0, 128, 128], [180, 100, 25], "teal"],
+ "008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"],
+ "00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"],
+ "00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"],
+ "00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"],
+ "00FF00": [[0, 255, 0], [120, 100, 50], "lime"],
+ "00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"],
+ "00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"],
+ "191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"],
+ "1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"],
+ "20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"],
+ "228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"],
+ "2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"],
+ "2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"],
+ "32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"],
+ "3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"],
+ "40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"],
+ "4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"],
+ "4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"],
+ "483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"],
+ "48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"],
+ "4B0082": [[75, 0, 130], [275, 100, 25], "indigo"],
+ "556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"],
+ "5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"],
+ "6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"],
+ "66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"],
+ "696969": [[105, 105, 105], [0, 0, 41], "dimGray"],
+ "6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"],
+ "6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"],
+ "708090": [[112, 128, 144], [210, 13, 50], "slateGray"],
+ "778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"],
+ "7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"],
+ "7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"],
+ "7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"],
+ "7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"],
+ "800000": [[128, 0, 0], [0, 100, 25], "maroon"],
+ "800080": [[128, 0, 128], [300, 100, 25], "purple"],
+ "808000": [[128, 128, 0], [60, 100, 25], "olive"],
+ "808080": [[128, 128, 128], [0, 0, 50], "gray"],
+ "87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"],
+ "87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"],
+ "8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"],
+ "8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"],
+ "8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"],
+ "8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"],
+ "8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"],
+ "90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"],
+ "9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"],
+ "9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"],
+ "98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"],
+ "9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"],
+ "9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"],
+ "A0522D": [[160, 82, 45], [19, 56, 40], "sienna"],
+ "A52A2A": [[165, 42, 42], [0, 59, 41], "brown"],
+ "A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"],
+ "ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"],
+ "ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"],
+ "AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"],
+ "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"],
+ "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"],
+ "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"],
+ "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenRod"],
+ "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"],
+ "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"],
+ "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"],
+ "C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"],
+ "C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"],
+ "CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"],
+ "CD853F": [[205, 133, 63], [30, 59, 53], "peru"],
+ "D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"],
+ "D2B48C": [[210, 180, 140], [34, 44, 69], "tan"],
+ "D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"],
+ "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"],
+ "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"],
+ "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"],
+ "DAA520": [[218, 165, 32], [43, 74, 49], "goldenRod"],
+ "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"],
+ "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"],
+ "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"],
+ "DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"],
+ "E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"],
+ "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"],
+ "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"],
+ "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"],
+ "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenRod"],
+ "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"],
+ "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"],
+ "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"],
+ "F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"],
+ "F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"],
+ "F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"],
+ "F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"],
+ "F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"],
+ "F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"],
+ "F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"],
+ "F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"],
+ "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"],
+ "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"],
+ "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"],
+ "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenRodYellow"],
+ "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"],
+ "FF0000": [[255, 0, 0], [0, 100, 50], "red"],
+ "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"],
+ "FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"],
+ "FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"],
+ "FF6347": [[255, 99, 71], [9, 100, 64], "tomato"],
+ "FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"],
+ "FF7F50": [[255, 127, 80], [16, 100, 66], "coral"],
+ "FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"],
+ "FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"],
+ "FFA500": [[255, 165, 0], [39, 100, 50], "orange"],
+ "FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"],
+ "FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"],
+ "FFD700": [[255, 215, 0], [51, 100, 50], "gold"],
+ "FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"],
+ "FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"],
+ "FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"],
+ "FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"],
+ "FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"],
+ "FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"],
+ "FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"],
+ "FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"],
+ "FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"],
+ "FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"],
+ "FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"],
+ "FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"],
+ "FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"],
+ "FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"],
+ "FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"],
+ "FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"],
+ "FFFFFF": [[255, 255, 255], [0, 100, 100], "white"]
+};
+
+// Simple Values
+WebInspector.Color.Nicknames = {
+ "aliceblue": "F0F8FF",
+ "antiquewhite": "FAEBD7",
+ "aqua": "00FFFF",
+ "aquamarine": "7FFFD4",
+ "azure": "F0FFFF",
+ "beige": "F5F5DC",
+ "bisque": "FFE4C4",
+ "black": "000000",
+ "blanchedalmond": "FFEBCD",
+ "blue": "0000FF",
+ "blueviolet": "8A2BE2",
+ "brown": "A52A2A",
+ "burlywood": "DEB887",
+ "cadetblue": "5F9EA0",
+ "chartreuse": "7FFF00",
+ "chocolate": "D2691E",
+ "coral": "FF7F50",
+ "cornflowerblue": "6495ED",
+ "cornsilk": "FFF8DC",
+ "crimson": "DC143C",
+ "cyan": "00FFFF",
+ "darkblue": "00008B",
+ "darkcyan": "008B8B",
+ "darkgoldenrod": "B8860B",
+ "darkgray": "A9A9A9",
+ "darkgreen": "006400",
+ "darkkhaki": "BDB76B",
+ "darkmagenta": "8B008B",
+ "darkolivegreen": "556B2F",
+ "darkorange": "FF8C00",
+ "darkorchid": "9932CC",
+ "darkred": "8B0000",
+ "darksalmon": "E9967A",
+ "darkseagreen": "8FBC8F",
+ "darkslateblue": "483D8B",
+ "darkslategray": "2F4F4F",
+ "darkturquoise": "00CED1",
+ "darkviolet": "9400D3",
+ "deeppink": "FF1493",
+ "deepskyblue": "00BFFF",
+ "dimgray": "696969",
+ "dodgerblue": "1E90FF",
+ "firebrick": "B22222",
+ "floralwhite": "FFFAF0",
+ "forestgreen": "228B22",
+ "fuchsia": "FF00FF",
+ "gainsboro": "DCDCDC",
+ "ghostwhite": "F8F8FF",
+ "gold": "FFD700",
+ "goldenrod": "DAA520",
+ "gray": "808080",
+ "green": "008000",
+ "greenyellow": "ADFF2F",
+ "honeydew": "F0FFF0",
+ "hotpink": "FF69B4",
+ "indianred": "CD5C5C",
+ "indigo": "4B0082",
+ "ivory": "FFFFF0",
+ "khaki": "F0E68C",
+ "lavender": "E6E6FA",
+ "lavenderblush": "FFF0F5",
+ "lawngreen": "7CFC00",
+ "lemonchiffon": "FFFACD",
+ "lightblue": "ADD8E6",
+ "lightcoral": "F08080",
+ "lightcyan": "E0FFFF",
+ "lightgoldenrodyellow": "FAFAD2",
+ "lightgreen": "90EE90",
+ "lightgrey": "D3D3D3",
+ "lightpink": "FFB6C1",
+ "lightsalmon": "FFA07A",
+ "lightseagreen": "20B2AA",
+ "lightskyblue": "87CEFA",
+ "lightslategray": "778899",
+ "lightsteelblue": "B0C4DE",
+ "lightyellow": "FFFFE0",
+ "lime": "00FF00",
+ "limegreen": "32CD32",
+ "linen": "FAF0E6",
+ "magenta": "FF00FF",
+ "maroon": "800000",
+ "mediumaquamarine": "66CDAA",
+ "mediumblue": "0000CD",
+ "mediumorchid": "BA55D3",
+ "mediumpurple": "9370D8",
+ "mediumseagreen": "3CB371",
+ "mediumslateblue": "7B68EE",
+ "mediumspringgreen": "00FA9A",
+ "mediumturquoise": "48D1CC",
+ "mediumvioletred": "C71585",
+ "midnightblue": "191970",
+ "mintcream": "F5FFFA",
+ "mistyrose": "FFE4E1",
+ "moccasin": "FFE4B5",
+ "navajowhite": "FFDEAD",
+ "navy": "000080",
+ "oldlace": "FDF5E6",
+ "olive": "808000",
+ "olivedrab": "6B8E23",
+ "orange": "FFA500",
+ "orangered": "FF4500",
+ "orchid": "DA70D6",
+ "palegoldenrod": "EEE8AA",
+ "palegreen": "98FB98",
+ "paleturquoise": "AFEEEE",
+ "palevioletred": "D87093",
+ "papayawhip": "FFEFD5",
+ "peachpuff": "FFDAB9",
+ "peru": "CD853F",
+ "pink": "FFC0CB",
+ "plum": "DDA0DD",
+ "powderblue": "B0E0E6",
+ "purple": "800080",
+ "red": "FF0000",
+ "rosybrown": "BC8F8F",
+ "royalblue": "4169E1",
+ "saddlebrown": "8B4513",
+ "salmon": "FA8072",
+ "sandybrown": "F4A460",
+ "seagreen": "2E8B57",
+ "seashell": "FFF5EE",
+ "sienna": "A0522D",
+ "silver": "C0C0C0",
+ "skyblue": "87CEEB",
+ "slateblue": "6A5ACD",
+ "slategray": "708090",
+ "snow": "FFFAFA",
+ "springgreen": "00FF7F",
+ "steelblue": "4682B4",
+ "tan": "D2B48C",
+ "teal": "008080",
+ "thistle": "D8BFD8",
+ "tomato": "FF6347",
+ "turquoise": "40E0D0",
+ "violet": "EE82EE",
+ "wheat": "F5DEB3",
+ "white": "FFFFFF",
+ "whitesmoke": "F5F5F5",
+ "yellow": "FFFF00",
+ "yellowgreen": "9ACD32"
+};
+
+// Advanced Values [rgba, hsla, nickname]
+WebInspector.Color.AdvancedNickNames = {
+ "transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+ "rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+ "hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
+};
diff --git a/WebCore/inspector/front-end/Console.js b/WebCore/inspector/front-end/ConsoleView.js
index 65cc7d0..6851eea 100644
--- a/WebCore/inspector/front-end/Console.js
+++ b/WebCore/inspector/front-end/ConsoleView.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,11 +27,16 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.Console = function()
+WebInspector.ConsoleView = function(drawer)
{
+ WebInspector.View.call(this, document.getElementById("console-view"));
+
this.messages = [];
+ this.drawer = drawer;
- WebInspector.View.call(this, document.getElementById("console"));
+ this.clearButton = document.getElementById("clear-console-status-bar-item");
+ this.clearButton.title = WebInspector.UIString("Clear console log.");
+ this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
this.messagesElement = document.getElementById("console-messages");
this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false);
@@ -40,103 +46,49 @@ WebInspector.Console = function()
this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this);
this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " .=:[({;");
- this.toggleButton = document.getElementById("console-status-bar-item");
- this.toggleButton.title = WebInspector.UIString("Show console.");
- this.toggleButton.addEventListener("click", this._toggleButtonClicked.bind(this), false);
-
- this.clearButton = document.getElementById("clear-console-status-bar-item");
- this.clearButton.title = WebInspector.UIString("Clear console log.");
- this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
-
this.topGroup = new WebInspector.ConsoleGroup(null, 0);
this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
this.groupLevel = 0;
this.currentGroup = this.topGroup;
- document.getElementById("main-status-bar").addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
-}
-
-WebInspector.Console.prototype = {
- show: function()
- {
- if (this._animating || this.visible)
- return;
-
- WebInspector.View.prototype.show.call(this);
+ this.toggleConsoleButton = document.getElementById("console-status-bar-item");
+ this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
+ this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false);
- this._animating = true;
+ var anchoredStatusBar = document.getElementById("anchored-status-bar-items");
+ anchoredStatusBar.appendChild(this.toggleConsoleButton);
- this.toggleButton.addStyleClass("toggled-on");
- this.toggleButton.title = WebInspector.UIString("Hide console.");
-
- document.body.addStyleClass("console-visible");
-
- var anchoredItems = document.getElementById("anchored-status-bar-items");
-
- var animations = [
- {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}},
- {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
- {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}}
- ];
-
- var consoleStatusBar = document.getElementById("console-status-bar");
- consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild);
+}
- function animationFinished()
- {
- if ("updateStatusBarItems" in WebInspector.currentPanel)
- WebInspector.currentPanel.updateStatusBarItems();
- WebInspector.currentFocusElement = this.promptElement;
- delete this._animating;
- }
+WebInspector.ConsoleView.prototype = {
+ _toggleConsoleButtonClicked: function()
+ {
+ this.drawer.visibleView = this;
+ },
- WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ attach: function(mainElement, statusBarElement)
+ {
+ mainElement.appendChild(this.element);
+ statusBarElement.appendChild(this.clearButton);
+ },
+ show: function()
+ {
+ this.toggleConsoleButton.addStyleClass("toggled-on");
+ this.toggleConsoleButton.title = WebInspector.UIString("Hide console.");
if (!this.prompt.isCaretInsidePrompt())
this.prompt.moveCaretToEndOfPrompt();
},
- hide: function()
+ afterShow: function()
{
- if (this._animating || !this.visible)
- return;
-
- WebInspector.View.prototype.hide.call(this);
-
- this._animating = true;
-
- this.toggleButton.removeStyleClass("toggled-on");
- this.toggleButton.title = WebInspector.UIString("Show console.");
-
- if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
- WebInspector.currentFocusElement = WebInspector.previousFocusElement;
-
- var anchoredItems = document.getElementById("anchored-status-bar-items");
-
- // Temporally set properties and classes to mimic the post-animation values so panels
- // like Elements in their updateStatusBarItems call will size things to fit the final location.
- document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
- document.body.removeStyleClass("console-visible");
- if ("updateStatusBarItems" in WebInspector.currentPanel)
- WebInspector.currentPanel.updateStatusBarItems();
- document.body.addStyleClass("console-visible");
-
- var animations = [
- {element: document.getElementById("main"), end: {bottom: 0}},
- {element: document.getElementById("main-status-bar"), start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
- {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 1}, end: {opacity: 0}}
- ];
-
- function animationFinished()
- {
- var mainStatusBar = document.getElementById("main-status-bar");
- mainStatusBar.insertBefore(anchoredItems, mainStatusBar.firstChild);
- mainStatusBar.style.removeProperty("padding-left");
- document.body.removeStyleClass("console-visible");
- delete this._animating;
- }
+ WebInspector.currentFocusElement = this.promptElement;
+ },
- WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ hide: function()
+ {
+ this.toggleConsoleButton.removeStyleClass("toggled-on");
+ this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
},
addMessage: function(msg)
@@ -198,7 +150,7 @@ WebInspector.Console.prototype = {
this.messages.push(msg);
- if (msg.level === WebInspector.ConsoleMessage.MessageLevel.EndGroup) {
+ if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) {
if (this.groupLevel < 1)
return;
@@ -206,7 +158,7 @@ WebInspector.Console.prototype = {
this.currentGroup = this.currentGroup.parentGroup;
} else {
- if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup) {
this.groupLevel++;
var group = new WebInspector.ConsoleGroup(this.currentGroup, this.groupLevel);
@@ -241,7 +193,7 @@ WebInspector.Console.prototype = {
delete this.previousMessage;
},
- completions: function(wordRange, bestMatchOnly)
+ completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
{
// Pass less stop characters to rangeOfWord so the range will be a more complete expression.
const expressionStopCharacters = " =:{;";
@@ -259,22 +211,11 @@ WebInspector.Console.prototype = {
if (!expressionString && !prefix)
return;
- var result;
- if (expressionString) {
- try {
- result = this._evalInInspectedWindow(expressionString);
- } catch(e) {
- // Do nothing, the prefix will be considered a window property.
- }
- } else {
- // There is no expressionString, so the completion should happen against global properties.
- // Or if the debugger is paused, against properties in scope of the selected call frame.
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
- result = WebInspector.panels.scripts.variablesInScopeForSelectedCallFrame();
- else
- result = InspectorController.inspectedWindow();
- }
+ var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix);
+ this._evalInInspectedWindow(expressionString, reportCompletions);
+ },
+ _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result) {
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
@@ -283,7 +224,17 @@ WebInspector.Console.prototype = {
}
var results = [];
- var properties = Object.sortedProperties(result);
+ var properties = Object.properties(result);
+ if (!dotNotation && !bracketNotation && result._inspectorCommandLineAPI) {
+ var commandLineAPI = Object.properties(result._inspectorCommandLineAPI);
+ for (var i = 0; i < commandLineAPI.length; ++i) {
+ var property = commandLineAPI[i];
+ if (property.charAt(0) !== "_")
+ properties.push(property);
+ }
+ }
+ properties.sort();
+
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
@@ -305,13 +256,7 @@ WebInspector.Console.prototype = {
if (bestMatchOnly)
break;
}
-
- return results;
- },
-
- _toggleButtonClicked: function()
- {
- this.visible = !this.visible;
+ setTimeout(completionsReadyCallback, 0, results);
},
_clearButtonClicked: function()
@@ -359,47 +304,17 @@ WebInspector.Console.prototype = {
this.prompt.handleKeyEvent(event);
},
- _startStatusBarDragging: function(event)
+ _evalInInspectedWindow: function(expression, callback)
{
- if (!this.visible || event.target !== document.getElementById("main-status-bar"))
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, callback);
return;
-
- WebInspector.elementDragStart(document.getElementById("main-status-bar"), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");
-
- this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;
-
- event.stopPropagation();
- },
-
- _statusBarDragging: function(event)
- {
- var mainElement = document.getElementById("main");
-
- var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
- height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight);
-
- mainElement.style.bottom = height + "px";
- this.element.style.height = height + "px";
-
- event.preventDefault();
- event.stopPropagation();
- },
-
- _endStatusBarDragging: function(event)
- {
- WebInspector.elementDragEnd(event);
-
- delete this._statusBarDragOffset;
-
- event.stopPropagation();
+ }
+ this.doEvalInWindow(expression, callback);
},
- _evalInInspectedWindow: function(expression)
+ _ensureCommandLineAPIInstalled: function(inspectedWindow)
{
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
- return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
-
- var inspectedWindow = InspectorController.inspectedWindow();
if (!inspectedWindow._inspectorCommandLineAPI) {
inspectedWindow.eval("window._inspectorCommandLineAPI = { \
$: function() { return document.getElementById.apply(document, arguments) }, \
@@ -416,20 +331,79 @@ WebInspector.Console.prototype = {
}, \
dir: function() { return console.dir.apply(console, arguments) }, \
dirxml: function() { return console.dirxml.apply(console, arguments) }, \
- keys: function(o) { var a = []; for (k in o) a.push(k); return a; }, \
- values: function(o) { var a = []; for (k in o) a.push(o[k]); return a; }, \
+ keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \
+ values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \
profile: function() { return console.profile.apply(console, arguments) }, \
- profileEnd: function() { return console.profileEnd.apply(console, arguments) } \
+ profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \
+ _inspectedNodes: [], \
+ get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \
+ get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \
+ get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \
+ get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \
+ get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \
};");
inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this));
+ inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this));
+
+ function inspectObject(o)
+ {
+ if (arguments.length === 0)
+ return;
+
+ InspectorController.inspectedWindow().console.log(o);
+ if (Object.type(o, InspectorController.inspectedWindow()) === "node") {
+ WebInspector.showElementsPanel();
+ WebInspector.panels.elements.treeOutline.revealAndSelectNode(o);
+ } else {
+ switch (Object.describe(o)) {
+ case "Database":
+ WebInspector.showDatabasesPanel();
+ WebInspector.panels.databases.selectDatabase(o);
+ break;
+ case "Storage":
+ WebInspector.showDatabasesPanel();
+ WebInspector.panels.databases.selectDOMStorage(o);
+ break;
+ }
+ }
+ }
+ }
+ },
+
+ addInspectedNode: function(node)
+ {
+ var inspectedWindow = InspectorController.inspectedWindow();
+ this._ensureCommandLineAPIInstalled(inspectedWindow);
+ var inspectedNodes = inspectedWindow._inspectorCommandLineAPI._inspectedNodes;
+ inspectedNodes.unshift(node);
+ if (inspectedNodes.length >= 5)
+ inspectedNodes.pop();
+ },
+
+ doEvalInWindow: function(expression, callback)
+ {
+ if (!expression) {
+ // There is no expression, so the completion should happen against global properties.
+ expression = "this";
}
// 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.
expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
- return inspectedWindow.eval(expression);
+ var self = this;
+ function delayedEvaluation()
+ {
+ var inspectedWindow = InspectorController.inspectedWindow();
+ self._ensureCommandLineAPIInstalled(inspectedWindow);
+ try {
+ callback(inspectedWindow.eval(expression));
+ } catch (e) {
+ callback(e, true);
+ }
+ }
+ setTimeout(delayedEvaluation, 0);
},
_enterKeyPressed: function(event)
@@ -449,25 +423,26 @@ WebInspector.Console.prototype = {
var commandMessage = new WebInspector.ConsoleCommand(str);
this.addMessage(commandMessage);
- var result;
- var exception = false;
- try {
- result = this._evalInInspectedWindow(str);
- } catch(e) {
- result = e;
- exception = true;
+ var self = this;
+ function printResult(result, exception)
+ {
+ self.prompt.history.push(str);
+ self.prompt.historyOffset = 0;
+ self.prompt.text = "";
+ self.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
}
-
- this.prompt.history.push(str);
- this.prompt.historyOffset = 0;
- this.prompt.text = "";
-
- this.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
+ this._evalInInspectedWindow(str, printResult);
},
_format: function(output, forceObjectFormat)
{
- var type = (forceObjectFormat ? "object" : Object.type(output, InspectorController.inspectedWindow()));
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (forceObjectFormat)
+ var type = "object";
+ else if (output instanceof inspectedWindow.NodeList)
+ var type = "array";
+ else
+ var type = Object.type(output, inspectedWindow);
// We don't perform any special formatting on these types, so we just
// pass them through the simple _formatvalue function.
@@ -538,7 +513,7 @@ WebInspector.Console.prototype = {
_formatobject: function(obj, elem)
{
- elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, null, null, null, true).element);
+ elem.appendChild(new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(obj), Object.describe(obj, true), null, null, true).element);
},
_formaterror: function(obj, elem)
@@ -564,28 +539,29 @@ WebInspector.Console.prototype = {
elem.appendChild(urlElement);
elem.appendChild(document.createTextNode(")"));
}
- },
+ }
}
-WebInspector.Console.prototype.__proto__ = WebInspector.View.prototype;
+WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype;
-WebInspector.ConsoleMessage = function(source, level, line, url, groupLevel, repeatCount)
+WebInspector.ConsoleMessage = function(source, type, level, line, url, groupLevel, repeatCount)
{
this.source = source;
+ this.type = type;
this.level = level;
this.line = line;
this.url = url;
this.groupLevel = groupLevel;
this.repeatCount = repeatCount;
- if (arguments.length > 6)
- this.setMessageBody(Array.prototype.slice.call(arguments, 6));
+ if (arguments.length > 7)
+ this.setMessageBody(Array.prototype.slice.call(arguments, 7));
}
WebInspector.ConsoleMessage.prototype = {
setMessageBody: function(args)
{
- switch (this.level) {
- case WebInspector.ConsoleMessage.MessageLevel.Trace:
+ switch (this.type) {
+ case WebInspector.ConsoleMessage.MessageType.Trace:
var span = document.createElement("span");
span.addStyleClass("console-formatted-trace");
var stack = Array.prototype.slice.call(args);
@@ -595,7 +571,7 @@ WebInspector.ConsoleMessage.prototype = {
span.appendChild(document.createTextNode(funcNames.join("\n")));
this.formattedMessage = span;
break;
- case WebInspector.ConsoleMessage.MessageLevel.Object:
+ case WebInspector.ConsoleMessage.MessageType.Object:
this.formattedMessage = this._format(["%O", args[0]]);
break;
default:
@@ -713,8 +689,10 @@ WebInspector.ConsoleMessage.prototype = {
case WebInspector.ConsoleMessage.MessageLevel.Error:
element.addStyleClass("console-error-level");
break;
- case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
- element.addStyleClass("console-group-title-level");
+ }
+
+ if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup) {
+ element.addStyleClass("console-group-title");
}
if (this.elementsTreeOutline) {
@@ -781,6 +759,25 @@ WebInspector.ConsoleMessage.prototype = {
break;
}
+ var typeString;
+ switch (this.type) {
+ case WebInspector.ConsoleMessage.MessageType.Log:
+ typeString = "Log";
+ break;
+ case WebInspector.ConsoleMessage.MessageType.Object:
+ typeString = "Object";
+ break;
+ case WebInspector.ConsoleMessage.MessageType.Trace:
+ typeString = "Trace";
+ break;
+ case WebInspector.ConsoleMessage.MessageType.StartGroup:
+ typeString = "Start Group";
+ break;
+ case WebInspector.ConsoleMessage.MessageType.EndGroup:
+ typeString = "End Group";
+ break;
+ }
+
var levelString;
switch (this.level) {
case WebInspector.ConsoleMessage.MessageLevel.Tip:
@@ -795,21 +792,9 @@ WebInspector.ConsoleMessage.prototype = {
case WebInspector.ConsoleMessage.MessageLevel.Error:
levelString = "Error";
break;
- case WebInspector.ConsoleMessage.MessageLevel.Object:
- levelString = "Object";
- break;
- case WebInspector.ConsoleMessage.MessageLevel.Trace:
- levelString = "Trace";
- break;
- case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
- levelString = "Start Group";
- break;
- case WebInspector.ConsoleMessage.MessageLevel.EndGroup:
- levelString = "End Group";
- break;
}
- return sourceString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line;
+ return sourceString + " " + typeString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line;
},
isEqual: function(msg, disreguardGroup)
@@ -818,6 +803,7 @@ WebInspector.ConsoleMessage.prototype = {
return false;
var ret = (this.source == msg.source)
+ && (this.type == msg.type)
&& (this.level == msg.level)
&& (this.line == msg.line)
&& (this.url == msg.url)
@@ -837,15 +823,19 @@ WebInspector.ConsoleMessage.MessageSource = {
Other: 5
}
+WebInspector.ConsoleMessage.MessageType = {
+ Log: 0,
+ Object: 1,
+ Trace: 2,
+ StartGroup: 3,
+ EndGroup: 4
+}
+
WebInspector.ConsoleMessage.MessageLevel = {
Tip: 0,
Log: 1,
Warning: 2,
- Error: 3,
- Object: 4,
- Trace: 5,
- StartGroup: 6,
- EndGroup: 7
+ Error: 3
}
WebInspector.ConsoleCommand = function(command)
@@ -876,7 +866,7 @@ WebInspector.ConsoleCommandResult = function(result, exception, originatingComma
var line = (exception ? result.line : -1);
var url = (exception ? result.sourceURL : null);
- WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, line, url, null, 1, message);
+ WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, line, url, null, 1, message);
this.originatingCommand = originatingCommand;
}
@@ -913,7 +903,7 @@ WebInspector.ConsoleGroup.prototype = {
{
var element = msg.toMessageElement();
- if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup) {
this.messagesElement.parentNode.insertBefore(element, this.messagesElement);
element.addEventListener("click", this._titleClicked.bind(this), true);
} else
@@ -925,7 +915,7 @@ WebInspector.ConsoleGroup.prototype = {
_titleClicked: function(event)
{
- var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title-level");
+ var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title");
if (groupTitleElement) {
var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group");
if (groupElement)
diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js
new file mode 100644
index 0000000..5aacd41
--- /dev/null
+++ b/WebCore/inspector/front-end/DOMAgent.js
@@ -0,0 +1,724 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DOMNode = function(doc, payload) {
+ this.ownerDocument = doc;
+
+ this._id = payload.id;
+ this.nodeType = payload.nodeType;
+ this.nodeName = payload.nodeName;
+ this._nodeValue = payload.nodeValue;
+ this.textContent = this.nodeValue;
+
+ this.attributes = [];
+ this._attributesMap = {};
+ if (payload.attributes)
+ this._setAttributesPayload(payload.attributes);
+
+ this._childNodeCount = payload.childNodeCount;
+ this.children = null;
+
+ this.nextSibling = null;
+ this.prevSibling = null;
+ this.firstChild = null;
+ this.parentNode = null;
+
+ if (payload.childNodes)
+ this._setChildrenPayload(payload.childNodes);
+
+ this._computedStyle = null;
+ this.style = null;
+ this._matchedCSSRules = [];
+}
+
+WebInspector.DOMNode.prototype = {
+ hasAttributes: function()
+ {
+ return this.attributes.length > 0;
+ },
+
+ hasChildNodes: function() {
+ return this._childNodeCount > 0;
+ },
+
+ get nodeValue() {
+ return this._nodeValue;
+ },
+
+ set nodeValue(value) {
+ if (this.nodeType != Node.TEXT_NODE)
+ return;
+ var self = this;
+ var callback = function()
+ {
+ self._nodeValue = value;
+ self.textContent = value;
+ };
+ this.ownerDocument._domAgent.setTextNodeValueAsync(this, value, callback);
+ },
+
+ getAttribute: function(name)
+ {
+ var attr = this._attributesMap[name];
+ return attr ? attr.value : undefined;
+ },
+
+ setAttribute: function(name, value)
+ {
+ var self = this;
+ var callback = function()
+ {
+ var attr = self._attributesMap[name];
+ if (attr)
+ attr.value = value;
+ else
+ attr = self._addAttribute(name, value);
+ };
+ this.ownerDocument._domAgent.setAttributeAsync(this, name, value, callback);
+ },
+
+ removeAttribute: function(name)
+ {
+ var self = this;
+ var callback = function()
+ {
+ delete self._attributesMap[name];
+ for (var i = 0; i < self.attributes.length; ++i) {
+ if (self.attributes[i].name == name) {
+ self.attributes.splice(i, 1);
+ break;
+ }
+ }
+ };
+ this.ownerDocument._domAgent.removeAttributeAsync(this, name, callback);
+ },
+
+ _setAttributesPayload: function(attrs)
+ {
+ for (var i = 0; i < attrs.length; i += 2)
+ this._addAttribute(attrs[i], attrs[i + 1]);
+ },
+
+ _insertChild: function(prev, payload)
+ {
+ var node = new WebInspector.DOMNode(this.ownerDocument, payload);
+ if (!prev)
+ // First node
+ this.children = [ node ];
+ else
+ this.children.splice(this.children.indexOf(prev) + 1, 0, node);
+ this._renumber();
+ return node;
+ },
+
+ removeChild_: function(node)
+ {
+ this.children.splice(this.children.indexOf(node), 1);
+ node.parentNode = null;
+ this._renumber();
+ },
+
+ _setChildrenPayload: function(payloads)
+ {
+ this.children = [];
+ for (var i = 0; i < payloads.length; ++i) {
+ var payload = payloads[i];
+ var node = new WebInspector.DOMNode(this.ownerDocument, payload);
+ this.children.push(node);
+ }
+ this._renumber();
+ },
+
+ _renumber: function()
+ {
+ this._childNodeCount = this.children.length;
+ if (this._childNodeCount == 0) {
+ this.firstChild = null;
+ return;
+ }
+ this.firstChild = this.children[0];
+ for (var i = 0; i < this._childNodeCount; ++i) {
+ var child = this.children[i];
+ child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null;
+ child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null;
+ child.parentNode = this;
+ }
+ },
+
+ _addAttribute: function(name, value)
+ {
+ var attr = {
+ "name": name,
+ "value": value,
+ "_node": this
+ };
+ this._attributesMap[name] = attr;
+ this.attributes.push(attr);
+ },
+
+ _setStyles: function(computedStyle, inlineStyle, styleAttributes, matchedCSSRules)
+ {
+ this._computedStyle = new WebInspector.CSSStyleDeclaration(computedStyle);
+ this.style = new WebInspector.CSSStyleDeclaration(inlineStyle);
+
+ for (var name in styleAttributes) {
+ if (this._attributesMap[name])
+ this._attributesMap[name].style = new WebInspector.CSSStyleDeclaration(styleAttributes[name]);
+ }
+
+ this._matchedCSSRules = [];
+ for (var i = 0; i < matchedCSSRules.length; i++)
+ this._matchedCSSRules.push(WebInspector.CSSStyleDeclaration.parseRule(matchedCSSRules[i]));
+ },
+
+ _clearStyles: function()
+ {
+ this.computedStyle = null;
+ this.style = null;
+ for (var name in this._attributesMap)
+ this._attributesMap[name].style = null;
+ this._matchedCSSRules = null;
+ }
+}
+
+WebInspector.DOMDocument = function(domAgent, defaultView)
+{
+ WebInspector.DOMNode.call(this, null,
+ {
+ id: 0,
+ nodeType: Node.DOCUMENT_NODE,
+ nodeName: "",
+ nodeValue: "",
+ attributes: [],
+ childNodeCount: 0
+ });
+ this._listeners = {};
+ this._domAgent = domAgent;
+ this.defaultView = defaultView;
+}
+
+WebInspector.DOMDocument.prototype = {
+
+ addEventListener: function(name, callback, useCapture)
+ {
+ var listeners = this._listeners[name];
+ if (!listeners) {
+ listeners = [];
+ this._listeners[name] = listeners;
+ }
+ listeners.push(callback);
+ },
+
+ removeEventListener: function(name, callback, useCapture)
+ {
+ var listeners = this._listeners[name];
+ if (!listeners)
+ return;
+
+ var index = listeners.indexOf(callback);
+ if (index != -1)
+ listeners.splice(index, 1);
+ },
+
+ _fireDomEvent: function(name, event)
+ {
+ var listeners = this._listeners[name];
+ if (!listeners)
+ return;
+
+ for (var i = 0; i < listeners.length; ++i)
+ listeners[i](event);
+ }
+}
+
+WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;
+
+
+WebInspector.DOMWindow = function(domAgent)
+{
+ this._domAgent = domAgent;
+}
+
+WebInspector.DOMWindow.prototype = {
+ get document()
+ {
+ return this._domAgent.document;
+ },
+
+ get Node()
+ {
+ return WebInspector.DOMNode;
+ },
+
+ get Element()
+ {
+ return WebInspector.DOMNode;
+ },
+
+ Object: function()
+ {
+ },
+
+ getComputedStyle: function(node)
+ {
+ return node._computedStyle;
+ },
+
+ getMatchedCSSRules: function(node, pseudoElement, authorOnly)
+ {
+ return node._matchedCSSRules;
+ }
+}
+
+WebInspector.DOMAgent = function() {
+ this._window = new WebInspector.DOMWindow(this);
+ this._idToDOMNode = null;
+ this.document = null;
+
+ // Install onpopulate handler. This is a temporary measure.
+ // TODO: add this code into the original updateChildren once domAgent
+ // becomes primary source of DOM information.
+ // TODO2: update ElementsPanel to not track embedded iframes - it is already being handled
+ // in the agent backend.
+ var domAgent = this;
+ var originalUpdateChildren = WebInspector.ElementsTreeElement.prototype.updateChildren;
+ WebInspector.ElementsTreeElement.prototype.updateChildren = function()
+ {
+ domAgent.getChildNodesAsync(this.representedObject, originalUpdateChildren.bind(this));
+ };
+
+ // Mute console handle to avoid crash on selection change.
+ // TODO: Re-implement inspectorConsoleAPI to work in a serialized way and remove this workaround.
+ WebInspector.Console.prototype.addInspectedNode = function()
+ {
+ };
+
+ // Whitespace is ignored in InspectorDOMAgent already -> no need to filter.
+ // TODO: Either remove all of its usages or push value into the agent backend.
+ Preferences.ignoreWhitespace = false;
+}
+
+WebInspector.DOMAgent.prototype = {
+ get inspectedWindow()
+ {
+ return this._window;
+ },
+
+ getChildNodesAsync: function(parent, opt_callback)
+ {
+ var children = parent.children;
+ if (children && opt_callback) {
+ opt_callback(children);
+ return;
+ }
+ var mycallback = function() {
+ if (opt_callback) {
+ opt_callback(parent.children);
+ }
+ };
+ var callId = WebInspector.Callback.wrap(mycallback);
+ InspectorController.getChildNodes(callId, parent._id);
+ },
+
+ setAttributeAsync: function(node, name, value, callback)
+ {
+ var mycallback = this._didApplyDomChange.bind(this, node, callback);
+ InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node._id, name, value);
+ },
+
+ removeAttributeAsync: function(node, name, callback)
+ {
+ var mycallback = this._didApplyDomChange.bind(this, node, callback);
+ InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node._id, name);
+ },
+
+ setTextNodeValueAsync: function(node, text, callback)
+ {
+ var mycallback = this._didApplyDomChange.bind(this, node, callback);
+ InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node._id, text);
+ },
+
+ _didApplyDomChange: function(node, callback, success)
+ {
+ if (!success)
+ return;
+ callback();
+ // TODO(pfeldman): Fix this hack.
+ var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node);
+ if (elem) {
+ elem._updateTitle();
+ }
+ },
+
+ _attributesUpdated: function(nodeId, attrsArray)
+ {
+ var node = this._idToDOMNode[nodeId];
+ node._setAttributesPayload(attrsArray);
+ },
+
+ getNodeForId: function(nodeId) {
+ return this._idToDOMNode[nodeId];
+ },
+
+ _setDocumentElement: function(payload)
+ {
+ this.document = new WebInspector.DOMDocument(this, this._window);
+ this._idToDOMNode = { 0 : this.document };
+ this._setChildNodes(0, [payload]);
+ this.document.documentElement = this.document.firstChild;
+ this.document.documentElement.ownerDocument = this.document;
+ WebInspector.panels.elements.reset();
+ },
+
+ _setChildNodes: function(parentId, payloads)
+ {
+ var parent = this._idToDOMNode[parentId];
+ if (parent.children) {
+ return;
+ }
+ parent._setChildrenPayload(payloads);
+ this._bindNodes(parent.children);
+ },
+
+ _bindNodes: function(children)
+ {
+ for (var i = 0; i < children.length; ++i) {
+ var child = children[i];
+ this._idToDOMNode[child._id] = child;
+ if (child.children)
+ this._bindNodes(child.children);
+ }
+ },
+
+ _hasChildrenUpdated: function(nodeId, newValue)
+ {
+ var node = this._idToDOMNode[nodeId];
+ var outline = WebInspector.panels.elements.treeOutline;
+ var treeElement = outline.findTreeElement(node);
+ if (treeElement) {
+ treeElement.hasChildren = newValue;
+ treeElement.whitespaceIgnored = Preferences.ignoreWhitespace;
+ }
+ },
+
+ _childNodeInserted: function(parentId, prevId, payload)
+ {
+ var parent = this._idToDOMNode[parentId];
+ var prev = this._idToDOMNode[prevId];
+ var node = parent._insertChild(prev, payload);
+ this._idToDOMNode[node._id] = node;
+ var event = { target : node, relatedNode : parent };
+ this.document._fireDomEvent("DOMNodeInserted", event);
+ },
+
+ _childNodeRemoved: function(parentId, nodeId)
+ {
+ var parent = this._idToDOMNode[parentId];
+ var node = this._idToDOMNode[nodeId];
+ parent.removeChild_(node);
+ var event = { target : node, relatedNode : parent };
+ this.document._fireDomEvent("DOMNodeRemoved", event);
+ delete this._idToDOMNode[nodeId];
+ }
+}
+
+WebInspector.CSSStyleDeclaration = function(payload) {
+ this._id = payload.id;
+ this.width = payload.width;
+ this.height = payload.height;
+ this.__disabledProperties = payload.__disabledProperties;
+ this.__disabledPropertyValues = payload.__disabledPropertyValues;
+ this.__disabledPropertyPriorities = payload.__disabledPropertyPriorities;
+ this.uniqueStyleProperties = payload.uniqueStyleProperties;
+ this._shorthandValues = payload.shorthandValues;
+ this._propertyMap = {};
+ this._longhandProperties = {};
+ this.length = payload.properties.length;
+
+ for (var i = 0; i < this.length; ++i) {
+ var property = payload.properties[i];
+ var name = property.name;
+ this[i] = name;
+ this._propertyMap[name] = property;
+ }
+
+ // Index longhand properties.
+ for (var i = 0; i < this.uniqueStyleProperties.length; ++i) {
+ var name = this.uniqueStyleProperties[i];
+ var property = this._propertyMap[name];
+ if (property.shorthand) {
+ var longhands = this._longhandProperties[property.shorthand];
+ if (!longhands) {
+ longhands = [];
+ this._longhandProperties[property.shorthand] = longhands;
+ }
+ longhands.push(name);
+ }
+ }
+}
+
+WebInspector.CSSStyleDeclaration.parseStyle = function(payload)
+{
+ return new WebInspector.CSSStyleDeclaration(payload);
+}
+
+WebInspector.CSSStyleDeclaration.parseRule = function(payload)
+{
+ var rule = {};
+ rule._id = payload.id;
+ rule.selectorText = payload.selectorText;
+ rule.style = new WebInspector.CSSStyleDeclaration(payload.style);
+ rule.style.parentRule = rule;
+ rule.isUserAgent = payload.isUserAgent;
+ rule.isUser = payload.isUser;
+ if (payload.parentStyleSheet)
+ rule.parentStyleSheet = { href: payload.parentStyleSheet.href };
+
+ return rule;
+}
+
+WebInspector.CSSStyleDeclaration.prototype = {
+ getPropertyValue: function(name)
+ {
+ var property = this._propertyMap[name];
+ return property ? property.value : "";
+ },
+
+ getPropertyPriority: function(name)
+ {
+ var property = this._propertyMap[name];
+ return property ? property.priority : "";
+ },
+
+ getPropertyShorthand: function(name)
+ {
+ var property = this._propertyMap[name];
+ return property ? property.shorthand : "";
+ },
+
+ isPropertyImplicit: function(name)
+ {
+ var property = this._propertyMap[name];
+ return property ? property.implicit : "";
+ },
+
+ styleTextWithShorthands: function()
+ {
+ var cssText = "";
+ var foundProperties = {};
+ for (var i = 0; i < this.length; ++i) {
+ var individualProperty = this[i];
+ var shorthandProperty = this.getPropertyShorthand(individualProperty);
+ var propertyName = (shorthandProperty || individualProperty);
+
+ if (propertyName in foundProperties)
+ continue;
+
+ if (shorthandProperty) {
+ var value = this.getPropertyValue(shorthandProperty);
+ var priority = this.getShorthandPriority(shorthandProperty);
+ } else {
+ var value = this.getPropertyValue(individualProperty);
+ var priority = this.getPropertyPriority(individualProperty);
+ }
+
+ foundProperties[propertyName] = true;
+
+ cssText += propertyName + ": " + value;
+ if (priority)
+ cssText += " !" + priority;
+ cssText += "; ";
+ }
+
+ return cssText;
+ },
+
+ getLonghandProperties: function(name)
+ {
+ return this._longhandProperties[name] || [];
+ },
+
+ getShorthandValue: function(shorthandProperty)
+ {
+ return this._shorthandValues[shorthandProperty];
+ },
+
+ getShorthandPriority: function(shorthandProperty)
+ {
+ var priority = this.getPropertyPriority(shorthandProperty);
+ if (priority)
+ return priority;
+
+ var longhands = this._longhandProperties[shorthandProperty];
+ return longhands ? this.getPropertyPriority(longhands[0]) : null;
+ }
+}
+
+WebInspector.attributesUpdated = function()
+{
+ this.domAgent._attributesUpdated.apply(this.domAgent, arguments);
+}
+
+WebInspector.setDocumentElement = function()
+{
+ this.domAgent._setDocumentElement.apply(this.domAgent, arguments);
+}
+
+WebInspector.setChildNodes = function()
+{
+ this.domAgent._setChildNodes.apply(this.domAgent, arguments);
+}
+
+WebInspector.hasChildrenUpdated = function()
+{
+ this.domAgent._hasChildrenUpdated.apply(this.domAgent, arguments);
+}
+
+WebInspector.childNodeInserted = function()
+{
+ this.domAgent._childNodeInserted.apply(this.domAgent, arguments);
+ this._childNodeInserted.bind(this);
+}
+
+WebInspector.childNodeRemoved = function()
+{
+ this.domAgent._childNodeRemoved.apply(this.domAgent, arguments);
+ this._childNodeRemoved.bind(this);
+}
+
+WebInspector.didGetChildNodes = WebInspector.Callback.processCallback;
+WebInspector.didPerformSearch = WebInspector.Callback.processCallback;
+WebInspector.didApplyDomChange = WebInspector.Callback.processCallback;
+WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback;
+WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback;
+
+// Temporary methods for DOMAgent migration.
+WebInspector.wrapNodeWithStyles = function(node, styles)
+{
+ var windowStub = new WebInspector.DOMWindow(null);
+ var docStub = new WebInspector.DOMDocument(null, windowStub);
+ var payload = {};
+ payload.nodeType = node.nodeType;
+ payload.nodeName = node.nodeName;
+ payload.nodeValue = node.nodeValue;
+ payload.attributes = [];
+ payload.childNodeCount = 0;
+
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ payload.attributes.push(attr.name);
+ payload.attributes.push(attr.value);
+ }
+ var nodeStub = new WebInspector.DOMNode(docStub, payload);
+ nodeStub._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules);
+ return nodeStub;
+}
+
+// Temporary methods that will be dispatched via InspectorController into the injected context.
+InspectorController.getStyles = function(nodeId, authorOnly, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.getStyles(nodeId, authorOnly));
+ }, 0)
+}
+
+InspectorController.getComputedStyle = function(nodeId, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.getComputedStyle(nodeId));
+ }, 0)
+}
+
+InspectorController.getInlineStyle = function(nodeId, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.getInlineStyle(nodeId));
+ }, 0)
+}
+
+InspectorController.applyStyleText = function(styleId, styleText, propertyName, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.applyStyleText(styleId, styleText, propertyName));
+ }, 0)
+}
+
+InspectorController.setStyleText = function(style, cssText, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.setStyleText(style, cssText));
+ }, 0)
+}
+
+InspectorController.toggleStyleEnabled = function(styleId, propertyName, disabled, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.toggleStyleEnabled(styleId, propertyName, disabled));
+ }, 0)
+}
+
+InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNode, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNode));
+ }, 0)
+}
+
+InspectorController.addStyleSelector = function(newContent, callback)
+{
+ setTimeout(function() {
+ callback(InjectedScript.addStyleSelector(newContent));
+ }, 0)
+}
+
+InspectorController.setStyleProperty = function(styleId, name, value, callback) {
+ setTimeout(function() {
+ callback(InjectedScript.setStyleProperty(styleId, name, value));
+ }, 0)
+}
+
+InspectorController.getPrototypes = function(objectProxy, callback) {
+ setTimeout(function() {
+ callback(InjectedScript.getPrototypes(objectProxy));
+ }, 0)
+}
+
+InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) {
+ setTimeout(function() {
+ callback(InjectedScript.getProperties(objectProxy, ignoreHasOwnProperty));
+ }, 0)
+}
+
+InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) {
+ setTimeout(function() {
+ callback(InjectedScript.setPropertyValue(objectProxy, propertyName, expression));
+ }, 0)
+}
+
diff --git a/WebCore/inspector/front-end/DOMStorageDataGrid.js b/WebCore/inspector/front-end/DOMStorageDataGrid.js
index 9946415..0326bc7 100644
--- a/WebCore/inspector/front-end/DOMStorageDataGrid.js
+++ b/WebCore/inspector/front-end/DOMStorageDataGrid.js
@@ -38,39 +38,93 @@ WebInspector.DOMStorageDataGrid.prototype = {
return;
this._startEditing(event);
},
-
+
+ _startEditingColumnOfDataGridNode: function(node, column)
+ {
+ this._editing = true;
+ this._editingNode = node;
+ this._editingNode.select();
+ WebInspector.panels.databases._unregisterStorageEventListener();
+
+ var element = this._editingNode._element.children[column];
+ WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
+ window.getSelection().setBaseAndExtent(element, 0, element, 1);
+ },
+
_startEditing: function(event)
{
var element = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!element)
return;
+
this._editingNode = this.dataGridNodeFromEvent(event);
- if (!this._editingNode)
- return;
+ if (!this._editingNode) {
+ if (!this.creationNode)
+ return;
+ this._editingNode = this.creationNode;
+ }
+
+ // Force editing the "Key" column when editing the creation node
+ if (this._editingNode.isCreationNode)
+ return this._startEditingColumnOfDataGridNode(this._editingNode, 0);
+
this._editing = true;
-
+ WebInspector.panels.databases._unregisterStorageEventListener();
WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},
-
- _editingCommitted: function(element, newText)
+
+ _editingCommitted: function(element, newText, oldText, context, moveDirection)
{
- if (element.hasStyleClass("0-column"))
- columnIdentifier = 0;
- else
- columnIdentifier = 1;
- textBeforeEditing = this._editingNode.data[columnIdentifier];
+ var columnIdentifier = (element.hasStyleClass("0-column") ? 0 : 1);
+ var textBeforeEditing = this._editingNode.data[columnIdentifier];
+ var currentEditingNode = this._editingNode;
+
+ function moveToNextIfNeeded(wasChange) {
+ if (!moveDirection)
+ return;
+
+ if (moveDirection === "forward") {
+ if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange)
+ return;
+
+ if (columnIdentifier === 0)
+ return this._startEditingColumnOfDataGridNode(currentEditingNode, 1);
+
+ var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true);
+ if (nextDataGridNode)
+ return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0);
+ if (currentEditingNode.isCreationNode && wasChange) {
+ addCreationNode(false);
+ return this._startEditingColumnOfDataGridNode(this.creationNode, 0);
+ }
+ return;
+ }
+
+ if (moveDirection === "backward") {
+ if (columnIdentifier === 1)
+ return this._startEditingColumnOfDataGridNode(currentEditingNode, 0);
+ var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true);
+
+ if (nextDataGridNode)
+ return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1);
+ return;
+ }
+ }
+
if (textBeforeEditing == newText) {
this._editingCancelled(element);
+ moveToNextIfNeeded.call(this, false);
return;
}
-
+
var domStorage = WebInspector.panels.databases.visibleView.domStorage.domStorage;
if (domStorage) {
if (columnIdentifier == 0) {
if (domStorage.getItem(newText) != null) {
element.textContent = this._editingNode.data[0];
this._editingCancelled(element);
+ moveToNextIfNeeded.call(this, false);
return;
}
domStorage.removeItem(this._editingNode.data[0]);
@@ -81,19 +135,27 @@ WebInspector.DOMStorageDataGrid.prototype = {
this._editingNode.data[1] = newText;
}
}
-
+
+ if (this._editingNode.isCreationNode)
+ this.addCreationNode(false);
+
this._editingCancelled(element);
+ moveToNextIfNeeded.call(this, true);
},
-
+
_editingCancelled: function(element, context)
{
delete this._editing;
this._editingNode = null;
+ WebInspector.panels.databases._registerStorageEventListener();
},
-
+
deleteSelectedRow: function()
{
var node = this.selectedNode;
+ if (this.selectedNode.isCreationNode)
+ return;
+
var domStorage = WebInspector.panels.databases.visibleView.domStorage.domStorage;
if (node && domStorage)
domStorage.removeItem(node.data[0]);
diff --git a/WebCore/inspector/front-end/DOMStorageItemsView.js b/WebCore/inspector/front-end/DOMStorageItemsView.js
index 912573e..fad6e3c 100644
--- a/WebCore/inspector/front-end/DOMStorageItemsView.js
+++ b/WebCore/inspector/front-end/DOMStorageItemsView.js
@@ -75,6 +75,7 @@ WebInspector.DOMStorageItemsView.prototype = {
else {
this._dataGrid = dataGrid;
this.element.appendChild(dataGrid.element);
+ this._dataGrid.updateWidths();
this.deleteButton.removeStyleClass("hidden");
}
}
@@ -89,6 +90,12 @@ WebInspector.DOMStorageItemsView.prototype = {
this.deleteButton.addStyleClass("hidden");
}
},
+
+ resize: function()
+ {
+ if (this._dataGrid)
+ this._dataGrid.updateWidths();
+ },
_deleteButtonClicked: function(event)
{
diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js
index 2fcb08c..42e001c 100644
--- a/WebCore/inspector/front-end/DataGrid.js
+++ b/WebCore/inspector/front-end/DataGrid.js
@@ -89,7 +89,8 @@ WebInspector.DataGrid = function(columns)
cell.className = "corner";
headerRow.appendChild(cell);
- this._headerTable.appendChild(columnGroup);
+ this._headerTableColumnGroup = columnGroup;
+ this._headerTable.appendChild(this._headerTableColumnGroup);
this.headerTableBody.appendChild(headerRow);
var fillerRow = document.createElement("tr");
@@ -99,8 +100,9 @@ WebInspector.DataGrid = function(columns)
var cell = document.createElement("td");
fillerRow.appendChild(cell);
}
-
- this._dataTable.appendChild(columnGroup.cloneNode(true));
+
+ this._dataTableColumnGroup = columnGroup.cloneNode(true);
+ this._dataTable.appendChild(this._dataTableColumnGroup);
this.dataTableBody.appendChild(fillerRow);
this.columns = columns || {};
@@ -114,6 +116,8 @@ WebInspector.DataGrid = function(columns)
this.selected = false;
this.dataGrid = this;
this.indentWidth = 15;
+ this.resizers = [];
+ this.columnWidthsInitialized = false;
}
WebInspector.DataGrid.prototype = {
@@ -160,6 +164,75 @@ WebInspector.DataGrid.prototype = {
return this._dataTableBody;
},
+
+ // Updates the widths of the table, including the positions of the column
+ // resizers.
+ //
+ // IMPORTANT: This function MUST be called once after the element of the
+ // DataGrid is attached to its parent element and every subsequent time the
+ // width of the parent element is changed in order to make it possible to
+ // resize the columns.
+ //
+ // If this function is not called after the DataGrid is attached to its
+ // parent element, then the DataGrid's columns will not be resizable.
+ updateWidths: function()
+ {
+ var headerTableColumns = this._headerTableColumnGroup.children;
+
+ var left = 0;
+ var tableWidth = this._dataTable.offsetWidth;
+ var numColumns = headerTableColumns.length;
+
+ if (!this.columnWidthsInitialized) {
+ // Give all the columns initial widths now so that during a resize,
+ // when the two columns that get resized get a percent value for
+ // their widths, all the other columns already have percent values
+ // for their widths.
+ for (var i = 0; i < numColumns; i++) {
+ var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth;
+ var percentWidth = ((columnWidth / tableWidth) * 100) + "%";
+ this._headerTableColumnGroup.children[i].style.width = percentWidth;
+ this._dataTableColumnGroup.children[i].style.width = percentWidth;
+ }
+ this.columnWidthsInitialized = true;
+ }
+
+ // Make n - 1 resizers for n columns.
+ for (var i = 0; i < numColumns - 1; i++) {
+ var resizer = this.resizers[i];
+
+ if (!resizer) {
+ // This is the first call to updateWidth, so the resizers need
+ // to be created.
+ resizer = document.createElement("div");
+ resizer.addStyleClass("data-grid-resizer");
+ // This resizer is associated with the column to its right.
+ resizer.rightNeighboringColumnID = i + 1;
+ resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
+ this.element.appendChild(resizer);
+ this.resizers[i] = resizer;
+ }
+
+ // Get the width of the cell in the first (and only) row of the
+ // header table in order to determine the width of the column, since
+ // it is not possible to query a column for its width.
+ left += this.headerTableBody.rows[0].cells[i].offsetWidth;
+
+ resizer.style.left = left + "px";
+ }
+ },
+
+ addCreationNode: function(hasChildren)
+ {
+ if (this.creationNode)
+ this.creationNode.makeNormal();
+
+ var emptyData = {};
+ for (var column in this.columns)
+ emptyData[column] = '';
+ this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren);
+ this.appendChild(this.creationNode);
+ },
appendChild: function(child)
{
@@ -429,7 +502,63 @@ WebInspector.DataGrid.prototype = {
else
gridNode.expand();
}
- }
+ },
+
+ _startResizerDragging: function(event)
+ {
+ this.currentResizer = event.target;
+ if (!this.currentResizer.rightNeighboringColumnID)
+ return;
+ WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bind(this),
+ this._endResizerDragging.bind(this), event, "col-resize");
+ },
+
+ _resizerDragging: function(event)
+ {
+ var resizer = this.currentResizer;
+ if (!resizer)
+ return;
+
+ // Constrain the dragpoint to be within the containing div of the
+ // datagrid.
+ var dragPoint = event.clientX - this.element.totalOffsetLeft;
+ // Constrain the dragpoint to be within the space made up by the
+ // column directly to the left and the column directly to the right.
+ var leftEdgeOfPreviousColumn = 0;
+ var firstRowCells = this.headerTableBody.rows[0].cells;
+ for (var i = 0; i < resizer.rightNeighboringColumnID - 1; i++)
+ leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
+
+ var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.rightNeighboringColumnID - 1].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth;
+
+ // Give each column some padding so that they don't disappear.
+ var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding;
+ var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding;
+
+ dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
+
+ resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
+
+ var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%";
+ this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
+ this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
+
+ var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%";
+ this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
+ this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
+
+ event.preventDefault();
+ },
+
+ _endResizerDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ this.currentResizer = null;
+ },
+
+ ColumnResizePadding: 10,
+
+ CenterResizerOverBorderAdjustment: 3,
}
WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;
@@ -883,3 +1012,19 @@ WebInspector.DataGridNode.prototype = {
}
WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.CreationDataGridNode = function(data, hasChildren)
+{
+ WebInspector.DataGridNode.call(this, data, hasChildren);
+ this.isCreationNode = true;
+}
+
+WebInspector.CreationDataGridNode.prototype = {
+ makeNormal: function()
+ {
+ delete this.isCreationNode;
+ delete this.makeNormal;
+ }
+}
+
+WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/WebCore/inspector/front-end/DatabaseQueryView.js b/WebCore/inspector/front-end/DatabaseQueryView.js
index 122707f..429c2c3 100644
--- a/WebCore/inspector/front-end/DatabaseQueryView.js
+++ b/WebCore/inspector/front-end/DatabaseQueryView.js
@@ -58,7 +58,7 @@ WebInspector.DatabaseQueryView.prototype = {
setTimeout(moveBackIfOutside.bind(this), 0);
},
- completions: function(wordRange, bestMatchOnly)
+ completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
{
var prefix = wordRange.toString().toLowerCase();
if (!prefix.length)
@@ -85,7 +85,7 @@ WebInspector.DatabaseQueryView.prototype = {
accumulateMatches(this.database.tableNames.map(function(name) { return name + " " }));
accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
- return results;
+ completionsReadyCallback(results);
},
_promptKeyDown: function(event)
@@ -157,7 +157,7 @@ WebInspector.DatabaseQueryView.prototype = {
else if (error.code == 2)
var message = WebInspector.UIString("Database no longer has expected version.");
else
- var message = WebInspector.UIString("An unexpected error %s occured.", error.code);
+ var message = WebInspector.UIString("An unexpected error %s occurred.", error.code);
this._appendQueryResult(query, message, "error");
},
diff --git a/WebCore/inspector/front-end/DatabasesPanel.js b/WebCore/inspector/front-end/DatabasesPanel.js
index 4644b3b..a31e3ff 100644
--- a/WebCore/inspector/front-end/DatabasesPanel.js
+++ b/WebCore/inspector/front-end/DatabasesPanel.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -85,6 +86,7 @@ WebInspector.DatabasesPanel.prototype = {
{
WebInspector.Panel.prototype.show.call(this);
this._updateSidebarWidth();
+ this._registerStorageEventListener();
},
reset: function()
@@ -101,6 +103,8 @@ WebInspector.DatabasesPanel.prototype = {
this._databases = [];
+ this._unregisterStorageEventListener();
+
if (this._domStorage) {
var domStorageLength = this._domStorage.length;
for (var i = 0; i < domStorageLength; ++i) {
@@ -145,6 +149,32 @@ WebInspector.DatabasesPanel.prototype = {
this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
},
+ selectDatabase: function(db)
+ {
+ var database;
+ for (var i = 0, len = this._databases.length; i < len; ++i) {
+ database = this._databases[i];
+ if ( db === database.database ) {
+ this.showDatabase(database);
+ database._databasesTreeElement.select();
+ return;
+ }
+ }
+ },
+
+ selectDOMStorage: function(s)
+ {
+ var isLocalStorage = (s === InspectorController.inspectedWindow().localStorage);
+ for (var i = 0, len = this._domStorage.length; i < len; ++i) {
+ var storage = this._domStorage[i];
+ if ( isLocalStorage === storage.isLocalStorage ) {
+ this.showDOMStorage(storage);
+ storage._domStorageTreeElement.select();
+ return;
+ }
+ }
+ },
+
showDatabase: function(database, tableName)
{
if (!database)
@@ -175,7 +205,7 @@ WebInspector.DatabasesPanel.prototype = {
this.visibleView = view;
this.storageViewStatusBarItemsContainer.removeChildren();
- var statusBarItems = view.statusBarItems;
+ var statusBarItems = view.statusBarItems || [];
for (var i = 0; i < statusBarItems.length; ++i)
this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},
@@ -332,7 +362,7 @@ WebInspector.DatabasesPanel.prototype = {
var nodes = [];
var length = domStorage.length;
- for (index = 0; index < domStorage.length; index++) {
+ for (var index = 0; index < domStorage.length; index++) {
var data = {};
var key = String(domStorage.key(index));
@@ -365,10 +395,58 @@ WebInspector.DatabasesPanel.prototype = {
var length = nodes.length;
for (var i = 0; i < length; ++i)
dataGrid.appendChild(nodes[i]);
+ dataGrid.addCreationNode(false);
if (length > 0)
nodes[0].selected = true;
return dataGrid;
},
+
+ resize: function()
+ {
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
+
+ _registerStorageEventListener: function()
+ {
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow || !inspectedWindow.document)
+ return;
+
+ this._storageEventListener = InspectorController.wrapCallback(this._storageEvent.bind(this));
+ inspectedWindow.addEventListener("storage", this._storageEventListener, true);
+ },
+
+ _unregisterStorageEventListener: function()
+ {
+ if (!this._storageEventListener)
+ return;
+
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow || !inspectedWindow.document)
+ return;
+
+ inspectedWindow.removeEventListener("storage", this._storageEventListener, true);
+ delete this._storageEventListener;
+ },
+
+ _storageEvent: function(event)
+ {
+ if (!this._domStorage)
+ return;
+
+ var isLocalStorage = (event.storageArea === InspectorController.inspectedWindow().localStorage);
+ var domStorageLength = this._domStorage.length;
+ for (var i = 0; i < domStorageLength; ++i) {
+ var domStorage = this._domStorage[i];
+ if (isLocalStorage === domStorage.isLocalStorage) {
+ var view = domStorage._domStorageView;
+ if (this.visibleView && view === this.visibleView)
+ domStorage._domStorageView.update();
+ }
+ }
+ },
_startSidebarDragging: function(event)
{
@@ -409,6 +487,10 @@ WebInspector.DatabasesPanel.prototype = {
this.storageViews.style.left = width + "px";
this.storageViewStatusBarItemsContainer.style.left = width + "px";
this.sidebarResizeElement.style.left = (width - 3) + "px";
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
}
}
diff --git a/WebCore/inspector/front-end/Drawer.js b/WebCore/inspector/front-end/Drawer.js
new file mode 100644
index 0000000..23dc483
--- /dev/null
+++ b/WebCore/inspector/front-end/Drawer.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Drawer = function()
+{
+ WebInspector.View.call(this, document.getElementById("drawer"));
+
+ this.mainStatusBar = document.getElementById("main-status-bar");
+ this.mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
+ this.viewStatusBar = document.getElementById("other-drawer-status-bar-items");
+}
+
+WebInspector.Drawer.prototype = {
+ get visibleView()
+ {
+ return this._visibleView;
+ },
+
+ set visibleView(x)
+ {
+ if (this._visibleView === x) {
+ this.visible = !this.visible;
+ return;
+ }
+
+ var firstTime = !this._visibleView;
+ if (this._visibleView)
+ this._visibleView.hide();
+
+ this._visibleView = x;
+
+ if (x && !firstTime) {
+ this._safelyRemoveChildren();
+ this.viewStatusBar.removeChildren(); // optimize this? call old.detach()
+ x.attach(this.element, this.viewStatusBar);
+ x.show();
+ this.visible = true;
+ }
+ },
+
+ show: function()
+ {
+ if (this._animating || this.visible)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.show();
+
+ WebInspector.View.prototype.show.call(this);
+
+ this._animating = true;
+
+ document.body.addStyleClass("drawer-visible");
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
+ {element: document.getElementById("other-drawer-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}}
+ ];
+
+ var consoleStatusBar = document.getElementById("drawer-status-bar");
+ consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild);
+
+ function animationFinished()
+ {
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ if (this.visibleView.afterShow)
+ this.visibleView.afterShow();
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ },
+
+ hide: function()
+ {
+ if (this._animating || !this.visible)
+ return;
+
+ WebInspector.View.prototype.hide.call(this);
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ this._animating = true;
+
+ if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ // Temporally set properties and classes to mimic the post-animation values so panels
+ // like Elements in their updateStatusBarItems call will size things to fit the final location.
+ document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
+ document.body.removeStyleClass("drawer-visible");
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ document.body.addStyleClass("drawer-visible");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: 0}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
+ {element: document.getElementById("other-drawer-status-bar-items"), start: {opacity: 1}, end: {opacity: 0}}
+ ];
+
+ function animationFinished()
+ {
+ var mainStatusBar = document.getElementById("main-status-bar");
+ mainStatusBar.insertBefore(anchoredItems, mainStatusBar.firstChild);
+ mainStatusBar.style.removeProperty("padding-left");
+ document.body.removeStyleClass("drawer-visible");
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ },
+
+ _safelyRemoveChildren: function()
+ {
+ var child = this.element.firstChild;
+ while (child) {
+ if (child.id !== "drawer-status-bar") {
+ var moveTo = child.nextSibling;
+ this.element.removeChild(child);
+ child = moveTo;
+ } else
+ child = child.nextSibling;
+ }
+ },
+
+ _startStatusBarDragging: function(event)
+ {
+ if (!this.visible || event.target !== document.getElementById("main-status-bar"))
+ return;
+
+ WebInspector.elementDragStart(document.getElementById("main-status-bar"), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");
+
+ this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;
+
+ event.stopPropagation();
+ },
+
+ _statusBarDragging: function(event)
+ {
+ var mainElement = document.getElementById("main");
+
+ var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
+ height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+
+ mainElement.style.bottom = height + "px";
+ this.element.style.height = height + "px";
+
+ event.preventDefault();
+ event.stopPropagation();
+ },
+
+ _endStatusBarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this._statusBarDragOffset;
+
+ event.stopPropagation();
+ }
+}
+
+WebInspector.Drawer.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js
index 3c9be54..ffa0000 100644
--- a/WebCore/inspector/front-end/ElementsPanel.js
+++ b/WebCore/inspector/front-end/ElementsPanel.js
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,6 +61,7 @@ WebInspector.ElementsPanel = function()
InspectorController.toggleNodeSearch();
this.panel.nodeSearchButton.removeStyleClass("toggled-on");
}
+ WebInspector.console.addInspectedNode(this._focusedDOMNode);
};
this.contentElement.appendChild(this.treeOutline.element);
@@ -95,7 +97,7 @@ WebInspector.ElementsPanel = function()
this.sidebarResizeElement.className = "sidebar-resizer-vertical";
this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
- this.nodeSearchButton = document.createElement("button");
+ this.nodeSearchButton = this.createStatusBarButton();
this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it.");
this.nodeSearchButton.id = "node-search-status-bar-item";
this.nodeSearchButton.className = "status-bar-item";
@@ -112,6 +114,9 @@ WebInspector.ElementsPanel = function()
this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this));
this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this));
+ this.stylesheet = null;
+ this.styles = {};
+
this.reset();
}
@@ -179,7 +184,7 @@ WebInspector.ElementsPanel.prototype = {
delete this.currentQuery;
this.searchCanceled();
- var inspectedWindow = InspectorController.inspectedWindow();
+ var inspectedWindow = Preferences.useDOMAgent ? WebInspector.domAgent.inspectedWindow : InspectorController.inspectedWindow();
if (!inspectedWindow || !inspectedWindow.document)
return;
@@ -516,6 +521,121 @@ WebInspector.ElementsPanel.prototype = {
this.updateMutationEventListeners(window);
},
+ renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector)
+ {
+ // TODO: Implement Shifting the oldSelector, and its contents to a newSelector
+ },
+
+ addStyleChange: function(identifier, style, property)
+ {
+ if (!style.parentRule)
+ return;
+
+ var selector = style.parentRule.selectorText;
+ if (!this.styles[identifier])
+ this.styles[identifier] = {};
+
+ if (!this.styles[identifier][selector])
+ this.styles[identifier][selector] = {};
+
+ if (!this.styles[identifier][selector][property])
+ WebInspector.styleChanges += 1;
+
+ this.styles[identifier][selector][property] = style.getPropertyValue(property);
+ },
+
+ removeStyleChange: function(identifier, style, property)
+ {
+ if (!style.parentRule)
+ return;
+
+ var selector = style.parentRule.selectorText;
+ if (!this.styles[identifier] || !this.styles[identifier][selector])
+ return;
+
+ if (this.styles[identifier][selector][property]) {
+ delete this.styles[identifier][selector][property];
+ WebInspector.styleChanges -= 1;
+ }
+ },
+
+ generateStylesheet: function()
+ {
+ if (!WebInspector.styleChanges)
+ return;
+
+ // Merge Down to Just Selectors
+ var mergedSelectors = {};
+ for (var identifier in this.styles) {
+ for (var selector in this.styles[identifier]) {
+ if (!mergedSelectors[selector])
+ mergedSelectors[selector] = this.styles[identifier][selector];
+ else { // merge on selector
+ var merge = {};
+ for (var property in mergedSelectors[selector])
+ merge[property] = mergedSelectors[selector][property];
+ for (var property in this.styles[identifier][selector]) {
+ if (!merge[property])
+ merge[property] = this.styles[identifier][selector][property];
+ else { // merge on property within a selector, include comment to notify user
+ var value1 = merge[property];
+ var value2 = this.styles[identifier][selector][property];
+
+ if (value1 === value2)
+ merge[property] = [value1];
+ else if (Object.type(value1) === "array")
+ merge[property].push(value2);
+ else
+ merge[property] = [value1, value2];
+ }
+ }
+ mergedSelectors[selector] = merge;
+ }
+ }
+ }
+
+ var builder = [];
+ builder.push("/**");
+ builder.push(" * Inspector Generated Stylesheet"); // UIString?
+ builder.push(" */\n");
+
+ var indent = " ";
+ function displayProperty(property, value, comment) {
+ if (comment)
+ return indent + "/* " + property + ": " + value + "; */";
+ else
+ return indent + property + ": " + value + ";";
+ }
+
+ for (var selector in mergedSelectors) {
+ var psuedoStyle = mergedSelectors[selector];
+ var properties = Object.properties(psuedoStyle);
+ if (properties.length) {
+ builder.push(selector + " {");
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i];
+ var value = psuedoStyle[property];
+ if (Object.type(value) !== "array")
+ builder.push(displayProperty(property, value));
+ else {
+ if (value.length === 1)
+ builder.push(displayProperty(property, value) + " /* merged from equivalent edits */"); // UIString?
+ else {
+ builder.push(indent + "/* There was a Conflict... There were Multiple Edits for '" + property + "' */"); // UIString?
+ for (var j = 0; j < value.length; ++j)
+ builder.push(displayProperty(property, value, true));
+ }
+ }
+ }
+ builder.push("}\n");
+ }
+ }
+
+ WebInspector.showConsole();
+ var result = builder.join("\n");
+ InspectorController.inspectedWindow().console.log(result);
+ },
+
_addMutationEventListeners: function(monitoredWindow)
{
monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
@@ -913,7 +1033,7 @@ WebInspector.ElementsPanel.prototype = {
{
var rightPadding = 20;
var errorWarningElement = document.getElementById("error-warning-count");
- if (!WebInspector.console.visible && errorWarningElement)
+ if (!WebInspector.drawer.visible && errorWarningElement)
rightPadding += errorWarningElement.offsetWidth;
return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth);
}
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index 2da2f10..ef53209 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -255,6 +256,9 @@ WebInspector.ElementsTreeElement = function(node)
// The title will be updated in onattach.
TreeElement.call(this, "", node, titleInfo.hasChildren);
+
+ if (this.representedObject.nodeType == Node.ELEMENT_NODE)
+ this._canAddAttributes = true;
}
WebInspector.ElementsTreeElement.prototype = {
@@ -296,9 +300,36 @@ WebInspector.ElementsTreeElement.prototype = {
this.listItemElement.addStyleClass("hovered");
} else
this.listItemElement.removeStyleClass("hovered");
+ if (this._canAddAttributes)
+ this.toggleNewAttributeButton();
}
},
+ toggleNewAttributeButton: function()
+ {
+ function removeWhenEditing(event)
+ {
+ if (this._addAttributeElement && this._addAttributeElement.parentNode)
+ this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
+ delete this._addAttributeElement;
+ }
+
+ if (!this._addAttributeElement && this._hovered && !this._editing) {
+ var span = document.createElement("span");
+ span.className = "add-attribute";
+ span.textContent = "\u2026";
+ span.addEventListener("dblclick", removeWhenEditing.bind(this), false);
+ this._addAttributeElement = span;
+
+ var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
+ this._insertInLastAttributePosition(tag, span);
+ } else if (!this._hovered && this._addAttributeElement) {
+ if (this._addAttributeElement.parentNode)
+ this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
+ delete this._addAttributeElement;
+ }
+ },
+
updateSelection: function()
{
var listItemElement = this.listItemElement;
@@ -483,7 +514,7 @@ WebInspector.ElementsTreeElement.prototype = {
if (this._editing)
return;
- if (this._startEditing(event))
+ if (this._startEditing(event, treeElement))
return;
if (this.treeOutline.panel) {
@@ -495,7 +526,20 @@ WebInspector.ElementsTreeElement.prototype = {
this.expand();
},
- _startEditing: function(event)
+ _insertInLastAttributePosition: function(tag, node)
+ {
+ if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
+ tag.insertBefore(node, tag.lastChild);
+ else {
+ var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
+ tag.textContent = '';
+ tag.appendChild(document.createTextNode('<'+nodeName));
+ tag.appendChild(node);
+ tag.appendChild(document.createTextNode('>'));
+ }
+ },
+
+ _startEditing: function(event, treeElement)
{
if (this.treeOutline.focusedDOMNode != this.representedObject)
return;
@@ -509,12 +553,51 @@ WebInspector.ElementsTreeElement.prototype = {
var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
if (attribute)
- return this._startEditingAttribute(attribute, event);
+ return this._startEditingAttribute(attribute, event.target);
+
+ var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");
+ if (newAttribute)
+ return this._addNewAttribute(treeElement.listItemElement);
return false;
},
- _startEditingAttribute: function(attribute, event)
+ _addNewAttribute: function(listItemElement)
+ {
+ var attr = document.createElement("span");
+ attr.className = "webkit-html-attribute";
+ attr.style.marginLeft = "2px"; // overrides the .editing margin rule
+ attr.style.marginRight = "2px"; // overrides the .editing margin rule
+ var name = document.createElement("span");
+ name.className = "webkit-html-attribute-name new-attribute";
+ name.textContent = " ";
+ var value = document.createElement("span");
+ value.className = "webkit-html-attribute-value";
+ attr.appendChild(name);
+ attr.appendChild(value);
+
+ var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0];
+ this._insertInLastAttributePosition(tag, attr);
+ return this._startEditingAttribute(attr, attr);
+ },
+
+ _triggerEditAttribute: function(attributeName)
+ {
+ var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
+ for (var i = 0, len = attributeElements.length; i < len; ++i) {
+ if (attributeElements[i].textContent === attributeName) {
+ for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
+ if (elem.nodeType !== Node.ELEMENT_NODE)
+ continue;
+
+ if (elem.hasStyleClass("webkit-html-attribute-value"))
+ return this._startEditingAttribute(attributeElements[i].parentNode, elem);
+ }
+ }
+ }
+ },
+
+ _startEditingAttribute: function(attribute, elementForSelection)
{
if (WebInspector.isBeingEdited(attribute))
return true;
@@ -545,7 +628,7 @@ WebInspector.ElementsTreeElement.prototype = {
this._editing = true;
WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
- window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1);
+ window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
return true;
},
@@ -563,15 +646,56 @@ WebInspector.ElementsTreeElement.prototype = {
return true;
},
- _attributeEditingCommitted: function(element, newText, oldText, attributeName)
+ _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
{
delete this._editing;
+ // Before we do anything, determine where we should move
+ // next based on the current element's settings
+ var moveToAttribute;
+ var newAttribute;
+ if (moveDirection) {
+ var found = false;
+ var attributes = this.representedObject.attributes;
+ for (var i = 0, len = attributes.length; i < len; ++i) {
+ if (attributes[i].name === attributeName) {
+ found = true;
+ if (moveDirection === "backward" && i > 0)
+ moveToAttribute = attributes[i - 1].name;
+ else if (moveDirection === "forward" && i < attributes.length - 1)
+ moveToAttribute = attributes[i + 1].name;
+ else if (moveDirection === "forward" && i === attributes.length - 1)
+ newAttribute = true;
+ }
+ }
+
+ if (!found && moveDirection === "backward")
+ moveToAttribute = attributes[attributes.length - 1].name;
+ else if (!found && moveDirection === "forward" && !/^\s*$/.test(newText))
+ newAttribute = true;
+ }
+
+ function moveToNextAttributeIfNeeded() {
+ if (moveToAttribute)
+ this._triggerEditAttribute(moveToAttribute);
+ else if (newAttribute)
+ this._addNewAttribute(this.listItemElement);
+ }
+
var parseContainerElement = document.createElement("span");
parseContainerElement.innerHTML = "<span " + newText + "></span>";
var parseElement = parseContainerElement.firstChild;
- if (!parseElement || !parseElement.hasAttributes()) {
- this._editingCancelled(element, context);
+
+ if (!parseElement) {
+ this._editingCancelled(element, attributeName);
+ moveToNextAttributeIfNeeded.call(this);
+ return;
+ }
+
+ if (!parseElement.hasAttributes()) {
+ InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
+ this._updateTitle();
+ moveToNextAttributeIfNeeded.call(this);
return;
}
@@ -579,7 +703,9 @@ WebInspector.ElementsTreeElement.prototype = {
for (var i = 0; i < parseElement.attributes.length; ++i) {
var attr = parseElement.attributes[i];
foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
- InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
+ try {
+ InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
+ } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
}
if (!foundOriginalAttribute)
@@ -588,6 +714,8 @@ WebInspector.ElementsTreeElement.prototype = {
this._updateTitle();
this.treeOutline.focusedNodeChanged(true);
+
+ moveToNextAttributeIfNeeded.call(this);
},
_textNodeEditingCommitted: function(element, newText)
diff --git a/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png b/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png
new file mode 100644
index 0000000..b1f9465
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/clearConsoleButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/clearConsoleButtons.png b/WebCore/inspector/front-end/Images/clearConsoleButtons.png
deleted file mode 100644
index 140a4fb..0000000
--- a/WebCore/inspector/front-end/Images/clearConsoleButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/consoleButtonGlyph.png b/WebCore/inspector/front-end/Images/consoleButtonGlyph.png
new file mode 100644
index 0000000..d10d43c
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/consoleButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/consoleButtons.png b/WebCore/inspector/front-end/Images/consoleButtons.png
deleted file mode 100644
index fb5f089..0000000
--- a/WebCore/inspector/front-end/Images/consoleButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/dockButtonGlyph.png b/WebCore/inspector/front-end/Images/dockButtonGlyph.png
new file mode 100644
index 0000000..7052f4b
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/dockButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/dockButtons.png b/WebCore/inspector/front-end/Images/dockButtons.png
deleted file mode 100644
index 4b01d66..0000000
--- a/WebCore/inspector/front-end/Images/dockButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/enableButtons.png b/WebCore/inspector/front-end/Images/enableButtons.png
deleted file mode 100644
index facee60..0000000
--- a/WebCore/inspector/front-end/Images/enableButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png b/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png
new file mode 100644
index 0000000..85e0bd6
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/enableOutlineButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png b/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png
new file mode 100644
index 0000000..25b2e96
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/enableSolidButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/excludeButtonGlyph.png b/WebCore/inspector/front-end/Images/excludeButtonGlyph.png
new file mode 100644
index 0000000..5128576
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/excludeButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/excludeButtons.png b/WebCore/inspector/front-end/Images/excludeButtons.png
deleted file mode 100644
index f1c53a9..0000000
--- a/WebCore/inspector/front-end/Images/excludeButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/focusButtonGlyph.png b/WebCore/inspector/front-end/Images/focusButtonGlyph.png
new file mode 100644
index 0000000..b71807c
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/focusButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/focusButtons.png b/WebCore/inspector/front-end/Images/focusButtons.png
deleted file mode 100644
index 47eaa04..0000000
--- a/WebCore/inspector/front-end/Images/focusButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png b/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png
new file mode 100644
index 0000000..71256d6
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/largerResourcesButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/largerResourcesButtons.png b/WebCore/inspector/front-end/Images/largerResourcesButtons.png
deleted file mode 100644
index caf3f14..0000000
--- a/WebCore/inspector/front-end/Images/largerResourcesButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png b/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png
new file mode 100644
index 0000000..faf5df2
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/nodeSearchButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/nodeSearchButtons.png b/WebCore/inspector/front-end/Images/nodeSearchButtons.png
deleted file mode 100644
index 0599bd4..0000000
--- a/WebCore/inspector/front-end/Images/nodeSearchButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png b/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png
new file mode 100644
index 0000000..c3cec5f
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/pauseOnExceptionButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/pauseOnExceptionButtons.png b/WebCore/inspector/front-end/Images/pauseOnExceptionButtons.png
deleted file mode 100644
index a4dd33a..0000000
--- a/WebCore/inspector/front-end/Images/pauseOnExceptionButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/percentButtonGlyph.png b/WebCore/inspector/front-end/Images/percentButtonGlyph.png
new file mode 100644
index 0000000..0ace3b7
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/percentButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/percentButtons.png b/WebCore/inspector/front-end/Images/percentButtons.png
deleted file mode 100644
index 2635b24..0000000
--- a/WebCore/inspector/front-end/Images/percentButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/recordButtonGlyph.png b/WebCore/inspector/front-end/Images/recordButtonGlyph.png
new file mode 100644
index 0000000..bfdad1a
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/recordButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/recordButtons.png b/WebCore/inspector/front-end/Images/recordButtons.png
deleted file mode 100644
index 3676154..0000000
--- a/WebCore/inspector/front-end/Images/recordButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png b/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png
new file mode 100644
index 0000000..2c22f87
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/recordToggledButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/reloadButtonGlyph.png b/WebCore/inspector/front-end/Images/reloadButtonGlyph.png
new file mode 100644
index 0000000..28e047a
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/reloadButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/reloadButtons.png b/WebCore/inspector/front-end/Images/reloadButtons.png
deleted file mode 100644
index 1e45671..0000000
--- a/WebCore/inspector/front-end/Images/reloadButtons.png
+++ /dev/null
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/resourcesSilhouette.png b/WebCore/inspector/front-end/Images/resourcesSilhouette.png
new file mode 100644
index 0000000..9c8bb53
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/resourcesSilhouette.png
Binary files differ
diff --git a/WebCore/inspector/front-end/Images/undockButtonGlyph.png b/WebCore/inspector/front-end/Images/undockButtonGlyph.png
new file mode 100644
index 0000000..eed2b65
--- /dev/null
+++ b/WebCore/inspector/front-end/Images/undockButtonGlyph.png
Binary files differ
diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js
new file mode 100644
index 0000000..4611b48
--- /dev/null
+++ b/WebCore/inspector/front-end/InjectedScript.js
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * 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.
+ */
+
+var InjectedScript = {
+ _styles: {},
+ _styleRules: {},
+ _lastStyleId: 0,
+ _lastStyleRuleId: 0
+};
+
+InjectedScript.getStyles = function(nodeId, authorOnly)
+{
+ var node = InjectedScript._nodeForId(nodeId);
+ if (!node)
+ return false;
+ var matchedRules = InjectedScript._window().getMatchedCSSRules(node, "", authorOnly);
+ var matchedCSSRules = [];
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i)
+ matchedCSSRules.push(InjectedScript._serializeRule(matchedRules[i]));
+
+ var styleAttributes = {};
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style)
+ styleAttributes[attributes[i].name] = InjectedScript._serializeStyle(attributes[i].style, true);
+ }
+ var result = {};
+ result.inlineStyle = InjectedScript._serializeStyle(node.style, true);
+ result.computedStyle = InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node));
+ result.matchedCSSRules = matchedCSSRules;
+ result.styleAttributes = styleAttributes;
+ return result;
+}
+
+InjectedScript.getComputedStyle = function(nodeId)
+{
+ var node = InjectedScript._nodeForId(nodeId);
+ if (!node)
+ return false;
+ return InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node));
+}
+
+InjectedScript.getInlineStyle = function(nodeId)
+{
+ var node = InjectedScript._nodeForId(nodeId);
+ if (!node)
+ return false;
+ return InjectedScript._serializeStyle(node.style, true);
+}
+
+InjectedScript.applyStyleText = function(styleId, styleText, propertyName)
+{
+ var style = InjectedScript._styles[styleId];
+ if (!style)
+ return false;
+
+ var styleTextLength = styleText.length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (style.getPropertyShorthand(propertyName)) {
+ var longhandProperties = InjectedScript._getLonghandProperties(style, propertyName);
+ for (var i = 0; i < longhandProperties.length; ++i)
+ style.removeProperty(longhandProperties[i]);
+ } else
+ style.removeProperty(propertyName);
+ }
+
+ if (!tempStyle.length)
+ return false;
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var changedProperties = [];
+ var uniqueProperties = InjectedScript._getUniqueStyleProperties(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands)
+ continue;
+
+ if (shorthand) {
+ var value = InjectedScript._getShorthandValue(tempStyle, shorthand);
+ var priority = InjectedScript._getShorthandPriority(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+
+ // Set the property on the real style declaration.
+ style.setProperty((shorthand || name), value, priority);
+ changedProperties.push(shorthand || name);
+ }
+ return [InjectedScript._serializeStyle(style, true), changedProperties];
+}
+
+InjectedScript.setStyleText = function(style, cssText)
+{
+ style.cssText = cssText;
+}
+
+InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled)
+{
+ var style = InjectedScript._styles[styleId];
+ if (!style)
+ return false;
+
+ if (disabled) {
+ if (!style.__disabledPropertyValues || !style.__disabledPropertyPriorities) {
+ var inspectedWindow = InjectedScript._window();
+ style.__disabledProperties = new inspectedWindow.Object;
+ style.__disabledPropertyValues = new inspectedWindow.Object;
+ style.__disabledPropertyPriorities = new inspectedWindow.Object;
+ }
+
+ style.__disabledPropertyValues[propertyName] = style.getPropertyValue(propertyName);
+ style.__disabledPropertyPriorities[propertyName] = style.getPropertyPriority(propertyName);
+
+ if (style.getPropertyShorthand(propertyName)) {
+ var longhandProperties = InjectedScript._getLonghandProperties(style, propertyName);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.__disabledProperties[longhandProperties[i]] = true;
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.__disabledProperties[propertyName] = true;
+ style.removeProperty(propertyName);
+ }
+ } else if (style.__disabledProperties && style.__disabledProperties[propertyName]) {
+ var value = style.__disabledPropertyValues[propertyName];
+ var priority = style.__disabledPropertyPriorities[propertyName];
+
+ style.setProperty(propertyName, value, priority);
+ delete style.__disabledProperties[propertyName];
+ delete style.__disabledPropertyValues[propertyName];
+ delete style.__disabledPropertyPriorities[propertyName];
+ }
+ return InjectedScript._serializeStyle(style, true);
+}
+
+InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode)
+{
+ var rule = InjectedScript._styleRules[ruleId];
+ if (!rule)
+ return false;
+
+ try {
+ var stylesheet = rule.parentStyleSheet;
+ stylesheet.addRule(newContent);
+ var newRule = stylesheet.cssRules[stylesheet.cssRules.length - 1];
+ newRule.style.cssText = rule.style.cssText;
+
+ var parentRules = stylesheet.cssRules;
+ for (var i = 0; i < parentRules.length; ++i) {
+ if (parentRules[i] === rule) {
+ rule.parentStyleSheet.removeRule(i);
+ break;
+ }
+ }
+
+ var nodes = selectedNode.ownerDocument.querySelectorAll(newContent);
+ for (var i = 0; i < nodes.length; ++i) {
+ if (nodes[i] === selectedNode) {
+ return [InjectedScript._serializeRule(newRule), true];
+ }
+ }
+ return [InjectedScript._serializeRule(newRule), false];
+ } catch(e) {
+ // Report invalid syntax.
+ return false;
+ }
+}
+
+InjectedScript.addStyleSelector = function(newContent)
+{
+ var stylesheet = InjectedScript.stylesheet;
+ if (!stylesheet) {
+ var inspectedDocument = InjectedScript._window().document;
+ var head = inspectedDocument.getElementsByTagName("head")[0];
+ var styleElement = inspectedDocument.createElement("style");
+ styleElement.type = "text/css";
+ head.appendChild(styleElement);
+ stylesheet = inspectedDocument.styleSheets[inspectedDocument.styleSheets.length - 1];
+ InjectedScript.stylesheet = stylesheet;
+ }
+
+ try {
+ stylesheet.addRule(newContent);
+ } catch (e) {
+ // Invalid Syntax for a Selector
+ return false;
+ }
+
+ return InjectedScript._serializeRule(stylesheet.cssRules[stylesheet.cssRules.length - 1]);
+}
+
+InjectedScript.setStyleProperty = function(styleId, name, value) {
+ var style = InjectedScript._styles[styleId];
+ if (!style)
+ return false;
+
+ style.setProperty(name, value, "");
+ return true;
+}
+
+InjectedScript._serializeRule = function(rule)
+{
+ var parentStyleSheet = rule.parentStyleSheet;
+
+ var ruleValue = {};
+ ruleValue.selectorText = rule.selectorText;
+ if (parentStyleSheet) {
+ ruleValue.parentStyleSheet = {};
+ ruleValue.parentStyleSheet.href = parentStyleSheet.href;
+ }
+ ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && !parentStyleSheet.href;
+ ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentStyleSheet.ownerNode.nodeName == "#document";
+
+ // Bind editable scripts only.
+ var doBind = !ruleValue.isUserAgent && !ruleValue.isUser;
+ ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind);
+
+ if (doBind) {
+ if (!rule._id) {
+ rule._id = InjectedScript._lastStyleRuleId++;
+ InjectedScript._styleRules[rule._id] = rule;
+ }
+ ruleValue.id = rule._id;
+ }
+ return ruleValue;
+}
+
+InjectedScript._serializeStyle = function(style, doBind)
+{
+ var result = {};
+ result.width = style.width;
+ result.height = style.height;
+ result.__disabledProperties = style.__disabledProperties;
+ result.__disabledPropertyValues = style.__disabledPropertyValues;
+ result.__disabledPropertyPriorities = style.__disabledPropertyPriorities;
+ result.properties = [];
+ result.shorthandValues = {};
+ var foundShorthands = {};
+ for (var i = 0; i < style.length; ++i) {
+ var property = {};
+ var name = style[i];
+ property.name = name;
+ property.priority = style.getPropertyPriority(name);
+ property.implicit = style.isPropertyImplicit(name);
+ var shorthand = style.getPropertyShorthand(name);
+ property.shorthand = shorthand;
+ if (shorthand && !(shorthand in foundShorthands)) {
+ foundShorthands[shorthand] = true;
+ result.shorthandValues[shorthand] = InjectedScript._getShorthandValue(style, shorthand);
+ }
+ property.value = style.getPropertyValue(name);
+ result.properties.push(property);
+ }
+ result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(style);
+
+ if (doBind) {
+ if (!style._id) {
+ style._id = InjectedScript._lastStyleId++;
+ InjectedScript._styles[style._id] = style;
+ }
+ result.id = style._id;
+ }
+ return result;
+}
+
+InjectedScript._getUniqueStyleProperties = function(style)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties)
+ continue;
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+
+ return properties;
+}
+
+
+InjectedScript._getLonghandProperties = function(style, shorthandProperty)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+
+ return properties;
+}
+
+InjectedScript._getShorthandValue = function(style, shorthandProperty)
+{
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823 is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) || individualValue === "initial")
+ continue;
+
+ foundProperties[individualProperty] = true;
+
+ if (!value)
+ value = "";
+ else if (value.length)
+ value += " ";
+ value += individualValue;
+ }
+ }
+ return value;
+}
+
+InjectedScript._getShorthandPriority = function(style, shorthandProperty)
+{
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+}
+
+InjectedScript.getPrototypes = function(nodeId)
+{
+ var node = InjectedScript._nodeForId(nodeId);
+ if (!node)
+ return false;
+
+ var result = [];
+ for (var prototype = node; prototype; prototype = prototype.__proto__) {
+ var title = Object.describe(prototype);
+ if (title.match(/Prototype$/)) {
+ title = title.replace(/Prototype$/, "");
+ }
+ result.push(title);
+ }
+ return result;
+}
+
+InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty)
+{
+ var object = InjectedScript._resolveObject(objectProxy);
+ if (!object)
+ return false;
+
+ var properties = [];
+ // Go over properties, prepare results.
+ for (var propertyName in object) {
+ if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
+ continue;
+
+ //TODO: remove this once object becomes really remote.
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ var property = {};
+ property.name = propertyName;
+ var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName);
+ if (!property.isGetter) {
+ var childObject = object[propertyName];
+ property.type = typeof childObject;
+ property.textContent = Object.describe(childObject, true);
+ property.parentObjectProxy = objectProxy;
+ var parentPath = objectProxy.path.slice();
+ property.childObjectProxy = {
+ objectId : objectProxy.objectId,
+ path : parentPath.splice(parentPath.length, 0, propertyName),
+ protoDepth : objectProxy.protoDepth
+ };
+ if (childObject && (property.type === "object" || property.type === "function")) {
+ for (var subPropertyName in childObject) {
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ property.hasChildren = true;
+ break;
+ }
+ }
+ } else {
+ // FIXME: this should show something like "getter" (bug 16734).
+ property.textContent = "\u2014"; // em dash
+ property.isGetter = true;
+ }
+ properties.push(property);
+ }
+ return properties;
+}
+
+InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression)
+{
+ var object = InjectedScript._resolveObject(objectProxy);
+ if (!object)
+ return false;
+
+ var expressionLength = expression.length;
+ if (!expressionLength) {
+ delete object[propertyName];
+ return !(propertyName in object);
+ }
+
+ try {
+ // Surround the expression in parenthesis so the result of the eval is the result
+ // of the whole expression not the last potential sub-expression.
+
+ // There is a regression introduced here: eval is now happening against global object,
+ // not call frame while on a breakpoint.
+ // TODO: bring evaluation against call frame back.
+ var result = InjectedScript._window().eval("(" + expression + ")");
+ // Store the result in the property.
+ object[propertyName] = result;
+ return true;
+ } catch(e) {
+ try {
+ var result = InjectedScript._window().eval("\"" + expression.escapeCharacters("\"") + "\"");
+ object[propertyName] = result;
+ return true;
+ } catch(e) {
+ return false;
+ }
+ }
+}
+
+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; object && i < path.length; ++i)
+ object = object[path[i]];
+
+ // Get to the necessary proto layer.
+ for (var i = 0; object && i < protoDepth; ++i)
+ object = object.__proto__;
+
+ return object;
+}
+
+InjectedScript._window = function()
+{
+ // TODO: replace with 'return window;' once this script is injected into
+ // the page's context.
+ return InspectorController.inspectedWindow();
+}
+
+InjectedScript._nodeForId = function(nodeId)
+{
+ // TODO: replace with node lookup in the InspectorDOMAgent once DOMAgent nodes are used.
+ return nodeId;
+}
+
+InjectedScript._objectForId = function(objectId)
+{
+ // TODO: replace with node lookups for node ids and evaluation result lookups for the rest of ids.
+ return objectId;
+}
diff --git a/WebCore/inspector/front-end/KeyboardShortcut.js b/WebCore/inspector/front-end/KeyboardShortcut.js
new file mode 100644
index 0000000..ed28a48
--- /dev/null
+++ b/WebCore/inspector/front-end/KeyboardShortcut.js
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.KeyboardShortcut = function()
+{
+};
+
+/**
+ * Constants for encoding modifier key set as a bit mask.
+ * @see #_makeKeyFromCodeAndModifiers
+ */
+WebInspector.KeyboardShortcut.Modifiers = {
+ None: 0, // Constant for empty modifiers set.
+ Shift: 1,
+ Ctrl: 2,
+ Alt: 4,
+ Meta: 8 // Command key on Mac, Win key on other platforms.
+};
+
+WebInspector.KeyboardShortcut.KeyCodes = {
+ Esc: 27,
+ Space: 32,
+ PageUp: 33, // also NUM_NORTH_EAST
+ PageDown: 34, // also NUM_SOUTH_EAST
+ End: 35, // also NUM_SOUTH_WEST
+ Home: 36, // also NUM_NORTH_WEST
+ Left: 37, // also NUM_WEST
+ Up: 38, // also NUM_NORTH
+ Right: 39, // also NUM_EAST
+ Down: 40, // also NUM_SOUTH
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123,
+ Semicolon: 186, // ;
+ Comma: 188, // ,
+ Period: 190, // .
+ Slash: 191, // /
+ Apostrophe: 192, // `
+ SingleQuote: 222, // '
+};
+
+/**
+ * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits.
+ * It is usefull for matching pressed keys.
+ * @param {number} keyCode Code of the key.
+ * @param {number} optModifiers Optional list of modifiers passed as additional paramerters.
+ */
+WebInspector.KeyboardShortcut.makeKey = function(keyCode, optModifiers)
+{
+ var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
+ for (var i = 1; i < arguments.length; i++)
+ modifiers |= arguments[i];
+ return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
+};
+
+WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent)
+{
+ var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
+ if (keyboardEvent.shiftKey)
+ modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift;
+ if (keyboardEvent.ctrlKey)
+ modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl;
+ if (keyboardEvent.altKey)
+ modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt;
+ if (keyboardEvent.metaKey)
+ modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta;
+ return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers);
+};
+
+WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers)
+{
+ return (keyCode & 255) | (modifiers << 8);
+};
diff --git a/WebCore/inspector/front-end/MetricsSidebarPane.js b/WebCore/inspector/front-end/MetricsSidebarPane.js
index a22a000..8712dcd 100644
--- a/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -29,6 +29,7 @@
WebInspector.MetricsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));
+ this._inlineStyleId = null;
}
WebInspector.MetricsSidebarPane.prototype = {
@@ -46,12 +47,28 @@ WebInspector.MetricsSidebarPane.prototype = {
if (!node || !node.ownerDocument.defaultView)
return;
- var style;
- if (node.nodeType === Node.ELEMENT_NODE)
- style = node.ownerDocument.defaultView.getComputedStyle(node);
- if (!style)
+ if (node.nodeType !== Node.ELEMENT_NODE)
return;
+ var self = this;
+ var callback = function(stylePayload) {
+ if (!stylePayload)
+ return;
+ var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload);
+ self._update(node, body, style);
+ };
+ InspectorController.getComputedStyle(node, callback);
+
+ var inlineStyleCallback = function(stylePayload) {
+ if (!stylePayload)
+ return;
+ self._inlineStyleId = stylePayload.id;
+ };
+ InspectorController.getInlineStyle(node, inlineStyleCallback);
+ },
+
+ _update: function(node, body, style)
+ {
var metricsElement = document.createElement("div");
metricsElement.className = "metrics";
@@ -184,11 +201,14 @@ WebInspector.MetricsSidebarPane.prototype = {
if (/^\d+$/.test(userInput))
userInput += "px";
- this.node.style.setProperty(context.styleProperty, userInput, "");
-
- this.dispatchEventToListeners("metrics edited");
-
- this.update();
+ var self = this;
+ var callback = function(success) {
+ if (!success)
+ return;
+ self.dispatchEventToListeners("metrics edited");
+ self.update();
+ };
+ InspectorController.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback);
}
}
diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js
index ab6ac55..9b03940 100644
--- a/WebCore/inspector/front-end/ObjectPropertiesSection.js
+++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,15 +26,6 @@
WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
{
- if (!title) {
- title = Object.describe(object);
- if (title.match(/Prototype$/)) {
- title = title.replace(/Prototype$/, "");
- if (!subtitle)
- subtitle = WebInspector.UIString("Prototype");
- }
- }
-
this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
this.object = object;
this.ignoreHasOwnProperty = ignoreHasOwnProperty;
@@ -52,42 +44,80 @@ WebInspector.ObjectPropertiesSection.prototype = {
update: function()
{
- var properties = [];
- for (var prop in this.object)
- properties.push(prop);
+ var self = this;
+ var callback = function(properties) {
+ if (!properties)
+ return;
+ self._update(properties);
+ };
+ InspectorController.getProperties(this.object, this.ignoreHasOwnProperty, callback);
+ },
+
+ _update: function(properties)
+ {
if (this.extraProperties)
for (var prop in this.extraProperties)
- properties.push(prop);
- properties.sort();
+ properties.push(new WebInspector.ObjectPropertyProxy(prop, this.extraProperties[prop]));
+ properties.sort(this._displaySort);
this.propertiesTreeOutline.removeChildren();
- for (var i = 0; i < properties.length; ++i) {
- var object = this.object;
- var propertyName = properties[i];
- if (this.extraProperties && propertyName in this.extraProperties)
- object = this.extraProperties;
- if (propertyName === "__treeElementIdentifier")
- continue;
- if (!this.ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
- continue;
- this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(object, propertyName));
- }
+ for (var i = 0; i < properties.length; ++i)
+ this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(properties[i]));
if (!this.propertiesTreeOutline.children.length) {
var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
var infoElement = new TreeElement(title, null, false);
this.propertiesTreeOutline.appendChild(infoElement);
}
+ },
+
+ _displaySort: function(propertyA, propertyB) {
+ var a = propertyA.name;
+ var b = propertyB.name;
+
+ // if used elsewhere make sure to
+ // - convert a and b to strings (not needed here, properties are all strings)
+ // - check if a == b (not needed here, no two properties can be the same)
+
+ var diff = 0;
+ var chunk = /^\d+|^\D+/;
+ var chunka, chunkb, anum, bnum;
+ while (diff === 0) {
+ if (!a && b)
+ return -1;
+ if (!b && a)
+ return 1;
+ chunka = a.match(chunk)[0];
+ chunkb = b.match(chunk)[0];
+ anum = !isNaN(chunka);
+ bnum = !isNaN(chunkb);
+ if (anum && !bnum)
+ return -1;
+ if (bnum && !anum)
+ return 1;
+ if (anum && bnum) {
+ diff = chunka - chunkb;
+ if (diff === 0 && chunka.length !== chunkb.length) {
+ if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
+ return chunka.length - chunkb.length;
+ else
+ return chunkb.length - chunka.length;
+ }
+ } else if (chunka !== chunkb)
+ return (chunka < chunkb) ? -1 : 1;
+ a = a.substring(chunka.length);
+ b = b.substring(chunkb.length);
+ }
+ return diff;
}
}
WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-WebInspector.ObjectPropertyTreeElement = function(parentObject, propertyName)
+WebInspector.ObjectPropertyTreeElement = function(property)
{
- this.parentObject = parentObject;
- this.propertyName = propertyName;
+ this.property = property;
// Pass an empty title, the title gets made later in onattach.
TreeElement.call(this, "", null, false);
@@ -106,16 +136,18 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
if (this.children.length && !this.shouldRefreshChildren)
return;
- this.removeChildren();
+ var self = this;
+ var callback = function(properties) {
+ self.removeChildren();
+ if (!properties)
+ return;
- var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
- var properties = Object.sortedProperties(childObject);
- for (var i = 0; i < properties.length; ++i) {
- var propertyName = properties[i];
- if (propertyName === "__treeElementIdentifier")
- continue;
- this.appendChild(new this.treeOutline.section.treeElementConstructor(childObject, propertyName));
- }
+ properties.sort(self._displaySort);
+ for (var i = 0; i < properties.length; ++i) {
+ self.appendChild(new self.treeOutline.section.treeElementConstructor(properties[i]));
+ }
+ };
+ InspectorController.getProperties(this.property.childObjectProxy, false, callback);
},
ondblclick: function(element, event)
@@ -130,41 +162,22 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
update: function()
{
- var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
- var isGetter = ("__lookupGetter__" in this.parentObject && this.parentObject.__lookupGetter__(this.propertyName));
-
var nameElement = document.createElement("span");
nameElement.className = "name";
- nameElement.textContent = this.propertyName;
+ nameElement.textContent = this.property.name;
this.valueElement = document.createElement("span");
this.valueElement.className = "value";
- if (!isGetter) {
- this.valueElement.textContent = Object.describe(childObject, true);
- } else {
- // FIXME: this should show something like "getter" (bug 16734).
- this.valueElement.textContent = "\u2014"; // em dash
- this.valueElement.addStyleClass("dimmed");
- }
+ this.valueElement.textContent = this.property.textContent;
+ if (this.property.isGetter)
+ this.valueElement.addStyleClass("dimmed");
this.listItemElement.removeChildren();
this.listItemElement.appendChild(nameElement);
this.listItemElement.appendChild(document.createTextNode(": "));
this.listItemElement.appendChild(this.valueElement);
-
- var hasSubProperties = false;
- var type = typeof childObject;
- if (childObject && (type === "object" || type === "function")) {
- for (subPropertyName in childObject) {
- if (subPropertyName === "__treeElementIdentifier")
- continue;
- hasSubProperties = true;
- break;
- }
- }
-
- this.hasChildren = hasSubProperties;
+ this.hasChildren = this.property.hasChildren;
},
updateSiblings: function()
@@ -214,62 +227,27 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
this.editingEnded(context);
},
- evaluateExpression: function(expression)
- {
- // Evaluate in the currently selected call frame if the debugger is paused.
- // Otherwise evaluate in against the inspected window.
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused && this.treeOutline.section.editInSelectedCallFrameWhenPaused)
- return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false);
- return InspectorController.inspectedWindow().eval(expression);
- },
-
applyExpression: function(expression, updateInterface)
{
- var expressionLength = expression.trimWhitespace().length;
-
- if (!expressionLength) {
- // The user deleted everything, so try to delete the property.
- delete this.parentObject[this.propertyName];
-
- if (updateInterface) {
- if (this.propertyName in this.parentObject) {
- // The property was not deleted, so update.
- this.update();
- } else {
- // The property was deleted, so remove this tree element.
- this.parent.removeChild(this);
- }
- }
+ expression = expression.trimWhitespace();
+ var expressionLength = expression.length;
+ var self = this;
+ var callback = function(success) {
+ if (!updateInterface)
+ return;
- return;
- }
+ if (!success)
+ self.update();
- try {
- // Surround the expression in parenthesis so the result of the eval is the result
- // of the whole expression not the last potential sub-expression.
- var result = this.evaluateExpression("(" + expression + ")");
-
- // Store the result in the property.
- this.parentObject[this.propertyName] = result;
- } catch(e) {
- try {
- // Try to update as a string
- var result = this.evaluateExpression("\"" + expression.escapeCharacters("\"") + "\"");
-
- // Store the result in the property.
- this.parentObject[this.propertyName] = result;
- } catch(e) {
- // The expression failed so don't change the value. So just update and return.
- if (updateInterface)
- this.update();
- return;
+ if (!expressionLength) {
+ // The property was deleted, so remove this tree element.
+ self.parent.removeChild(this);
+ } else {
+ // Call updateSiblings since their value might be based on the value that just changed.
+ self.updateSiblings();
}
- }
-
- if (updateInterface) {
- // Call updateSiblings since their value might be based on the value that just changed.
- this.updateSiblings();
- }
+ };
+ InspectorController.setPropertyValue(this.property.parentObjectProxy, this.property.name, expression.trimWhitespace(), callback);
}
}
diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js
new file mode 100644
index 0000000..fa7816e
--- /dev/null
+++ b/WebCore/inspector/front-end/ObjectProxy.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectProxy = function(objectId, path, protoDepth)
+{
+ this.objectId = objectId;
+ this.path = path || [];
+ this.protoDepth = protoDepth || 0;
+}
+
+WebInspector.ObjectPropertyProxy = function(name, object)
+{
+ this.name = name;
+ this.type = "object";
+ this.hasChildren = true;
+ this.textContent = Object.describe(object, true);
+ this.childObjectProxy = new WebInspector.ObjectProxy(object);
+}
diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js
index 5046f6b..3e2212c 100644
--- a/WebCore/inspector/front-end/Panel.js
+++ b/WebCore/inspector/front-end/Panel.js
@@ -66,6 +66,18 @@ WebInspector.Panel.prototype = {
return this._toolbarItem;
},
+ createStatusBarButton: function()
+ {
+ var button = document.createElement("button");
+ var glyph = document.createElement("div");
+ glyph.className = "glyph";
+ button.appendChild(glyph);
+ var glyphShadow = document.createElement("div");
+ glyphShadow.className = "glyph shadow";
+ button.appendChild(glyphShadow);
+ return button;
+ },
+
show: function()
{
WebInspector.View.prototype.show.call(this);
diff --git a/WebCore/inspector/front-end/ProfileView.js b/WebCore/inspector/front-end/ProfileView.js
index d00733c..2517bd2 100644
--- a/WebCore/inspector/front-end/ProfileView.js
+++ b/WebCore/inspector/front-end/ProfileView.js
@@ -148,11 +148,23 @@ WebInspector.ProfileView.prototype = {
return this._bottomUpTree;
},
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.dataGrid.updateWidths();
+ },
+
hide: function()
{
WebInspector.View.prototype.hide.call(this);
this._currentSearchResultIndex = -1;
},
+
+ resize: function()
+ {
+ if (this.dataGrid)
+ this.dataGrid.updateWidths();
+ },
refresh: function()
{
@@ -166,8 +178,8 @@ WebInspector.ProfileView.prototype = {
for (var index = 0; index < count; ++index)
this.dataGrid.appendChild(children[index]);
- if (selectedProfileNode && selectedProfileNode._dataGridNode)
- selectedProfileNode._dataGridNode.selected = true;
+ if (selectedProfileNode)
+ selectedProfileNode.selected = true;
},
refreshVisibleData: function()
@@ -196,8 +208,7 @@ WebInspector.ProfileView.prototype = {
delete profileNode._searchMatchedCallsColumn;
delete profileNode._searchMatchedFunctionColumn;
- if (profileNode._dataGridNode)
- profileNode._dataGridNode.refresh();
+ profileNode.refresh();
}
}
@@ -313,7 +324,7 @@ WebInspector.ProfileView.prototype = {
profileDataGridNode._searchMatchedTotalColumn ||
profileDataGridNode._searchMatchedAverageColumn ||
profileDataGridNode._searchMatchedCallsColumn ||
- profileDataGridNode._searchMatchedFunctionColumn);
+ profileDataGridNode._searchMatchedFunctionColumn)
{
profileDataGridNode.refresh();
return true;
@@ -322,48 +333,14 @@ WebInspector.ProfileView.prototype = {
return false;
}
- var current = this.dataGrid;
- var ancestors = [];
- var nextIndexes = [];
- var startIndex = 0;
+ var current = this.profileDataGridTree.children[0];
while (current) {
- var children = current.children;
- var childrenLength = children.length;
-
- if (startIndex >= childrenLength) {
- current = ancestors.pop();
- startIndex = nextIndexes.pop();
- continue;
+ if (matchesQuery(current)) {
+ this._searchResults.push({ profileNode: current });
}
- for (var i = startIndex; i < childrenLength; ++i) {
- var child = children[i];
-
- if (matchesQuery(child)) {
- if (child._dataGridNode) {
- // The child has a data grid node already, no need to remember the ancestors.
- this._searchResults.push({ profileNode: child });
- } else {
- var ancestorsCopy = [].concat(ancestors);
- ancestorsCopy.push(current);
- this._searchResults.push({ profileNode: child, ancestors: ancestorsCopy });
- }
- }
-
- if (child.children.length) {
- ancestors.push(current);
- nextIndexes.push(i + 1);
- current = child;
- startIndex = 0;
- break;
- }
-
- if (i === (childrenLength - 1)) {
- current = ancestors.pop();
- startIndex = nextIndexes.pop();
- }
- }
+ current = current.traverseNextNode(false, null, false);
}
finishedCallback(this, this._searchResults.length);
@@ -419,26 +396,9 @@ WebInspector.ProfileView.prototype = {
if (!searchResult)
return;
- var profileNode = this._searchResults[index].profileNode;
- if (!profileNode._dataGridNode && searchResult.ancestors) {
- var ancestors = searchResult.ancestors;
- for (var i = 0; i < ancestors.length; ++i) {
- var ancestorProfileNode = ancestors[i];
- var gridNode = ancestorProfileNode._dataGridNode;
- if (gridNode)
- gridNode.expand();
- }
-
- // No need to keep the ancestors around.
- delete searchResult.ancestors;
- }
-
- gridNode = profileNode._dataGridNode;
- if (!gridNode)
- return;
-
- gridNode.reveal();
- gridNode.select();
+ var profileNode = searchResult.profileNode;
+ profileNode.reveal();
+ profileNode.select();
},
_changeView: function(event)
diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js
index aafc306..c8b948a 100644
--- a/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/WebCore/inspector/front-end/ProfilesPanel.js
@@ -59,11 +59,11 @@ WebInspector.ProfilesPanel = function()
this.profileViews.id = "profile-views";
this.element.appendChild(this.profileViews);
- this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton = this.createStatusBarButton();
this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
- this.recordButton = document.createElement("button");
+ this.recordButton = this.createStatusBarButton();
this.recordButton.title = WebInspector.UIString("Start profiling.");
this.recordButton.id = "record-profile-status-bar-item";
this.recordButton.className = "status-bar-item";
@@ -266,8 +266,10 @@ WebInspector.ProfilesPanel.prototype = {
groupNumber = ++this._profileGroupsForLinks[title];
- if (groupNumber >= 2)
- title += " " + WebInspector.UIString("Run %d", groupNumber);
+ if (groupNumber > 2)
+ // The title is used in the console message announcing that a profile has started so it gets
+ // incremented twice as often as it's displayed
+ title += " " + WebInspector.UIString("Run %d", groupNumber / 2);
}
return title;
@@ -322,6 +324,13 @@ WebInspector.ProfilesPanel.prototype = {
this.recordButton.title = WebInspector.UIString("Start profiling.");
}
},
+
+ resize: function()
+ {
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
_updateInterface: function()
{
@@ -422,6 +431,10 @@ WebInspector.ProfilesPanel.prototype = {
this.profileViews.style.left = width + "px";
this.profileViewStatusBarItemsContainer.style.left = width + "px";
this.sidebarResizeElement.style.left = (width - 3) + "px";
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
}
}
diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js
index 70db805..2d32137 100644
--- a/WebCore/inspector/front-end/PropertiesSidebarPane.js
+++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js
@@ -43,11 +43,21 @@ WebInspector.PropertiesSidebarPane.prototype = {
if (!object)
return;
- for (var prototype = object; prototype; prototype = prototype.__proto__) {
- var section = new WebInspector.ObjectPropertiesSection(prototype);
- this.sections.push(section);
- body.appendChild(section.element);
- }
+ var self = this;
+ var callback = function(prototypes) {
+ var body = self.bodyElement;
+ body.removeChildren();
+ self.sections = [];
+
+ // Get array of prototype user-friendly names.
+ for (var i = 0; i < prototypes.length; ++i) {
+ var prototype = new WebInspector.ObjectProxy(object, [], i);
+ var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype"));
+ self.sections.push(section);
+ body.appendChild(section.element);
+ }
+ };
+ InspectorController.getPrototypes(object, callback);
}
}
diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js
index 058f232..bcb7b2a 100644
--- a/WebCore/inspector/front-end/Resource.js
+++ b/WebCore/inspector/front-end/Resource.js
@@ -341,12 +341,6 @@ WebInspector.Resource.prototype = {
}
},
- get documentNode() {
- if ("identifier" in this)
- return InspectorController.getResourceDocumentNode(this.identifier);
- return null;
- },
-
get requestHeaders()
{
if (this._requestHeaders === undefined)
@@ -489,7 +483,8 @@ WebInspector.Resource.prototype = {
// Otherwise, we flood the Console with too many tips.
/*
var msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
- WebInspector.ConsoleMessage.MessageLevel.Tip, -1, this.url, null, 1, tip.message);
+ WebInspector.ConsoleMessage.MessageType.Log, WebInspector.ConsoleMessage.MessageLevel.Tip,
+ -1, this.url, null, 1, tip.message);
WebInspector.console.addMessage(msg);
*/
},
@@ -549,6 +544,7 @@ WebInspector.Resource.prototype = {
case WebInspector.Warnings.IncorrectMIMEType.id:
if (!this._mimeTypeIsConsistentWithType())
msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageType.Log,
WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, null, 1,
String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message,
WebInspector.Resource.Type.toString(this.type), this.mimeType));
diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js
index 04d998e..fb43551 100644
--- a/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/WebCore/inspector/front-end/ResourcesPanel.js
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Anthony Ricaud (rik24d@gmail.com)
+ * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,6 +33,10 @@ WebInspector.ResourcesPanel = function()
this.element.addStyleClass("resources");
+ this.filterBarElement = document.createElement("div");
+ this.filterBarElement.id = "resources-filter";
+ this.element.appendChild(this.filterBarElement);
+
this.viewsContainerElement = document.createElement("div");
this.viewsContainerElement.id = "resource-views";
this.element.appendChild(this.viewsContainerElement);
@@ -126,7 +130,7 @@ WebInspector.ResourcesPanel = function()
this.resourcesTreeElement.expand();
- var panelEnablerHeading = WebInspector.UIString("You need to enable resource tracking to use the this panel.");
+ var panelEnablerHeading = WebInspector.UIString("You need to enable resource tracking to use this panel.");
var panelEnablerDisclaimer = WebInspector.UIString("Enabling resource tracking will reload the page and make page loading slower.");
var panelEnablerButton = WebInspector.UIString("Enable resource tracking");
@@ -135,11 +139,11 @@ WebInspector.ResourcesPanel = function()
this.element.appendChild(this.panelEnablerView.element);
- this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton = this.createStatusBarButton();
this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false);
- this.largerResourcesButton = document.createElement("button");
+ this.largerResourcesButton = this.createStatusBarButton();
this.largerResourcesButton.id = "resources-larger-resources-status-bar-item";
this.largerResourcesButton.className = "status-bar-item toggled-on";
this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
@@ -149,6 +153,24 @@ WebInspector.ResourcesPanel = function()
this.sortingSelectElement.className = "status-bar-item";
this.sortingSelectElement.addEventListener("change", this._changeSortingFunction.bind(this), false);
+ var createFilterElement = function (category) {
+ var categoryElement = document.createElement("li");
+ categoryElement.category = category;
+ categoryElement.addStyleClass(category);
+ var label = WebInspector.UIString("All");
+ if (WebInspector.resourceCategories[category])
+ label = WebInspector.resourceCategories[category].title;
+ categoryElement.appendChild(document.createTextNode(label));
+ categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
+ this.filterBarElement.appendChild(categoryElement);
+ return categoryElement;
+ };
+
+ var allElement = createFilterElement.call(this, "all");
+ this.filter(allElement.category);
+ for (var i = 0; i < this.categoryOrder.length; i++)
+ createFilterElement.call(this, this.categoryOrder[i]);
+
this.reset();
timeGraphItem.select();
@@ -157,6 +179,31 @@ WebInspector.ResourcesPanel = function()
WebInspector.ResourcesPanel.prototype = {
toolbarItemClass: "resources",
+ categoryOrder: ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"],
+
+ filter: function (category) {
+ if (this._filterCategory && this._filterCategory === category)
+ return;
+
+ if (this._filterCategory) {
+ var filterElement = this.filterBarElement.getElementsByClassName(this._filterCategory)[0];
+ filterElement.removeStyleClass("selected");
+ var oldClass = "filter-" + this._filterCategory;
+ this.resourcesTreeElement.childrenListElement.removeStyleClass(oldClass);
+ this.resourcesGraphsElement.removeStyleClass(oldClass);
+ }
+ this._filterCategory = category;
+ var filterElement = this.filterBarElement.getElementsByClassName(this._filterCategory)[0];
+ filterElement.addStyleClass("selected");
+ var newClass = "filter-" + this._filterCategory;
+ this.resourcesTreeElement.childrenListElement.addStyleClass(newClass);
+ this.resourcesGraphsElement.addStyleClass(newClass);
+ },
+
+ _updateFilter: function (e) {
+ this.filter(e.target.category);
+ },
+
get toolbarItemLabel()
{
return WebInspector.UIString("Resources");
@@ -957,14 +1004,13 @@ WebInspector.ResourcesPanel.prototype = {
{
var graphInfo = this.calculator.computeSummaryValues(this._resources);
- var categoryOrder = ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"];
var categoryColors = {documents: {r: 47, g: 102, b: 236}, stylesheets: {r: 157, g: 231, b: 119}, images: {r: 164, g: 60, b: 255}, scripts: {r: 255, g: 121, b: 0}, xhr: {r: 231, g: 231, b: 10}, fonts: {r: 255, g: 82, b: 62}, other: {r: 186, g: 186, b: 186}};
var fillSegments = [];
this.legendElement.removeChildren();
- for (var i = 0; i < categoryOrder.length; ++i) {
- var category = categoryOrder[i];
+ for (var i = 0; i < this.categoryOrder.length; ++i) {
+ var category = this.categoryOrder[i];
var size = graphInfo.categoryValues[category];
if (!size)
continue;
@@ -1453,6 +1499,12 @@ WebInspector.ResourceSidebarTreeElement.prototype = {
{
WebInspector.SidebarTreeElement.prototype.onattach.call(this);
+ var link = document.createElement("a");
+ link.href = this.resource.url;
+ link.className = "invisible";
+ while (this._listItemNode.firstChild)
+ link.appendChild(this._listItemNode.firstChild);
+ this._listItemNode.appendChild(link);
this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name);
},
@@ -1460,6 +1512,11 @@ WebInspector.ResourceSidebarTreeElement.prototype = {
{
WebInspector.panels.resources.showResource(this.resource);
},
+
+ ondblclick: function(treeElement, event)
+ {
+ InspectorController.inspectedWindow().open(this.resource.url);
+ },
get mainTitle()
{
diff --git a/WebCore/inspector/front-end/ScopeChainSidebarPane.js b/WebCore/inspector/front-end/ScopeChainSidebarPane.js
index 157cee9..a293fa0 100644
--- a/WebCore/inspector/front-end/ScopeChainSidebarPane.js
+++ b/WebCore/inspector/front-end/ScopeChainSidebarPane.js
@@ -85,7 +85,7 @@ WebInspector.ScopeChainSidebarPane.prototype = {
if (!title || title === subtitle)
subtitle = null;
- var section = new WebInspector.ObjectPropertiesSection(scopeObject, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+ var section = new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(scopeObject), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
section.editInSelectedCallFrameWhenPaused = true;
section.pane = this;
@@ -100,9 +100,9 @@ WebInspector.ScopeChainSidebarPane.prototype = {
WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
-WebInspector.ScopeVariableTreeElement = function(parentObject, propertyName)
+WebInspector.ScopeVariableTreeElement = function(property)
{
- WebInspector.ObjectPropertyTreeElement.call(this, parentObject, propertyName);
+ WebInspector.ObjectPropertyTreeElement.call(this, property);
}
WebInspector.ScopeVariableTreeElement.prototype = {
@@ -142,9 +142,9 @@ WebInspector.ScopeVariableTreeElement.prototype = {
do {
if (result)
- result = current.propertyName + "." + result;
+ result = current.property.name + "." + result;
else
- result = current.propertyName;
+ result = current.property.name;
current = current.parent;
} while (current && !current.root);
diff --git a/WebCore/inspector/front-end/Script.js b/WebCore/inspector/front-end/Script.js
index 46502a6..e6413a9 100644
--- a/WebCore/inspector/front-end/Script.js
+++ b/WebCore/inspector/front-end/Script.js
@@ -31,6 +31,19 @@ WebInspector.Script = function(sourceID, sourceURL, source, startingLine, errorL
this.startingLine = startingLine;
this.errorLine = errorLine;
this.errorMessage = errorMessage;
+
+ // if no URL, look for "//@ sourceURL=" decorator
+ // note that this sourceURL comment decorator is behavior that FireBug added
+ // in it's 1.1 release as noted in the release notes:
+ // http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
+ if (!sourceURL) {
+ // use of [ \t] rather than \s is to prevent \n from matching
+ var pattern = /^\s*\/\/[ \t]*@[ \t]*sourceURL[ \t]*=[ \t]*(\S+).*$/m;
+ var match = pattern.exec(source);
+
+ if (match)
+ this.sourceURL = WebInspector.UIString("(program): %s", match[1]);
+ }
}
WebInspector.Script.prototype = {
diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js
index 7af9292..0058374 100644
--- a/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/WebCore/inspector/front-end/ScriptsPanel.js
@@ -56,6 +56,7 @@ WebInspector.ScriptsPanel = function()
this.filesSelectElement.className = "status-bar-item";
this.filesSelectElement.id = "scripts-files";
this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
+ this.filesSelectElement.handleKeyEvent = this.handleKeyEvent.bind(this);
this.topStatusBar.appendChild(this.filesSelectElement);
this.functionsSelectElement = document.createElement("select");
@@ -132,13 +133,11 @@ WebInspector.ScriptsPanel = function()
for (var pane in this.sidebarPanes)
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
- // FIXME: remove the following line of code when the Breakpoints pane has content.
- this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element);
-
this.sidebarPanes.callstack.expanded = true;
this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
this.sidebarPanes.scopechain.expanded = true;
+ this.sidebarPanes.breakpoints.expanded = true;
var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
@@ -152,17 +151,50 @@ WebInspector.ScriptsPanel = function()
this.element.appendChild(this.sidebarElement);
this.element.appendChild(this.sidebarResizeElement);
- this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton = this.createStatusBarButton();
this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
- this.pauseOnExceptionButton = document.createElement("button");
+ this.pauseOnExceptionButton = this.createStatusBarButton();
this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item";
this.pauseOnExceptionButton.className = "status-bar-item";
this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
this._breakpointsURLMap = {};
+ this._shortcuts = {};
+
+ var isMac = InspectorController.platform().indexOf("mac-") === 0;
+ var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
+
+ // Continue.
+ var handler = this.pauseButton.click.bind(this.pauseButton);
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8);
+ this._shortcuts[shortcut] = handler;
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier);
+ this._shortcuts[shortcut] = handler;
+
+ // Step over.
+ var handler = this.stepOverButton.click.bind(this.stepOverButton);
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10);
+ this._shortcuts[shortcut] = handler;
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier);
+ this._shortcuts[shortcut] = handler;
+
+ // Step into.
+ var handler = this.stepIntoButton.click.bind(this.stepIntoButton);
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11);
+ this._shortcuts[shortcut] = handler;
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier);
+ this._shortcuts[shortcut] = handler;
+
+ // Step out.
+ var handler = this.stepOutButton.click.bind(this.stepOutButton);
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift);
+ this._shortcuts[shortcut] = handler;
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier);
+ this._shortcuts[shortcut] = handler;
+
this.reset();
}
@@ -206,7 +238,7 @@ WebInspector.ScriptsPanel.prototype = {
view.visible = false;
}
if (this._attachDebuggerWhenShown) {
- InspectorController.enableDebuggerFromFrontend(false);
+ InspectorController.enableDebugger(false);
delete this._attachDebuggerWhenShown;
}
},
@@ -265,6 +297,11 @@ WebInspector.ScriptsPanel.prototype = {
this._addScriptToFilesMenu(script);
},
+ scriptOrResourceForID: function(id)
+ {
+ return this._sourceIDMap[id];
+ },
+
addBreakpoint: function(breakpoint)
{
this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
@@ -316,33 +353,53 @@ WebInspector.ScriptsPanel.prototype = {
sourceFrame.removeBreakpoint(breakpoint);
},
- evaluateInSelectedCallFrame: function(code, updateInterface)
+ evaluateInSelectedCallFrame: function(code, updateInterface, callback)
{
var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
if (!this._paused || !selectedCallFrame)
return;
+
if (typeof updateInterface === "undefined")
updateInterface = true;
- var result = selectedCallFrame.evaluate(code);
- if (updateInterface)
- this.sidebarPanes.scopechain.update(selectedCallFrame);
- return result;
+
+ var self = this;
+ function updatingCallbackWrapper(result, exception)
+ {
+ callback(result, exception);
+ if (updateInterface)
+ self.sidebarPanes.scopechain.update(selectedCallFrame);
+ }
+ this.doEvalInCallFrame(selectedCallFrame, code, updatingCallbackWrapper);
},
- variablesInScopeForSelectedCallFrame: function()
+ doEvalInCallFrame: function(callFrame, code, callback)
{
- var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
- if (!this._paused || !selectedCallFrame)
- return {};
+ var panel = this;
+ function delayedEvaluation()
+ {
+ if (!code) {
+ // Evaluate into properties in scope of the selected call frame.
+ callback(panel._variablesInScope(callFrame));
+ return;
+ }
+ try {
+ callback(callFrame.evaluate(code));
+ } catch (e) {
+ callback(e, true);
+ }
+ }
+ setTimeout(delayedEvaluation, 0);
+ },
+ _variablesInScope: function(callFrame)
+ {
var result = {};
- var scopeChain = selectedCallFrame.scopeChain;
+ var scopeChain = callFrame.scopeChain;
for (var i = 0; i < scopeChain.length; ++i) {
var scopeObject = scopeChain[i];
for (var property in scopeObject)
result[property] = true;
}
-
return result;
},
@@ -375,7 +432,7 @@ WebInspector.ScriptsPanel.prototype = {
attachDebuggerWhenShown: function()
{
if (this.element.parentElement) {
- InspectorController.enableDebuggerFromFrontend(false);
+ InspectorController.enableDebugger(false);
} else {
this._attachDebuggerWhenShown = true;
}
@@ -467,6 +524,19 @@ WebInspector.ScriptsPanel.prototype = {
this._showScriptOrResource((view.resource || view.script));
},
+ handleKeyEvent: function(event)
+ {
+ var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+ var handler = this._shortcuts[shortcut];
+ if (handler) {
+ handler(event);
+ event.preventDefault();
+ event.handled = true;
+ } else {
+ this.sidebarPanes.callstack.handleKeyEvent(event);
+ }
+ },
+
scriptViewForScript: function(script)
{
if (!script)
@@ -796,7 +866,7 @@ WebInspector.ScriptsPanel.prototype = {
if (InspectorController.debuggerEnabled())
InspectorController.disableDebugger(true);
else
- InspectorController.enableDebuggerFromFrontend(!!optionalAlways);
+ InspectorController.enableDebugger(!!optionalAlways);
},
_togglePauseOnExceptions: function()
diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js
index 18d9073..930eb16 100644
--- a/WebCore/inspector/front-end/SourceFrame.js
+++ b/WebCore/inspector/front-end/SourceFrame.js
@@ -27,6 +27,7 @@ WebInspector.SourceFrame = function(element, addBreakpointDelegate)
{
this.messages = [];
this.breakpoints = [];
+ this._shortcuts = {};
this.addBreakpointDelegate = addBreakpointDelegate;
@@ -199,8 +200,16 @@ WebInspector.SourceFrame.prototype = {
{
WebInspector.addMainEventListeners(this.element.contentDocument);
this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true);
+ this.element.contentDocument.addEventListener("keydown", this._documentKeyDown.bind(this), true);
+ this.element.contentDocument.addEventListener("keyup", WebInspector.documentKeyUp.bind(WebInspector), true);
this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false);
+ // Register 'eval' shortcut.
+ var isMac = InspectorController.platform().indexOf("mac-") === 0;
+ var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platformSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift);
+ this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this);
+
var headElement = this.element.contentDocument.getElementsByTagName("head")[0];
if (!headElement) {
headElement = this.element.contentDocument.createElement("head");
@@ -286,6 +295,36 @@ WebInspector.SourceFrame.prototype = {
this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
},
+ _documentKeyDown: function(event)
+ {
+ var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
+ var handler = this._shortcuts[shortcut];
+ if (handler) {
+ handler(event);
+ event.preventDefault();
+ } else {
+ WebInspector.documentKeyDown(event);
+ }
+ },
+
+ _evalSelectionInCallFrame: function(event)
+ {
+ if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+ return;
+
+ var selection = this.element.contentWindow.getSelection();
+ if (!selection.rangeCount)
+ return;
+
+ var expression = selection.getRangeAt(0).toString().trimWhitespace();
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, function(result, exception) {
+ WebInspector.showConsole();
+ var commandMessage = new WebInspector.ConsoleCommand(expression);
+ WebInspector.console.addMessage(commandMessage);
+ WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
+ });
+ },
+
_breakpointEnableChanged: function(event)
{
var breakpoint = event.target;
@@ -332,6 +371,8 @@ WebInspector.SourceFrame.prototype = {
if (!sourceRow)
return;
+ breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-content')[0].textContent;
+
this._drawBreakpointImagesIfNeeded();
sourceRow._breakpointObject = breakpoint;
diff --git a/WebCore/inspector/front-end/SourceView.js b/WebCore/inspector/front-end/SourceView.js
index 7510c8c..97a5bd5 100644
--- a/WebCore/inspector/front-end/SourceView.js
+++ b/WebCore/inspector/front-end/SourceView.js
@@ -104,8 +104,11 @@ WebInspector.SourceView.prototype = {
{
delete this._frameNeedsSetup;
this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
-
- if (this.resource.type === WebInspector.Resource.Type.Script) {
+
+ if (this.resource.type === WebInspector.Resource.Type.Script
+ || this.resource.mimeType === 'application/json'
+ || this.resource.mimeType === 'application/javascript'
+ || /\.js(on)?$/.test(this.resource.lastPathComponent) ) {
this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
this.sourceFrame.syntaxHighlightJavascript();
} else
diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js
index c30444b..8a3a67f 100644
--- a/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -62,14 +63,33 @@ WebInspector.StylesSidebarPane.prototype = {
if (!node)
return;
+ var self = this;
+ var callback = function(styles) {
+ if (!styles)
+ return;
+ var nodeWrapper = WebInspector.wrapNodeWithStyles(node, styles);
+ self._update(refresh, body, nodeWrapper, editedSection, forceUpdate);
+ };
+ InspectorController.getStyles(node, !Preferences.showUserAgentStyles, callback);
+ },
+
+ _update: function(refresh, body, node, editedSection, forceUpdate)
+ {
+ if (!refresh) {
+ body.removeChildren();
+ this.sections = [];
+ }
+
var styleRules = [];
if (refresh) {
for (var i = 0; i < this.sections.length; ++i) {
var section = this.sections[i];
+ if (section._blank)
+ continue;
if (section.computedStyle)
section.styleRule.style = node.ownerDocument.defaultView.getComputedStyle(node);
- var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle };
+ var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule };
styleRules.push(styleRule);
}
} else {
@@ -90,8 +110,9 @@ WebInspector.StylesSidebarPane.prototype = {
}
}
- if (node.style && (node.style.length || Object.hasProperties(node.style.__disabledProperties))) {
- var inlineStyle = { selectorText: WebInspector.UIString("Inline Style Attribute"), style: node.style };
+ // Always Show element's Style Attributes
+ if (node.nodeType === Node.ELEMENT_NODE) {
+ var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: node.style, isAttribute: true };
inlineStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", "style");
styleRules.push(inlineStyle);
}
@@ -101,7 +122,7 @@ WebInspector.StylesSidebarPane.prototype = {
// Add rules in reverse order to match the cascade order.
for (var i = (matchedStyleRules.length - 1); i >= 0; --i) {
var rule = matchedStyleRules[i];
- styleRules.push({ style: rule.style, selectorText: rule.selectorText, parentStyleSheet: rule.parentStyleSheet });
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, parentStyleSheet: rule.parentStyleSheet, rule: rule });
}
}
}
@@ -127,6 +148,8 @@ WebInspector.StylesSidebarPane.prototype = {
var styleRule = styleRules[i];
if (styleRule.computedStyle)
continue;
+ if (styleRule.section && styleRule.section.noAffect)
+ continue;
styleRule.usedProperties = {};
@@ -181,7 +204,7 @@ WebInspector.StylesSidebarPane.prototype = {
continue;
var style = styleRules[i].style;
- var uniqueProperties = getUniqueStyleProperties(style);
+ var uniqueProperties = style.uniqueStyleProperties;
for (var j = 0; j < uniqueProperties.length; ++j) {
var name = uniqueProperties[j];
if (style.getPropertyPriority(name).length) {
@@ -222,6 +245,9 @@ WebInspector.StylesSidebarPane.prototype = {
var editable = styleRule.editable;
delete styleRule.editable;
+ var isAttribute = styleRule.isAttribute;
+ delete styleRule.isAttribute;
+
// Default editable to true if it was omitted.
if (typeof editable === "undefined")
editable = true;
@@ -235,13 +261,49 @@ WebInspector.StylesSidebarPane.prototype = {
section.expanded = Preferences.styleRulesExpandedState[section.identifier];
else if (computedStyle)
section.collapse(true);
+ else if (isAttribute && styleRule.style.length === 0)
+ section.collapse(true);
else
section.expand(true);
body.appendChild(section.element);
this.sections.push(section);
}
+
+ this.addBlankSection();
}
+ },
+
+ addBlankSection: function()
+ {
+ var blankSection = new WebInspector.BlankStylePropertiesSection();
+ blankSection.pane = this;
+
+ this.bodyElement.insertBefore(blankSection.element, this.bodyElement.firstChild.nextSibling.nextSibling); // 0 is computed, 1 is element.style
+ var computed = this.sections.shift();
+ var elementStyle = this.sections.shift();
+ this.sections.unshift(blankSection);
+ this.sections.unshift(elementStyle);
+ this.sections.unshift(computed);
+ },
+
+ appropriateSelectorForNode: function()
+ {
+ var node = this.node;
+ if (!node)
+ return;
+
+ if (node.id)
+ return "#" + node.id;
+
+ if (node.className)
+ return "." + node.className.replace(/\s+/, ".");
+
+ var nodeName = node.nodeName.toLowerCase();
+ if (nodeName === "input" && node.type)
+ return nodeName + "[type=\"" + node.type + "\"]";
+
+ return nodeName;
}
}
@@ -250,14 +312,19 @@ WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.pr
WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyle, usedProperties, editable)
{
WebInspector.PropertiesSection.call(this, styleRule.selectorText);
+ this.titleElement.addEventListener("click", function(e) { e.stopPropagation(); }, false);
+ this.titleElement.addEventListener("dblclick", this._dblclickSelector.bind(this), false);
+ this.element.addEventListener("dblclick", this._dblclickEmptySpace.bind(this), false);
this.styleRule = styleRule;
+ this.rule = this.styleRule.rule;
this.computedStyle = computedStyle;
this.editable = (editable && !computedStyle);
// Prevent editing the user agent and user rules.
- var isUserAgent = this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode && !this.styleRule.parentStyleSheet.href;
- var isUser = this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.ownerNode && this.styleRule.parentStyleSheet.ownerNode.nodeName == '#document';
+ var isUserAgent = this.styleRule.isUserAgent;
+ var isUser = this.styleRule.isUser;
+
if (isUserAgent || isUser)
this.editable = false;
@@ -299,6 +366,8 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
subtitle = WebInspector.UIString("user agent stylesheet");
else if (isUser)
subtitle = WebInspector.UIString("user stylesheet");
+ else if (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet)
+ subtitle = WebInspector.UIString("via inspector");
else
subtitle = WebInspector.UIString("inline stylesheet");
}
@@ -308,7 +377,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl
this.identifier = styleRule.selectorText;
if (this.subtitle)
- this.identifier += ":" + this.subtitleElement.textContent;
+ this.identifier += ":" + this.subtitleElement.textContent;
}
WebInspector.StylePropertiesSection.prototype = {
@@ -325,6 +394,9 @@ WebInspector.StylePropertiesSection.prototype = {
expand: function(dontRememberState)
{
+ if (this._blank)
+ return;
+
WebInspector.PropertiesSection.prototype.expand.call(this);
if (dontRememberState)
return;
@@ -347,7 +419,7 @@ WebInspector.StylePropertiesSection.prototype = {
isPropertyInherited: function(property)
{
- if (!this.computedStyle || !this._usedProperties)
+ if (!this.computedStyle || !this._usedProperties || this.noAffect)
return false;
// These properties should always show for Computed Style.
var alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
@@ -356,7 +428,7 @@ WebInspector.StylePropertiesSection.prototype = {
isPropertyOverloaded: function(property, shorthand)
{
- if (this.computedStyle || !this._usedProperties)
+ if (this.computedStyle || !this._usedProperties || this.noAffect)
return false;
var used = (property in this.usedProperties);
@@ -365,7 +437,7 @@ WebInspector.StylePropertiesSection.prototype = {
// Find out if any of the individual longhand properties of the shorthand
// are used, if none are then the shorthand is overloaded too.
- var longhandProperties = getLonghandProperties(this.styleRule.style, property);
+ var longhandProperties = this.styleRule.style.getLonghandProperties(property);
for (var j = 0; j < longhandProperties.length; ++j) {
var individualProperty = longhandProperties[j];
if (individualProperty in this.usedProperties)
@@ -375,6 +447,11 @@ WebInspector.StylePropertiesSection.prototype = {
return true;
},
+ isInspectorStylesheet: function()
+ {
+ return (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet);
+ },
+
update: function(full)
{
if (full || this.computedStyle) {
@@ -387,6 +464,11 @@ WebInspector.StylePropertiesSection.prototype = {
child = child.traverseNextTreeElement(false, null, true);
}
}
+
+ if (this._afterUpdate) {
+ this._afterUpdate(this);
+ delete this._afterUpdate;
+ }
},
onpopulate: function()
@@ -394,7 +476,7 @@ WebInspector.StylePropertiesSection.prototype = {
var style = this.styleRule.style;
var foundShorthands = {};
- var uniqueProperties = getUniqueStyleProperties(style);
+ var uniqueProperties = style.uniqueStyleProperties;
var disabledProperties = style.__disabledPropertyValues || {};
for (var name in disabledProperties)
@@ -422,16 +504,224 @@ WebInspector.StylePropertiesSection.prototype = {
var inherited = this.isPropertyInherited(name);
var overloaded = this.isPropertyOverloaded(name, isShorthand);
- var item = new WebInspector.StylePropertyTreeElement(style, name, isShorthand, inherited, overloaded, disabled);
+ var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, name, isShorthand, inherited, overloaded, disabled);
this.propertiesTreeOutline.appendChild(item);
}
+ },
+
+ findTreeElementWithName: function(name)
+ {
+ var treeElement = this.propertiesTreeOutline.children[0];
+ while (treeElement) {
+ if (treeElement.name === name)
+ return treeElement;
+ treeElement = treeElement.traverseNextTreeElement(true, null, true);
+ }
+ return null;
+ },
+
+ addNewBlankProperty: function()
+ {
+ var item = new WebInspector.StylePropertyTreeElement(this.styleRule, this.styleRule.style, "", false, false, false, false);
+ this.propertiesTreeOutline.appendChild(item);
+ item.listItemElement.textContent = "";
+ item._newProperty = true;
+ return item;
+ },
+
+ _dblclickEmptySpace: function(event)
+ {
+ this.expand();
+ this.addNewBlankProperty().startEditing();
+ },
+
+ _dblclickSelector: function(event)
+ {
+ if (!this.editable)
+ return;
+
+ if (!this.rule && this.propertiesTreeOutline.children.length === 0) {
+ this.expand();
+ this.addNewBlankProperty().startEditing();
+ return;
+ }
+
+ if (!this.rule)
+ return;
+
+ this.startEditingSelector();
+ event.stopPropagation();
+ },
+
+ startEditingSelector: function()
+ {
+ var element = this.titleElement;
+ if (WebInspector.isBeingEdited(element))
+ return;
+
+ var context = this.styleRule.selectorText;
+ WebInspector.startEditing(this.titleElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), context);
+ window.getSelection().setBaseAndExtent(element, 0, element, 1);
+ },
+
+ editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
+ {
+ function moveToNextIfNeeded() {
+ if (!moveDirection || moveDirection !== "forward")
+ return;
+
+ this.expand();
+ if (this.propertiesTreeOutline.children.length === 0)
+ this.addNewBlankProperty().startEditing();
+ else {
+ var item = this.propertiesTreeOutline.children[0]
+ item.startEditing(item.valueElement);
+ }
+ }
+
+ if (newContent === oldContent)
+ return moveToNextIfNeeded.call(this);
+
+ var self = this;
+ var callback = function(result) {
+ if (!result) {
+ // Invalid Syntax for a Selector
+ self.editingSelectorCancelled(element, context);
+ moveToNextIfNeeded.call(self);
+ return;
+ }
+
+ var newRulePayload = result[0];
+ var doesAffectSelectedNode = result[1];
+ if (!doesAffectSelectedNode) {
+ self.noAffect = true;
+ self.element.addStyleClass("no-affect");
+ } else {
+ delete self.noAffect;
+ self.element.removeStyleClass("no-affect");
+ }
+
+ var newRule = WebInspector.CSSStyleDeclaration.parseRule(newRulePayload);
+ self.rule = newRule;
+ self.styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, parentStyleSheet: newRule.parentStyleSheet, rule: newRule };
+ var oldIdentifier = this.identifier;
+ self.identifier = newRule.selectorText + ":" + self.subtitleElement.textContent;
+ self.pane.update(null, true);
+ WebInspector.panels.elements.renameSelector(oldIdentifier, this.identifier, oldContent, newContent);
+ moveToNextIfNeeded.call(self);
+ };
+
+ InspectorController.applyStyleRuleText(this.rule._id, newContent, this.pane.node, callback);
+ },
+
+ editingSelectorCancelled: function(element, context)
+ {
+ element.textContent = context;
+ },
+
+ _doesSelectorAffectSelectedNode: function(selector)
+ {
+ var selectedNode = this.pane.node;
+ var nodes = selectedNode.ownerDocument.querySelectorAll(selector);
+ for (var i = 0; i < nodes.length; ++i) {
+ if (nodes[i] === selectedNode)
+ return true;
+ }
+
+ return false;
}
}
WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-WebInspector.StylePropertyTreeElement = function(style, name, shorthand, inherited, overloaded, disabled)
+WebInspector.BlankStylePropertiesSection = function()
{
+ WebInspector.PropertiesSection.call(this, WebInspector.UIString("Double-Click to Add"), null);
+
+ this._blank = true;
+ this._dblclickListener = this._dblclick.bind(this);
+ this.element.addStyleClass("blank-section");
+ this.titleElement.addStyleClass("blank-title");
+ this.titleElement.addEventListener("click", function(e) { e.stopPropagation(); }, false);
+ this.titleElement.addEventListener("dblclick", this._dblclickListener, false);
+}
+
+WebInspector.BlankStylePropertiesSection.prototype = {
+ _dblclick: function(event)
+ {
+ this.startEditing();
+ },
+
+ startEditing: function()
+ {
+ var element = this.titleElement;
+ if (WebInspector.isBeingEdited(element))
+ return;
+
+ this.titleElement.textContent = this.pane.appropriateSelectorForNode();
+ this.titleElement.removeStyleClass("blank-title");
+ WebInspector.startEditing(this.titleElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), "");
+ window.getSelection().setBaseAndExtent(element, 0, element, 1);
+ },
+
+ editingCancelled: function()
+ {
+ this.titleElement.textContent = WebInspector.UIString("Double-Click to Add");
+ this.titleElement.addStyleClass("blank-title");
+ },
+
+ editingCommitted: function(element, newContent, oldContent, context)
+ {
+ var self = this;
+ var callback = function(styleRule) {
+ if (!styleRule) {
+ // Invalid Syntax for a Selector
+ self.editingCancelled();
+ return;
+ }
+ self.makeNormal(WebInspector.CSSStyleDeclaration.parseRule(styleRule));
+
+ if (!self._doesSelectorAffectSelectedNode(newContent)) {
+ self.noAffect = true;
+ self.element.addStyleClass("no-affect");
+ }
+
+ self.subtitleElement.textContent = WebInspector.UIString("via inspector");
+ self.expand();
+
+ self.pane.addBlankSection();
+ self.addNewBlankProperty().startEditing();
+ };
+ InspectorController.addStyleSelector(newContent, callback);
+ },
+
+ makeNormal: function(styleRule)
+ {
+ this.titleElement.removeEventListener("dblclick", this._dblclickListener, false);
+ this.titleElement.addEventListener("dblclick", this._dblclickSelector.bind(this), false);
+ this.element.addEventListener("dblclick", this._dblclickEmptySpace.bind(this), false);
+ this.element.removeStyleClass("blank-section");
+ delete this._blank;
+ delete this._dblclick;
+ delete this.startEditing;
+ delete this.editingCancelled;
+ delete this.editingCommitted;
+ delete this._dblclickListener;
+ delete this.makeNormal;
+ this.styleRule = styleRule;
+ this.rule = styleRule.rule;
+ this.computedStyle = false;
+ this.editable = true;
+ this.identifier = styleRule.selectorText + ":inspector";
+ // leftovers are: this.noAffect if applicable
+ }
+}
+
+WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype;
+
+WebInspector.StylePropertyTreeElement = function(styleRule, style, name, shorthand, inherited, overloaded, disabled)
+{
+ this._styleRule = styleRule;
this.style = style;
this.name = name;
this.shorthand = shorthand;
@@ -487,14 +777,14 @@ WebInspector.StylePropertyTreeElement.prototype = {
{
if (this.disabled && this.style.__disabledPropertyPriorities && this.name in this.style.__disabledPropertyPriorities)
return this.style.__disabledPropertyPriorities[this.name];
- return (this.shorthand ? getShorthandPriority(this.style, this.name) : this.style.getPropertyPriority(this.name));
+ return (this.shorthand ? this.style.getShorthandPriority(this.name) : this.style.getPropertyPriority(this.name));
},
get value()
{
if (this.disabled && this.style.__disabledPropertyValues && this.name in this.style.__disabledPropertyValues)
return this.style.__disabledPropertyValues[this.name];
- return (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name));
+ return (this.shorthand ? this.style.getShorthandValue(this.name) : this.style.getPropertyValue(this.name));
},
onattach: function()
@@ -558,10 +848,12 @@ WebInspector.StylePropertyTreeElement.prototype = {
var nameElement = document.createElement("span");
nameElement.className = "name";
nameElement.textContent = this.name;
+ this.nameElement = nameElement;
var valueElement = document.createElement("span");
valueElement.className = "value";
valueElement.innerHTML = htmlValue;
+ this.valueElement = valueElement;
if (priority) {
var priorityElement = document.createElement("span");
@@ -587,7 +879,8 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (value) {
// FIXME: this only covers W3C and CSS 16 valid color names
- var colors = value.match(/((rgb|hsl)a?\([^)]+\))|(#[0-9a-fA-F]{6})|(#[0-9a-fA-F]{3})|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow/g);
+ var colors = value.match(/((rgb|hsl)a?\([^)]+\))|(#[0-9a-fA-F]{6})|(#[0-9a-fA-F]{3})|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow|transparent/g);
+ var swatch;
if (colors) {
var colorsLength = colors.length;
for (var i = 0; i < colorsLength; ++i) {
@@ -595,6 +888,72 @@ WebInspector.StylePropertyTreeElement.prototype = {
swatchElement.className = "swatch";
swatchElement.style.setProperty("background-color", colors[i]);
this.listItemElement.appendChild(swatchElement);
+ swatch = swatchElement;
+ }
+ }
+
+ // Rotate through Color Representations by Clicking on the Swatch
+ // Simple: rgb -> hsl -> nickname? -> shorthex? -> hex -> ...
+ // Advanced: rgba -> hsla -> nickname? -> ...
+ if (colors && colors.length === 1) {
+ var color = new WebInspector.Color(htmlValue);
+ swatch.addEventListener("click", changeColorDisplay, false);
+ swatch.addEventListener("dblclick", function(event) {
+ event.stopPropagation();
+ }, false);
+
+ var mode = color.mode;
+ var valueElement = this.valueElement;
+ function changeColorDisplay(event) {
+
+ function changeTo(newMode, content) {
+ mode = newMode;
+ valueElement.textContent = content;
+ }
+
+ switch (mode) {
+ case "rgb":
+ changeTo("hsl", color.toHsl());
+ break;
+
+ case "shorthex":
+ changeTo("hex", color.toHex());
+ break;
+
+ case "hex":
+ changeTo("rgb", color.toRgb());
+ break;
+
+ case "nickname":
+ if (color.simple) {
+ if (color.hasShortHex())
+ changeTo("shorthex", color.toShortHex());
+ else
+ changeTo("hex", color.toHex());
+ } else
+ changeTo("rgba", color.toRgba());
+ break;
+
+ case "hsl":
+ if (color.nickname)
+ changeTo("nickname", color.toNickname());
+ else if (color.hasShortHex())
+ changeTo("shorthex", color.toShortHex());
+ else
+ changeTo("hex", color.toHex());
+ break;
+
+ case "rgba":
+ changeTo("hsla", color.toHsla());
+ break;
+
+ case "hsla":
+ if (color.nickname)
+ changeTo("nickname", color.toNickname());
+ else
+ changeTo("rgba", color.toRgba());
+ break;
+ }
}
}
}
@@ -616,42 +975,24 @@ WebInspector.StylePropertyTreeElement.prototype = {
{
var disabled = !event.target.checked;
- if (disabled) {
- if (!this.style.__disabledPropertyValues || !this.style.__disabledPropertyPriorities) {
- var inspectedWindow = InspectorController.inspectedWindow();
- this.style.__disabledProperties = new inspectedWindow.Object;
- this.style.__disabledPropertyValues = new inspectedWindow.Object;
- this.style.__disabledPropertyPriorities = new inspectedWindow.Object;
- }
-
- this.style.__disabledPropertyValues[this.name] = this.value;
- this.style.__disabledPropertyPriorities[this.name] = this.priority;
+ var self = this;
+ var callback = function(newPayload) {
+ if (!newPayload)
+ return;
- if (this.shorthand) {
- var longhandProperties = getLonghandProperties(this.style, this.name);
- for (var i = 0; i < longhandProperties.length; ++i) {
- this.style.__disabledProperties[longhandProperties[i]] = true;
- this.style.removeProperty(longhandProperties[i]);
- }
- } else {
- this.style.__disabledProperties[this.name] = true;
- this.style.removeProperty(this.name);
- }
- } else {
- this.style.setProperty(this.name, this.value, this.priority);
- delete this.style.__disabledProperties[this.name];
- delete this.style.__disabledPropertyValues[this.name];
- delete this.style.__disabledPropertyPriorities[this.name];
- }
+ self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload);
+ self._styleRule.style = self.style;
- // Set the disabled property here, since the code above replies on it not changing
- // until after the value and priority are retrieved.
- this.disabled = disabled;
+ // Set the disabled property here, since the code above replies on it not changing
+ // until after the value and priority are retrieved.
+ self.disabled = disabled;
- if (this.treeOutline.section && this.treeOutline.section.pane)
- this.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
+ if (self.treeOutline.section && self.treeOutline.section.pane)
+ self.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
- this.updateAll(true);
+ self.updateAll(true);
+ };
+ InspectorController.toggleStyleEnabled(this.style._id, this.name, disabled, callback);
},
updateState: function()
@@ -686,7 +1027,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (this.children.length || !this.shorthand)
return;
- var longhandProperties = getLonghandProperties(this.style, this.name);
+ var longhandProperties = this.style.getLonghandProperties(this.name);
for (var i = 0; i < longhandProperties.length; ++i) {
var name = longhandProperties[i];
@@ -695,7 +1036,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
var overloaded = this.treeOutline.section.isPropertyOverloaded(name);
}
- var item = new WebInspector.StylePropertyTreeElement(this.style, name, false, inherited, overloaded);
+ var item = new WebInspector.StylePropertyTreeElement(this._styleRule, this.style, name, false, inherited, overloaded);
this.appendChild(item);
}
},
@@ -703,6 +1044,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
ondblclick: function(element, event)
{
this.startEditing(event.target);
+ event.stopPropagation();
},
startEditing: function(selectElement)
@@ -809,11 +1151,11 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (!this.originalCSSText) {
// Remember the rule's original CSS text, so it can be restored
// if the editing is canceled and before each apply.
- this.originalCSSText = getStyleTextWithShorthands(this.style);
+ this.originalCSSText = this.style.styleTextWithShorthands();
} else {
// Restore the original CSS text before applying user changes. This is needed to prevent
// new properties from sticking around if the user adds one, then removes it.
- this.style.cssText = this.originalCSSText;
+ InspectorController.setStyleText(this.style, this.originalCSSText);
}
this.applyStyleText(this.listItemElement.textContent);
@@ -830,8 +1172,10 @@ WebInspector.StylePropertyTreeElement.prototype = {
editingCancelled: function(element, context)
{
- if (this.originalCSSText) {
- this.style.cssText = this.originalCSSText;
+ if (this._newProperty)
+ this.treeOutline.removeChild(this);
+ else if (this.originalCSSText) {
+ InspectorController.setStyleText(this.style, this.originalCSSText);
if (this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane.dispatchEventToListeners("style edited");
@@ -843,84 +1187,114 @@ WebInspector.StylePropertyTreeElement.prototype = {
this.editingEnded(context);
},
- editingCommitted: function(element, userInput, previousContent, context)
+ editingCommitted: function(element, userInput, previousContent, context, moveDirection)
{
this.editingEnded(context);
- if (userInput === previousContent)
- return; // nothing changed, so do nothing else
+ // Determine where to move to before making changes
+ var newProperty, moveToPropertyName, moveToSelector;
+ var moveTo = (moveDirection === "forward" ? this.nextSibling : this.previousSibling);
+ if (moveTo)
+ moveToPropertyName = moveTo.name;
+ else if (moveDirection === "forward")
+ newProperty = true;
+ else if (moveDirection === "backward" && this.treeOutline.section.rule)
+ moveToSelector = true;
+
+ // Make the Changes and trigger the moveToNextCallback after updating
+ var blankInput = /^\s*$/.test(userInput);
+ if (userInput !== previousContent || (this._newProperty && blankInput)) { // only if something changed, or adding a new style and it was blank
+ this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput);
+ this.applyStyleText(userInput, true);
+ } else
+ moveToNextCallback(this._newProperty, false, this.treeOutline.section, false);
- this.applyStyleText(userInput, true);
+ // The Callback to start editing the next property
+ function moveToNextCallback(alreadyNew, valueChanged, section) {
+ if (!moveDirection)
+ return;
+
+ // User just tabbed through without changes
+ if (moveTo && moveTo.parent) {
+ moveTo.startEditing(moveTo.valueElement);
+ return;
+ }
+
+ // User has made a change then tabbed, wiping all the original treeElements,
+ // recalculate the new treeElement for the same property we were going to edit next
+ if (moveTo && !moveTo.parent) {
+ var treeElement = section.findTreeElementWithName(moveToPropertyName);
+ if (treeElement)
+ treeElement.startEditing(treeElement.valueElement);
+ return;
+ }
+
+ // Create a new attribute in this section
+ if (newProperty) {
+ if (alreadyNew && !valueChanged)
+ return;
+
+ var item = section.addNewBlankProperty();
+ item.startEditing();
+ return;
+ }
+
+ if (moveToSelector)
+ section.startEditingSelector();
+ }
},
applyStyleText: function(styleText, updateInterface)
{
+ var section = this.treeOutline.section;
+ var elementsPanel = WebInspector.panels.elements;
var styleTextLength = styleText.trimWhitespace().length;
-
- // Create a new element to parse the user input CSS.
- var parseElement = document.createElement("span");
- parseElement.setAttribute("style", styleText);
-
- var tempStyle = parseElement.style;
- if (tempStyle.length || !styleTextLength) {
- // The input was parsable or the user deleted everything, so remove the
- // original property from the real style declaration. If this represents
- // a shorthand remove all the longhand properties.
- if (this.shorthand) {
- var longhandProperties = getLonghandProperties(this.style, this.name);
- for (var i = 0; i < longhandProperties.length; ++i)
- this.style.removeProperty(longhandProperties[i]);
- } else
- this.style.removeProperty(this.name);
- }
-
if (!styleTextLength) {
if (updateInterface) {
- // The user deleted the everything, so remove the tree element and update.
- if (this.treeOutline.section && this.treeOutline.section.pane)
- this.treeOutline.section.pane.update();
+ // The user deleted everything, so remove the tree element and update.
+ if (!this._newProperty)
+ delete section._afterUpdate;
+ if (section && section.pane)
+ section.pane.update();
this.parent.removeChild(this);
+ elementsPanel.removeStyleChange(section.identifier, this.style, this.name);
}
return;
}
- if (!tempStyle.length) {
- // The user typed something, but it didn't parse. Just abort and restore
- // the original title for this property.
- if (updateInterface)
- this.updateTitle();
- return;
- }
-
- // Iterate of the properties on the test element's style declaration and
- // add them to the real style declaration. We take care to move shorthands.
- var foundShorthands = {};
- var uniqueProperties = getUniqueStyleProperties(tempStyle);
- for (var i = 0; i < uniqueProperties.length; ++i) {
- var name = uniqueProperties[i];
- var shorthand = tempStyle.getPropertyShorthand(name);
-
- if (shorthand && shorthand in foundShorthands)
- continue;
-
- if (shorthand) {
- var value = getShorthandValue(tempStyle, shorthand);
- var priority = getShorthandPriority(tempStyle, shorthand);
- foundShorthands[shorthand] = true;
- } else {
- var value = tempStyle.getPropertyValue(name);
- var priority = tempStyle.getPropertyPriority(name);
+ var self = this;
+ var callback = function(result) {
+ if (!result) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property. If this was a new attribute and
+ // we couldn't parse, then just remove it.
+ if (self._newProperty) {
+ self.parent.removeChild(self);
+ return;
+ }
+ if (updateInterface)
+ self.updateTitle();
+ return;
}
- // Set the property on the real style declaration.
- this.style.setProperty((shorthand || name), value, priority);
- }
+ var newPayload = result[0];
+ var changedProperties = result[1];
+ elementsPanel.removeStyleChange(section.identifier, self.style, self.name);
- if (this.treeOutline.section && this.treeOutline.section.pane)
- this.treeOutline.section.pane.dispatchEventToListeners("style edited");
+ self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload);
+ for (var i = 0; i < changedProperties.length; ++i)
+ elementsPanel.addStyleChange(section.identifier, self.style, changedProperties[i]);
+ self._styleRule.style = self.style;
+ if (section && section.pane)
+ section.pane.dispatchEventToListeners("style edited");
- if (updateInterface)
- this.updateAll(true);
+ if (updateInterface)
+ self.updateAll(true);
+
+ if (!self.rule)
+ WebInspector.panels.elements.treeOutline.update();
+ };
+ InspectorController.applyStyleText(this.style._id, styleText.trimWhitespace(), this.name, callback);
}
}
diff --git a/WebCore/inspector/front-end/TextPrompt.js b/WebCore/inspector/front-end/TextPrompt.js
index 61e1b52..5ff774f 100644
--- a/WebCore/inspector/front-end/TextPrompt.js
+++ b/WebCore/inspector/front-end/TextPrompt.js
@@ -66,6 +66,7 @@ WebInspector.TextPrompt.prototype = {
this._tabKeyPressed(event);
break;
case "Right":
+ case "End":
if (!this.acceptAutoComplete())
this.autoCompleteSoon();
break;
@@ -140,7 +141,6 @@ WebInspector.TextPrompt.prototype = {
complete: function(auto)
{
this.clearAutoComplete(true);
-
var selection = window.getSelection();
if (!selection.rangeCount)
return;
@@ -150,17 +150,24 @@ WebInspector.TextPrompt.prototype = {
return;
if (auto && !this.isCaretAtEndOfPrompt())
return;
-
var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
- var completions = this.completions(wordPrefixRange, auto);
+ this.completions(wordPrefixRange, auto, this._completionsReady.bind(this, selection, auto, wordPrefixRange));
+ },
+ _completionsReady: function(selection, auto, originalWordPrefixRange, completions)
+ {
if (!completions || !completions.length)
return;
+ var selectionRange = selection.getRangeAt(0);
+
var fullWordRange = document.createRange();
- fullWordRange.setStart(wordPrefixRange.startContainer, wordPrefixRange.startOffset);
+ fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset);
fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+ if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString())
+ return;
+
if (completions.length === 1 || selection.isCollapsed || auto) {
var completionText = completions[0];
} else {
@@ -178,7 +185,7 @@ WebInspector.TextPrompt.prototype = {
var completionText = completions[foundIndex + 1];
}
- var wordPrefixLength = wordPrefixRange.toString().length;
+ var wordPrefixLength = originalWordPrefixRange.toString().length;
this._userEnteredRange = fullWordRange;
this._userEnteredText = fullWordRange.toString();
diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc
index 76a925b..c39c95b 100644
--- a/WebCore/inspector/front-end/WebKit.qrc
+++ b/WebCore/inspector/front-end/WebKit.qrc
@@ -4,24 +4,32 @@
<file>BottomUpProfileDataGridTree.js</file>
<file>Breakpoint.js</file>
<file>BreakpointsSidebarPane.js</file>
+ <file>Callback.js</file>
<file>CallStackSidebarPane.js</file>
- <file>Console.js</file>
+ <file>ChangesView.js</file>
+ <file>Color.js</file>
+ <file>ConsoleView.js</file>
<file>Database.js</file>
<file>DatabaseQueryView.js</file>
<file>DatabasesPanel.js</file>
<file>DatabaseTableView.js</file>
<file>DataGrid.js</file>
+ <file>DOMAgent.js</file>
<file>DOMStorage.js</file>
<file>DOMStorageDataGrid.js</file>
<file>DOMStorageItemsView.js</file>
+ <file>Drawer.js</file>
<file>ElementsPanel.js</file>
<file>ElementsTreeOutline.js</file>
<file>FontView.js</file>
<file>ImageView.js</file>
+ <file>InjectedScript.js</file>
<file>inspector.js</file>
+ <file>KeyboardShortcut.js</file>
<file>MetricsSidebarPane.js</file>
<file>Object.js</file>
<file>ObjectPropertiesSection.js</file>
+ <file>ObjectProxy.js</file>
<file>Panel.js</file>
<file>PanelEnablerView.js</file>
<file>Placard.js</file>
@@ -51,9 +59,9 @@
<file>inspector.css</file>
<file>Images/back.png</file>
<file>Images/checker.png</file>
- <file>Images/clearConsoleButtons.png</file>
+ <file>Images/clearConsoleButtonGlyph.png</file>
<file>Images/closeButtons.png</file>
- <file>Images/consoleButtons.png</file>
+ <file>Images/consoleButtonGlyph.png</file>
<file>Images/database.png</file>
<file>Images/databasesIcon.png</file>
<file>Images/databaseTable.png</file>
@@ -71,14 +79,15 @@
<file>Images/disclosureTriangleSmallRightDownBlack.png</file>
<file>Images/disclosureTriangleSmallRightDownWhite.png</file>
<file>Images/disclosureTriangleSmallRightWhite.png</file>
- <file>Images/dockButtons.png</file>
+ <file>Images/dockButtonGlyph.png</file>
<file>Images/domStorage.png</file>
<file>Images/elementsIcon.png</file>
- <file>Images/enableButtons.png</file>
+ <file>Images/enableOutlineButtonGlyph.png</file>
+ <file>Images/enableSolidButtonGlyph.png</file>
<file>Images/errorIcon.png</file>
<file>Images/errorMediumIcon.png</file>
- <file>Images/excludeButtons.png</file>
- <file>Images/focusButtons.png</file>
+ <file>Images/excludeButtonGlyph.png</file>
+ <file>Images/focusButtonGlyph.png</file>
<file>Images/forward.png</file>
<file>Images/glossyHeader.png</file>
<file>Images/glossyHeaderPressed.png</file>
@@ -87,21 +96,22 @@
<file>Images/goArrow.png</file>
<file>Images/graphLabelCalloutLeft.png</file>
<file>Images/graphLabelCalloutRight.png</file>
- <file>Images/largerResourcesButtons.png</file>
- <file>Images/nodeSearchButtons.png</file>
+ <file>Images/largerResourcesButtonGlyph.png</file>
+ <file>Images/nodeSearchButtonGlyph.png</file>
<file>Images/paneBottomGrow.png</file>
<file>Images/paneBottomGrowActive.png</file>
<file>Images/paneGrowHandleLine.png</file>
- <file>Images/pauseOnExceptionButtons.png</file>
- <file>Images/percentButtons.png</file>
+ <file>Images/pauseOnExceptionButtonGlyph.png</file>
+ <file>Images/percentButtonGlyph.png</file>
<file>Images/profileGroupIcon.png</file>
<file>Images/profileIcon.png</file>
<file>Images/profilesIcon.png</file>
<file>Images/profileSmallIcon.png</file>
<file>Images/profilesSilhouette.png</file>
<file>Images/radioDot.png</file>
- <file>Images/recordButtons.png</file>
- <file>Images/reloadButtons.png</file>
+ <file>Images/recordButtonGlyph.png</file>
+ <file>Images/recordToggledButtonGlyph.png</file>
+ <file>Images/reloadButtonGlyph.png</file>
<file>Images/resourceCSSIcon.png</file>
<file>Images/resourceDocumentIcon.png</file>
<file>Images/resourceDocumentIconSmall.png</file>
@@ -109,6 +119,7 @@
<file>Images/resourcePlainIcon.png</file>
<file>Images/resourcePlainIconSmall.png</file>
<file>Images/resourcesIcon.png</file>
+ <file>Images/resourcesSilhouette.png</file>
<file>Images/resourcesSizeGraphIcon.png</file>
<file>Images/resourcesTimeGraphIcon.png</file>
<file>Images/scriptsIcon.png</file>
@@ -157,6 +168,7 @@
<file>Images/treeRightTriangleWhite.png</file>
<file>Images/treeUpTriangleBlack.png</file>
<file>Images/treeUpTriangleWhite.png</file>
+ <file>Images/undockButtonGlyph.png</file>
<file>Images/userInputIcon.png</file>
<file>Images/userInputPreviousIcon.png</file>
<file>Images/userInputResultIcon.png</file>
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 2653781..51d626a 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Anthony Ricaud <rik@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -259,7 +260,7 @@ body.attached #main {
right: 0;
}
-body.console-visible #main-status-bar {
+body.drawer-visible #main-status-bar {
height: 24px;
background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackground.png);
background-repeat: no-repeat, repeat-x;
@@ -267,11 +268,11 @@ body.console-visible #main-status-bar {
cursor: row-resize;
}
-body.console-visible #main-status-bar * {
+body.drawer-visible #main-status-bar * {
cursor: default;
}
-body.console-visible #main-panels {
+body.drawer-visible #main-panels {
bottom: 24px;
}
@@ -306,14 +307,39 @@ body.console-visible #main-panels {
z-index: 200;
}
+.glyph {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.75);
+ z-index: 1;
+}
+
+.glyph.shadow {
+ top: 1px;
+ background-color: white !important;
+ z-index: 0;
+}
+
button.status-bar-item {
+ position: relative;
width: 32px;
background-image: url(Images/statusbarButtons.png);
background-position: 0 0;
}
button.status-bar-item:active {
- background-position: 32px 0;
+ background-position: 32px 0 !important;
+}
+
+button.status-bar-item .glyph.shadow {
+ background-color: rgba(255, 255, 255, 0.33) !important;
+}
+
+button.status-bar-item.toggled-on .glyph {
+ background-color: rgb(66, 129, 235);
}
button.status-bar-item:disabled {
@@ -338,47 +364,31 @@ select.status-bar-item:active {
-webkit-border-image: url(Images/statusbarMenuButtonSelected.png) 0 17 0 2;
}
-#dock-status-bar-item {
- background-image: url(Images/dockButtons.png);
-}
-
-body.attached #dock-status-bar-item:active {
- background-position: 32px 0;
-}
-
-body.detached #dock-status-bar-item {
- background-position: 0 24px;
+#dock-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/undockButtonGlyph.png);
}
-body.detached #dock-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+body.detached #dock-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/dockButtonGlyph.png);
}
-#console-status-bar-item {
- background-image: url(Images/consoleButtons.png);
+#console-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/consoleButtonGlyph.png);
}
-#console-status-bar-item:active {
- background-position: 32px 0;
+#clear-console-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png);
}
-#console-status-bar-item.toggled-on {
- background-position: 0 24px;
+#changes-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/consoleButtonGlyph.png); /* TODO: Needs Image for Changes Toggle Button */
}
-#console-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+#clear-changes-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png);
}
-#clear-console-status-bar-item {
- background-image: url(Images/clearConsoleButtons.png);
-}
-
-#clear-console-status-bar-item:active {
- background-position: 32px 0;
-}
-
-#error-warning-count {
+#count-items {
position: absolute;
right: 16px;
top: 0;
@@ -388,10 +398,22 @@ body.detached #dock-status-bar-item.toggled-on:active {
height: 19px;
}
-#error-warning-count:hover {
+#changes-count, #error-warning-count {
+ display: inline;
+}
+
+#error-warning-count:hover, #changes-count:hover {
border-bottom: 1px solid rgb(96, 96, 96);
}
+#style-changes-count::before {
+ content: url(Images/styleIcon.png); /* TODO: Needs Image for Style Changes Icon */
+ width: 10px;
+ height: 10px;
+ vertical-align: -1px;
+ margin-right: 2px;
+}
+
#error-count::before {
content: url(Images/errorIcon.png);
width: 10px;
@@ -399,8 +421,8 @@ body.detached #dock-status-bar-item.toggled-on:active {
vertical-align: -1px;
margin-right: 2px;
}
-
-#error-count + #warning-count {
+
+#changes-count + #error-warning-count, #error-count + #warning-count {
margin-left: 6px;
}
@@ -412,7 +434,7 @@ body.detached #dock-status-bar-item.toggled-on:active {
margin-right: 2px;
}
-#console {
+#drawer {
display: none;
position: absolute;
bottom: 0;
@@ -425,11 +447,11 @@ body.detached #dock-status-bar-item.toggled-on:active {
background-position: bottom;
}
-body.console-visible #console {
+body.drawer-visible #drawer {
display: block;
}
-#console-status-bar {
+#drawer-status-bar {
position: absolute;
bottom: 0;
left: 0;
@@ -444,8 +466,8 @@ body.console-visible #console {
left: 0;
right: 0;
bottom: 23px;
- font-size: 10px;
- font-family: Monaco, Lucida Console, monospace;
+ font-size: initial;
+ font-family: monospace;
padding: 2px 0;
overflow-y: overlay;
-webkit-user-select: text;
@@ -483,7 +505,7 @@ body.console-visible #console {
background-image: none;
}
-.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title-level::before {
+.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title::before {
position: absolute;
display: block;
content: "";
@@ -529,18 +551,18 @@ body.console-visible #console {
margin-left: 16px;
}
-.console-group-title-level {
+.console-group-title {
font-weight: bold;
}
-.console-group-title-level::before {
+.console-group-title::before {
background-image: url(Images/disclosureTriangleSmallDown.png);
top: 0.6em;
width: 11px;
height: 12px;
}
-.console-group.collapsed .console-group-title-level::before {
+.console-group.collapsed .console-group-title::before {
background-image: url(Images/disclosureTriangleSmallRight.png);
}
@@ -644,6 +666,10 @@ body.console-visible #console {
margin-right: -6px;
}
+.console-group-messages .add-attribute {
+ display: none;
+}
+
.console-formatted-object, .console-formatted-node {
position: relative;
display: inline-block;
@@ -768,6 +794,11 @@ body.console-visible #console {
vertical-align: top;
}
+.invisible {
+ color: inherit;
+ text-decoration: none;
+}
+
.webkit-line-gutter-backdrop {
/* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */
width: 31px;
@@ -1090,6 +1121,11 @@ body.console-visible #console {
text-decoration: underline;
}
+.add-attribute {
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
.placard {
position: relative;
margin-top: 1px;
@@ -1168,6 +1204,10 @@ body.inactive .placard.selected {
-webkit-background-clip: padding;
}
+.section.no-affect .header {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(167, 167, 167)), to(rgb(123, 123, 123)))
+}
+
.section .header::before {
position: absolute;
top: 4px;
@@ -1177,6 +1217,10 @@ body.inactive .placard.selected {
content: url(Images/treeRightTriangleWhite.png);
}
+.section.blank-section .header::before {
+ display: none;
+}
+
.section.expanded .header::before {
content: url(Images/treeDownTriangleWhite.png);
}
@@ -1188,6 +1232,10 @@ body.inactive .placard.selected {
white-space: normal;
}
+.section .header .title.blank-title {
+ font-style: italic;
+}
+
.section .header label {
display: none;
}
@@ -1225,6 +1273,15 @@ body.inactive .placard.selected {
padding: 2px 6px 3px;
list-style: none;
background-color: white;
+ min-height: 18px;
+}
+
+.section.no-affect .properties li {
+ opacity: 0.5;
+}
+
+.section.no-affect .properties li.editing {
+ opacity: 1.0;
}
.section.expanded .properties {
@@ -1810,9 +1867,18 @@ body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-des
text-indent: 10px;
}
+.data-grid-resizer {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 5px;
+ z-index: 500;
+ cursor: col-resize;
+}
+
.storage-view.query {
- font-size: 10px;
- font-family: Monaco, Lucida Console, monospace;
+ font-size: initial;
+ font-family: monospace;
padding: 2px 0;
overflow-y: overlay;
overflow-x: hidden;
@@ -2006,7 +2072,7 @@ body.inactive .panel-enabler-view button, .panel-enabler-view button:disabled {
}
.panel-enabler-view.resources img {
- content: url(Images/scriptsSilhouette.png);
+ content: url(Images/resourcesSilhouette.png);
}
.panel-enabler-view.scripts img {
@@ -2017,36 +2083,16 @@ body.inactive .panel-enabler-view button, .panel-enabler-view button:disabled {
content: url(Images/profilesSilhouette.png);
}
-button.enable-toggle-status-bar-item {
- background-image: url(Images/enableButtons.png);
-}
-
-button.enable-toggle-status-bar-item:active {
- background-position: 32px 0;
-}
-
-button.enable-toggle-status-bar-item.toggled-on {
- background-position: 0 24px;
-}
-
-button.enable-toggle-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
-}
-
-#scripts-pause-on-exceptions-status-bar-item {
- background-image: url(Images/pauseOnExceptionButtons.png);
+button.enable-toggle-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/enableOutlineButtonGlyph.png);
}
-#scripts-pause-on-exceptions-status-bar-item:active {
- background-position: 32px 0;
-}
-
-#scripts-pause-on-exceptions-status-bar-item.toggled-on {
- background-position: 0 24px;
+button.enable-toggle-status-bar-item.toggled-on .glyph {
+ -webkit-mask-image: url(Images/enableSolidButtonGlyph.png);
}
-#scripts-pause-on-exceptions-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+#scripts-pause-on-exceptions-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png);
}
#scripts-status-bar {
@@ -2163,25 +2209,54 @@ button.enable-toggle-status-bar-item.toggled-on:active {
overflow: auto;
}
-#resources-larger-resources-status-bar-item {
- background-image: url(Images/largerResourcesButtons.png);
+#resources-larger-resources-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png);
}
-#resources-larger-resources-status-bar-item:active {
- background-position: 32px 0;
+#resources-filter {
+ height: 24px;
+ padding: 2px 10px 0;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207)));
+ border-bottom: 1px solid rgb(177, 177, 177);
+ overflow: hidden;
}
-#resources-larger-resources-status-bar-item.toggled-on {
- background-position: 0 24px;
+#resources-filter li {
+ display: inline-block;
+ margin: 1px 1px 0 0;
+ padding: 0 6px 3px;
+ font-size: 12px;
+ line-height: 12px;
+ font-weight: bold;
+ color: rgb(40, 40, 40);
+ border: 1px solid transparent;
+ border-bottom: 0;
+ background: transparent;
+ -webkit-border-radius: 8px;
+ text-shadow: rgba(255, 255, 255, 0.5) 1px 1px 0;
+}
+
+#resources-filter li.selected, #resources-filter li:hover, #resources-filter li:active {
+ color: white;
+ text-shadow: rgb(80, 80, 80) 1px 1px 1px;
+ background: rgba(20, 20, 20, 0.4);
+ border-color: rgba(20, 20, 20, 0.2);
+ -webkit-box-shadow: 0 1px 0px rgba(255, 255, 255, 0.5);
}
-#resources-larger-resources-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+#resources-filter li:hover {
+ background: rgba(20, 20, 20, 0.4);
+ border-color: transparent;
+ -webkit-box-shadow: none;
+}
+
+#resources-filter li:active {
+ background: rgba(20, 20, 20, 0.6);
}
#resources-container {
position: absolute;
- top: 0;
+ top: 24px;
left: 0;
bottom: 0;
right: 0;
@@ -2386,6 +2461,22 @@ button.enable-toggle-status-bar-item.toggled-on:active {
-webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
}
+.resources-category-documents, .resources-category-stylesheets, .resources-category-images,
+.resources-category-scripts, .resources-category-xhr, .resources-category-fonts, .resources-category-other {
+ display: none;
+}
+
+.filter-all .resources-category-documents, .filter-documents .resources-category-documents,
+.filter-all .resources-category-stylesheets, .filter-stylesheets .resources-category-stylesheets,
+.filter-all .resources-category-images, .filter-images .resources-category-images,
+.filter-all .resources-category-scripts, .filter-scripts .resources-category-scripts,
+.filter-all .resources-category-xhr, .filter-xhr .resources-category-xhr,
+.filter-all .resources-category-fonts, .filter-fonts .resources-category-fonts,
+.filter-all .resources-category-other, .filter-other .resources-category-other,
+.resource-sidebar-tree-item.selected {
+ display: list-item;
+}
+
.resources-graph-bar.waiting {
opacity: 0.35;
}
@@ -2489,7 +2580,7 @@ button.enable-toggle-status-bar-item.toggled-on:active {
#resource-views {
position: absolute;
- top: 0;
+ top: 24px;
right: 0;
left: 200px;
bottom: 0;
@@ -2509,6 +2600,10 @@ button.enable-toggle-status-bar-item.toggled-on:active {
cursor: col-resize;
}
+.resources .sidebar-resizer-vertical {
+ top: 24px;
+}
+
.sidebar-tree, .sidebar-tree .children {
position: relative;
padding: 0;
@@ -2995,84 +3090,40 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
color: white;
}
-#record-profile-status-bar-item {
- background-image: url(Images/recordButtons.png);
-}
-
-#record-profile-status-bar-item:active {
- background-position: 32px 0;
-}
-
-#record-profile-status-bar-item.toggled-on {
- background-position: 0 24px;
-}
-
-#record-profile-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+button.enable-toggle-status-bar-item .glyph {
}
-#node-search-status-bar-item {
- background-image: url(Images/nodeSearchButtons.png);
+#record-profile-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/recordButtonGlyph.png);
}
-#node-search-status-bar-item:active {
- background-position: 32px 0;
+#record-profile-status-bar-item.toggled-on .glyph {
+ -webkit-mask-image: url(Images/recordToggledButtonGlyph.png);
+ background-color: rgb(216, 0, 0);
}
-#node-search-status-bar-item.toggled-on {
- background-position: 0 24px;
+#node-search-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/nodeSearchButtonGlyph.png);
}
-#node-search-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
+.percent-time-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/percentButtonGlyph.png);
}
-.percent-time-status-bar-item {
- background-image: url(Images/percentButtons.png) !important;
+.focus-profile-node-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/focusButtonGlyph.png);
}
-.percent-time-status-bar-item:active {
- background-position: 32px 0;
+.exclude-profile-node-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/excludeButtonGlyph.png);
}
-.percent-time-status-bar-item.toggled-on {
- background-position: 0 24px;
+.reset-profile-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/reloadButtonGlyph.png);
}
-.percent-time-status-bar-item.toggled-on:active {
- background-position: 32px 24px;
-}
-
-.focus-profile-node-status-bar-item {
- background-image: url(Images/focusButtons.png) !important;
-}
-
-.focus-profile-node-status-bar-item:active {
- background-position: 32px 0;
-}
-
-.exclude-profile-node-status-bar-item {
- background-image: url(Images/excludeButtons.png) !important;
-}
-
-.exclude-profile-node-status-bar-item:active {
- background-position: 32px 0;
-}
-
-.reset-profile-status-bar-item {
- background-image: url(Images/reloadButtons.png) !important;
-}
-
-.reset-profile-status-bar-item:active {
- background-position: 32px 0;
-}
-
-.delete-storage-status-bar-item {
- background-image: url(Images/excludeButtons.png) !important;
-}
-
-.delete-storage-status-bar-item:active {
- background-position: 32px 0;
+.delete-storage-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/excludeButtonGlyph.png);
}
#storage-view-status-bar-items {
@@ -3102,3 +3153,41 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches {
border-left: 1px solid rgb(184, 184, 184);
margin-left: -1px;
}
+
+ol.breakpoint-list {
+ -webkit-padding-start: 2px;
+ list-style: none;
+ margin: 0;
+}
+
+.breakpoint-list li {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ margin: 4px 0;
+}
+
+.breakpoint-list .checkbox-elem {
+ font-size: 10px;
+ margin: 0 4px;
+ vertical-align: top;
+ position: relative;
+ z-index: 1;
+}
+
+.breakpoint-list .source-text {
+ font-family: monospace;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ margin: 2px 0 0px 20px;
+}
+
+.breakpoint-list a {
+ color: rgb(33%, 33%, 33%);
+ cursor: pointer;
+}
+
+.breakpoint-list a:hover {
+ color: rgb(15%, 15%, 15%);
+}
diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html
index 184bb45..a3dc407 100644
--- a/WebCore/inspector/front-end/inspector.html
+++ b/WebCore/inspector/front-end/inspector.html
@@ -34,10 +34,14 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="treeoutline.js"></script>
<script type="text/javascript" src="inspector.js"></script>
<script type="text/javascript" src="Object.js"></script>
+ <script type="text/javascript" src="KeyboardShortcut.js"></script>
<script type="text/javascript" src="TextPrompt.js"></script>
<script type="text/javascript" src="Placard.js"></script>
<script type="text/javascript" src="View.js"></script>
- <script type="text/javascript" src="Console.js"></script>
+ <script type="text/javascript" src="Callback.js"></script>
+ <script type="text/javascript" src="Drawer.js"></script>
+ <script type="text/javascript" src="ChangesView.js"></script>
+ <script type="text/javascript" src="ConsoleView.js"></script>
<script type="text/javascript" src="Resource.js"></script>
<script type="text/javascript" src="ResourceCategory.js"></script>
<script type="text/javascript" src="Database.js"></script>
@@ -51,12 +55,14 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ElementsTreeOutline.js"></script>
<script type="text/javascript" src="SidebarTreeElement.js"></script>
<script type="text/javascript" src="PropertiesSection.js"></script>
+ <script type="text/javascript" src="ObjectProxy.js"></script>
<script type="text/javascript" src="ObjectPropertiesSection.js"></script>
<script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
<script type="text/javascript" src="CallStackSidebarPane.js"></script>
<script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
<script type="text/javascript" src="MetricsSidebarPane.js"></script>
<script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="Color.js"></script>
<script type="text/javascript" src="StylesSidebarPane.js"></script>
<script type="text/javascript" src="Panel.js"></script>
<script type="text/javascript" src="PanelEnablerView.js"></script>
@@ -77,6 +83,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
<script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
<script type="text/javascript" src="ProfileView.js"></script>
+ <script type="text/javascript" src="DOMAgent.js"></script>
+ <script type="text/javascript" src="InjectedScript.js"></script>
</head>
<body class="detached">
<div id="toolbar">
@@ -86,12 +94,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
</div>
<div id="main">
- <div id="main-panels" tabindex="0"></div>
- <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div>
+ <div id="main-panels" tabindex="0" spellcheck="false"></div>
+ <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="changes-status-bar-item" class="status-bar-item hidden"></button><div id="count-items"><div id="changes-count" class="hidden"></div><div id="error-warning-count" class="hidden"></div></div></div></div>
</div>
- <div id="console">
- <div id="console-messages"><div id="console-prompt"><br></div></div>
- <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div>
+ <div id="drawer">
+ <div id="console-view"><div id="console-messages"><div id="console-prompt" spellcheck="false"><br></div></div></div>
+ <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button></div></div>
</div>
</body>
</html>
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index 9d5bac0..aa21a86 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +38,8 @@ var Preferences = {
minScriptsSidebarWidth: 200,
showInheritedComputedStyleProperties: false,
styleRulesExpandedState: {},
- showMissingLocalizedStrings: false
+ showMissingLocalizedStrings: false,
+ useDOMAgent: false
}
var WebInspector = {
@@ -117,6 +119,26 @@ var WebInspector = {
}
}
}
+
+ for (var panelName in WebInspector.panels) {
+ if (WebInspector.panels[panelName] == x)
+ InspectorController.storeLastActivePanel(panelName);
+ }
+ },
+
+ _createPanels: function()
+ {
+ var hiddenPanels = (InspectorController.hiddenPanels() || "").split(',');
+ if (hiddenPanels.indexOf("elements") === -1)
+ this.panels.elements = new WebInspector.ElementsPanel();
+ if (hiddenPanels.indexOf("resources") === -1)
+ this.panels.resources = new WebInspector.ResourcesPanel();
+ if (hiddenPanels.indexOf("scripts") === -1)
+ this.panels.scripts = new WebInspector.ScriptsPanel();
+ if (hiddenPanels.indexOf("profiles") === -1)
+ this.panels.profiles = new WebInspector.ProfilesPanel();
+ if (hiddenPanels.indexOf("databases") === -1)
+ this.panels.databases = new WebInspector.DatabasesPanel();
},
get attached()
@@ -231,6 +253,53 @@ var WebInspector = {
errorWarningElement.title = null;
},
+ get styleChanges()
+ {
+ return this._styleChanges;
+ },
+
+ set styleChanges(x)
+ {
+ x = Math.max(x, 0);
+
+ if (this._styleChanges === x)
+ return;
+ this._styleChanges = x;
+ this._updateChangesCount();
+ },
+
+ _updateChangesCount: function()
+ {
+ // TODO: Remove immediate return when enabling the Changes Panel
+ return;
+
+ var changesElement = document.getElementById("changes-count");
+ if (!changesElement)
+ return;
+
+ if (!this.styleChanges) {
+ changesElement.addStyleClass("hidden");
+ return;
+ }
+
+ changesElement.removeStyleClass("hidden");
+ changesElement.removeChildren();
+
+ if (this.styleChanges) {
+ var styleChangesElement = document.createElement("span");
+ styleChangesElement.id = "style-changes-count";
+ styleChangesElement.textContent = this.styleChanges;
+ changesElement.appendChild(styleChangesElement);
+ }
+
+ if (this.styleChanges) {
+ if (this.styleChanges === 1)
+ changesElement.title = WebInspector.UIString("%d style change", this.styleChanges);
+ else
+ changesElement.title = WebInspector.UIString("%d style changes", this.styleChanges);
+ }
+ },
+
get hoveredDOMNode()
{
return this._hoveredDOMNode;
@@ -278,27 +347,37 @@ WebInspector.loaded = function()
var platform = InspectorController.platform();
document.body.addStyleClass("platform-" + platform);
- this.console = new WebInspector.Console();
+ this.drawer = new WebInspector.Drawer();
+ this.console = new WebInspector.ConsoleView(this.drawer);
+ // TODO: Uncomment when enabling the Changes Panel
+ // this.changes = new WebInspector.ChangesView(this.drawer);
+ // TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item
+ this.drawer.visibleView = this.console;
+
+ if (Preferences.useDOMAgent)
+ this.domAgent = new WebInspector.DOMAgent();
+
+ this.resourceCategories = {
+ documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"),
+ stylesheets: new WebInspector.ResourceCategory(WebInspector.UIString("Stylesheets"), "stylesheets"),
+ images: new WebInspector.ResourceCategory(WebInspector.UIString("Images"), "images"),
+ scripts: new WebInspector.ResourceCategory(WebInspector.UIString("Scripts"), "scripts"),
+ xhr: new WebInspector.ResourceCategory(WebInspector.UIString("XHR"), "xhr"),
+ fonts: new WebInspector.ResourceCategory(WebInspector.UIString("Fonts"), "fonts"),
+ other: new WebInspector.ResourceCategory(WebInspector.UIString("Other"), "other")
+ };
this.panels = {};
- var hiddenPanels = (InspectorController.hiddenPanels() || "").split(',');
- if (hiddenPanels.indexOf("elements") === -1)
- this.panels.elements = new WebInspector.ElementsPanel();
- if (hiddenPanels.indexOf("resources") === -1)
- this.panels.resources = new WebInspector.ResourcesPanel();
- if (hiddenPanels.indexOf("scripts") === -1)
- this.panels.scripts = new WebInspector.ScriptsPanel();
- if (hiddenPanels.indexOf("profiles") === -1)
- this.panels.profiles = new WebInspector.ProfilesPanel();
- if (hiddenPanels.indexOf("databases") === -1)
- this.panels.databases = new WebInspector.DatabasesPanel();
+ this._createPanels();
var toolbarElement = document.getElementById("toolbar");
var previousToolbarItem = toolbarElement.children[0];
+ this.panelOrder = [];
for (var panelName in this.panels) {
var panel = this.panels[panelName];
var panelToolbarItem = panel.toolbarItem;
+ this.panelOrder.push(panel);
panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
if (previousToolbarItem)
toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
@@ -307,18 +386,6 @@ WebInspector.loaded = function()
previousToolbarItem = panelToolbarItem;
}
- this.currentPanel = this.panels.elements;
-
- this.resourceCategories = {
- documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"),
- stylesheets: new WebInspector.ResourceCategory(WebInspector.UIString("Stylesheets"), "stylesheets"),
- images: new WebInspector.ResourceCategory(WebInspector.UIString("Images"), "images"),
- scripts: new WebInspector.ResourceCategory(WebInspector.UIString("Scripts"), "scripts"),
- xhr: new WebInspector.ResourceCategory(WebInspector.UIString("XHR"), "xhr"),
- fonts: new WebInspector.ResourceCategory(WebInspector.UIString("Fonts"), "fonts"),
- other: new WebInspector.ResourceCategory(WebInspector.UIString("Other"), "other")
- };
-
this.Tips = {
ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
};
@@ -357,9 +424,15 @@ WebInspector.loaded = function()
dockToggleButton.title = WebInspector.UIString("Dock to main window.");
var errorWarningCount = document.getElementById("error-warning-count");
- errorWarningCount.addEventListener("click", this.console.show.bind(this.console), false);
+ errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
this._updateErrorAndWarningCounts();
+ this.styleChanges = 0;
+ // TODO: Uncomment when enabling the Changes Panel
+ // var changesElement = document.getElementById("changes-count");
+ // changesElement.addEventListener("click", this.showChanges.bind(this), false);
+ // this._updateErrorAndWarningCounts();
+
var searchField = document.getElementById("search");
searchField.addEventListener("keydown", this.searchKeyDown.bind(this), false);
searchField.addEventListener("keyup", this.searchKeyUp.bind(this), false);
@@ -368,7 +441,7 @@ WebInspector.loaded = function()
document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true);
document.getElementById("close-button").addEventListener("click", this.close, true);
- InspectorController.loaded();
+ InspectorController.loaded(Preferences.useDOMAgent);
}
var windowLoaded = function()
@@ -488,7 +561,7 @@ WebInspector.documentKeyDown = function(event)
switch (event.keyIdentifier) {
case "U+001B": // Escape key
- this.console.visible = !this.console.visible;
+ this.drawer.visible = !this.drawer.visible;
event.preventDefault();
break;
@@ -523,6 +596,36 @@ WebInspector.documentKeyDown = function(event)
}
break;
+
+ case "U+005B": // [ key
+ if (isMac)
+ var isRotateLeft = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
+ else
+ var isRotateLeft = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
+
+ if (isRotateLeft) {
+ var index = this.panelOrder.indexOf(this.currentPanel);
+ index = (index === 0) ? this.panelOrder.length - 1 : index - 1;
+ this.panelOrder[index].toolbarItem.click();
+ event.preventDefault();
+ }
+
+ break;
+
+ case "U+005D": // ] key
+ if (isMac)
+ var isRotateRight = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
+ else
+ var isRotateRight = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
+
+ if (isRotateRight) {
+ var index = this.panelOrder.indexOf(this.currentPanel);
+ index = (index + 1) % this.panelOrder.length;
+ this.panelOrder[index].toolbarItem.click();
+ event.preventDefault();
+ }
+
+ break;
}
}
}
@@ -588,6 +691,7 @@ WebInspector.animateStyle = function(animations, duration, callback, complete)
var start = null;
var current = null;
var end = null;
+ var key = null;
for (key in animation) {
if (key === "element")
element = animation[key];
@@ -749,7 +853,12 @@ WebInspector.elementDragEnd = function(event)
WebInspector.showConsole = function()
{
- this.console.show();
+ this.drawer.visibleView = this.console;
+}
+
+WebInspector.showChanges = function()
+{
+ this.drawer.visibleView = this.changes;
}
WebInspector.showElementsPanel = function()
@@ -979,6 +1088,7 @@ WebInspector.addMessageToConsole = function(payload)
{
var consoleMessage = new WebInspector.ConsoleMessage(
payload.source,
+ payload.type,
payload.level,
payload.line,
payload.url,
@@ -1277,6 +1387,7 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
var oldText = element.textContent;
var oldHandleKeyEvent = element.handleKeyEvent;
+ var moveDirection = "";
element.addStyleClass("editing");
@@ -1314,7 +1425,7 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
function editingCommitted() {
cleanUpAfterEditing.call(this);
- committedCallback(this, this.textContent, oldText, context);
+ committedCallback(this, this.textContent, oldText, context, moveDirection);
}
element.handleKeyEvent = function(event) {
@@ -1330,7 +1441,8 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
editingCancelled.call(element);
event.preventDefault();
event.handled = true;
- }
+ } else if (event.keyIdentifier === "U+0009") // Tab key
+ moveDirection = (event.shiftKey ? "backward" : "forward");
}
element.addEventListener("blur", blurEventListener, false);
diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js
index 8fb50e2..eec0b87 100644
--- a/WebCore/inspector/front-end/utilities.js
+++ b/WebCore/inspector/front-end/utilities.js
@@ -38,7 +38,7 @@ Object.type = function(obj, win)
win = win || window;
if (obj instanceof win.Node)
- return "node";
+ return (obj.nodeType === undefined ? type : "node");
if (obj instanceof win.String)
return "string";
if (obj instanceof win.Array)
@@ -94,15 +94,19 @@ Object.describe = function(obj, abbreviated)
}
}
-Object.sortedProperties = function(obj)
+Object.properties = function(obj)
{
var properties = [];
for (var prop in obj)
properties.push(prop);
- properties.sort();
return properties;
}
+Object.sortedProperties = function(obj, sortFunc)
+{
+ return Object.properties(obj).sort(sortFunc);
+}
+
Function.prototype.bind = function(thisObject)
{
var func = this;
@@ -381,113 +385,6 @@ String.prototype.trimURL = function(baseURLDomain)
return result;
}
-function getStyleTextWithShorthands(style)
-{
- var cssText = "";
- var foundProperties = {};
- for (var i = 0; i < style.length; ++i) {
- var individualProperty = style[i];
- var shorthandProperty = style.getPropertyShorthand(individualProperty);
- var propertyName = (shorthandProperty || individualProperty);
-
- if (propertyName in foundProperties)
- continue;
-
- if (shorthandProperty) {
- var value = getShorthandValue(style, shorthandProperty);
- var priority = getShorthandPriority(style, shorthandProperty);
- } else {
- var value = style.getPropertyValue(individualProperty);
- var priority = style.getPropertyPriority(individualProperty);
- }
-
- foundProperties[propertyName] = true;
-
- cssText += propertyName + ": " + value;
- if (priority)
- cssText += " !" + priority;
- cssText += "; ";
- }
-
- return cssText;
-}
-
-function getShorthandValue(style, shorthandProperty)
-{
- var value = style.getPropertyValue(shorthandProperty);
- if (!value) {
- // Some shorthands (like border) return a null value, so compute a shorthand value.
- // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823 is fixed.
-
- var foundProperties = {};
- for (var i = 0; i < style.length; ++i) {
- var individualProperty = style[i];
- if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
- continue;
-
- var individualValue = style.getPropertyValue(individualProperty);
- if (style.isPropertyImplicit(individualProperty) || individualValue === "initial")
- continue;
-
- foundProperties[individualProperty] = true;
-
- if (!value)
- value = "";
- else if (value.length)
- value += " ";
- value += individualValue;
- }
- }
- return value;
-}
-
-function getShorthandPriority(style, shorthandProperty)
-{
- var priority = style.getPropertyPriority(shorthandProperty);
- if (!priority) {
- for (var i = 0; i < style.length; ++i) {
- var individualProperty = style[i];
- if (style.getPropertyShorthand(individualProperty) !== shorthandProperty)
- continue;
- priority = style.getPropertyPriority(individualProperty);
- break;
- }
- }
- return priority;
-}
-
-function getLonghandProperties(style, shorthandProperty)
-{
- var properties = [];
- var foundProperties = {};
-
- for (var i = 0; i < style.length; ++i) {
- var individualProperty = style[i];
- if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
- continue;
- foundProperties[individualProperty] = true;
- properties.push(individualProperty);
- }
-
- return properties;
-}
-
-function getUniqueStyleProperties(style)
-{
- var properties = [];
- var foundProperties = {};
-
- for (var i = 0; i < style.length; ++i) {
- var property = style[i];
- if (property in foundProperties)
- continue;
- foundProperties[property] = true;
- properties.push(property);
- }
-
- return properties;
-}
-
function isNodeWhitespace()
{
if (!this || this.nodeType !== Node.TEXT_NODE)