diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-14 16:29:47 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-14 16:29:47 +0200 |
commit | d0424a769059c84ae20beb3c217812792ea6726b (patch) | |
tree | 6f94a5c3db8c52c6694ee56498542a6c35417350 /Source/WebCore/inspector | |
parent | 88a04ac016f57c2d78e714682445dff2e7db4ade (diff) | |
download | qtwebkit-d0424a769059c84ae20beb3c217812792ea6726b.tar.gz |
Imported WebKit commit 37c5e5041d39a14ea0d429a77ebd352e4bd26516 (http://svn.webkit.org/repository/webkit/trunk@128608)
New snapshot that enables WebKit2 build on Windows (still some bugs) and allows for WebKit to be built with qmake && make
Diffstat (limited to 'Source/WebCore/inspector')
58 files changed, 1765 insertions, 671 deletions
diff --git a/Source/WebCore/inspector/DOMEditor.h b/Source/WebCore/inspector/DOMEditor.h index 264913232..9a0d9915e 100644 --- a/Source/WebCore/inspector/DOMEditor.h +++ b/Source/WebCore/inspector/DOMEditor.h @@ -47,7 +47,7 @@ class Text; typedef String ErrorString; class DOMEditor { - WTF_MAKE_NONCOPYABLE(DOMEditor); + WTF_MAKE_NONCOPYABLE(DOMEditor); WTF_MAKE_FAST_ALLOCATED; public: explicit DOMEditor(InspectorHistory*); ~DOMEditor(); diff --git a/Source/WebCore/inspector/InjectedScriptHost.h b/Source/WebCore/inspector/InjectedScriptHost.h index ab50fb939..af66b28b3 100644 --- a/Source/WebCore/inspector/InjectedScriptHost.h +++ b/Source/WebCore/inspector/InjectedScriptHost.h @@ -92,6 +92,7 @@ public: void disconnect(); class InspectableObject { + WTF_MAKE_FAST_ALLOCATED; public: virtual ScriptValue get(ScriptState*); virtual ~InspectableObject() { } diff --git a/Source/WebCore/inspector/InjectedScriptManager.h b/Source/WebCore/inspector/InjectedScriptManager.h index ed51c03ef..111e2b2b8 100644 --- a/Source/WebCore/inspector/InjectedScriptManager.h +++ b/Source/WebCore/inspector/InjectedScriptManager.h @@ -44,7 +44,7 @@ class InspectorObject; class ScriptObject; class InjectedScriptManager { - WTF_MAKE_NONCOPYABLE(InjectedScriptManager); + WTF_MAKE_NONCOPYABLE(InjectedScriptManager); WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<InjectedScriptManager> createForPage(); static PassOwnPtr<InjectedScriptManager> createForWorker(); diff --git a/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js b/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js index dd3b5b772..6780af3c4 100644 --- a/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js +++ b/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js @@ -559,8 +559,9 @@ Resource.prototype = { */ proxyObject: function() { - // No proxy wrapping by default. - return this.wrappedObject(); + if (!this._proxyObject) + this._proxyObject = this._wrapObject(); + return this._proxyObject; }, /** @@ -667,6 +668,167 @@ Resource.prototype = { enumerable: false, configurable: true }); + }, + + /** + * @return {Object} + */ + _wrapObject: function() + { + var wrappedObject = this.wrappedObject(); + if (!wrappedObject) + return null; + var proxy = Object.create(wrappedObject.__proto__); // In order to emulate "instanceof". + + var self = this; + var customWrapFunctions = this._customWrapFunctions(); + function processProperty(property) + { + if (typeof wrappedObject[property] === "function") { + var customWrapFunction = customWrapFunctions[property]; + if (customWrapFunction) + proxy[property] = self._wrapCustomFunction(self, wrappedObject, wrappedObject[property], property, customWrapFunction); + else + proxy[property] = self._wrapFunction(self, wrappedObject, wrappedObject[property], property); + } else if (/^[A-Z0-9_]+$/.test(property) && typeof wrappedObject[property] === "number") { + // Fast access to enums and constants. + proxy[property] = wrappedObject[property]; + } else { + Object.defineProperty(proxy, property, { + get: function() + { + return wrappedObject[property]; + }, + set: function(value) + { + // FIXME: Log the setter calls. + console.error("FIXME: Setting an attribute %s was not logged.", property); + wrappedObject[property] = value; + }, + enumerable: true + }); + } + } + + var isEmpty = true; + for (var property in wrappedObject) { + isEmpty = false; + processProperty(property); + } + if (isEmpty) + return wrappedObject; // Nothing to proxy. + + this._bindObjectToResource(proxy); + return proxy; + }, + + /** + * @param {Resource} resource + * @param {Object} originalObject + * @param {Function} originalFunction + * @param {string} functionName + * @param {Function} customWrapFunction + * @return {Function} + */ + _wrapCustomFunction: function(resource, originalObject, originalFunction, functionName, customWrapFunction) + { + return function() + { + var manager = resource.manager(); + var isCapturing = manager && manager.capturing(); + if (isCapturing) + manager.captureArguments(resource, arguments); + var wrapFunction = new Resource.WrapFunction(originalObject, originalFunction, functionName, arguments); + customWrapFunction.apply(wrapFunction, arguments); + if (isCapturing) { + var call = wrapFunction.call(); + call.setStackTrace(StackTrace.create(1, arguments.callee)); + manager.reportCall(call); + } + return wrapFunction.result(); + }; + }, + + /** + * @param {Resource} resource + * @param {Object} originalObject + * @param {Function} originalFunction + * @param {string} functionName + * @return {Function} + */ + _wrapFunction: function(resource, originalObject, originalFunction, functionName) + { + return function() + { + var manager = resource.manager(); + if (!manager || !manager.capturing()) + return originalFunction.apply(originalObject, arguments); + manager.captureArguments(resource, arguments); + var result = originalFunction.apply(originalObject, arguments); + var stackTrace = StackTrace.create(1, arguments.callee); + var call = new Call(resource, functionName, arguments, result, stackTrace); + manager.reportCall(call); + return result; + }; + }, + + /** + * @return {Object.<string, Function>} + */ + _customWrapFunctions: function() + { + return {}; // May be overridden by subclasses. + } +} + +/** + * @constructor + * @param {Object} originalObject + * @param {Function} originalFunction + * @param {string} functionName + * @param {Array|Arguments} args + */ +Resource.WrapFunction = function(originalObject, originalFunction, functionName, args) +{ + this._originalObject = originalObject; + this._originalFunction = originalFunction; + this._functionName = functionName; + this._args = args; + this._resource = Resource.forObject(originalObject); + console.assert(this._resource, "Expected a wrapped call on a Resource object."); +} + +Resource.WrapFunction.prototype = { + /** + * @return {*} + */ + result: function() + { + if (!this._executed) { + this._executed = true; + this._result = this._originalFunction.apply(this._originalObject, this._args); + } + return this._result; + }, + + /** + * @return {Call} + */ + call: function() + { + if (!this._call) + this._call = new Call(this._resource, this._functionName, this._args, this.result()); + return this._call; + }, + + /** + * @param {*} result + */ + overrideResult: function(result) + { + var call = this.call(); + call.setResult(result); + this._result = result; } } @@ -1110,7 +1272,6 @@ function WebGLRenderingContextResource(glContext, replayContextCallback) { Resource.call(this, glContext); this._replayContextCallback = replayContextCallback; - this._proxyObject = null; /** @type {Object.<number, boolean>} */ this._customErrors = null; } @@ -1217,16 +1378,6 @@ WebGLRenderingContextResource.forObject = function(obj) WebGLRenderingContextResource.prototype = { /** - * @return {Object} - */ - proxyObject: function() - { - if (!this._proxyObject) - this._proxyObject = this._wrapObject(); - return this._proxyObject; - }, - - /** * @return {Array.<number>} */ getAllErrors: function() @@ -1362,7 +1513,6 @@ WebGLRenderingContextResource.prototype = { _doReplayCalls: function(data, cache) { this._replayContextCallback = data.replayContextCallback; - this._proxyObject = null; this._customErrors = null; var gl = Resource.wrappedObject(this._replayContextCallback()); @@ -1502,248 +1652,107 @@ WebGLRenderingContextResource.prototype = { }, /** - * @return {Object} - */ - _wrapObject: function() - { - var gl = this.wrappedObject(); - var proxy = Object.create(gl.__proto__); // In order to emulate "instanceof". - - var self = this; - var customWrapFunctions = WebGLRenderingContextResource.wrapFunctions(); - function processProperty(property) - { - if (typeof gl[property] === "function") { - var customWrapFunction = customWrapFunctions[property]; - if (customWrapFunction) - proxy[property] = self._wrapCustomFunction(self, gl, gl[property], property, customWrapFunction); - else - proxy[property] = self._wrapFunction(self, gl, gl[property], property); - } else if (/^[A-Z0-9_]+$/.test(property)) { - // Fast access to enums and constants. - console.assert(typeof gl[property] === "number", "Expected a number for property " + property); - proxy[property] = gl[property]; - } else { - Object.defineProperty(proxy, property, { - get: function() - { - return gl[property]; - }, - set: function(value) - { - console.error("ASSERT_NOT_REACHED: We assume all WebGLRenderingContext attributes are readonly. Trying to mutate " + property); - gl[property] = value; - } - }); - } - } - - for (var property in gl) - processProperty(property); - - this._bindObjectToResource(proxy); - return proxy; - }, - - /** - * @param {Resource} resource - * @param {WebGLRenderingContext} originalObject - * @param {Function} originalFunction - * @param {string} functionName - * @param {Function} customWrapFunction - * @return {Function} - */ - _wrapCustomFunction: function(resource, originalObject, originalFunction, functionName, customWrapFunction) - { - return function() - { - var manager = resource.manager(); - if (manager) - manager.captureArguments(resource, arguments); - var wrapFunction = new WebGLRenderingContextResource.WrapFunction(originalObject, originalFunction, functionName, arguments); - customWrapFunction.apply(wrapFunction, arguments); - if (manager && manager.capturing()) { - var call = wrapFunction.call(); - call.setStackTrace(StackTrace.create(1, arguments.callee)); - manager.reportCall(call); - } - return wrapFunction.result(); - }; - }, - - /** - * @param {Resource} resource - * @param {WebGLRenderingContext} originalObject - * @param {Function} originalFunction - * @param {string} functionName - * @return {Function} - */ - _wrapFunction: function(resource, originalObject, originalFunction, functionName) - { - return function() - { - var manager = resource.manager(); - if (!manager || !manager.capturing()) - return originalFunction.apply(originalObject, arguments); - manager.captureArguments(resource, arguments); - var result = originalFunction.apply(originalObject, arguments); - var stackTrace = StackTrace.create(1, arguments.callee); - var call = new Call(resource, functionName, arguments, result, stackTrace); - manager.reportCall(call); - return result; - }; - } -} - -WebGLRenderingContextResource.prototype.__proto__ = Resource.prototype; - -/** - * @constructor - * @param {WebGLRenderingContext} originalObject - * @param {Function} originalFunction - * @param {string} functionName - * @param {Array|Arguments} args - */ -WebGLRenderingContextResource.WrapFunction = function(originalObject, originalFunction, functionName, args) -{ - this._originalObject = originalObject; - this._originalFunction = originalFunction; - this._functionName = functionName; - this._args = args; - this._glResource = Resource.forObject(originalObject); -} - -WebGLRenderingContextResource.WrapFunction.prototype = { - /** - * @return {*} - */ - result: function() - { - if (!this._executed) { - this._executed = true; - this._result = this._originalFunction.apply(this._originalObject, this._args); - } - return this._result; - }, - - /** - * @return {Call} - */ - call: function() - { - if (!this._call) - this._call = new Call(this._glResource, this._functionName, this._args, this.result()); - return this._call; - }, - - /** - * @param {*} result + * @override + * @return {Object.<string, Function>} */ - _overrideResult: function(result) + _customWrapFunctions: function() { - var call = this.call(); - call.setResult(result); - this._result = result; - } -} + var wrapFunctions = WebGLRenderingContextResource._wrapFunctions; + if (!wrapFunctions) { + wrapFunctions = Object.create(null); -/** - * @return {Object.<string, Function>} - */ -WebGLRenderingContextResource.wrapFunctions = function() -{ - var wrapFunctions = WebGLRenderingContextResource._wrapFunctions; - if (!wrapFunctions) { - wrapFunctions = Object.create(null); - - /** - * @param {string} methodName - * @param {Function} resourceConstructor - */ - function createResourceWrapFunction(methodName, resourceConstructor) - { - /** @this WebGLRenderingContextResource.WrapFunction */ - wrapFunctions[methodName] = function() + /** + * @param {string} methodName + * @param {Function} resourceConstructor + */ + function createResourceWrapFunction(methodName, resourceConstructor) { - var wrappedObject = this.result(); - if (!wrappedObject) - return; - var resource = new resourceConstructor(wrappedObject); - var manager = this._glResource.manager(); - if (manager) - manager.registerResource(resource); - resource.pushCall(this.call()); + /** @this Resource.WrapFunction */ + wrapFunctions[methodName] = function() + { + var wrappedObject = this.result(); + if (!wrappedObject) + return; + var resource = new resourceConstructor(wrappedObject); + var manager = this._resource.manager(); + if (manager) + manager.registerResource(resource); + this.overrideResult(resource.proxyObject()); + resource.pushCall(this.call()); + } } - } - createResourceWrapFunction("createBuffer", WebGLBufferResource); - createResourceWrapFunction("createShader", WebGLShaderResource); - createResourceWrapFunction("createProgram", WebGLProgramResource); - createResourceWrapFunction("createTexture", WebGLTextureResource); - createResourceWrapFunction("createFramebuffer", WebGLFramebufferResource); - createResourceWrapFunction("createRenderbuffer", WebGLRenderbufferResource); - createResourceWrapFunction("getUniformLocation", Resource); + createResourceWrapFunction("createBuffer", WebGLBufferResource); + createResourceWrapFunction("createShader", WebGLShaderResource); + createResourceWrapFunction("createProgram", WebGLProgramResource); + createResourceWrapFunction("createTexture", WebGLTextureResource); + createResourceWrapFunction("createFramebuffer", WebGLFramebufferResource); + createResourceWrapFunction("createRenderbuffer", WebGLRenderbufferResource); + createResourceWrapFunction("getUniformLocation", Resource); - /** - * @param {string} methodName - */ - function customWrapFunction(methodName) - { - var customPushCall = "pushCall_" + methodName; /** - * @param {Object|number} target - * @this WebGLRenderingContextResource.WrapFunction + * @param {string} methodName */ - wrapFunctions[methodName] = function(target) + function customWrapFunction(methodName) { - var resource = this._glResource.currentBinding(target); - if (!resource) - return; - if (resource[customPushCall]) - resource[customPushCall].call(resource, this.call()); - else - resource.pushCall(this.call()); + var customPushCall = "pushCall_" + methodName; + /** + * @param {Object|number} target + * @this Resource.WrapFunction + */ + wrapFunctions[methodName] = function(target) + { + var resource = this._resource.currentBinding(target); + if (!resource) + return; + if (resource[customPushCall]) + resource[customPushCall].call(resource, this.call()); + else + resource.pushCall(this.call()); + } } - } - customWrapFunction("attachShader"); - customWrapFunction("bindAttribLocation"); - customWrapFunction("compileShader"); - customWrapFunction("detachShader"); - customWrapFunction("linkProgram"); - customWrapFunction("shaderSource"); - customWrapFunction("bufferData"); - customWrapFunction("bufferSubData"); - customWrapFunction("compressedTexImage2D"); - customWrapFunction("compressedTexSubImage2D"); - customWrapFunction("copyTexImage2D"); - customWrapFunction("copyTexSubImage2D"); - customWrapFunction("generateMipmap"); - customWrapFunction("texImage2D"); - customWrapFunction("texSubImage2D"); - customWrapFunction("texParameterf"); - customWrapFunction("texParameteri"); - customWrapFunction("framebufferRenderbuffer"); - customWrapFunction("framebufferTexture2D"); - customWrapFunction("renderbufferStorage"); - - /** @this WebGLRenderingContextResource.WrapFunction */ - wrapFunctions["getError"] = function() - { - var gl = this._originalObject; - var error = this.result(); - if (error !== gl.NO_ERROR) - this._glResource.clearError(error); - else { - error = this._glResource.nextError(); + customWrapFunction("attachShader"); + customWrapFunction("bindAttribLocation"); + customWrapFunction("compileShader"); + customWrapFunction("detachShader"); + customWrapFunction("linkProgram"); + customWrapFunction("shaderSource"); + customWrapFunction("bufferData"); + customWrapFunction("bufferSubData"); + customWrapFunction("compressedTexImage2D"); + customWrapFunction("compressedTexSubImage2D"); + customWrapFunction("copyTexImage2D"); + customWrapFunction("copyTexSubImage2D"); + customWrapFunction("generateMipmap"); + customWrapFunction("texImage2D"); + customWrapFunction("texSubImage2D"); + customWrapFunction("texParameterf"); + customWrapFunction("texParameteri"); + customWrapFunction("framebufferRenderbuffer"); + customWrapFunction("framebufferTexture2D"); + customWrapFunction("renderbufferStorage"); + + /** @this Resource.WrapFunction */ + wrapFunctions["getError"] = function() + { + var gl = this._originalObject; + var error = this.result(); if (error !== gl.NO_ERROR) - this._overrideResult(error); + this._resource.clearError(error); + else { + error = this._resource.nextError(); + if (error !== gl.NO_ERROR) + this.overrideResult(error); + } } - } - WebGLRenderingContextResource._wrapFunctions = wrapFunctions; + WebGLRenderingContextResource._wrapFunctions = wrapFunctions; + } + return wrapFunctions; } - return wrapFunctions; } +WebGLRenderingContextResource.prototype.__proto__ = Resource.prototype; + /** * @constructor */ diff --git a/Source/WebCore/inspector/Inspector.json b/Source/WebCore/inspector/Inspector.json index 8184cc008..8b501c9ff 100644 --- a/Source/WebCore/inspector/Inspector.json +++ b/Source/WebCore/inspector/Inspector.json @@ -875,6 +875,14 @@ ] }, { + "name": "replayXHR", + "description": "This method sends a new XMLHttpRequest which is identical to the original one. The following parameters should be identical: method, url, async, request body, extra headers, withCredentials attribute, user, password.", + "parameters": [ + { "name": "requestId", "$ref": "RequestId", "description": "Identifier of XHR to replay." } + ], + "hidden": true + }, + { "name": "canClearBrowserCache", "description": "Tells whether clearing browser cache is supported.", "returns": [ @@ -2339,18 +2347,6 @@ ], "description": "Returns the Named Flows from the document.", "hidden": true - }, - { - "name": "getFlowByName", - "parameters": [ - { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id." }, - { "name": "name", "type": "string", "description": "Named Flow identifier." } - ], - "returns": [ - { "name": "namedFlow", "$ref": "NamedFlow", "description": "A Named Flow." } - ], - "description": "Returns the Named Flow identified by the given name", - "hidden": true } ], "events": [ @@ -2368,8 +2364,7 @@ { "name": "namedFlowCreated", "parameters": [ - { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id." }, - { "name": "namedFlow", "type": "string", "description": "Identifier of the new Named Flow." } + { "name": "namedFlow", "$ref": "NamedFlow", "description": "The new Named Flow." } ], "description": "Fires when a Named Flow is created.", "hidden": true @@ -2378,10 +2373,18 @@ "name": "namedFlowRemoved", "parameters": [ { "name": "documentNodeId", "$ref": "DOM.NodeId", "description": "The document node id." }, - { "name": "namedFlow", "type": "string", "description": "Identifier of the removed Named Flow." } + { "name": "flowName", "type": "string", "description": "Identifier of the removed Named Flow." } ], "description": "Fires when a Named Flow is removed: has no associated content nodes and regions.", "hidden": true + }, + { + "name": "regionLayoutUpdated", + "parameters": [ + { "name": "namedFlow", "$ref": "NamedFlow", "description": "The Named Flow whose layout may have changed." } + ], + "description": "Fires when a Named Flow's layout may have changed.", + "hidden": true } ] }, diff --git a/Source/WebCore/inspector/InspectorCSSAgent.cpp b/Source/WebCore/inspector/InspectorCSSAgent.cpp index 24c7197b6..60ebd9312 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.cpp +++ b/Source/WebCore/inspector/InspectorCSSAgent.cpp @@ -103,6 +103,7 @@ struct RuleMatchingStats { }; class SelectorProfile { + WTF_MAKE_FAST_ALLOCATED; public: SelectorProfile() : m_totalMatchingTimeMs(0.0) @@ -226,6 +227,67 @@ PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject return result.release(); } +class UpdateRegionLayoutTask { +public: + UpdateRegionLayoutTask(InspectorCSSAgent*); + void scheduleFor(WebKitNamedFlow*, int documentNodeId); + void unschedule(WebKitNamedFlow*); + void reset(); + void onTimer(Timer<UpdateRegionLayoutTask>*); + +private: + InspectorCSSAgent* m_cssAgent; + Timer<UpdateRegionLayoutTask> m_timer; + HashMap<WebKitNamedFlow*, int> m_namedFlows; +}; + +UpdateRegionLayoutTask::UpdateRegionLayoutTask(InspectorCSSAgent* cssAgent) + : m_cssAgent(cssAgent) + , m_timer(this, &UpdateRegionLayoutTask::onTimer) +{ +} + +void UpdateRegionLayoutTask::scheduleFor(WebKitNamedFlow* namedFlow, int documentNodeId) +{ + m_namedFlows.add(namedFlow, documentNodeId); + + if (!m_timer.isActive()) + m_timer.startOneShot(0); +} + +void UpdateRegionLayoutTask::unschedule(WebKitNamedFlow* namedFlow) +{ + m_namedFlows.remove(namedFlow); +} + +void UpdateRegionLayoutTask::reset() +{ + m_timer.stop(); + m_namedFlows.clear(); +} + +void UpdateRegionLayoutTask::onTimer(Timer<UpdateRegionLayoutTask>*) +{ + // The timer is stopped on m_cssAgent destruction, so this method will never be called after m_cssAgent has been destroyed. + Vector<std::pair<WebKitNamedFlow*, int> > namedFlows; + + for (HashMap<WebKitNamedFlow*, int>::iterator it = m_namedFlows.begin(), end = m_namedFlows.end(); it != end; ++it) + namedFlows.append(std::make_pair(it->first, it->second)); + + for (unsigned i = 0, size = namedFlows.size(); i < size; ++i) { + WebKitNamedFlow* namedFlow = namedFlows.at(i).first; + int documentNodeId = namedFlows.at(i).second; + + if (m_namedFlows.contains(namedFlow)) { + m_cssAgent->regionLayoutUpdated(namedFlow, documentNodeId); + m_namedFlows.remove(namedFlow); + } + } + + if (!m_namedFlows.isEmpty() && !m_timer.isActive()) + m_timer.startOneShot(0); +} + class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action { WTF_MAKE_NONCOPYABLE(StyleSheetAction); public: @@ -480,15 +542,13 @@ void InspectorCSSAgent::setFrontend(InspectorFrontend* frontend) { ASSERT(!m_frontend); m_frontend = frontend->css(); - m_instrumentingAgents->setInspectorCSSAgent(this); } void InspectorCSSAgent::clearFrontend() { ASSERT(m_frontend); m_frontend = 0; - m_instrumentingAgents->setInspectorCSSAgent(0); - resetPseudoStates(); + resetNonPersistentData(); String errorString; stopSelectorProfilerImpl(&errorString, false); } @@ -517,17 +577,26 @@ void InspectorCSSAgent::reset() m_cssStyleSheetToInspectorStyleSheet.clear(); m_nodeToInspectorStyleSheet.clear(); m_documentToInspectorStyleSheet.clear(); + resetNonPersistentData(); +} + +void InspectorCSSAgent::resetNonPersistentData() +{ m_namedFlowCollectionsRequested.clear(); + if (m_updateRegionLayoutTask) + m_updateRegionLayoutTask->reset(); resetPseudoStates(); } void InspectorCSSAgent::enable(ErrorString*) { m_state->setBoolean(CSSAgentState::cssAgentEnabled, true); + m_instrumentingAgents->setInspectorCSSAgent(this); } void InspectorCSSAgent::disable(ErrorString*) { + m_instrumentingAgents->setInspectorCSSAgent(0); m_state->setBoolean(CSSAgentState::cssAgentEnabled, false); } @@ -537,22 +606,48 @@ void InspectorCSSAgent::mediaQueryResultChanged() m_frontend->mediaQueryResultChanged(); } -void InspectorCSSAgent::didCreateNamedFlow(Document* document, const AtomicString& name) +void InspectorCSSAgent::didCreateNamedFlow(Document* document, WebKitNamedFlow* namedFlow) +{ + int documentNodeId = documentNodeWithRequestedFlowsId(document); + if (!documentNodeId) + return; + + ErrorString errorString; + m_frontend->namedFlowCreated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId)); +} + +void InspectorCSSAgent::willRemoveNamedFlow(Document* document, WebKitNamedFlow* namedFlow) { - int nodeId = m_domAgent->boundNodeId(document); - if (!nodeId || !m_namedFlowCollectionsRequested.contains(nodeId)) + int documentNodeId = documentNodeWithRequestedFlowsId(document); + if (!documentNodeId) return; - m_frontend->namedFlowCreated(nodeId, name.string()); + if (m_updateRegionLayoutTask) + m_updateRegionLayoutTask->unschedule(namedFlow); + + m_frontend->namedFlowRemoved(documentNodeId, namedFlow->name().string()); +} + +void InspectorCSSAgent::didUpdateRegionLayout(Document* document, WebKitNamedFlow* namedFlow) +{ + int documentNodeId = documentNodeWithRequestedFlowsId(document); + if (!documentNodeId) + return; + + if (!m_updateRegionLayoutTask) + m_updateRegionLayoutTask = adoptPtr(new UpdateRegionLayoutTask(this)); + m_updateRegionLayoutTask->scheduleFor(namedFlow, documentNodeId); } -void InspectorCSSAgent::didRemoveNamedFlow(Document* document, const AtomicString& name) +void InspectorCSSAgent::regionLayoutUpdated(WebKitNamedFlow* namedFlow, int documentNodeId) { - int nodeId = m_domAgent->boundNodeId(document); - if (!nodeId || !m_namedFlowCollectionsRequested.contains(nodeId)) + if (namedFlow->flowState() == WebKitNamedFlow::FlowStateNull) return; - m_frontend->namedFlowRemoved(nodeId, name.string()); + ErrorString errorString; + RefPtr<WebKitNamedFlow> protector(namedFlow); + + m_frontend->regionLayoutUpdated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId)); } bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType) @@ -828,32 +923,16 @@ void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int doc return; m_namedFlowCollectionsRequested.add(documentNodeId); + Vector<RefPtr<WebKitNamedFlow> > namedFlowsVector = document->namedFlows()->namedFlows(); RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> > namedFlows = TypeBuilder::Array<TypeBuilder::CSS::NamedFlow>::create(); - for (Vector<RefPtr<WebKitNamedFlow> >::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it) namedFlows->addItem(buildObjectForNamedFlow(errorString, it->get(), documentNodeId)); result = namedFlows.release(); } -void InspectorCSSAgent::getFlowByName(ErrorString* errorString, int documentNodeId, const String& flowName, RefPtr<TypeBuilder::CSS::NamedFlow>& result) -{ - Document* document = m_domAgent->assertDocument(errorString, documentNodeId); - if (!document) - return; - - WebKitNamedFlow* webkitNamedFlow = document->namedFlows()->flowByName(flowName); - if (!webkitNamedFlow) { - *errorString = "No target CSS Named Flow found"; - return; - } - - RefPtr<WebKitNamedFlow> protector(webkitNamedFlow); - result = buildObjectForNamedFlow(errorString, webkitNamedFlow, documentNodeId); -} - void InspectorCSSAgent::startSelectorProfiler(ErrorString*) { m_currentSelectorProfile = adoptPtr(new SelectorProfile()); @@ -933,6 +1012,15 @@ Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId) return toElement(node); } +int InspectorCSSAgent::documentNodeWithRequestedFlowsId(Document* document) +{ + int documentNodeId = m_domAgent->boundNodeId(document); + if (!documentNodeId || !m_namedFlowCollectionsRequested.contains(documentNodeId)) + return 0; + + return documentNodeId; +} + void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>* result) { InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet)); diff --git a/Source/WebCore/inspector/InspectorCSSAgent.h b/Source/WebCore/inspector/InspectorCSSAgent.h index 931ed3dfb..c9aa3a48e 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.h +++ b/Source/WebCore/inspector/InspectorCSSAgent.h @@ -55,6 +55,7 @@ class Node; class NodeList; class SelectorProfile; class StyleResolver; +class UpdateRegionLayoutTask; #if ENABLE(INSPECTOR) @@ -99,8 +100,10 @@ public: virtual void disable(ErrorString*); void reset(); void mediaQueryResultChanged(); - void didCreateNamedFlow(Document*, const AtomicString& name); - void didRemoveNamedFlow(Document*, const AtomicString& name); + void didCreateNamedFlow(Document*, WebKitNamedFlow*); + void willRemoveNamedFlow(Document*, WebKitNamedFlow*); + void didUpdateRegionLayout(Document*, WebKitNamedFlow*); + void regionLayoutUpdated(WebKitNamedFlow*, int documentNodeId); virtual void getComputedStyleForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >&); virtual void getInlineStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributes); @@ -116,7 +119,6 @@ public: virtual void getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& result); virtual void forcePseudoState(ErrorString*, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses); virtual void getNamedFlowCollection(ErrorString*, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result); - virtual void getFlowByName(ErrorString*, int documentNodeId, const String& flowName, RefPtr<TypeBuilder::CSS::NamedFlow>& result); virtual void startSelectorProfiler(ErrorString*); virtual void stopSelectorProfiler(ErrorString*, RefPtr<TypeBuilder::CSS::SelectorProfile>&); @@ -143,8 +145,10 @@ private: typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet> > DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets typedef HashMap<int, unsigned> NodeIdToForcedPseudoState; + void resetNonPersistentData(); InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element); Element* elementForId(ErrorString*, int nodeId); + int documentNodeWithRequestedFlowsId(Document*); void collectStyleSheets(CSSStyleSheet*, TypeBuilder::Array<WebCore::TypeBuilder::CSS::CSSStyleSheetHeader>*); InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*); @@ -176,6 +180,7 @@ private: DocumentToViaInspectorStyleSheet m_documentToInspectorStyleSheet; NodeIdToForcedPseudoState m_nodeIdToForcedPseudoState; HashSet<int> m_namedFlowCollectionsRequested; + OwnPtr<UpdateRegionLayoutTask> m_updateRegionLayoutTask; int m_lastStyleSheetId; diff --git a/Source/WebCore/inspector/InspectorConsoleAgent.cpp b/Source/WebCore/inspector/InspectorConsoleAgent.cpp index 2f3e2246d..aceb2da4a 100644 --- a/Source/WebCore/inspector/InspectorConsoleAgent.cpp +++ b/Source/WebCore/inspector/InspectorConsoleAgent.cpp @@ -219,7 +219,7 @@ void InspectorConsoleAgent::frameWindowDiscarded(DOMWindow* window) m_injectedScriptManager->discardInjectedScriptsFor(window); } -void InspectorConsoleAgent::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const String& url, const String& sendURL, unsigned sendLineNumber) +void InspectorConsoleAgent::didFinishXHRLoading(unsigned long identifier, const String& url, const String& sendURL, unsigned sendLineNumber) { if (!developerExtrasEnabled()) return; diff --git a/Source/WebCore/inspector/InspectorConsoleAgent.h b/Source/WebCore/inspector/InspectorConsoleAgent.h index 7bd689997..52be11818 100644 --- a/Source/WebCore/inspector/InspectorConsoleAgent.h +++ b/Source/WebCore/inspector/InspectorConsoleAgent.h @@ -77,7 +77,7 @@ public: void frameWindowDiscarded(DOMWindow*); - void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const String& url, const String& sendURL, unsigned sendLineNumber); + void didFinishXHRLoading(unsigned long identifier, const String& url, const String& sendURL, unsigned sendLineNumber); void didReceiveResponse(unsigned long identifier, const ResourceResponse&); void didFailLoading(unsigned long identifier, const ResourceError&); #if ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/Source/WebCore/inspector/InspectorCounters.h b/Source/WebCore/inspector/InspectorCounters.h index 3becf76c1..82e1b5cea 100644 --- a/Source/WebCore/inspector/InspectorCounters.h +++ b/Source/WebCore/inspector/InspectorCounters.h @@ -31,6 +31,8 @@ #ifndef InspectorCounters_h #define InspectorCounters_h +#include <wtf/FastAllocBase.h> + #if !ASSERT_DISABLED #include <wtf/MainThread.h> #endif @@ -77,6 +79,7 @@ private: #if ENABLE(INSPECTOR) class ThreadLocalInspectorCounters { + WTF_MAKE_FAST_ALLOCATED; public: enum CounterType { JSEventListenerCounter, diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp index ed47b5d0a..817f1df3b 100644 --- a/Source/WebCore/inspector/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp @@ -144,6 +144,7 @@ static Color parseConfigColor(const String& fieldName, InspectorObject* configOb } class RevalidateStyleAttributeTask { + WTF_MAKE_FAST_ALLOCATED; public: RevalidateStyleAttributeTask(InspectorDOMAgent*); void scheduleFor(Element*); diff --git a/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp b/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp index ebd9b219f..530827353 100644 --- a/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp +++ b/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp @@ -65,6 +65,7 @@ static const float minimumAttachedHeight = 250.0f; static const float maximumAttachedHeightRatio = 0.75f; class InspectorBackendDispatchTask { + WTF_MAKE_FAST_ALLOCATED; public: InspectorBackendDispatchTask(InspectorController* inspectorController) : m_inspectorController(inspectorController) diff --git a/Source/WebCore/inspector/InspectorHistory.h b/Source/WebCore/inspector/InspectorHistory.h index 037344b60..cb72a4a2a 100644 --- a/Source/WebCore/inspector/InspectorHistory.h +++ b/Source/WebCore/inspector/InspectorHistory.h @@ -46,9 +46,10 @@ class Node; #if ENABLE(INSPECTOR) class InspectorHistory { - WTF_MAKE_NONCOPYABLE(InspectorHistory); + WTF_MAKE_NONCOPYABLE(InspectorHistory); WTF_MAKE_FAST_ALLOCATED; public: class Action { + WTF_MAKE_FAST_ALLOCATED; public: Action(const String& name); virtual ~Action(); diff --git a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp index 5dfd99519..f12bd0dac 100644 --- a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp +++ b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp @@ -172,35 +172,35 @@ private: String m_securityOrigin; }; -class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> { -public: - virtual ~ExecutableWithDatabase() { }; - void start(IDBFactoryBackendInterface*, SecurityOrigin*, ScriptExecutionContext*, const String& databaseName); - virtual void execute(PassRefPtr<IDBDatabaseBackendInterface>) = 0; -}; - class DatabaseConnection { public: DatabaseConnection() : m_idbDatabaseCallbacks(InspectorIDBDatabaseCallbacks::create()) { } - void connect(PassRefPtr<IDBDatabaseBackendInterface> idbDatabase) - { - m_idbDatabase = idbDatabase; - m_idbDatabase->registerFrontendCallbacks(m_idbDatabaseCallbacks); - } - ~DatabaseConnection() { if (m_idbDatabase) m_idbDatabase->close(m_idbDatabaseCallbacks); } + void connect(PassRefPtr<IDBDatabaseBackendInterface> database) { m_idbDatabase = database; } + PassRefPtr<IDBDatabaseCallbacks> callbacks() { return m_idbDatabaseCallbacks; } + private: RefPtr<IDBDatabaseBackendInterface> m_idbDatabase; RefPtr<IDBDatabaseCallbacks> m_idbDatabaseCallbacks; }; +class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> { +public: + virtual ~ExecutableWithDatabase() { }; + void start(IDBFactoryBackendInterface*, SecurityOrigin*, ScriptExecutionContext*, const String& databaseName); + void connect(PassRefPtr<IDBDatabaseBackendInterface> database) { m_connection.connect(database); } + virtual void execute(PassRefPtr<IDBDatabaseBackendInterface>) = 0; +private: + DatabaseConnection m_connection; +}; + class OpenDatabaseCallback : public InspectorIDBCallback { public: static PassRefPtr<OpenDatabaseCallback> create(ExecutableWithDatabase* executableWithDatabase) @@ -213,6 +213,7 @@ public: virtual void onSuccess(PassRefPtr<IDBDatabaseBackendInterface> prpDatabase) { RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase; + m_executableWithDatabase->connect(idbDatabase); m_executableWithDatabase->execute(idbDatabase); } @@ -225,7 +226,7 @@ private: void ExecutableWithDatabase::start(IDBFactoryBackendInterface* idbFactory, SecurityOrigin* securityOrigin, ScriptExecutionContext* context, const String& databaseName) { RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this); - idbFactory->open(databaseName, IDBDatabaseMetadata::NoIntVersion, callback.get(), securityOrigin, context, String()); + idbFactory->open(databaseName, IDBDatabaseMetadata::NoIntVersion, callback, m_connection.callbacks(), securityOrigin, context, String()); } static PassRefPtr<IDBTransactionBackendInterface> transactionForDatabase(IDBDatabaseBackendInterface* idbDatabase, const String& objectStoreName) @@ -296,7 +297,6 @@ public: virtual void execute(PassRefPtr<IDBDatabaseBackendInterface> prpDatabase) { RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase; - m_connection.connect(idbDatabase); if (!m_requestCallback->isActive()) return; @@ -339,7 +339,6 @@ private: DatabaseLoaderCallback(PassRefPtr<RequestDatabaseCallback> requestCallback) : m_requestCallback(requestCallback) { } RefPtr<RequestDatabaseCallback> m_requestCallback; - DatabaseConnection m_connection; }; static PassRefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key) @@ -555,7 +554,6 @@ public: virtual void execute(PassRefPtr<IDBDatabaseBackendInterface> prpDatabase) { RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase; - m_connection.connect(idbDatabase); if (!m_requestCallback->isActive()) return; @@ -597,7 +595,6 @@ private: RefPtr<IDBKeyRange> m_idbKeyRange; int m_skipCount; unsigned m_pageSize; - DatabaseConnection m_connection; }; } // namespace diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp index f50bdd35e..4eda51da4 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp @@ -231,16 +231,22 @@ void InspectorInstrumentation::willPopShadowRootImpl(InstrumentingAgents* instru domAgent->willPopShadowRoot(host, root); } -void InspectorInstrumentation::didCreateNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, const AtomicString& name) +void InspectorInstrumentation::didCreateNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, WebKitNamedFlow* namedFlow) { if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent()) - cssAgent->didCreateNamedFlow(document, name); + cssAgent->didCreateNamedFlow(document, namedFlow); } -void InspectorInstrumentation::didRemoveNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, const AtomicString& name) +void InspectorInstrumentation::willRemoveNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, WebKitNamedFlow* namedFlow) { if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent()) - cssAgent->didRemoveNamedFlow(document, name); + cssAgent->willRemoveNamedFlow(document, namedFlow); +} + +void InspectorInstrumentation::didUpdateRegionLayoutImpl(InstrumentingAgents* instrumentingAgents, Document* document, WebKitNamedFlow* namedFlow) +{ + if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent()) + cssAgent->didUpdateRegionLayout(document, namedFlow); } void InspectorInstrumentation::mouseDidMoveOverElementImpl(InstrumentingAgents* instrumentingAgents, const HitTestResult& result, unsigned modifierFlags) @@ -319,21 +325,21 @@ void InspectorInstrumentation::didCallFunctionImpl(const InspectorInstrumentatio timelineAgent->didCallFunction(); } -InspectorInstrumentationCookie InspectorInstrumentation::willChangeXHRReadyStateImpl(InstrumentingAgents* instrumentingAgents, XMLHttpRequest* request, ScriptExecutionContext* context) +InspectorInstrumentationCookie InspectorInstrumentation::willDispatchXHRReadyStateChangeEventImpl(InstrumentingAgents* instrumentingAgents, XMLHttpRequest* request, ScriptExecutionContext* context) { int timelineAgentId = 0; InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent(); if (timelineAgent && request->hasEventListeners(eventNames().readystatechangeEvent)) { - timelineAgent->willChangeXHRReadyState(request->url().string(), request->readyState(), frameForScriptExecutionContext(context)); + timelineAgent->willDispatchXHRReadyStateChangeEvent(request->url().string(), request->readyState(), frameForScriptExecutionContext(context)); timelineAgentId = timelineAgent->id(); } return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId); } -void InspectorInstrumentation::didChangeXHRReadyStateImpl(const InspectorInstrumentationCookie& cookie) +void InspectorInstrumentation::didDispatchXHRReadyStateChangeEventImpl(const InspectorInstrumentationCookie& cookie) { if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie)) - timelineAgent->didChangeXHRReadyState(); + timelineAgent->didDispatchXHRReadyStateChangeEvent(); } InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventImpl(InstrumentingAgents* instrumentingAgents, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors, Document* document) @@ -463,21 +469,21 @@ void InspectorInstrumentation::didLayoutImpl(const InspectorInstrumentationCooki pageAgent->didLayout(); } -InspectorInstrumentationCookie InspectorInstrumentation::willLoadXHRImpl(InstrumentingAgents* instrumentingAgents, XMLHttpRequest* request, ScriptExecutionContext* context) +InspectorInstrumentationCookie InspectorInstrumentation::willDispatchXHRLoadEventImpl(InstrumentingAgents* instrumentingAgents, XMLHttpRequest* request, ScriptExecutionContext* context) { int timelineAgentId = 0; InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent(); if (timelineAgent && request->hasEventListeners(eventNames().loadEvent)) { - timelineAgent->willLoadXHR(request->url(), frameForScriptExecutionContext(context)); + timelineAgent->willDispatchXHRLoadEvent(request->url(), frameForScriptExecutionContext(context)); timelineAgentId = timelineAgent->id(); } return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId); } -void InspectorInstrumentation::didLoadXHRImpl(const InspectorInstrumentationCookie& cookie) +void InspectorInstrumentation::didDispatchXHRLoadEventImpl(const InspectorInstrumentationCookie& cookie) { if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie)) - timelineAgent->didLoadXHR(); + timelineAgent->didDispatchXHRLoadEvent(); } InspectorInstrumentationCookie InspectorInstrumentation::willPaintImpl(InstrumentingAgents* instrumentingAgents, GraphicsContext* context, const LayoutRect& rect, Frame* frame) @@ -757,12 +763,30 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents* instrumen consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this. } -void InspectorInstrumentation::resourceRetrievedByXMLHttpRequestImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber) +void InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClientImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, ThreadableLoaderClient* client) +{ + if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent()) + resourceAgent->documentThreadableLoaderStartedLoadingForClient(identifier, client); +} + +void InspectorInstrumentation::willLoadXHRImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials) +{ + if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent()) + resourceAgent->willLoadXHR(client, method, url, async, formData, headers, includeCredentials); +} + +void InspectorInstrumentation::didFailXHRLoadingImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client) +{ + if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent()) + resourceAgent->didFailXHRLoading(client); +} + +void InspectorInstrumentation::didFinishXHRLoadingImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber) { if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent()) - consoleAgent->resourceRetrievedByXMLHttpRequest(identifier, url, sendURL, sendLineNumber); + consoleAgent->didFinishXHRLoading(identifier, url, sendURL, sendLineNumber); if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent()) - resourceAgent->setInitialXHRContent(identifier, sourceString); + resourceAgent->didFinishXHRLoading(client, identifier, sourceString); } void InspectorInstrumentation::didReceiveXHRResponseImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier) diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h index 2a8cefc3c..6936137b7 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -77,6 +77,7 @@ class SecurityOrigin; class ShadowRoot; class StorageArea; class StyleRule; +class ThreadableLoaderClient; class WorkerContext; class WorkerContextProxy; class XMLHttpRequest; @@ -114,8 +115,9 @@ public: static void mediaQueryResultChanged(Document*); static void didPushShadowRoot(Element* host, ShadowRoot*); static void willPopShadowRoot(Element* host, ShadowRoot*); - static void didCreateNamedFlow(Document*, const AtomicString& name); - static void didRemoveNamedFlow(Document*, const AtomicString& name); + static void didCreateNamedFlow(Document*, WebKitNamedFlow*); + static void willRemoveNamedFlow(Document*, WebKitNamedFlow*); + static void didUpdateRegionLayout(Document*, WebKitNamedFlow*); static void mouseDidMoveOverElement(Page*, const HitTestResult&, unsigned modifierFlags); static bool handleMousePress(Page*); @@ -128,8 +130,8 @@ public: static InspectorInstrumentationCookie willCallFunction(ScriptExecutionContext*, const String& scriptName, int scriptLine); static void didCallFunction(const InspectorInstrumentationCookie&); - static InspectorInstrumentationCookie willChangeXHRReadyState(ScriptExecutionContext*, XMLHttpRequest* request); - static void didChangeXHRReadyState(const InspectorInstrumentationCookie&); + static InspectorInstrumentationCookie willDispatchXHRReadyStateChangeEvent(ScriptExecutionContext*, XMLHttpRequest*); + static void didDispatchXHRReadyStateChangeEvent(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willDispatchEvent(Document*, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors); static void didDispatchEvent(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willHandleEvent(ScriptExecutionContext*, Event*); @@ -147,8 +149,8 @@ public: static InspectorInstrumentationCookie willLayout(Frame*); static void didLayout(const InspectorInstrumentationCookie&, RenderObject*); static void didScroll(Page*); - static InspectorInstrumentationCookie willLoadXHR(ScriptExecutionContext*, XMLHttpRequest*); - static void didLoadXHR(const InspectorInstrumentationCookie&); + static InspectorInstrumentationCookie willDispatchXHRLoadEvent(ScriptExecutionContext*, XMLHttpRequest*); + static void didDispatchXHRLoadEvent(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willPaint(Frame*, GraphicsContext*, const LayoutRect&); static void didPaint(const InspectorInstrumentationCookie&); static void willComposite(Page*); @@ -182,7 +184,10 @@ public: static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, double finishTime); static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&); - static void resourceRetrievedByXMLHttpRequest(ScriptExecutionContext*, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber); + static void documentThreadableLoaderStartedLoadingForClient(ScriptExecutionContext*, unsigned long identifier, ThreadableLoaderClient*); + static void willLoadXHR(ScriptExecutionContext*, ThreadableLoaderClient*, const String&, const KURL&, bool, PassRefPtr<FormData>, const HTTPHeaderMap&, bool); + static void didFailXHRLoading(ScriptExecutionContext*, ThreadableLoaderClient*); + static void didFinishXHRLoading(ScriptExecutionContext*, ThreadableLoaderClient*, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber); static void didReceiveXHRResponse(ScriptExecutionContext*, unsigned long identifier); static void willLoadXHRSynchronously(ScriptExecutionContext*); static void didLoadXHRSynchronously(ScriptExecutionContext*); @@ -291,8 +296,9 @@ private: static void mediaQueryResultChangedImpl(InstrumentingAgents*); static void didPushShadowRootImpl(InstrumentingAgents*, Element* host, ShadowRoot*); static void willPopShadowRootImpl(InstrumentingAgents*, Element* host, ShadowRoot*); - static void didCreateNamedFlowImpl(InstrumentingAgents*, Document*, const AtomicString& name); - static void didRemoveNamedFlowImpl(InstrumentingAgents*, Document*, const AtomicString& name); + static void didCreateNamedFlowImpl(InstrumentingAgents*, Document*, WebKitNamedFlow*); + static void willRemoveNamedFlowImpl(InstrumentingAgents*, Document*, WebKitNamedFlow*); + static void didUpdateRegionLayoutImpl(InstrumentingAgents*, Document*, WebKitNamedFlow*); static void mouseDidMoveOverElementImpl(InstrumentingAgents*, const HitTestResult&, unsigned modifierFlags); static bool handleMousePressImpl(InstrumentingAgents*); @@ -305,8 +311,8 @@ private: static InspectorInstrumentationCookie willCallFunctionImpl(InstrumentingAgents*, const String& scriptName, int scriptLine, ScriptExecutionContext*); static void didCallFunctionImpl(const InspectorInstrumentationCookie&); - static InspectorInstrumentationCookie willChangeXHRReadyStateImpl(InstrumentingAgents*, XMLHttpRequest*, ScriptExecutionContext*); - static void didChangeXHRReadyStateImpl(const InspectorInstrumentationCookie&); + static InspectorInstrumentationCookie willDispatchXHRReadyStateChangeEventImpl(InstrumentingAgents*, XMLHttpRequest*, ScriptExecutionContext*); + static void didDispatchXHRReadyStateChangeEventImpl(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents*, const Event&, DOMWindow*, Node*, const Vector<EventContext>& ancestors, Document*); static InspectorInstrumentationCookie willHandleEventImpl(InstrumentingAgents*, Event*); static void didHandleEventImpl(const InspectorInstrumentationCookie&); @@ -324,8 +330,8 @@ private: static InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents*, Frame*); static void didLayoutImpl(const InspectorInstrumentationCookie&, RenderObject*); static void didScrollImpl(InstrumentingAgents*); - static InspectorInstrumentationCookie willLoadXHRImpl(InstrumentingAgents*, XMLHttpRequest*, ScriptExecutionContext*); - static void didLoadXHRImpl(const InspectorInstrumentationCookie&); + static InspectorInstrumentationCookie willDispatchXHRLoadEventImpl(InstrumentingAgents*, XMLHttpRequest*, ScriptExecutionContext*); + static void didDispatchXHRLoadEventImpl(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willPaintImpl(InstrumentingAgents*, GraphicsContext*, const LayoutRect&, Frame*); static void didPaintImpl(const InspectorInstrumentationCookie&); static void willCompositeImpl(InstrumentingAgents*); @@ -360,7 +366,10 @@ private: static void didReceiveDataImpl(InstrumentingAgents*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); static void didFinishLoadingImpl(InstrumentingAgents*, unsigned long identifier, DocumentLoader*, double finishTime); static void didFailLoadingImpl(InstrumentingAgents*, unsigned long identifier, DocumentLoader*, const ResourceError&); - static void resourceRetrievedByXMLHttpRequestImpl(InstrumentingAgents*, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber); + static void documentThreadableLoaderStartedLoadingForClientImpl(InstrumentingAgents*, unsigned long identifier, ThreadableLoaderClient*); + static void willLoadXHRImpl(InstrumentingAgents*, ThreadableLoaderClient*, const String&, const KURL&, bool, PassRefPtr<FormData>, const HTTPHeaderMap&, bool); + static void didFailXHRLoadingImpl(InstrumentingAgents*, ThreadableLoaderClient*); + static void didFinishXHRLoadingImpl(InstrumentingAgents*, ThreadableLoaderClient*, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber); static void didReceiveXHRResponseImpl(InstrumentingAgents*, unsigned long identifier); static void willLoadXHRSynchronouslyImpl(InstrumentingAgents*); static void didLoadXHRSynchronouslyImpl(InstrumentingAgents*); @@ -562,21 +571,30 @@ inline void InspectorInstrumentation::willPopShadowRoot(Element* host, ShadowRoo #endif } -inline void InspectorInstrumentation::didCreateNamedFlow(Document* document, const AtomicString& name) +inline void InspectorInstrumentation::didCreateNamedFlow(Document* document, WebKitNamedFlow* namedFlow) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(void()); if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) - didCreateNamedFlowImpl(instrumentingAgents, document, name); + didCreateNamedFlowImpl(instrumentingAgents, document, namedFlow); #endif } -inline void InspectorInstrumentation::didRemoveNamedFlow(Document* document, const AtomicString& name) +inline void InspectorInstrumentation::willRemoveNamedFlow(Document* document, WebKitNamedFlow* namedFlow) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(void()); if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) - didRemoveNamedFlowImpl(instrumentingAgents, document, name); + willRemoveNamedFlowImpl(instrumentingAgents, document, namedFlow); +#endif +} + +inline void InspectorInstrumentation::didUpdateRegionLayout(Document* document, WebKitNamedFlow* namedFlow) +{ +#if ENABLE(INSPECTOR) + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) + didUpdateRegionLayoutImpl(instrumentingAgents, document, namedFlow); #endif } @@ -674,22 +692,22 @@ inline void InspectorInstrumentation::didCallFunction(const InspectorInstrumenta #endif } -inline InspectorInstrumentationCookie InspectorInstrumentation::willChangeXHRReadyState(ScriptExecutionContext* context, XMLHttpRequest* request) +inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(ScriptExecutionContext* context, XMLHttpRequest* request) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie()); if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) - return willChangeXHRReadyStateImpl(instrumentingAgents, request, context); + return willDispatchXHRReadyStateChangeEventImpl(instrumentingAgents, request, context); #endif return InspectorInstrumentationCookie(); } -inline void InspectorInstrumentation::didChangeXHRReadyState(const InspectorInstrumentationCookie& cookie) +inline void InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(const InspectorInstrumentationCookie& cookie) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(void()); if (cookie.first) - didChangeXHRReadyStateImpl(cookie); + didDispatchXHRReadyStateChangeEventImpl(cookie); #endif } @@ -852,22 +870,22 @@ inline void InspectorInstrumentation::didScroll(Page* page) #endif } -inline InspectorInstrumentationCookie InspectorInstrumentation::willLoadXHR(ScriptExecutionContext* context, XMLHttpRequest* request) +inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchXHRLoadEvent(ScriptExecutionContext* context, XMLHttpRequest* request) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie()); if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) - return willLoadXHRImpl(instrumentingAgents, request, context); + return willDispatchXHRLoadEventImpl(instrumentingAgents, request, context); #endif return InspectorInstrumentationCookie(); } -inline void InspectorInstrumentation::didLoadXHR(const InspectorInstrumentationCookie& cookie) +inline void InspectorInstrumentation::didDispatchXHRLoadEvent(const InspectorInstrumentationCookie& cookie) { #if ENABLE(INSPECTOR) FAST_RETURN_IF_NO_FRONTENDS(void()); if (cookie.first) - didLoadXHRImpl(cookie); + didDispatchXHRLoadEventImpl(cookie); #endif } @@ -1157,11 +1175,36 @@ inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoade #endif } -inline void InspectorInstrumentation::resourceRetrievedByXMLHttpRequest(ScriptExecutionContext* context, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber) +inline void InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(ScriptExecutionContext* context, unsigned long identifier, ThreadableLoaderClient* client) +{ +#if ENABLE(INSPECTOR) + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) + documentThreadableLoaderStartedLoadingForClientImpl(instrumentingAgents, identifier, client); +#endif +} + +inline void InspectorInstrumentation::willLoadXHR(ScriptExecutionContext* context, ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials) +{ +#if ENABLE(INSPECTOR) + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) + willLoadXHRImpl(instrumentingAgents, client, method, url, async, formData, headers, includeCredentials); +#endif +} + +inline void InspectorInstrumentation::didFailXHRLoading(ScriptExecutionContext* context, ThreadableLoaderClient* client) +{ +#if ENABLE(INSPECTOR) + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) + didFailXHRLoadingImpl(instrumentingAgents, client); +#endif +} + + +inline void InspectorInstrumentation::didFinishXHRLoading(ScriptExecutionContext* context, ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber) { #if ENABLE(INSPECTOR) if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) - resourceRetrievedByXMLHttpRequestImpl(instrumentingAgents, identifier, sourceString, url, sendURL, sendLineNumber); + didFinishXHRLoadingImpl(instrumentingAgents, client, identifier, sourceString, url, sendURL, sendLineNumber); #endif } diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp index e8874cce5..2cef9ad56 100644 --- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp +++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp @@ -481,6 +481,7 @@ public: RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > domChildren = TypeBuilder::Array<InspectorMemoryBlock>::create(); totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::DOM); + totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Image); totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::CSS); totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Binding); totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Loader); diff --git a/Source/WebCore/inspector/InspectorOverlay.h b/Source/WebCore/inspector/InspectorOverlay.h index 3cd57591b..31a63051c 100644 --- a/Source/WebCore/inspector/InspectorOverlay.h +++ b/Source/WebCore/inspector/InspectorOverlay.h @@ -50,6 +50,8 @@ class Node; class Page; struct HighlightConfig { + WTF_MAKE_FAST_ALLOCATED; +public: Color content; Color contentOutline; Color padding; @@ -86,6 +88,7 @@ struct Highlight { }; class InspectorOverlay { + WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<InspectorOverlay> create(Page* page, InspectorClient* client) { diff --git a/Source/WebCore/inspector/InspectorPageAgent.cpp b/Source/WebCore/inspector/InspectorPageAgent.cpp index 707c7515e..fa23aaaf9 100644 --- a/Source/WebCore/inspector/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/InspectorPageAgent.cpp @@ -1018,6 +1018,9 @@ void InspectorPageAgent::setGeolocationOverride(ErrorString* error, const double controller->positionChanged(0); // Kick location update. #else *error = "Geolocation is not available."; + UNUSED_PARAM(latitude); + UNUSED_PARAM(longitude); + UNUSED_PARAM(accuracy); #endif } diff --git a/Source/WebCore/inspector/InspectorResourceAgent.cpp b/Source/WebCore/inspector/InspectorResourceAgent.cpp index 9d929c9a1..d8a23ed12 100644 --- a/Source/WebCore/inspector/InspectorResourceAgent.cpp +++ b/Source/WebCore/inspector/InspectorResourceAgent.cpp @@ -34,6 +34,7 @@ #include "InspectorResourceAgent.h" +#include "CachedRawResource.h" #include "CachedResource.h" #include "CachedResourceLoader.h" #include "Document.h" @@ -64,6 +65,7 @@ #include "WebSocketFrame.h" #include "WebSocketHandshakeRequest.h" #include "WebSocketHandshakeResponse.h" +#include "XMLHttpRequest.h" #include <wtf/CurrentTime.h> #include <wtf/HexNumber.h> @@ -333,6 +335,12 @@ void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* load String requestId = IdentifiersFactory::requestId(identifier); m_resourcesData->resourceCreated(requestId, loaderId); m_resourcesData->addCachedResource(requestId, resource); + if (resource->type() == CachedResource::RawResource) { + CachedRawResource* rawResource = static_cast<CachedRawResource*>(resource); + String rawRequestId = IdentifiersFactory::requestId(rawResource->identifier()); + m_resourcesData->reuseXHRReplayData(requestId, rawRequestId); + } + RefPtr<TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0); m_frontend->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(*resource, loader)); @@ -348,12 +356,41 @@ void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier) m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource); } -void InspectorResourceAgent::setInitialXHRContent(unsigned long identifier, const String& sourceString) +void InspectorResourceAgent::documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient* client) +{ + if (!client) + return; + + PendingXHRReplayDataMap::iterator it = m_pendingXHRReplayData.find(client); + if (it == m_pendingXHRReplayData.end()) + return; + + XHRReplayData* xhrReplayData = it->second.get(); + String requestId = IdentifiersFactory::requestId(identifier); + m_resourcesData->setXHRReplayData(requestId, xhrReplayData); +} + +void InspectorResourceAgent::willLoadXHR(ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials) +{ + RefPtr<XHRReplayData> xhrReplayData = XHRReplayData::create(method, url, async, formData, includeCredentials); + HTTPHeaderMap::const_iterator end = headers.end(); + for (HTTPHeaderMap::const_iterator it = headers.begin(); it!= end; ++it) + xhrReplayData->addHeader(it->first, it->second); + m_pendingXHRReplayData.set(client, xhrReplayData); +} + +void InspectorResourceAgent::didFailXHRLoading(ThreadableLoaderClient* client) +{ + m_pendingXHRReplayData.remove(client); +} + +void InspectorResourceAgent::didFinishXHRLoading(ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString) { // For Asynchronous XHRs, the inspector can grab the data directly off of the CachedResource. For sync XHRs, we need to // provide the data here, since no CachedResource was involved. if (m_loadingXHRSynchronously) m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString); + m_pendingXHRReplayData.remove(client); } void InspectorResourceAgent::didReceiveXHRResponse(unsigned long identifier) @@ -570,6 +607,23 @@ void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const Str *errorString = "No data found for resource with given identifier"; } +void InspectorResourceAgent::replayXHR(ErrorString*, const String& requestId) +{ + RefPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(m_pageAgent->mainFrame()->document()); + ExceptionCode code; + String actualRequestId = requestId; + + XHRReplayData* xhrReplayData = m_resourcesData->xhrReplayData(requestId); + if (!xhrReplayData) + return; + + xhr->open(xhrReplayData->method(), xhrReplayData->url(), xhrReplayData->async(), code); + HTTPHeaderMap::const_iterator end = xhrReplayData->headers().end(); + for (HTTPHeaderMap::const_iterator it = xhrReplayData->headers().begin(); it!= end; ++it) + xhr->setRequestHeader(it->first, it->second, code); + xhr->sendFromInspector(xhrReplayData->formData(), code); +} + void InspectorResourceAgent::canClearBrowserCache(ErrorString*, bool* result) { *result = m_client->canClearBrowserCache(); diff --git a/Source/WebCore/inspector/InspectorResourceAgent.h b/Source/WebCore/inspector/InspectorResourceAgent.h index f8fc8bd30..5949e5ab8 100644 --- a/Source/WebCore/inspector/InspectorResourceAgent.h +++ b/Source/WebCore/inspector/InspectorResourceAgent.h @@ -50,7 +50,9 @@ namespace WebCore { class CachedResource; class Document; class DocumentLoader; +class FormData; class Frame; +class HTTPHeaderMap; class InspectorArray; class InspectorClient; class InspectorFrontend; @@ -66,6 +68,9 @@ class ResourceLoader; class ResourceRequest; class ResourceResponse; class SharedBuffer; +class ThreadableLoaderClient; +class XHRReplayData; +class XMLHttpRequest; #if ENABLE(WEB_SOCKETS) struct WebSocketFrame; @@ -100,10 +105,15 @@ public: void mainFrameNavigated(DocumentLoader*); void setInitialScriptContent(unsigned long identifier, const String& sourceString); void didReceiveScriptResponse(unsigned long identifier); - void setInitialXHRContent(unsigned long identifier, const String& sourceString); + + void documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient*); + void willLoadXHR(ThreadableLoaderClient*, const String& method, const KURL&, bool async, PassRefPtr<FormData> body, const HTTPHeaderMap& headers, bool includeCrendentials); + void didFailXHRLoading(ThreadableLoaderClient*); + void didFinishXHRLoading(ThreadableLoaderClient*, unsigned long identifier, const String& sourceString); void didReceiveXHRResponse(unsigned long identifier); void willLoadXHRSynchronously(); void didLoadXHRSynchronously(); + void willDestroyCachedResource(CachedResource*); void applyUserAgentOverride(String* userAgent); @@ -135,6 +145,8 @@ public: virtual void setExtraHTTPHeaders(ErrorString*, const RefPtr<InspectorObject>&); virtual void getResponseBody(ErrorString*, const String& requestId, String* content, bool* base64Encoded); + virtual void replayXHR(ErrorString*, const String& requestId); + virtual void canClearBrowserCache(ErrorString*, bool*); virtual void clearBrowserCache(ErrorString*); virtual void canClearBrowserCookies(ErrorString*, bool*); @@ -153,6 +165,8 @@ private: OwnPtr<NetworkResourcesData> m_resourcesData; bool m_loadingXHRSynchronously; + typedef HashMap<ThreadableLoaderClient*, RefPtr<XHRReplayData> > PendingXHRReplayDataMap; + PendingXHRReplayDataMap m_pendingXHRReplayData; // FIXME: InspectorResourceAgent should now be aware of style recalculation. RefPtr<TypeBuilder::Network::Initiator> m_styleRecalculationInitiator; bool m_isRecalculatingStyle; diff --git a/Source/WebCore/inspector/InspectorState.h b/Source/WebCore/inspector/InspectorState.h index 1ec373e77..360b25977 100644 --- a/Source/WebCore/inspector/InspectorState.h +++ b/Source/WebCore/inspector/InspectorState.h @@ -43,6 +43,7 @@ namespace WebCore { class InspectorStateClient; class InspectorState { + WTF_MAKE_FAST_ALLOCATED; public: InspectorState(InspectorStateClient*); virtual ~InspectorState() {} diff --git a/Source/WebCore/inspector/InspectorStyleSheet.cpp b/Source/WebCore/inspector/InspectorStyleSheet.cpp index 3cf4d489c..2de8d9cba 100644 --- a/Source/WebCore/inspector/InspectorStyleSheet.cpp +++ b/Source/WebCore/inspector/InspectorStyleSheet.cpp @@ -65,6 +65,7 @@ using WebCore::RuleSourceDataList; using WebCore::CSSRuleSourceData; class ParsedStyleSheet { + WTF_MAKE_FAST_ALLOCATED; public: ParsedStyleSheet(); diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.cpp b/Source/WebCore/inspector/InspectorTimelineAgent.cpp index 38410ca6d..a994cdd11 100644 --- a/Source/WebCore/inspector/InspectorTimelineAgent.cpp +++ b/Source/WebCore/inspector/InspectorTimelineAgent.cpp @@ -344,22 +344,22 @@ void InspectorTimelineAgent::didFireTimer() didCompleteCurrentRecord(TimelineRecordType::TimerFire); } -void InspectorTimelineAgent::willChangeXHRReadyState(const String& url, int readyState, Frame* frame) +void InspectorTimelineAgent::willDispatchXHRReadyStateChangeEvent(const String& url, int readyState, Frame* frame) { pushCurrentRecord(TimelineRecordFactory::createXHRReadyStateChangeData(url, readyState), TimelineRecordType::XHRReadyStateChange, false, frame); } -void InspectorTimelineAgent::didChangeXHRReadyState() +void InspectorTimelineAgent::didDispatchXHRReadyStateChangeEvent() { didCompleteCurrentRecord(TimelineRecordType::XHRReadyStateChange); } -void InspectorTimelineAgent::willLoadXHR(const String& url, Frame* frame) +void InspectorTimelineAgent::willDispatchXHRLoadEvent(const String& url, Frame* frame) { pushCurrentRecord(TimelineRecordFactory::createXHRLoadData(url), TimelineRecordType::XHRLoad, true, frame); } -void InspectorTimelineAgent::didLoadXHR() +void InspectorTimelineAgent::didDispatchXHRLoadEvent() { didCompleteCurrentRecord(TimelineRecordType::XHRLoad); } diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.h b/Source/WebCore/inspector/InspectorTimelineAgent.h index e5b0dc9c2..8f048cfcb 100644 --- a/Source/WebCore/inspector/InspectorTimelineAgent.h +++ b/Source/WebCore/inspector/InspectorTimelineAgent.h @@ -121,10 +121,10 @@ public: void willFireTimer(int timerId, Frame*); void didFireTimer(); - void willChangeXHRReadyState(const String&, int, Frame*); - void didChangeXHRReadyState(); - void willLoadXHR(const String&, Frame*); - void didLoadXHR(); + void willDispatchXHRReadyStateChangeEvent(const String&, int, Frame*); + void didDispatchXHRReadyStateChangeEvent(); + void willDispatchXHRLoadEvent(const String&, Frame*); + void didDispatchXHRLoadEvent(); void willEvaluateScript(const String&, int, Frame*); void didEvaluateScript(); diff --git a/Source/WebCore/inspector/InspectorWorkerAgent.cpp b/Source/WebCore/inspector/InspectorWorkerAgent.cpp index 24beeb57d..1b7cedbc3 100644 --- a/Source/WebCore/inspector/InspectorWorkerAgent.cpp +++ b/Source/WebCore/inspector/InspectorWorkerAgent.cpp @@ -52,6 +52,7 @@ static const char autoconnectToWorkers[] = "autoconnectToWorkers"; }; class InspectorWorkerAgent::WorkerFrontendChannel : public WorkerContextProxy::PageInspector { + WTF_MAKE_FAST_ALLOCATED; public: explicit WorkerFrontendChannel(InspectorFrontend* frontend, WorkerContextProxy* proxy) : m_frontend(frontend) diff --git a/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp b/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp index 47a91d5b3..946888ce2 100644 --- a/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp +++ b/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp @@ -52,7 +52,7 @@ void MemoryInstrumentationImpl::processDeferredInstrumentedPointers() void MemoryInstrumentationImpl::countObjectSize(MemoryObjectType objectType, size_t size) { - ASSERT(objectType != GenericMemoryTypes::Undefined); + ASSERT(objectType); TypeToSizeMap::AddResult result = m_totalSizes.add(objectType, size); if (!result.isNewEntry) result.iterator->second += size; diff --git a/Source/WebCore/inspector/MemoryInstrumentationImpl.h b/Source/WebCore/inspector/MemoryInstrumentationImpl.h index 9ef0fec14..8a2aee5e0 100644 --- a/Source/WebCore/inspector/MemoryInstrumentationImpl.h +++ b/Source/WebCore/inspector/MemoryInstrumentationImpl.h @@ -32,16 +32,19 @@ #define MemoryInstrumentationImpl_h +#include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/MemoryInstrumentation.h> #include <wtf/Vector.h> +using WTF::MemoryObjectType; + namespace WebCore { typedef HashSet<const void*> VisitedObjects; -class MemoryInstrumentationImpl : public MemoryInstrumentation { +class MemoryInstrumentationImpl : public WTF::MemoryInstrumentation { public: explicit MemoryInstrumentationImpl(VisitedObjects&); diff --git a/Source/WebCore/inspector/NetworkResourcesData.cpp b/Source/WebCore/inspector/NetworkResourcesData.cpp index 4416adf76..4198fb51d 100644 --- a/Source/WebCore/inspector/NetworkResourcesData.cpp +++ b/Source/WebCore/inspector/NetworkResourcesData.cpp @@ -47,6 +47,25 @@ static size_t maximumSingleResourceContentSize = 10 * 1000 * 1000; namespace WebCore { +PassRefPtr<XHRReplayData> XHRReplayData::create(const String &method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials) +{ + return adoptRef(new XHRReplayData(method, url, async, formData, includeCredentials)); +} + +void XHRReplayData::addHeader(const AtomicString& key, const String& value) +{ + m_headers.set(key, value); +} + +XHRReplayData::XHRReplayData(const String &method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials) + : m_method(method) + , m_url(url) + , m_async(async) + , m_formData(formData) + , m_includeCredentials(includeCredentials) +{ +} + // ResourceData NetworkResourcesData::ResourceData::ResourceData(const String& requestId, const String& loaderId) : m_requestId(requestId) @@ -253,6 +272,46 @@ NetworkResourcesData::ResourceData const* NetworkResourcesData::data(const Strin return m_requestIdToResourceDataMap.get(requestId); } +XHRReplayData* NetworkResourcesData::xhrReplayData(const String& requestId) +{ + if (m_reusedXHRReplayDataRequestIds.contains(requestId)) + return xhrReplayData(m_reusedXHRReplayDataRequestIds.get(requestId)); + + ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId); + if (!resourceData) + return 0; + return resourceData->xhrReplayData(); +} + +void NetworkResourcesData::setXHRReplayData(const String& requestId, XHRReplayData* xhrReplayData) +{ + ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId); + if (!resourceData) { + Vector<String> result; + ReusedRequestIds::iterator it; + ReusedRequestIds::iterator end = m_reusedXHRReplayDataRequestIds.end(); + for (it = m_reusedXHRReplayDataRequestIds.begin(); it != end; ++it) { + if (it->second == requestId) + setXHRReplayData(it->first, xhrReplayData); + } + return; + } + + resourceData->setXHRReplayData(xhrReplayData); +} + +void NetworkResourcesData::reuseXHRReplayData(const String& requestId, const String& reusedRequestId) +{ + ResourceData* reusedResourceData = m_requestIdToResourceDataMap.get(reusedRequestId); + ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId); + if (!reusedResourceData || !resourceData) { + m_reusedXHRReplayDataRequestIds.set(requestId, reusedRequestId); + return; + } + + resourceData->setXHRReplayData(reusedResourceData->xhrReplayData()); +} + Vector<String> NetworkResourcesData::removeCachedResource(CachedResource* cachedResource) { Vector<String> result; @@ -286,6 +345,8 @@ void NetworkResourcesData::clear(const String& preservedLoaderId) delete resourceData; } m_requestIdToResourceDataMap.swap(preservedMap); + + m_reusedXHRReplayDataRequestIds.clear(); } void NetworkResourcesData::setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize) diff --git a/Source/WebCore/inspector/NetworkResourcesData.h b/Source/WebCore/inspector/NetworkResourcesData.h index 8dfd5dd0d..22093ebd3 100644 --- a/Source/WebCore/inspector/NetworkResourcesData.h +++ b/Source/WebCore/inspector/NetworkResourcesData.h @@ -46,9 +46,33 @@ class CachedResource; class SharedBuffer; class TextResourceDecoder; +class XHRReplayData : public RefCounted<XHRReplayData> { +public: + static PassRefPtr<XHRReplayData> create(const String &method, const KURL&, bool async, PassRefPtr<FormData>, bool includeCredentials); + + void addHeader(const AtomicString& key, const String& value); + const String& method() const { return m_method; } + const KURL& url() const { return m_url; } + bool async() const { return m_async; } + PassRefPtr<FormData> formData() const { return m_formData; } + const HTTPHeaderMap& headers() const { return m_headers; } + bool includeCredentials() const { return m_includeCredentials; } +private: + XHRReplayData(const String &method, const KURL&, bool async, PassRefPtr<FormData>, bool includeCredentials); + + String m_method; + KURL m_url; + bool m_async; + RefPtr<FormData> m_formData; + HTTPHeaderMap m_headers; + bool m_includeCredentials; +}; + class NetworkResourcesData { + WTF_MAKE_FAST_ALLOCATED; public: class ResourceData { + WTF_MAKE_FAST_ALLOCATED; friend class NetworkResourcesData; public: ResourceData(const String& requestId, const String& loaderId); @@ -90,6 +114,8 @@ public: CachedResource* cachedResource() const { return m_cachedResource; } void setCachedResource(CachedResource* cachedResource) { m_cachedResource = cachedResource; } + XHRReplayData* xhrReplayData() const { return m_xhrReplayData.get(); } + void setXHRReplayData(XHRReplayData* xhrReplayData) { m_xhrReplayData = xhrReplayData; } private: bool hasData() const { return m_dataBuffer; } size_t dataLength() const; @@ -101,6 +127,7 @@ public: String m_frameId; String m_url; String m_content; + RefPtr<XHRReplayData> m_xhrReplayData; bool m_base64Encoded; RefPtr<SharedBuffer> m_dataBuffer; bool m_isContentPurged; @@ -132,6 +159,9 @@ public: void clear(const String& preservedLoaderId = String()); void setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize); + void setXHRReplayData(const String& requestId, XHRReplayData*); + void reuseXHRReplayData(const String& requestId, const String& reusedRequestId); + XHRReplayData* xhrReplayData(const String& requestId); private: void ensureNoDataForRequestId(const String& requestId); @@ -139,6 +169,8 @@ private: Deque<String> m_requestIdsDeque; + typedef HashMap<String, String> ReusedRequestIds; + ReusedRequestIds m_reusedXHRReplayDataRequestIds; typedef HashMap<String, ResourceData*> ResourceDataMap; ResourceDataMap m_requestIdToResourceDataMap; size_t m_contentSize; diff --git a/Source/WebCore/inspector/WorkerInspectorController.cpp b/Source/WebCore/inspector/WorkerInspectorController.cpp index 7d7aa9b89..d383c8cdd 100644 --- a/Source/WebCore/inspector/WorkerInspectorController.cpp +++ b/Source/WebCore/inspector/WorkerInspectorController.cpp @@ -59,6 +59,7 @@ namespace WebCore { namespace { class PageInspectorProxy : public InspectorFrontendChannel { + WTF_MAKE_FAST_ALLOCATED; public: explicit PageInspectorProxy(WorkerContext* workerContext) : m_workerContext(workerContext) { } virtual ~PageInspectorProxy() { } @@ -72,6 +73,7 @@ private: }; class WorkerStateClient : public InspectorStateClient { + WTF_MAKE_FAST_ALLOCATED; public: WorkerStateClient(WorkerContext* context) : m_workerContext(context) { } virtual ~WorkerStateClient() { } diff --git a/Source/WebCore/inspector/compile-front-end.py b/Source/WebCore/inspector/compile-front-end.py index 6baca120c..ef235bff7 100755 --- a/Source/WebCore/inspector/compile-front-end.py +++ b/Source/WebCore/inspector/compile-front-end.py @@ -179,6 +179,7 @@ modules = [ "name": "elements", "dependencies": ["components"], "sources": [ + "CSSNamedFlowCollectionsView.js", "ElementsPanel.js", "ElementsPanelDescriptor.js", "EventListenersSidebarPane.js", diff --git a/Source/WebCore/inspector/front-end/AuditLauncherView.js b/Source/WebCore/inspector/front-end/AuditLauncherView.js index 4f3dd487f..97d088653 100644 --- a/Source/WebCore/inspector/front-end/AuditLauncherView.js +++ b/Source/WebCore/inspector/front-end/AuditLauncherView.js @@ -30,14 +30,14 @@ /** * @constructor + * @param {function(Array.<string>, WebInspector.Progress, boolean, function(), function()):undefined} runnerCallback * @extends {WebInspector.View} */ -WebInspector.AuditLauncherView = function(runnerCallback, stopCallback) +WebInspector.AuditLauncherView = function(runnerCallback) { WebInspector.View.call(this); this._runnerCallback = runnerCallback; - this._stopCallback = stopCallback; this._categoryIdPrefix = "audit-category-item-"; this._auditRunning = false; @@ -118,27 +118,44 @@ WebInspector.AuditLauncherView.prototype = { if (this._auditRunning === auditRunning) return; this._auditRunning = auditRunning; - delete this._stopRequested; this._updateButton(); - this._updateResourceProgress(); + if (this._auditRunning) + this._startAudit(); + else + this._stopAudit(); }, - _launchButtonClicked: function(event) + _startAudit: function() { - if (!this._auditRunning) { - var catIds = []; - for (var category = 0; category < this._sortedCategories.length; ++category) { - if (this._sortedCategories[category]._checkboxElement.checked) - catIds.push(this._sortedCategories[category].id); - } - - this._setAuditRunning(true); - this._runnerCallback(catIds, this._resourceProgressElement, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false)); - } else { - this._stopRequested = true; - this._stopCallback(this._setAuditRunning.bind(this, false)); - this._updateButton(); + var catIds = []; + for (var category = 0; category < this._sortedCategories.length; ++category) { + if (this._sortedCategories[category]._checkboxElement.checked) + catIds.push(this._sortedCategories[category].id); + } + + this._resetResourceCount(); + this._progressIndicator = new WebInspector.ProgressIndicator(); + this._buttonContainerElement.appendChild(this._progressIndicator.element); + this._displayResourceLoadingProgress = true; + + function onAuditStarted() + { + this._displayResourceLoadingProgress = false; } + this._runnerCallback(catIds, this._progressIndicator, this._auditPresentStateElement.checked, onAuditStarted.bind(this), this._setAuditRunning.bind(this, false)); + }, + + _stopAudit: function() + { + this._displayResourceLoadingProgress = false; + this._progressIndicator.cancel(); + this._progressIndicator.done(); + delete this._progressIndicator; + }, + + _launchButtonClicked: function(event) + { + this._setAuditRunning(!this._auditRunning); }, _selectAllClicked: function(checkCategories) @@ -218,37 +235,20 @@ WebInspector.AuditLauncherView.prototype = { this._launchButton.textContent = WebInspector.UIString("Run"); this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false); - this._resourceProgressContainer = this._buttonContainerElement.createChild("span", "resource-progress"); - this._resourceProgressElement = this._resourceProgressContainer.createChild("progress"); - this._resourceProgressContainer.appendChild(document.createTextNode(" ")); - this._resourceProgressTextElement = this._resourceProgressContainer.createChild("span"); - - this._selectAllClicked(this._selectAllCheckboxElement.checked); this._updateButton(); - this._updateResourceProgress(); }, _updateResourceProgress: function() { - if (!this._resourceProgressContainer) - return; - - if (!this._auditRunning || this._stopRequested) { - this._resetResourceCount(); - this._resourceProgressContainer.addStyleClass("hidden"); - } else - this._resourceProgressContainer.removeStyleClass("hidden"); - if (this._loadedResources) - this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources); - else - this._resourceProgressTextElement.textContent = ""; + if (this._displayResourceLoadingProgress) + this._progressIndicator.setTitle(WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources)); }, _updateButton: function() { this._launchButton.textContent = this._auditRunning ? WebInspector.UIString("Stop") : WebInspector.UIString("Run"); - this._launchButton.disabled = !this._currentCategoriesCount || (this._auditRunning && this._stopRequested); + this._launchButton.disabled = !this._currentCategoriesCount; } } diff --git a/Source/WebCore/inspector/front-end/AuditRules.js b/Source/WebCore/inspector/front-end/AuditRules.js index 04efbdb11..e91f27064 100644 --- a/Source/WebCore/inspector/front-end/AuditRules.js +++ b/Source/WebCore/inspector/front-end/AuditRules.js @@ -75,8 +75,11 @@ WebInspector.AuditRules.GzipRule = function() WebInspector.AuditRules.GzipRule.prototype = { /** * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress */ - doRun: function(requests, result, callback, progressMonitor) + doRun: function(requests, result, callback, progress) { var totalSavings = 0; var compressedSize = 0; @@ -135,7 +138,13 @@ WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type, } WebInspector.AuditRules.CombineExternalResourcesRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests, [this._type], false); var penalizedResourceCount = 0; @@ -190,7 +199,13 @@ WebInspector.AuditRules.MinimizeDnsLookupsRule = function(hostCountThreshold) { } WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var summary = result.addChild(""); var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests, undefined, false); @@ -228,7 +243,13 @@ WebInspector.AuditRules.ParallelizeDownloadRule = function(optimalHostnameCount, } WebInspector.AuditRules.ParallelizeDownloadRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { function hostSorter(a, b) { @@ -297,12 +318,18 @@ WebInspector.AuditRules.UnusedCssRule = function() } WebInspector.AuditRules.UnusedCssRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var self = this; function evalCallback(styleSheets) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!styleSheets.length) @@ -324,7 +351,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { function selectorsCallback(callback, styleSheets, testedSelectors, foundSelectors) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; var inlineBlockOrdinal = 0; @@ -389,7 +416,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { function documentLoaded(selectors, document) { for (var i = 0; i < selectors.length; ++i) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; WebInspector.domAgent.querySelector(document.id, selectors[i], queryCallback.bind(null, i === selectors.length - 1 ? selectorsCallback.bind(null, callback, styleSheets, testedSelectors) : null, selectors[i], styleSheets, testedSelectors)); } @@ -400,7 +427,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { function styleSheetCallback(styleSheets, sourceURL, continuation, styleSheet) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (styleSheet) { @@ -413,7 +440,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { function allStylesCallback(error, styleSheetInfos) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (error || !styleSheetInfos || !styleSheetInfos.length) @@ -443,8 +470,13 @@ WebInspector.AuditRules.CacheControlRule = function(id, name) WebInspector.AuditRules.CacheControlRule.MillisPerMonth = 1000 * 60 * 60 * 24 * 30; WebInspector.AuditRules.CacheControlRule.prototype = { - - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(requests); if (cacheableAndNonCacheableResources[0].length) @@ -691,7 +723,13 @@ WebInspector.AuditRules.ImageDimensionsRule = function() } WebInspector.AuditRules.ImageDimensionsRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var urlToNoDimensionCount = {}; @@ -710,7 +748,7 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { function imageStylesReady(imageId, styles, isLastStyle, computedStyle) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; const node = WebInspector.domAgent.nodeForId(imageId); @@ -766,7 +804,7 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { function getStyles(nodeIds) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; var targetResult = {}; @@ -794,12 +832,12 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { function onDocumentAvailable(root) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; WebInspector.domAgent.querySelectorAll(root.id, "img[src]", getStyles); } - if (progressMonitor.canceled) + if (progress.isCanceled()) return; WebInspector.domAgent.requestDocument(onDocumentAvailable); } @@ -817,11 +855,17 @@ WebInspector.AuditRules.CssInHeadRule = function() } WebInspector.AuditRules.CssInHeadRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { function evalCallback(evalResult) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!evalResult) @@ -846,7 +890,7 @@ WebInspector.AuditRules.CssInHeadRule.prototype = { function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!nodeIds) @@ -869,7 +913,7 @@ WebInspector.AuditRules.CssInHeadRule.prototype = { function inlineStylesReceived(root, nodeIds) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!nodeIds) @@ -879,7 +923,7 @@ WebInspector.AuditRules.CssInHeadRule.prototype = { function onDocumentAvailable(root) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; WebInspector.domAgent.querySelectorAll(root.id, "body style", inlineStylesReceived.bind(null, root)); @@ -901,11 +945,17 @@ WebInspector.AuditRules.StylesScriptsOrderRule = function() } WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { function evalCallback(resultValue) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!resultValue) @@ -927,7 +977,7 @@ WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { function cssBeforeInlineReceived(lateStyleIds, nodeIds) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!nodeIds) @@ -950,7 +1000,7 @@ WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { function lateStylesReceived(root, nodeIds) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!nodeIds) @@ -961,7 +1011,7 @@ WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { function onDocumentAvailable(root) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; WebInspector.domAgent.querySelectorAll(root.id, "head script[src] ~ link[rel~='stylesheet'][href]", lateStylesReceived.bind(null, root)); @@ -983,7 +1033,13 @@ WebInspector.AuditRules.CSSRuleBase = function(id, name) } WebInspector.AuditRules.CSSRuleBase.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { CSSAgent.getAllStyleSheets(sheetsCallback.bind(this)); @@ -997,7 +1053,7 @@ WebInspector.AuditRules.CSSRuleBase.prototype = { if (header.disabled) continue; // Do not check disabled stylesheets. - this._visitStyleSheet(header.styleSheetId, i === headers.length - 1 ? finishedCallback : null, result, progressMonitor); + this._visitStyleSheet(header.styleSheetId, i === headers.length - 1 ? finishedCallback : null, result, progress); } } @@ -1007,13 +1063,13 @@ WebInspector.AuditRules.CSSRuleBase.prototype = { } }, - _visitStyleSheet: function(styleSheetId, callback, result, progressMonitor) + _visitStyleSheet: function(styleSheetId, callback, result, progress) { WebInspector.CSSStyleSheet.createForId(styleSheetId, sheetCallback.bind(this)); function sheetCallback(styleSheet) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; if (!styleSheet) { @@ -1144,11 +1200,17 @@ WebInspector.AuditRules.CookieRuleBase = function(id, name) } WebInspector.AuditRules.CookieRuleBase.prototype = { - doRun: function(requests, result, callback, progressMonitor) + /** + * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress + */ + doRun: function(requests, result, callback, progress) { var self = this; function resultCallback(receivedCookies, isAdvanced) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; self.processCookies(isAdvanced ? receivedCookies : [], requests, result); diff --git a/Source/WebCore/inspector/front-end/AuditsPanel.js b/Source/WebCore/inspector/front-end/AuditsPanel.js index 056813756..963a30d47 100644 --- a/Source/WebCore/inspector/front-end/AuditsPanel.js +++ b/Source/WebCore/inspector/front-end/AuditsPanel.js @@ -57,7 +57,7 @@ WebInspector.AuditsPanel = function() this._constructCategories(); - this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this), this.terminateAudit.bind(this)); + this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this)); for (var id in this.categoriesById) this._launcherView.addCategory(this.categoriesById[id]); @@ -104,27 +104,28 @@ WebInspector.AuditsPanel.prototype = { for (var i = 0; i < categories.length; ++i) rulesRemaining += categories[i].ruleCount; - this._progressMonitor.setTotalWork(rulesRemaining); + this._progress.setTotalWork(rulesRemaining); + this._progress.setTitle(WebInspector.UIString("Running audit")); var results = []; var mainResourceURL = WebInspector.inspectedPageURL; function ruleResultReadyCallback(categoryResult, ruleResult) { - if (this._progressMonitor.canceled) + if (this._progress.isCanceled()) return; if (ruleResult && ruleResult.children) categoryResult.addRuleResult(ruleResult); --rulesRemaining; - this._progressMonitor.worked(1); + this._progress.worked(); - if (this._progressMonitor.done() && resultCallback) + if (!rulesRemaining || this._progress.isCanceled()) resultCallback(mainResourceURL, results); } - if (this._progressMonitor.done()) { + if (!rulesRemaining || this._progress.isCanceled()) { resultCallback(mainResourceURL, results); return; } @@ -133,7 +134,7 @@ WebInspector.AuditsPanel.prototype = { var category = categories[i]; var result = new WebInspector.AuditCategoryResult(category); results.push(result); - category.run(requests, ruleResultReadyCallback.bind(this, result), this._progressMonitor); + category.run(requests, ruleResultReadyCallback.bind(this, result), this._progress); } }, @@ -149,40 +150,42 @@ WebInspector.AuditsPanel.prototype = { var resultTreeElement = new WebInspector.AuditResultSidebarTreeElement(this, results, mainResourceURL, ordinal); this.auditResultsTreeElement.appendChild(resultTreeElement); resultTreeElement.revealAndSelect(); - if (!this._progressMonitor.canceled && launcherCallback) + if (!this._progress.isCanceled()) launcherCallback(); }, - initiateAudit: function(categoryIds, progressElement, runImmediately, launcherCallback) + /** + * @param {Array.<string>} categoryIds + * @param {WebInspector.Progress} progress + * @param {boolean} runImmediately + * @param {function()} startedCallback + * @param {function()} finishedCallback + */ + initiateAudit: function(categoryIds, progress, runImmediately, startedCallback, finishedCallback) { if (!categoryIds || !categoryIds.length) return; - this._progressMonitor = new WebInspector.AuditProgressMonitor(progressElement); + this._progress = progress; var categories = []; for (var i = 0; i < categoryIds.length; ++i) categories.push(this.categoriesById[categoryIds[i]]); - function initiateAuditCallback(categories, launcherCallback) + function startAuditWhenResourcesReady() { - this._executeAudit(categories, this._auditFinishedCallback.bind(this, launcherCallback)); + startedCallback(); + this._executeAudit(categories, this._auditFinishedCallback.bind(this, finishedCallback)); } if (runImmediately) - initiateAuditCallback.call(this, categories, launcherCallback); + startAuditWhenResourcesReady.call(this); else - this._reloadResources(initiateAuditCallback.bind(this, categories, launcherCallback)); + this._reloadResources(startAuditWhenResourcesReady.bind(this)); WebInspector.userMetrics.AuditsStarted.record(); }, - terminateAudit: function(launcherCallback) - { - this._progressMonitor.canceled = true; - launcherCallback(); - }, - _reloadResources: function(callback) { this._pageReloadCallback = callback; @@ -281,12 +284,14 @@ WebInspector.AuditCategory.prototype = { /** * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {function()} callback + * @param {WebInspector.Progress} progress */ - run: function(requests, callback, progressMonitor) + run: function(requests, callback, progress) { this._ensureInitialized(); for (var i = 0; i < this._rules.length; ++i) - this._rules[i].run(requests, callback, progressMonitor); + this._rules[i].run(requests, callback, progress); }, _ensureInitialized: function() @@ -338,21 +343,26 @@ WebInspector.AuditRule.prototype = { /** * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress */ - run: function(requests, callback, progressMonitor) + run: function(requests, callback, progress) { - if (progressMonitor.canceled) + if (progress.isCanceled()) return; var result = new WebInspector.AuditRuleResult(this.displayName); result.severity = this._severity; - this.doRun(requests, result, callback, progressMonitor); + this.doRun(requests, result, callback, progress); }, /** * @param {Array.<WebInspector.NetworkRequest>} requests + * @param {WebInspector.AuditRuleResult} result + * @param {function(WebInspector.AuditRuleResult)} callback + * @param {WebInspector.Progress} progress */ - doRun: function(requests, result, callback, progressMonitor) + doRun: function(requests, result, callback, progress) { throw new Error("doRun() not implemented"); } @@ -459,67 +469,6 @@ WebInspector.AuditRuleResult.prototype = { /** * @constructor - * @param {Element} progressElement - */ -WebInspector.AuditProgressMonitor = function(progressElement) -{ - this._element = progressElement; - this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE); -} - -WebInspector.AuditProgressMonitor.INDETERMINATE = -1; - -WebInspector.AuditProgressMonitor.prototype = { - setTotalWork: function(total) - { - if (this.canceled || this._total === total) - return; - this._total = total; - this._value = 0; - this._element.max = total; - if (total === WebInspector.AuditProgressMonitor.INDETERMINATE) - this._element.removeAttribute("value"); - else - this._element.value = 0; - }, - - worked: function(items) - { - if (this.canceled || this.indeterminate || this.done()) - return; - this._value += items; - if (this._value > this._total) - this._value = this._total; - this._element.value = this._value; - }, - - get indeterminate() - { - return this._total === WebInspector.AuditProgressMonitor.INDETERMINATE; - }, - - done: function() - { - return !this.indeterminate && (this.canceled || this._value === this._total); - }, - - get canceled() - { - return !!this._canceled; - }, - - set canceled(x) - { - if (this._canceled === x) - return; - if (x) - this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE); - this._canceled = x; - } -} - -/** - * @constructor * @extends {WebInspector.SidebarTreeElement} * @param {WebInspector.AuditsPanel} panel */ diff --git a/Source/WebCore/inspector/front-end/CSSNamedFlowCollectionsView.js b/Source/WebCore/inspector/front-end/CSSNamedFlowCollectionsView.js new file mode 100644 index 000000000..b6be9e751 --- /dev/null +++ b/Source/WebCore/inspector/front-end/CSSNamedFlowCollectionsView.js @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 HOLDER 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. + */ + +/** + * @constructor + * @extends {WebInspector.SplitView} + */ +WebInspector.CSSNamedFlowCollectionsView = function() +{ + WebInspector.SplitView.call(this, WebInspector.SplitView.SidebarPosition.Left); + this.registerRequiredCSS("cssNamedFlows.css"); + + this._namedFlows = {}; + this._contentNodes = {}; + this._regionNodes = {}; + + this.element.addStyleClass("css-named-flow-collections-view"); + this.element.addStyleClass("fill"); + + this._statusElement = document.createElement("span"); + this._statusElement.textContent = WebInspector.UIString("CSS Named Flows"); + + var sidebarHeader = this._leftElement.createChild("div", "tabbed-pane-header selected sidebar-header") + var tab = sidebarHeader.createChild("div", "tabbed-pane-header-tab"); + tab.createChild("span", "tabbed-pane-header-tab-title").textContent = WebInspector.UIString("CSS Named Flows"); + + this._sidebarContentElement = this._leftElement.createChild("div", "sidebar-content outline-disclosure"); + this._flowListElement = this._sidebarContentElement.createChild("ol"); + this._flowTree = new TreeOutline(this._flowListElement); + + this._emptyElement = document.createElement("div"); + this._emptyElement.addStyleClass("info"); + this._emptyElement.textContent = WebInspector.UIString("No CSS Named Flows"); + + this._tabbedPane = new WebInspector.TabbedPane(); + this._tabbedPane.closeableTabs = true; + this._tabbedPane.show(this._rightElement); +} + +WebInspector.CSSNamedFlowCollectionsView.prototype = { + showInDrawer: function() + { + WebInspector.showViewInDrawer(this._statusElement, this); + }, + + reset: function() + { + if (!this._document) + return; + + WebInspector.cssModel.getNamedFlowCollectionAsync(this._document.id, this._resetNamedFlows.bind(this)); + }, + + /** + * @param {WebInspector.DOMDocument} document + */ + _setDocument: function(document) + { + this._document = document; + this.reset(); + }, + + /** + * @param {WebInspector.Event} event + */ + _documentUpdated: function(event) + { + var document = /** @type {WebInspector.DOMDocument} */ event.data; + this._setDocument(document); + }, + + /** + * @param {boolean} hasContent + */ + _setSidebarHasContent: function(hasContent) + { + if (hasContent) { + if (!this._emptyElement.parentNode) + return; + + this._sidebarContentElement.removeChild(this._emptyElement); + this._sidebarContentElement.appendChild(this._flowListElement); + } else { + if (!this._flowListElement.parentNode) + return; + + this._sidebarContentElement.removeChild(this._flowListElement); + this._sidebarContentElement.appendChild(this._emptyElement); + } + }, + + /** + * @param {WebInspector.NamedFlow} flow + */ + _appendNamedFlow: function(flow) + { + var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name); + var flowContainer = { flow: flow, flowHash: flowHash }; + + for (var i = 0; i < flow.content.length; ++i) + this._contentNodes[flow.content[i]] = flowHash; + for (var i = 0; i < flow.regions.length; ++i) + this._regionNodes[flow.regions[i].nodeId] = flowHash; + + var container = document.createElement("div"); + container.createChild("div", "selection"); + container.createChild("span", "title").createChild("span").textContent = flow.name; + + var flowTreeElement = new TreeElement(container, flowContainer); + if (flow.overset) + flowTreeElement.title.addStyleClass("named-flow-overflow") + + flowContainer.flowTreeElement = flowTreeElement; + this._namedFlows[flowHash] = flowContainer; + + if (!this._flowTree.children.length) + this._setSidebarHasContent(true); + this._flowTree.appendChild(flowTreeElement); + }, + + /** + * @param {string} flowHash + */ + _removeNamedFlow: function(flowHash) + { + var flowContainer = this._namedFlows[flowHash]; + + this._flowTree.removeChild(flowContainer.flowTreeElement); + + var flow = flowContainer.flow; + for (var i = 0; i < flow.content.length; ++i) + delete this._contentNodes[flow.content[i]]; + for (var i = 0; i < flow.regions.length; ++i) + delete this._regionNodes[flow.regions[i].nodeId]; + + delete this._namedFlows[flowHash]; + + if (!this._flowTree.children.length) + this._setSidebarHasContent(false); + }, + + /** + * @param {WebInspector.NamedFlow} flow + */ + _updateNamedFlow: function(flow) + { + var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name); + var flowContainer = this._namedFlows[flowHash]; + + if (!flowContainer) + return; + + var oldFlow = flowContainer.flow; + flowContainer.flow = flow; + + for (var i = 0; i < oldFlow.content.length; ++i) + delete this._contentNodes[oldFlow.content[i]]; + for (var i = 0; i < oldFlow.regions.length; ++i) + delete this._regionNodes[oldFlow.regions[i].nodeId]; + + for (var i = 0; i < flow.content.length; ++i) + this._contentNodes[flow.content[i]] = flowHash; + for (var i = 0; i < flow.regions.length; ++i) + this._regionNodes[flow.regions[i].nodeId] = flowHash; + + if (flow.overset !== oldFlow.overset) { + if (flow.overset) + flowContainer.flowTreeElement.title.addStyleClass("named-flow-overflow"); + else + flowContainer.flowTreeElement.title.removeStyleClass("named-flow-overflow"); + } + }, + + /** + * @param {WebInspector.NamedFlowCollection} namedFlowCollection + */ + _resetNamedFlows: function(namedFlowCollection) + { + for (var flowHash in this._namedFlows) + this._removeNamedFlow(flowHash); + + var namedFlows = namedFlowCollection.namedFlowMap; + for (var flowName in namedFlows) + this._appendNamedFlow(namedFlows[flowName]); + + if (!this._flowTree.children.length) + this._setSidebarHasContent(false); + else + this._showNamedFlowForNode(WebInspector.panel("elements").treeOutline.selectedDOMNode()); + }, + + /** + * @param {WebInspector.Event} event + */ + _namedFlowCreated: function(event) + { + // FIXME: We only have support for Named Flows in the main document. + if (event.data.documentNodeId !== this._document.id) + return; + + var flow = /** @type {WebInspector.NamedFlow} */ event.data; + this._appendNamedFlow(flow); + }, + + /** + * @param {WebInspector.Event} event + */ + _namedFlowRemoved: function(event) + { + // FIXME: We only have support for Named Flows in the main document. + if (event.data.documentNodeId !== this._document.id) + return; + + this._removeNamedFlow(this._hashNamedFlow(event.data.documentNodeId, event.data.flowName)); + }, + + /** + * @param {WebInspector.Event} event + */ + _regionLayoutUpdated: function(event) + { + // FIXME: We only have support for Named Flows in the main document. + if (event.data.documentNodeId !== this._document.id) + return; + + var flow = /** @type {WebInspector.NamedFlow} */ event.data; + this._updateNamedFlow(flow); + }, + + /** + * @param {DOMAgent.NodeId} documentNodeId + * @param {string} flowName + */ + _hashNamedFlow: function(documentNodeId, flowName) + { + return documentNodeId + "|" + flowName; + }, + + /** + * @param {string} flowHash + */ + _showNamedFlow: function(flowHash) + { + this._selectNamedFlowInSidebar(flowHash); + }, + + /** + * @param {string} flowHash + */ + _selectNamedFlowInSidebar: function(flowHash) + { + this._namedFlows[flowHash].flowTreeElement.select(true); + }, + + /** + * @param {WebInspector.Event} event + */ + _selectedNodeChanged: function(event) + { + var node = /** @type {WebInspector.DOMNode} */ event.data; + this._showNamedFlowForNode(node); + }, + + /** + * @param {?WebInspector.DOMNode} node + */ + _showNamedFlowForNode: function(node) + { + if (!node) + return; + + if (this._regionNodes[node.id]) { + this._showNamedFlow(this._regionNodes[node.id]); + return; + } + + while (node) { + if (this._contentNodes[node.id]) { + this._showNamedFlow(this._contentNodes[node.id]); + return; + } + + node = node.parentNode; + } + }, + + wasShown: function() + { + WebInspector.SplitView.prototype.wasShown.call(this); + + WebInspector.domAgent.requestDocument(this._setDocument.bind(this)); + + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); + + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this); + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this); + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this); + + WebInspector.panel("elements").treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); + }, + + willHide: function() + { + WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); + + WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this); + WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this); + WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this); + + WebInspector.panel("elements").treeOutline.removeEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); + } +} + +WebInspector.CSSNamedFlowCollectionsView.prototype.__proto__ = WebInspector.SplitView.prototype; diff --git a/Source/WebCore/inspector/front-end/CSSStyleModel.js b/Source/WebCore/inspector/front-end/CSSStyleModel.js index 820695bf8..6e99dac82 100644 --- a/Source/WebCore/inspector/front-end/CSSStyleModel.js +++ b/Source/WebCore/inspector/front-end/CSSStyleModel.js @@ -39,6 +39,8 @@ WebInspector.CSSStyleModel = function() WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoRequested, this._undoRedoRequested, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoCompleted, this._undoRedoCompleted, this); this._resourceBinding = new WebInspector.CSSStyleModelResourceBinding(this); + this._namedFlowCollections = {}; + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._resetNamedFlowCollections, this); InspectorBackend.registerCSSDispatcher(new WebInspector.CSSDispatcher(this)); CSSAgent.enable(); } @@ -58,7 +60,8 @@ WebInspector.CSSStyleModel.Events = { StyleSheetChanged: "StyleSheetChanged", MediaQueryResultChanged: "MediaQueryResultChanged", NamedFlowCreated: "NamedFlowCreated", - NamedFlowRemoved: "NamedFlowRemoved" + NamedFlowRemoved: "NamedFlowRemoved", + RegionLayoutUpdated: "RegionLayoutUpdated" } WebInspector.CSSStyleModel.prototype = { @@ -171,48 +174,62 @@ WebInspector.CSSStyleModel.prototype = { }, /** - * @param {DOMAgent.NodeId} nodeId - * @param {function(?Array.<WebInspector.NamedFlow>)} userCallback + * @param {DOMAgent.NodeId} documentNodeId + * @param {function(?WebInspector.NamedFlowCollection)} userCallback */ - getNamedFlowCollectionAsync: function(nodeId, userCallback) + getNamedFlowCollectionAsync: function(documentNodeId, userCallback) { + var namedFlowCollection = this._namedFlowCollections[documentNodeId]; + if (namedFlowCollection) { + userCallback(namedFlowCollection); + return; + } + /** - * @param {function(?Array.<WebInspector.NamedFlow>)} userCallback + * @param {function(?WebInspector.NamedFlowCollection)} userCallback * @param {?Protocol.Error} error - * @param {?Array.<CSSAgent.NamedFlow>=} namedFlowPayload + * @param {?Array.<CSSAgent.NamedFlow>} namedFlowPayload */ function callback(userCallback, error, namedFlowPayload) { if (error || !namedFlowPayload) userCallback(null); - else - userCallback(WebInspector.NamedFlow.parsePayloadArray(namedFlowPayload)); + else { + var namedFlowCollection = new WebInspector.NamedFlowCollection(namedFlowPayload); + this._namedFlowCollections[documentNodeId] = namedFlowCollection; + userCallback(namedFlowCollection); + } } - CSSAgent.getNamedFlowCollection(nodeId, callback.bind(this, userCallback)); + CSSAgent.getNamedFlowCollection(documentNodeId, callback.bind(this, userCallback)); }, /** - * @param {DOMAgent.NodeId} nodeId + * @param {DOMAgent.NodeId} documentNodeId * @param {string} flowName * @param {function(?WebInspector.NamedFlow)} userCallback */ - getFlowByNameAsync: function(nodeId, flowName, userCallback) + getFlowByNameAsync: function(documentNodeId, flowName, userCallback) { + var namedFlowCollection = this._namedFlowCollections[documentNodeId]; + if (namedFlowCollection) { + userCallback(namedFlowCollection.flowByName(flowName)); + return; + } + /** * @param {function(?WebInspector.NamedFlow)} userCallback - * @param {?Protocol.Error} error - * @param {?CSSAgent.NamedFlow=} namedFlowPayload + * @param {?WebInspector.NamedFlowCollection} namedFlowCollection */ - function callback(userCallback, error, namedFlowPayload) + function callback(userCallback, namedFlowCollection) { - if (error || !namedFlowPayload) + if (!namedFlowCollection) userCallback(null); else - userCallback(WebInspector.NamedFlow.parsePayload(namedFlowPayload)); + userCallback(namedFlowCollection.flowByName(flowName)); } - CSSAgent.getFlowByName(nodeId, flowName, callback.bind(this, userCallback)); + this.getNamedFlowCollectionAsync(documentNodeId, callback.bind(this, userCallback)); }, /** @@ -350,51 +367,48 @@ WebInspector.CSSStyleModel.prototype = { }, /** - * @param {DOMAgent.NodeId} documentNodeId - * @param {string} name + * @param {CSSAgent.NamedFlow} namedFlowPayload */ - _namedFlowCreated: function(documentNodeId, name) + _namedFlowCreated: function(namedFlowPayload) { - if (!this.hasEventListeners(WebInspector.CSSStyleModel.Events.NamedFlowCreated)) - return; - - /** - * @param {WebInspector.DOMDocument} root - */ - function callback(root) - { - // FIXME: At the moment we only want support for NamedFlows in the main document - if (documentNodeId !== root.id) - return; + var namedFlow = WebInspector.NamedFlow.parsePayload(namedFlowPayload); + var namedFlowCollection = this._namedFlowCollections[namedFlow.documentNodeId]; - this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowCreated, { documentNodeId: documentNodeId, name: name }); - } + if (!namedFlowCollection) + return; - WebInspector.domAgent.requestDocument(callback.bind(this)); + namedFlowCollection._appendNamedFlow(namedFlow); + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowCreated, namedFlow); }, /** * @param {DOMAgent.NodeId} documentNodeId - * @param {string} name + * @param {string} flowName */ - _namedFlowRemoved: function(documentNodeId, name) + _namedFlowRemoved: function(documentNodeId, flowName) { - if (!this.hasEventListeners(WebInspector.CSSStyleModel.Events.NamedFlowRemoved)) + var namedFlowCollection = this._namedFlowCollections[documentNodeId]; + + if (!namedFlowCollection) return; - /** - * @param {WebInspector.DOMDocument} root - */ - function callback(root) - { - // FIXME: At the moment we only want support for NamedFlows in the main document - if (documentNodeId !== root.id) - return; + namedFlowCollection._removeNamedFlow(flowName); + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, { documentNodeId: documentNodeId, flowName: flowName }); + }, - this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, { documentNodeId: documentNodeId, name: name }); - } + /** + * @param {CSSAgent.NamedFlow} namedFlowPayload + */ + _regionLayoutUpdated: function(namedFlowPayload) + { + var namedFlow = WebInspector.NamedFlow.parsePayload(namedFlowPayload); + var namedFlowCollection = this._namedFlowCollections[namedFlow.documentNodeId]; - WebInspector.domAgent.requestDocument(callback.bind(this)); + if (!namedFlowCollection) + return; + + namedFlowCollection._appendNamedFlow(namedFlow); + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, namedFlow); }, /** @@ -463,6 +477,11 @@ WebInspector.CSSStyleModel.prototype = { this._sourceMappings = {}; }, + _resetNamedFlowCollections: function() + { + this._namedFlowCollections = {}; + }, + /** * @param {WebInspector.CSSLocation} rawLocation * @return {?WebInspector.UILocation} @@ -1326,21 +1345,28 @@ WebInspector.CSSDispatcher.prototype = { }, /** - * @param {DOMAgent.NodeId} documentNodeId - * @param {string} name + * @param {CSSAgent.NamedFlow} namedFlowPayload */ - namedFlowCreated: function(documentNodeId, name) + namedFlowCreated: function(namedFlowPayload) { - this._cssModel._namedFlowCreated(documentNodeId, name); + this._cssModel._namedFlowCreated(namedFlowPayload); }, /** * @param {DOMAgent.NodeId} documentNodeId - * @param {string} name + * @param {string} flowName */ - namedFlowRemoved: function(documentNodeId, name) + namedFlowRemoved: function(documentNodeId, flowName) { - this._cssModel._namedFlowRemoved(documentNodeId, name); + this._cssModel._namedFlowRemoved(documentNodeId, flowName); + }, + + /** + * @param {CSSAgent.NamedFlow} namedFlowPayload + */ + regionLayoutUpdated: function(namedFlowPayload) + { + this._cssModel._regionLayoutUpdated(namedFlowPayload); } } @@ -1350,7 +1376,7 @@ WebInspector.CSSDispatcher.prototype = { */ WebInspector.NamedFlow = function(payload) { - this.nodeId = payload.documentNodeId; + this.documentNodeId = payload.documentNodeId; this.name = payload.name; this.overset = payload.overset; this.content = payload.content; @@ -1367,20 +1393,50 @@ WebInspector.NamedFlow.parsePayload = function(payload) } /** - * @param {?Array.<CSSAgent.NamedFlow>=} namedFlowPayload - * @return {?Array.<WebInspector.NamedFlow>} + * @constructor + * @param {Array.<CSSAgent.NamedFlow>} payload */ -WebInspector.NamedFlow.parsePayloadArray = function(namedFlowPayload) +WebInspector.NamedFlowCollection = function(payload) { - if (!namedFlowPayload) - return null; + /** @type {Object.<string, WebInspector.NamedFlow>} */ + this.namedFlowMap = {}; - var parsedArray = []; - for (var i = 0; i < namedFlowPayload.length; ++i) - parsedArray[i] = WebInspector.NamedFlow.parsePayload(namedFlowPayload[i]); - return parsedArray; + for (var i = 0; i < payload.length; ++i) { + var namedFlow = WebInspector.NamedFlow.parsePayload(payload[i]); + this.namedFlowMap[namedFlow.name] = namedFlow; + } } +WebInspector.NamedFlowCollection.prototype = { + /** + * @param {WebInspector.NamedFlow} namedFlow + */ + _appendNamedFlow: function(namedFlow) + { + this.namedFlowMap[namedFlow.name] = namedFlow; + }, + + /** + * @param {string} flowName + */ + _removeNamedFlow: function(flowName) + { + delete this.namedFlowMap[flowName]; + }, + + /** + * @param {string} flowName + * @return {WebInspector.NamedFlow} + */ + flowByName: function(flowName) + { + var namedFlow = this.namedFlowMap[flowName]; + + if (!namedFlow) + return null; + return namedFlow; + } +} /** * @type {WebInspector.CSSStyleModel} */ diff --git a/Source/WebCore/inspector/front-end/CompilerScriptMapping.js b/Source/WebCore/inspector/front-end/CompilerScriptMapping.js index 0ffdc28c1..7f4b9dae3 100644 --- a/Source/WebCore/inspector/front-end/CompilerScriptMapping.js +++ b/Source/WebCore/inspector/front-end/CompilerScriptMapping.js @@ -84,7 +84,7 @@ WebInspector.CompilerScriptMapping.prototype = { */ addScript: function(script) { - var originalUISourceCode = new WebInspector.JavaScriptSource(script.sourceURL, null, script, this, true); + var originalUISourceCode = new WebInspector.JavaScriptSource(script.sourceURL, null, script, true); this._originalUISourceCodeForScriptId[script.scriptId] = originalUISourceCode; this._scriptForOriginalUISource.put(originalUISourceCode, script); this._workspace.project().addUISourceCode(originalUISourceCode); diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js index 2f451f565..811fd2e6d 100644 --- a/Source/WebCore/inspector/front-end/DOMAgent.js +++ b/Source/WebCore/inspector/front-end/DOMAgent.js @@ -794,7 +794,6 @@ WebInspector.DOMAgent.Events = { DocumentUpdated: "DocumentUpdated", ChildNodeCountUpdated: "ChildNodeCountUpdated", InspectElementRequested: "InspectElementRequested", - StyleInvalidated: "StyleInvalidated", UndoRedoRequested: "UndoRedoRequested", UndoRedoCompleted: "UndoRedoCompleted" } @@ -916,12 +915,9 @@ WebInspector.DOMAgent.prototype = { var node = this._idToDOMNode[nodeId]; if (!node) return; - var issueStyleInvalidated = name === "style" && value !== node.getAttribute("style"); node._setAttribute(name, value); this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: name }); - if (issueStyleInvalidated) - this.dispatchEventToListeners(WebInspector.DOMAgent.Events.StyleInvalidated, node) }, /** @@ -965,10 +961,8 @@ WebInspector.DOMAgent.prototype = { } var node = this._idToDOMNode[nodeId]; if (node) { - if (node._setAttributesPayload(attributes)) { + if (node._setAttributesPayload(attributes)) this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: "style" }); - this.dispatchEventToListeners(WebInspector.DOMAgent.Events.StyleInvalidated, node); - } } } @@ -1080,7 +1074,7 @@ WebInspector.DOMAgent.prototype = { var node = this._idToDOMNode[nodeId]; parent._removeChild(node); this._unbind(node); - this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent}); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node: node, parent: parent}); }, /** diff --git a/Source/WebCore/inspector/front-end/ElementsPanel.js b/Source/WebCore/inspector/front-end/ElementsPanel.js index 2a4ff973c..e73588020 100644 --- a/Source/WebCore/inspector/front-end/ElementsPanel.js +++ b/Source/WebCore/inspector/front-end/ElementsPanel.js @@ -28,6 +28,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +importScript("CSSNamedFlowCollectionsView.js"); importScript("EventListenersSidebarPane.js"); importScript("MetricsSidebarPane.js"); importScript("PropertiesSidebarPane.js"); @@ -336,12 +337,25 @@ WebInspector.ElementsPanel.prototype = { var contextMenu = new WebInspector.ContextMenu(); var populated = this.treeOutline.populateContextMenu(contextMenu, event); + + if (WebInspector.experimentsSettings.cssRegions.isEnabled()) { + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.UIString("CSS Named Flows..."), this._showNamedFlowCollections.bind(this)); + } + contextMenu.appendSeparator(); contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Word wrap" : "Word Wrap"), toggleWordWrap.bind(this), WebInspector.settings.domWordWrap.get()); contextMenu.show(event); }, + _showNamedFlowCollections: function() + { + if (!WebInspector.cssNamedFlowCollectionsView) + WebInspector.cssNamedFlowCollectionsView = new WebInspector.CSSNamedFlowCollectionsView(); + WebInspector.cssNamedFlowCollectionsView.showInDrawer(); + }, + _domWordWrapSettingChanged: function(event) { if (event.data) diff --git a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js index 81836364d..07843c96b 100644 --- a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -812,10 +812,14 @@ WebInspector.ElementsTreeElement.prototype = { if (!listItemElement) return; - if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet or the window is closed, - // so we can't calculate what is need. Return early. - return; + if (!this._readyToUpdateSelection) { + if (document.body.offsetWidth > 0) + this._readyToUpdateSelection = true; + else { + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what we need. Return early. + return; + } } if (!this.selectionElement) { diff --git a/Source/WebCore/inspector/front-end/Images/namedFlowOverflow.png b/Source/WebCore/inspector/front-end/Images/namedFlowOverflow.png Binary files differnew file mode 100644 index 000000000..77b054ceb --- /dev/null +++ b/Source/WebCore/inspector/front-end/Images/namedFlowOverflow.png diff --git a/Source/WebCore/inspector/front-end/InspectorBackend.js b/Source/WebCore/inspector/front-end/InspectorBackend.js index 41e958498..c2722b34d 100644 --- a/Source/WebCore/inspector/front-end/InspectorBackend.js +++ b/Source/WebCore/inspector/front-end/InspectorBackend.js @@ -256,13 +256,13 @@ InspectorBackendClass.prototype = { } }, - loadFromJSONIfNeeded: function() + loadFromJSONIfNeeded: function(jsonUrl) { if (this._initialized) return; var xhr = new XMLHttpRequest(); - xhr.open("GET", "../Inspector.json", false); + xhr.open("GET", jsonUrl, false); xhr.send(null); var schema = JSON.parse(xhr.responseText); diff --git a/Source/WebCore/inspector/front-end/NetworkPanel.js b/Source/WebCore/inspector/front-end/NetworkPanel.js index 5c80ac178..c7b900632 100644 --- a/Source/WebCore/inspector/front-end/NetworkPanel.js +++ b/Source/WebCore/inspector/front-end/NetworkPanel.js @@ -962,8 +962,21 @@ WebInspector.NetworkLogView.prototype = { if (this._canClearBrowserCookies) contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cookies" : "Clear Browser Cookies"), this._clearBrowserCookies.bind(this)); + + if (request.type === WebInspector.resourceTypes.XHR) { + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.UIString("Replay XHR"), this._replayXHR.bind(this, request.requestId)); + contextMenu.appendSeparator(); + } + contextMenu.show(event); }, + + _replayXHR: function(requestId) + { + NetworkAgent.replayXHR(requestId); + }, + _copyAll: function() { diff --git a/Source/WebCore/inspector/front-end/ProgressBar.js b/Source/WebCore/inspector/front-end/ProgressBar.js index 84ed5a0bb..83a8a8d64 100644 --- a/Source/WebCore/inspector/front-end/ProgressBar.js +++ b/Source/WebCore/inspector/front-end/ProgressBar.js @@ -52,6 +52,11 @@ WebInspector.Progress.prototype = { */ setWorked: function(worked, title) { }, + /** + * @param {number=} worked + */ + worked: function(worked) { }, + done: function() { }, /** @@ -72,9 +77,10 @@ WebInspector.ProgressIndicator = function() this._labelElement = this.element.createChild("span"); this._progressElement = this.element.createChild("progress"); this._stopButton = new WebInspector.StatusBarButton(WebInspector.UIString("Cancel"), "progress-bar-stop-button"); - this._stopButton.addEventListener("click", this._cancel, this); + this._stopButton.addEventListener("click", this.cancel, this); this.element.appendChild(this._stopButton.element); this._isCanceled = false; + this._worked = 0; } WebInspector.ProgressIndicator.Events = { @@ -103,7 +109,7 @@ WebInspector.ProgressIndicator.prototype = { this.dispatchEventToListeners(WebInspector.ProgressIndicator.Events.Done); }, - _cancel: function() + cancel: function() { this._isCanceled = true; }, @@ -135,9 +141,18 @@ WebInspector.ProgressIndicator.prototype = { */ setWorked: function(worked, title) { + this._worked = worked; this._progressElement.value = worked; if (title) this.setTitle(title); + }, + + /** + * @param {number=} worked + */ + worked: function(worked) + { + this.setWorked(this._worked + (worked || 1)); } } @@ -243,5 +258,13 @@ WebInspector.SubProgress.prototype = { if (typeof title !== "undefined") this.setTitle(title); this._composite._update(); + }, + + /** + * @param {number=} worked + */ + worked: function(worked) + { + this.setWorked(this._worked + (worked || 1)); } } diff --git a/Source/WebCore/inspector/front-end/Resource.js b/Source/WebCore/inspector/front-end/Resource.js index 9fa6b8c0a..83c5a5fb8 100644 --- a/Source/WebCore/inspector/front-end/Resource.js +++ b/Source/WebCore/inspector/front-end/Resource.js @@ -311,7 +311,7 @@ WebInspector.Resource.prototype = { this._contentRequested = true; /** - * @param {string} content + * @param {?string} content * @param {boolean} contentEncoded */ function contentLoaded(content, contentEncoded) @@ -339,7 +339,7 @@ WebInspector.Resource.prototype = { if (this.request) { /** - * @param {string} content + * @param {?string} content * @param {boolean} contentEncoded * @param {string} mimeType */ diff --git a/Source/WebCore/inspector/front-end/Settings.js b/Source/WebCore/inspector/front-end/Settings.js index 6765dc542..e35384b04 100644 --- a/Source/WebCore/inspector/front-end/Settings.js +++ b/Source/WebCore/inspector/front-end/Settings.js @@ -197,6 +197,7 @@ WebInspector.ExperimentsSettings = function() this.deviceOrientationOverride = this._createExperiment("deviceOrientationOverride", "Override Device Orientation"); this.sass = this._createExperiment("sass", "Support for SASS"); this.codemirror = this._createExperiment("codemirror", "Use CodeMirror editor"); + this.cssRegions = this._createExperiment("cssRegions", "CSS Regions Support"); this._cleanUpSetting(); } diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js index 04678b094..af13f4189 100644 --- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js @@ -97,9 +97,8 @@ WebInspector.StylesSidebarPane = function(computedStylePane, setPseudoClassCallb WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this); - WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesModified, this); - WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesRemoved, this); - WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.StyleInvalidated, this._styleInvalidated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributeChanged, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributeChanged, this); WebInspector.settings.showUserAgentStyles.addChangeListener(this._showUserAgentStylesSettingChanged.bind(this)); } @@ -235,17 +234,14 @@ WebInspector.StylesSidebarPane.prototype = { } }, - /** - * @param {function()=} userCallback - */ - _rebuildUpdate: function(userCallback) + _rebuildUpdate: function() { if (this._rebuildUpdateInProgress) { this._lastNodeForInnerRebuild = this.node; return; } - var node = this._validateNode(userCallback); + var node = this._validateNode(); if (!node) return; @@ -257,10 +253,13 @@ WebInspector.StylesSidebarPane.prototype = { { delete this._rebuildUpdateInProgress; - if (this._lastNodeForInnerRebuild) { + var lastNodeForRebuild = this._lastNodeForInnerRebuild; + if (lastNodeForRebuild) { delete this._lastNodeForInnerRebuild; - this._rebuildUpdate(userCallback); - return; + if (lastNodeForRebuild !== this.node) { + this._rebuildUpdate(); + return; + } } if (matchedResult && this.node === node) { @@ -269,8 +268,12 @@ WebInspector.StylesSidebarPane.prototype = { resultStyles.inherited = matchedResult.inherited; this._innerRebuildUpdate(node, resultStyles); } - if (userCallback) - userCallback(); + + if (lastNodeForRebuild) { + // lastNodeForRebuild is the same as this.node - another rebuild has been requested. + this._rebuildUpdate(); + return; + } } function inlineCallback(inlineStyle, attributesStyle) @@ -314,37 +317,22 @@ WebInspector.StylesSidebarPane.prototype = { this._rebuildUpdate(); }, - _attributesModified: function(event) + _attributeChanged: function(event) { - if (this.node !== event.data.node) + // Any attribute removal or modification can affect the styles of "related" nodes. + // Do not touch the styles if they are being edited. + if (this._isEditingStyle || this._userOperation) return; - // Changing style attribute will anyways generate _styleInvalidated message. - if (event.data.name === "style") + if (!this._canAffectCurrentStyles(event.data.node)) return; - // "class" (or any other) attribute might have changed. Update styles unless they are being edited. - if (!this._isEditingStyle && !this._userOperation) - this._rebuildUpdate(); - }, - - _attributesRemoved: function(event) - { - if (this.node !== event.data.node) - return; - - // "style" attribute might have been removed. - if (!this._isEditingStyle && !this._userOperation) - this._rebuildUpdate(); + this._rebuildUpdate(); }, - _styleInvalidated: function(event) + _canAffectCurrentStyles: function(node) { - if (this.node !== event.data) - return; - - if (!this._isEditingStyle && !this._userOperation) - this._rebuildUpdate(); + return this.node && (this.node === node || node.parentNode === this.node.parentNode || node.isAncestor(this.node)); }, _innerRefreshUpdate: function(node, computedStyle, editedSection) diff --git a/Source/WebCore/inspector/front-end/TimelineOverviewPane.js b/Source/WebCore/inspector/front-end/TimelineOverviewPane.js index 797df208b..ecdfa820f 100644 --- a/Source/WebCore/inspector/front-end/TimelineOverviewPane.js +++ b/Source/WebCore/inspector/front-end/TimelineOverviewPane.js @@ -31,7 +31,6 @@ /** * @constructor * @extends {WebInspector.View} - * @implements {WebInspector.TimelinePresentationModel.Filter} * @param {WebInspector.TimelineModel} model */ WebInspector.TimelineOverviewPane = function(model) @@ -274,14 +273,6 @@ WebInspector.TimelineOverviewPane.prototype = { this._update(); }, - /** - * @param {WebInspector.TimelinePresentationModel.Record} record - */ - accept: function(record) - { - return record.lastChildEndTime >= this._windowStartTime && record.startTime <= this._windowEndTime; - }, - windowStartTime: function() { return this._windowStartTime || this._model.minimumRecordTime(); @@ -1232,3 +1223,24 @@ WebInspector.TimelineFrameOverview.prototype = { } WebInspector.TimelineFrameOverview.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @param {WebInspector.TimelineOverviewPane} pane + * @constructor + * @implements {WebInspector.TimelinePresentationModel.Filter} + */ +WebInspector.TimelineWindowFilter = function(pane) +{ + this._pane = pane; +} + +WebInspector.TimelineWindowFilter.prototype = { + /** + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @return {boolean} + */ + accept: function(record) + { + return record.lastChildEndTime >= this._pane._windowStartTime && record.startTime <= this._pane._windowEndTime; + } +} diff --git a/Source/WebCore/inspector/front-end/TimelinePanel.js b/Source/WebCore/inspector/front-end/TimelinePanel.js index 472ace2dd..4ccb7a42c 100644 --- a/Source/WebCore/inspector/front-end/TimelinePanel.js +++ b/Source/WebCore/inspector/front-end/TimelinePanel.js @@ -145,9 +145,9 @@ WebInspector.TimelinePanel = function() this._allRecordsCount = 0; - this._presentationModel.addFilter(this._overviewPane); + this._presentationModel.addFilter(new WebInspector.TimelineWindowFilter(this._overviewPane)); this._presentationModel.addFilter(new WebInspector.TimelineCategoryFilter()); - this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this)); + this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this)); } // Define row height, should be in sync with styles for timeline graphs. @@ -671,6 +671,7 @@ WebInspector.TimelinePanel.prototype = { _invalidateAndScheduleRefresh: function(preserveBoundaries) { this._presentationModel.invalidateFilteredRecords(); + delete this._searchResults; this._scheduleRefresh(preserveBoundaries); }, @@ -724,18 +725,19 @@ WebInspector.TimelinePanel.prototype = { revealRecordAt: function(time) { - var recordsInWindow = this._presentationModel.filteredRecords(); var recordToReveal; - for (var i = 0; i < recordsInWindow.length; ++i) { - var record = recordsInWindow[i]; + function findRecordToReveal(record) + { if (record.containsTime(time)) { recordToReveal = record; - break; + return true; } // If there is no record containing the time than use the latest one before that time. if (!recordToReveal || record.endTime < time && recordToReveal.endTime < record.endTime) recordToReveal = record; + return false; } + WebInspector.TimelinePresentationModel.forAllRecords(this._presentationModel.rootRecord().children, null, findRecordToReveal); // The record ends before the window left bound so scroll to the top. if (!recordToReveal) { @@ -743,9 +745,21 @@ WebInspector.TimelinePanel.prototype = { return; } + this._revealRecord(recordToReveal); + }, + + _revealRecord: function(recordToReveal) + { // Expand all ancestors. - for (var parent = recordToReveal.parent; parent !== this._rootRecord(); parent = parent.parent) + var treeUpdated = false; + for (var parent = recordToReveal.parent; parent !== this._rootRecord(); parent = parent.parent) { + treeUpdated = treeUpdated || parent.collapsed; parent.collapsed = false; + } + if (treeUpdated) + this._invalidateAndScheduleRefresh(true); + + var recordsInWindow = this._presentationModel.filteredRecords(); var index = recordsInWindow.indexOf(recordToReveal); this._containerElement.scrollTop = index * WebInspector.TimelinePanel.rowHeight; }, @@ -832,6 +846,7 @@ WebInspector.TimelinePanel.prototype = { this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement); this._itemsGraphsElement.appendChild(this._expandElements); this._adjustScrollPosition((recordsInWindow.length + this._headerLineCount) * rowHeight); + this._updateSearchHighlight(false); return recordsInWindow.length; }, @@ -1002,6 +1017,142 @@ WebInspector.TimelinePanel.prototype = { style.textContent = Object.values(categories).map(WebInspector.TimelinePresentationModel.createStyleRuleForCategory).join("\n"); document.head.appendChild(style); + }, + + jumpToNextSearchResult: function() + { + this._jumpToAdjacentRecord(1); + }, + + jumpToPreviousSearchResult: function() + { + this._jumpToAdjacentRecord(-1); + }, + + _jumpToAdjacentRecord: function(offset) + { + if (!this._searchResults || !this._searchResults.length || !this._selectedSearchResult) + return; + var index = this._searchResults.indexOf(this._selectedSearchResult); + index = (index + offset + this._searchResults.length) % this._searchResults.length; + this._selectSearchResult(index); + this._highlightSelectedSearchResult(true); + }, + + _selectSearchResult: function(index) + { + this._selectedSearchResult = this._searchResults[index]; + WebInspector.searchController.updateCurrentMatchIndex(index, this); + }, + + _highlightSelectedSearchResult: function(revealRecord) + { + this._clearHighlight(); + if (this._searchFilter) + return; + + var record = this._selectedSearchResult; + if (!record) + return; + + for (var element = this._sidebarListElement.firstChild; element; element = element.nextSibling) { + if (element.row._record === record) { + element.row.highlight(this._searchRegExp, this._highlightDomChanges); + return; + } + } + + if (revealRecord) + this._revealRecord(record); + }, + + _clearHighlight: function() + { + if (this._highlightDomChanges) + WebInspector.revertDomChanges(this._highlightDomChanges); + this._highlightDomChanges = []; + }, + + /** + * @param {boolean} revealRecord + */ + _updateSearchHighlight: function(revealRecord) + { + if (this._searchFilter || !this._searchRegExp) { + this._clearHighlight(); + return; + } + + if (!this._searchResults) + this._updateSearchResults(); + + this._highlightSelectedSearchResult(revealRecord); + }, + + _updateSearchResults: function() { + var searchRegExp = this._searchRegExp; + if (!searchRegExp) + return; + + var matches = []; + var presentationModel = this._presentationModel; + + function processRecord(record) + { + if (presentationModel.isVisible(record) && WebInspector.TimelineRecordListRow.testContentMatching(record, searchRegExp)) + matches.push(record); + return false; + } + WebInspector.TimelinePresentationModel.forAllRecords(presentationModel.rootRecord().children, processRecord); + + var matchesCount = matches.length; + if (matchesCount) { + this._searchResults = matches; + WebInspector.searchController.updateSearchMatchesCount(matchesCount, this); + + var selectedIndex = matches.indexOf(this._selectedSearchResult); + if (selectedIndex === -1) + selectedIndex = 0; + this._selectSearchResult(selectedIndex); + } else { + WebInspector.searchController.updateSearchMatchesCount(0, this); + delete this._selectedSearchResult; + } + }, + + searchCanceled: function() + { + this._clearHighlight(); + delete this._searchResults; + delete this._selectedSearchResult; + delete this._searchRegExp; + }, + + /** + * @return {boolean} + */ + canFilter: function() + { + return true; + }, + + performFilter: function(searchQuery) + { + this._presentationModel.removeFilter(this._searchFilter); + delete this._searchFilter; + this.searchCanceled(); + if (searchQuery) { + this._searchFilter = new WebInspector.TimelineSearchFilter(createPlainTextSearchRegex(searchQuery, "i")); + this._presentationModel.addFilter(this._searchFilter); + } + this._invalidateAndScheduleRefresh(true); + }, + + performSearch: function(searchQuery) + { + this._searchRegExp = createPlainTextSearchRegex(searchQuery, "i"); + delete this._searchResults; + this._updateSearchHighlight(true); } } @@ -1151,6 +1302,13 @@ WebInspector.TimelineRecordListRow.prototype = { } }, + highlight: function(regExp, domChanges) + { + var matchInfo = this.element.textContent.match(regExp); + if (matchInfo) + WebInspector.highlightSearchResult(this.element, matchInfo.index, matchInfo[0].length, domChanges); + }, + dispose: function() { this.element.parentElement.removeChild(this.element); @@ -1158,6 +1316,15 @@ WebInspector.TimelineRecordListRow.prototype = { } /** + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @param {!RegExp} regExp + */ +WebInspector.TimelineRecordListRow.testContentMatching = function(record, regExp) +{ + return regExp.test(record.title + " (" + record.details() + ")"); +} + +/** * @constructor */ WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh) @@ -1271,7 +1438,8 @@ WebInspector.TimelineCategoryFilter = function() WebInspector.TimelineCategoryFilter.prototype = { /** - * @param {WebInspector.TimelinePresentationModel.Record} record + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @return {boolean} */ accept: function(record) { @@ -1291,10 +1459,33 @@ WebInspector.TimelineIsLongFilter = function(panel) WebInspector.TimelineIsLongFilter.prototype = { /** - * @param {WebInspector.TimelinePresentationModel.Record} record + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @return {boolean} */ accept: function(record) { return this._panel._showShortEvents || record.isLong(); } } + +/** + * @param {!RegExp} regExp + * @constructor + * @implements {WebInspector.TimelinePresentationModel.Filter} + */ +WebInspector.TimelineSearchFilter = function(regExp) +{ + this._regExp = regExp; +} + +WebInspector.TimelineSearchFilter.prototype = { + + /** + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @return {boolean} + */ + accept: function(record) + { + return WebInspector.TimelineRecordListRow.testContentMatching(record, this._regExp); + } +} diff --git a/Source/WebCore/inspector/front-end/TimelinePresentationModel.js b/Source/WebCore/inspector/front-end/TimelinePresentationModel.js index d00c7cb5e..8065f5fa0 100644 --- a/Source/WebCore/inspector/front-end/TimelinePresentationModel.js +++ b/Source/WebCore/inspector/front-end/TimelinePresentationModel.js @@ -226,13 +226,23 @@ WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel WebInspector.TimelinePresentationModel.prototype = { /** - * @param {WebInspector.TimelinePresentationModel.Filter} filter + * @param {!WebInspector.TimelinePresentationModel.Filter} filter */ addFilter: function(filter) { this._filters.push(filter); }, + /** + * @param {!WebInspector.TimelinePresentationModel.Filter} filter + */ + removeFilter: function(filter) + { + var index = this._filters.indexOf(filter); + if (index !== -1) + this._filters.splice(index, 1); + }, + rootRecord: function() { return this._rootRecord; @@ -1112,7 +1122,8 @@ WebInspector.TimelinePresentationModel.Filter = function() WebInspector.TimelinePresentationModel.Filter.prototype = { /** - * @param {WebInspector.TimelinePresentationModel.Record} record + * @param {!WebInspector.TimelinePresentationModel.Record} record + * @return {boolean} */ accept: function(record) { return false; } } diff --git a/Source/WebCore/inspector/front-end/WebGLProfileView.js b/Source/WebCore/inspector/front-end/WebGLProfileView.js index a504f63ee..6028536c8 100644 --- a/Source/WebCore/inspector/front-end/WebGLProfileView.js +++ b/Source/WebCore/inspector/front-end/WebGLProfileView.js @@ -99,7 +99,7 @@ WebInspector.WebGLProfileView.prototype = { { function didReceiveTraceLog(error, traceLog) { - this._traceLogElement.innerHTML = ""; + this._traceLogElement.textContent = ""; if (!traceLog) return; var calls = traceLog.calls; diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc index 75b891427..2e1e2a284 100644 --- a/Source/WebCore/inspector/front-end/WebKit.qrc +++ b/Source/WebCore/inspector/front-end/WebKit.qrc @@ -31,6 +31,7 @@ <file>CPUProfileView.js</file> <file>CSSCompletions.js</file> <file>CSSKeywordCompletions.js</file> + <file>CSSNamedFlowCollectionsView.js</file> <file>CSSSelectorProfileView.js</file> <file>CSSStyleModel.js</file> <file>cm/codemirror.css</file> @@ -215,6 +216,7 @@ <file>UglifyJS/parse-js.js</file> <file>auditsPanel.css</file> <file>breadcrumbList.css</file> + <file>cssNamedFlows.css</file> <file>dataGrid.css</file> <file>cmdevtools.css</file> <file>dialog.css</file> @@ -288,6 +290,7 @@ <file>Images/indexedDBIndex.png</file> <file>Images/localStorage.png</file> <file>Images/navigatorShowHideButton.png</file> + <file>Images/namedFlowOverflow.png</file> <file>Images/paneAddButtons.png</file> <file>Images/paneBottomGrow.png</file> <file>Images/paneBottomGrowActive.png</file> diff --git a/Source/WebCore/inspector/front-end/auditsPanel.css b/Source/WebCore/inspector/front-end/auditsPanel.css index 4f6f17e8a..a8cc1b072 100644 --- a/Source/WebCore/inspector/front-end/auditsPanel.css +++ b/Source/WebCore/inspector/front-end/auditsPanel.css @@ -116,12 +116,6 @@ margin-left: 0; } -.audit-launcher-view .resource-progress > img { - content: url(Images/spinner.gif); - vertical-align: text-top; - margin: 0 4px 0 8px; -} - .audit-result-view { overflow: auto; position: absolute; @@ -233,3 +227,11 @@ margin-left: -28px; margin-top: -1px; } + +.audit-launcher-view .progress-bar-container { + display: inline-block; +} + +.audit-launcher-view .progress-bar-container .progress-bar-stop-button { + display: none; +} diff --git a/Source/WebCore/inspector/front-end/cssNamedFlows.css b/Source/WebCore/inspector/front-end/cssNamedFlows.css new file mode 100644 index 000000000..523a516a3 --- /dev/null +++ b/Source/WebCore/inspector/front-end/cssNamedFlows.css @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 HOLDER 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. + */ + +.css-named-flow-collections-view .split-view-sidebar-left { + border-right: 1px solid rgb(163, 163, 163); + overflow-x: hidden; +} + +.css-named-flow-collections-view .tabbed-pane-header { + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(236, 236, 236)), to(rgb(217, 217, 217))); +} + +.css-named-flow-collections-view .info { + font-style: italic; + font-size: 10px; + margin-top: -5px; + position: absolute; + top: 50%; + text-align: center; + width: 100%; +} + +.css-named-flow-collections-view .split-view-sidebar-left .sidebar-content { + bottom: 0px; + left: 0px; + padding: 0px; + position: absolute; + right: 0px; + top: 23px; +} + +.css-named-flow-collections-view .split-view-sidebar-left .selection { + margin-left: -12px; + z-index: 0; +} + +.css-named-flow-collections-view .split-view-contents .title { + position: relative; +} + +.css-named-flow-collections-view .split-view-sidebar-left .named-flow-overflow::before { + content: url(Images/namedFlowOverflow.png); + cursor: default; + float: left; + height: 10px; + margin: 2px 3px 0px -13px; + opacity: 0.75; + position: relative; + vertical-align: middle; + z-index: 1; +} diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css index fd07c43b9..710171500 100644 --- a/Source/WebCore/inspector/front-end/inspector.css +++ b/Source/WebCore/inspector/front-end/inspector.css @@ -572,6 +572,7 @@ body.drawer-visible #floating-status-bar-container { content: url(Images/statusbarResizerVertical.png); margin-top: 7px; pointer-events: none; + height: 8px; } #panel-status-bar { diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js index ffc1f7b35..ab67c474c 100644 --- a/Source/WebCore/inspector/front-end/inspector.js +++ b/Source/WebCore/inspector/front-end/inspector.js @@ -406,7 +406,7 @@ WebInspector.Events = { WebInspector.loaded = function() { - InspectorBackend.loadFromJSONIfNeeded(); + InspectorBackend.loadFromJSONIfNeeded("../Inspector.json"); if (WebInspector.WorkerManager.isDedicatedWorkerFrontend()) { // Do not create socket for the worker front-end. diff --git a/Source/WebCore/inspector/front-end/utilities.js b/Source/WebCore/inspector/front-end/utilities.js index 26bf47ef8..121f1eab8 100644 --- a/Source/WebCore/inspector/front-end/utilities.js +++ b/Source/WebCore/inspector/front-end/utilities.js @@ -631,7 +631,7 @@ function createSearchRegex(query, caseSensitive, isRegex) /** * @param {string} query * @param {string=} flags - * @return {RegExp} + * @return {!RegExp} */ function createPlainTextSearchRegex(query, flags) { |