InspectorCanvasAgent.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright (C) 2012 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  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
  13. * distribution.
  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.
  17. *
  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.
  29. */
  30. #include "config.h"
  31. #if ENABLE(INSPECTOR)
  32. #include "InspectorCanvasAgent.h"
  33. #include "BindingVisitors.h"
  34. #include "DOMWindow.h"
  35. #include "Frame.h"
  36. #include "HTMLCanvasElement.h"
  37. #include "HTMLNames.h"
  38. #include "InjectedScript.h"
  39. #include "InjectedScriptCanvasModule.h"
  40. #include "InjectedScriptManager.h"
  41. #include "InspectorFrontend.h"
  42. #include "InspectorPageAgent.h"
  43. #include "InspectorState.h"
  44. #include "InstrumentingAgents.h"
  45. #include "Page.h"
  46. #include "ScriptObject.h"
  47. #include "ScriptProfiler.h"
  48. #include "ScriptState.h"
  49. using WebCore::TypeBuilder::Array;
  50. using WebCore::TypeBuilder::Canvas::ResourceId;
  51. using WebCore::TypeBuilder::Canvas::ResourceInfo;
  52. using WebCore::TypeBuilder::Canvas::ResourceState;
  53. using WebCore::TypeBuilder::Canvas::TraceLog;
  54. using WebCore::TypeBuilder::Canvas::TraceLogId;
  55. using WebCore::TypeBuilder::Network::FrameId;
  56. namespace WebCore {
  57. namespace CanvasAgentState {
  58. static const char canvasAgentEnabled[] = "canvasAgentEnabled";
  59. };
  60. InspectorCanvasAgent::InspectorCanvasAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager)
  61. : InspectorBaseAgent<InspectorCanvasAgent>("Canvas", instrumentingAgents, state)
  62. , m_pageAgent(pageAgent)
  63. , m_injectedScriptManager(injectedScriptManager)
  64. , m_frontend(0)
  65. , m_enabled(false)
  66. {
  67. }
  68. InspectorCanvasAgent::~InspectorCanvasAgent()
  69. {
  70. }
  71. void InspectorCanvasAgent::setFrontend(InspectorFrontend* frontend)
  72. {
  73. ASSERT(frontend);
  74. m_frontend = frontend->canvas();
  75. }
  76. void InspectorCanvasAgent::clearFrontend()
  77. {
  78. m_frontend = 0;
  79. disable(0);
  80. }
  81. void InspectorCanvasAgent::restore()
  82. {
  83. if (m_state->getBoolean(CanvasAgentState::canvasAgentEnabled)) {
  84. ErrorString error;
  85. enable(&error);
  86. }
  87. }
  88. void InspectorCanvasAgent::enable(ErrorString*)
  89. {
  90. if (m_enabled)
  91. return;
  92. m_enabled = true;
  93. m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
  94. m_instrumentingAgents->setInspectorCanvasAgent(this);
  95. findFramesWithUninstrumentedCanvases();
  96. }
  97. void InspectorCanvasAgent::disable(ErrorString*)
  98. {
  99. m_enabled = false;
  100. m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
  101. m_instrumentingAgents->setInspectorCanvasAgent(0);
  102. m_framesWithUninstrumentedCanvases.clear();
  103. }
  104. void InspectorCanvasAgent::dropTraceLog(ErrorString* errorString, const TraceLogId& traceLogId)
  105. {
  106. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
  107. if (!module.hasNoValue())
  108. module.dropTraceLog(errorString, traceLogId);
  109. }
  110. void InspectorCanvasAgent::hasUninstrumentedCanvases(ErrorString* errorString, bool* result)
  111. {
  112. if (!checkIsEnabled(errorString))
  113. return;
  114. for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
  115. if (it->value) {
  116. *result = true;
  117. return;
  118. }
  119. }
  120. *result = false;
  121. }
  122. void InspectorCanvasAgent::captureFrame(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
  123. {
  124. Frame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
  125. if (!frame)
  126. return;
  127. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, mainWorldScriptState(frame));
  128. if (!module.hasNoValue())
  129. module.captureFrame(errorString, traceLogId);
  130. }
  131. void InspectorCanvasAgent::startCapturing(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
  132. {
  133. Frame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
  134. if (!frame)
  135. return;
  136. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, mainWorldScriptState(frame));
  137. if (!module.hasNoValue())
  138. module.startCapturing(errorString, traceLogId);
  139. }
  140. void InspectorCanvasAgent::stopCapturing(ErrorString* errorString, const TraceLogId& traceLogId)
  141. {
  142. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
  143. if (!module.hasNoValue())
  144. module.stopCapturing(errorString, traceLogId);
  145. }
  146. void InspectorCanvasAgent::getTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, const int* startOffset, const int* maxLength, RefPtr<TraceLog>& traceLog)
  147. {
  148. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
  149. if (!module.hasNoValue())
  150. module.traceLog(errorString, traceLogId, startOffset, maxLength, &traceLog);
  151. }
  152. void InspectorCanvasAgent::replayTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, int stepNo, RefPtr<ResourceState>& result)
  153. {
  154. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
  155. if (!module.hasNoValue())
  156. module.replayTraceLog(errorString, traceLogId, stepNo, &result);
  157. }
  158. void InspectorCanvasAgent::getResourceInfo(ErrorString* errorString, const ResourceId& resourceId, RefPtr<ResourceInfo>& result)
  159. {
  160. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, resourceId);
  161. if (!module.hasNoValue())
  162. module.resourceInfo(errorString, resourceId, &result);
  163. }
  164. void InspectorCanvasAgent::getResourceState(ErrorString* errorString, const TraceLogId& traceLogId, const ResourceId& resourceId, RefPtr<ResourceState>& result)
  165. {
  166. InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
  167. if (!module.hasNoValue())
  168. module.resourceState(errorString, traceLogId, resourceId, &result);
  169. }
  170. ScriptObject InspectorCanvasAgent::wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject& context)
  171. {
  172. ErrorString error;
  173. InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, context);
  174. if (module.hasNoValue())
  175. return ScriptObject();
  176. return notifyRenderingContextWasWrapped(module.wrapCanvas2DContext(context));
  177. }
  178. #if ENABLE(WEBGL)
  179. ScriptObject InspectorCanvasAgent::wrapWebGLRenderingContextForInstrumentation(const ScriptObject& glContext)
  180. {
  181. ErrorString error;
  182. InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, glContext);
  183. if (module.hasNoValue())
  184. return ScriptObject();
  185. return notifyRenderingContextWasWrapped(module.wrapWebGLContext(glContext));
  186. }
  187. #endif
  188. ScriptObject InspectorCanvasAgent::notifyRenderingContextWasWrapped(const ScriptObject& wrappedContext)
  189. {
  190. ASSERT(m_frontend);
  191. ScriptState* scriptState = wrappedContext.scriptState();
  192. DOMWindow* domWindow = scriptState ? domWindowFromScriptState(scriptState) : 0;
  193. Frame* frame = domWindow ? domWindow->frame() : 0;
  194. if (frame && !m_framesWithUninstrumentedCanvases.contains(frame))
  195. m_framesWithUninstrumentedCanvases.set(frame, false);
  196. String frameId = m_pageAgent->frameId(frame);
  197. if (!frameId.isEmpty())
  198. m_frontend->contextCreated(frameId);
  199. return wrappedContext;
  200. }
  201. InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, ScriptState* scriptState)
  202. {
  203. if (!checkIsEnabled(errorString))
  204. return InjectedScriptCanvasModule();
  205. InjectedScriptCanvasModule module = InjectedScriptCanvasModule::moduleForState(m_injectedScriptManager, scriptState);
  206. if (module.hasNoValue()) {
  207. ASSERT_NOT_REACHED();
  208. *errorString = "Internal error: no Canvas module";
  209. }
  210. return module;
  211. }
  212. InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const ScriptObject& scriptObject)
  213. {
  214. if (!checkIsEnabled(errorString))
  215. return InjectedScriptCanvasModule();
  216. if (scriptObject.hasNoValue()) {
  217. ASSERT_NOT_REACHED();
  218. *errorString = "Internal error: original ScriptObject has no value";
  219. return InjectedScriptCanvasModule();
  220. }
  221. return injectedScriptCanvasModule(errorString, scriptObject.scriptState());
  222. }
  223. InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const String& objectId)
  224. {
  225. if (!checkIsEnabled(errorString))
  226. return InjectedScriptCanvasModule();
  227. InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
  228. if (injectedScript.hasNoValue()) {
  229. *errorString = "Inspected frame has gone";
  230. return InjectedScriptCanvasModule();
  231. }
  232. return injectedScriptCanvasModule(errorString, injectedScript.scriptState());
  233. }
  234. void InspectorCanvasAgent::findFramesWithUninstrumentedCanvases()
  235. {
  236. class NodeVisitor : public WrappedNodeVisitor {
  237. public:
  238. NodeVisitor(Page* page, FramesWithUninstrumentedCanvases& result)
  239. : m_page(page)
  240. , m_framesWithUninstrumentedCanvases(result)
  241. {
  242. }
  243. virtual void visitNode(Node* node) OVERRIDE
  244. {
  245. if (!node->hasTagName(HTMLNames::canvasTag) || !node->document() || !node->document()->frame())
  246. return;
  247. Frame* frame = node->document()->frame();
  248. if (frame->page() != m_page)
  249. return;
  250. HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(node);
  251. if (canvas->renderingContext())
  252. m_framesWithUninstrumentedCanvases.set(frame, true);
  253. }
  254. private:
  255. Page* m_page;
  256. FramesWithUninstrumentedCanvases& m_framesWithUninstrumentedCanvases;
  257. } nodeVisitor(m_pageAgent->page(), m_framesWithUninstrumentedCanvases);
  258. m_framesWithUninstrumentedCanvases.clear();
  259. ScriptProfiler::visitNodeWrappers(&nodeVisitor);
  260. for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
  261. String frameId = m_pageAgent->frameId(it->key);
  262. if (!frameId.isEmpty())
  263. m_frontend->contextCreated(frameId);
  264. }
  265. }
  266. bool InspectorCanvasAgent::checkIsEnabled(ErrorString* errorString) const
  267. {
  268. if (m_enabled)
  269. return true;
  270. *errorString = "Canvas agent is not enabled";
  271. return false;
  272. }
  273. void InspectorCanvasAgent::frameNavigated(Frame* frame)
  274. {
  275. if (!m_enabled)
  276. return;
  277. if (frame == m_pageAgent->mainFrame()) {
  278. for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it)
  279. m_framesWithUninstrumentedCanvases.set(it->key, false);
  280. m_frontend->traceLogsRemoved(0, 0);
  281. } else {
  282. while (frame) {
  283. if (m_framesWithUninstrumentedCanvases.contains(frame))
  284. m_framesWithUninstrumentedCanvases.set(frame, false);
  285. if (m_pageAgent->hasIdForFrame(frame)) {
  286. String frameId = m_pageAgent->frameId(frame);
  287. m_frontend->traceLogsRemoved(&frameId, 0);
  288. }
  289. frame = frame->tree()->traverseNext();
  290. }
  291. }
  292. }
  293. void InspectorCanvasAgent::frameDetached(Frame* frame)
  294. {
  295. if (m_enabled)
  296. m_framesWithUninstrumentedCanvases.remove(frame);
  297. }
  298. void InspectorCanvasAgent::didBeginFrame()
  299. {
  300. if (!m_enabled)
  301. return;
  302. ErrorString error;
  303. for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
  304. InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, mainWorldScriptState(it->key));
  305. if (!module.hasNoValue())
  306. module.markFrameEnd();
  307. }
  308. }
  309. } // namespace WebCore
  310. #endif // ENABLE(INSPECTOR)