2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "core/inspector/InspectorCanvasAgent.h"
34 #include "bindings/v8/ScriptObject.h"
35 #include "bindings/v8/ScriptProfiler.h"
36 #include "core/html/HTMLCanvasElement.h"
37 #include "core/inspector/BindingVisitors.h"
38 #include "core/inspector/InjectedScript.h"
39 #include "core/inspector/InjectedScriptCanvasModule.h"
40 #include "core/inspector/InjectedScriptManager.h"
41 #include "core/inspector/InspectorPageAgent.h"
42 #include "core/inspector/InspectorState.h"
43 #include "core/inspector/InstrumentingAgents.h"
44 #include "core/loader/DocumentLoader.h"
45 #include "core/frame/DOMWindow.h"
46 #include "core/frame/LocalFrame.h"
48 using WebCore::TypeBuilder::Array;
49 using WebCore::TypeBuilder::Canvas::ResourceId;
50 using WebCore::TypeBuilder::Canvas::ResourceState;
51 using WebCore::TypeBuilder::Canvas::TraceLog;
52 using WebCore::TypeBuilder::Canvas::TraceLogId;
53 using WebCore::TypeBuilder::Page::FrameId;
54 using WebCore::TypeBuilder::Runtime::RemoteObject;
58 namespace CanvasAgentState {
59 static const char canvasAgentEnabled[] = "canvasAgentEnabled";
62 InspectorCanvasAgent::InspectorCanvasAgent(InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager)
63 : InspectorBaseAgent<InspectorCanvasAgent>("Canvas")
64 , m_pageAgent(pageAgent)
65 , m_injectedScriptManager(injectedScriptManager)
71 InspectorCanvasAgent::~InspectorCanvasAgent()
75 void InspectorCanvasAgent::setFrontend(InspectorFrontend* frontend)
78 m_frontend = frontend->canvas();
81 void InspectorCanvasAgent::clearFrontend()
87 void InspectorCanvasAgent::restore()
89 if (m_state->getBoolean(CanvasAgentState::canvasAgentEnabled)) {
95 void InspectorCanvasAgent::enable(ErrorString*)
100 m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
101 m_instrumentingAgents->setInspectorCanvasAgent(this);
102 findFramesWithUninstrumentedCanvases();
105 void InspectorCanvasAgent::disable(ErrorString*)
108 m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
109 m_instrumentingAgents->setInspectorCanvasAgent(0);
110 m_framesWithUninstrumentedCanvases.clear();
112 m_frontend->traceLogsRemoved(0, 0);
115 void InspectorCanvasAgent::dropTraceLog(ErrorString* errorString, const TraceLogId& traceLogId)
117 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
118 if (!module.isEmpty())
119 module.dropTraceLog(errorString, traceLogId);
122 void InspectorCanvasAgent::hasUninstrumentedCanvases(ErrorString* errorString, bool* result)
124 if (!checkIsEnabled(errorString))
126 for (FramesWithUninstrumentedCanvases::const_iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
135 void InspectorCanvasAgent::captureFrame(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
137 LocalFrame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
140 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, ScriptState::forMainWorld(frame));
141 if (!module.isEmpty())
142 module.captureFrame(errorString, traceLogId);
145 void InspectorCanvasAgent::startCapturing(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
147 LocalFrame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
150 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, ScriptState::forMainWorld(frame));
151 if (!module.isEmpty())
152 module.startCapturing(errorString, traceLogId);
155 void InspectorCanvasAgent::stopCapturing(ErrorString* errorString, const TraceLogId& traceLogId)
157 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
158 if (!module.isEmpty())
159 module.stopCapturing(errorString, traceLogId);
162 void InspectorCanvasAgent::getTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, const int* startOffset, const int* maxLength, RefPtr<TraceLog>& traceLog)
164 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
165 if (!module.isEmpty())
166 module.traceLog(errorString, traceLogId, startOffset, maxLength, &traceLog);
169 void InspectorCanvasAgent::replayTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, int stepNo, RefPtr<ResourceState>& result, double* replayTime)
171 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
172 if (!module.isEmpty())
173 module.replayTraceLog(errorString, traceLogId, stepNo, &result, replayTime);
176 void InspectorCanvasAgent::getResourceState(ErrorString* errorString, const TraceLogId& traceLogId, const ResourceId& resourceId, RefPtr<ResourceState>& result)
178 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
179 if (!module.isEmpty())
180 module.resourceState(errorString, traceLogId, resourceId, &result);
183 void InspectorCanvasAgent::evaluateTraceLogCallArgument(ErrorString* errorString, const TraceLogId& traceLogId, int callIndex, int argumentIndex, const String* objectGroup, RefPtr<RemoteObject>& result, RefPtr<ResourceState>& resourceState)
185 InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
186 if (!module.isEmpty())
187 module.evaluateTraceLogCallArgument(errorString, traceLogId, callIndex, argumentIndex, objectGroup ? *objectGroup : String(), &result, &resourceState);
190 ScriptObject InspectorCanvasAgent::wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject& context)
193 InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, context);
194 if (module.isEmpty())
195 return ScriptObject();
196 return notifyRenderingContextWasWrapped(module.wrapCanvas2DContext(context));
199 ScriptObject InspectorCanvasAgent::wrapWebGLRenderingContextForInstrumentation(const ScriptObject& glContext)
202 InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, glContext);
203 if (module.isEmpty())
204 return ScriptObject();
205 return notifyRenderingContextWasWrapped(module.wrapWebGLContext(glContext));
208 ScriptObject InspectorCanvasAgent::notifyRenderingContextWasWrapped(const ScriptObject& wrappedContext)
211 ScriptState* scriptState = wrappedContext.scriptState();
212 DOMWindow* domWindow = 0;
214 domWindow = scriptState->domWindow();
215 LocalFrame* frame = domWindow ? domWindow->frame() : 0;
216 if (frame && !m_framesWithUninstrumentedCanvases.contains(frame))
217 m_framesWithUninstrumentedCanvases.set(frame, false);
218 String frameId = m_pageAgent->frameId(frame);
219 if (!frameId.isEmpty())
220 m_frontend->contextCreated(frameId);
221 return wrappedContext;
224 InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, ScriptState* scriptState)
226 if (!checkIsEnabled(errorString))
227 return InjectedScriptCanvasModule();
228 InjectedScriptCanvasModule module = InjectedScriptCanvasModule::moduleForState(m_injectedScriptManager, scriptState);
229 if (module.isEmpty()) {
230 ASSERT_NOT_REACHED();
231 *errorString = "Internal error: no Canvas module";
236 InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const ScriptObject& scriptObject)
238 if (!checkIsEnabled(errorString))
239 return InjectedScriptCanvasModule();
240 if (scriptObject.isEmpty()) {
241 ASSERT_NOT_REACHED();
242 *errorString = "Internal error: original ScriptObject has no value";
243 return InjectedScriptCanvasModule();
245 return injectedScriptCanvasModule(errorString, scriptObject.scriptState());
248 InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const String& objectId)
250 if (!checkIsEnabled(errorString))
251 return InjectedScriptCanvasModule();
252 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
253 if (injectedScript.isEmpty()) {
254 *errorString = "Inspected frame has gone";
255 return InjectedScriptCanvasModule();
257 return injectedScriptCanvasModule(errorString, injectedScript.scriptState());
260 void InspectorCanvasAgent::findFramesWithUninstrumentedCanvases()
262 class NodeVisitor FINAL : public WrappedNodeVisitor {
264 NodeVisitor(Page* page, FramesWithUninstrumentedCanvases& result)
266 , m_framesWithUninstrumentedCanvases(result)
270 virtual void visitNode(Node* node) OVERRIDE
273 if (!isHTMLCanvasElement(*node) || !node->document().frame())
276 LocalFrame* frame = node->document().frame();
277 if (frame->page() != m_page)
280 if (toHTMLCanvasElement(node)->renderingContext())
281 m_framesWithUninstrumentedCanvases.set(frame, true);
286 FramesWithUninstrumentedCanvases& m_framesWithUninstrumentedCanvases;
287 } nodeVisitor(m_pageAgent->page(), m_framesWithUninstrumentedCanvases);
289 m_framesWithUninstrumentedCanvases.clear();
290 ScriptProfiler::visitNodeWrappers(&nodeVisitor);
293 for (FramesWithUninstrumentedCanvases::const_iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
294 String frameId = m_pageAgent->frameId(it->key);
295 if (!frameId.isEmpty())
296 m_frontend->contextCreated(frameId);
301 bool InspectorCanvasAgent::checkIsEnabled(ErrorString* errorString) const
305 *errorString = "Canvas agent is not enabled";
309 void InspectorCanvasAgent::didCommitLoad(LocalFrame*, DocumentLoader* loader)
313 LocalFrame* frame = loader->frame();
314 if (frame == m_pageAgent->mainFrame()) {
315 for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it)
317 m_frontend->traceLogsRemoved(0, 0);
320 if (m_framesWithUninstrumentedCanvases.contains(frame))
321 m_framesWithUninstrumentedCanvases.set(frame, false);
322 if (m_pageAgent->hasIdForFrame(frame)) {
323 String frameId = m_pageAgent->frameId(frame);
324 m_frontend->traceLogsRemoved(&frameId, 0);
326 frame = frame->tree().traverseNext();
331 void InspectorCanvasAgent::frameDetachedFromParent(LocalFrame* frame)
334 m_framesWithUninstrumentedCanvases.remove(frame);
337 void InspectorCanvasAgent::didBeginFrame()
342 for (FramesWithUninstrumentedCanvases::const_iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
343 InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, ScriptState::forMainWorld(it->key));
344 if (!module.isEmpty())
345 module.markFrameEnd();
349 } // namespace WebCore