Changeset 252792 in webkit


Ignore:
Timestamp:
Nov 22, 2019, 12:29:25 PM (6 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Canvas: adjust InspectorCanvasAgent::recordCanvasAction to actually check that the CanvasRenderingContext still exists
https://bugs.webkit.org/show_bug.cgi?id=204395
<rdar://problem/57347504>

Reviewed by Ryosuke Niwa.

The microtask we create to handle marking the end of a frame for a detached canvas doesn't
actually check that the CanvasRenderingContext still exists, such as if it gets GCd during
a recording.

Instead of creating a microtask per-canvas, create a microtask per-InspectorCanvasAgent
and save a list of canvasId that are actively recording, which can then be iterated to
handle marking the end of a frame for each once the microtask fires. If the canvasId can't
be re-found, then the related CanvasRenderingContext must have been removed.

  • inspector/agents/InspectorCanvasAgent.cpp:

(WebCore::InspectorCanvasAgent::recordCanvasAction):
(WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
(WebCore::InspectorCanvasAgent::reset):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252787 r252792  
     12019-11-22  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Canvas: adjust `InspectorCanvasAgent::recordCanvasAction` to actually check that the `CanvasRenderingContext` still exists
     4        https://bugs.webkit.org/show_bug.cgi?id=204395
     5        <rdar://problem/57347504>
     6
     7        Reviewed by Ryosuke Niwa.
     8
     9        The microtask we create to handle marking the end of a frame for a detached canvas doesn't
     10        actually check that the `CanvasRenderingContext` still exists, such as if it gets GCd during
     11        a recording.
     12
     13        Instead of creating a microtask per-canvas, create a microtask per-`InspectorCanvasAgent`
     14        and save a list of `canvasId` that are actively recording, which can then be iterated to
     15        handle marking the end of a frame for each once the microtask fires. If the `canvasId` can't
     16        be re-found, then the related `CanvasRenderingContext` must have been removed.
     17
     18        * inspector/agents/InspectorCanvasAgent.cpp:
     19        (WebCore::InspectorCanvasAgent::recordCanvasAction):
     20        (WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
     21        (WebCore::InspectorCanvasAgent::reset):
     22
    1232019-11-22  Sihui Liu  <sihui_liu@apple.com>
    224
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

    r252723 r252792  
    2727#include "InspectorCanvasAgent.h"
    2828
    29 #include "ActiveDOMCallbackMicrotask.h"
    3029#include "CanvasRenderingContext.h"
    3130#include "CanvasRenderingContext2D.h"
     
    4140#include "InstrumentingAgents.h"
    4241#include "JSExecState.h"
    43 #include "Microtasks.h"
    4442#include "ScriptState.h"
    4543#include "StringAdaptors.h"
     
    451449        return;
    452450
    453     // Only enqueue a microtask for the first action of each frame. Any subsequent actions will be
    454     // covered by the initial microtask until the next frame.
    455     if (!inspectorCanvas->currentFrameHasData()) {
     451    // Only enqueue one microtask for all actively recording canvases.
     452    if (m_recordingCanvasIdentifiers.isEmpty()) {
    456453        if (auto* scriptExecutionContext = inspectorCanvas->scriptExecutionContext()) {
    457             auto& eventLoop = scriptExecutionContext->eventLoop();
    458             auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
    459                 if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) {
    460                     if (canvasElement->isDescendantOf(canvasElement->document()))
    461                         return;
     454            scriptExecutionContext->eventLoop().queueMicrotask([weakThis = makeWeakPtr(*this)] {
     455                if (!weakThis)
     456                    return;
     457
     458                auto& canvasAgent = *weakThis;
     459
     460                for (auto& identifier : canvasAgent.m_recordingCanvasIdentifiers) {
     461                    auto inspectorCanvas = canvasAgent.m_identifierToInspectorCanvas.get(identifier);
     462                    if (!inspectorCanvas)
     463                        continue;
     464
     465                    auto* canvasRenderingContext = inspectorCanvas->canvasContext();
     466                    ASSERT(canvasRenderingContext);
     467                    // FIXME: <https://webkit.org/b/201651> Web Inspector: Canvas: support canvas recordings for WebGPUDevice
     468
     469                    if (canvasRenderingContext->callTracingActive())
     470                        canvasAgent.didFinishRecordingCanvasFrame(*canvasRenderingContext);
    462471                }
    463472
    464                 if (canvasRenderingContext.callTracingActive())
    465                     didFinishRecordingCanvasFrame(canvasRenderingContext);
     473                canvasAgent.m_recordingCanvasIdentifiers.clear();
    466474            });
    467             eventLoop.queueMicrotaskCallback(WTFMove(microtask));
    468475        }
    469476    }
     477
     478    m_recordingCanvasIdentifiers.add(inspectorCanvas->identifier());
    470479
    471480    inspectorCanvas->recordAction(name, WTFMove(parameters));
     
    517526            m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), nullptr);
    518527            inspectorCanvas->resetRecordingData();
     528            ASSERT(!m_recordingCanvasIdentifiers.contains(inspectorCanvas->identifier()));
    519529        }
    520530        return;
     
    532542
    533543    m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), inspectorCanvas->releaseObjectForRecording());
     544
     545    m_recordingCanvasIdentifiers.remove(inspectorCanvas->identifier());
    534546}
    535547
     
    743755    if (m_programDestroyedTimer.isActive())
    744756        m_programDestroyedTimer.stop();
     757
     758    m_recordingCanvasIdentifiers.clear();
    745759}
    746760
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.h

    r251425 r252792  
    3535#include <initializer_list>
    3636#include <wtf/Forward.h>
     37#include <wtf/WeakPtr.h>
    3738
    3839namespace Inspector {
     
    5758typedef String ErrorString;
    5859
    59 class InspectorCanvasAgent final : public InspectorAgentBase, public Inspector::CanvasBackendDispatcherHandler, public CanvasObserver {
     60class InspectorCanvasAgent final : public InspectorAgentBase, public Inspector::CanvasBackendDispatcherHandler, public CanvasObserver, public CanMakeWeakPtr<InspectorCanvasAgent> {
    6061    WTF_MAKE_NONCOPYABLE(InspectorCanvasAgent);
    6162    WTF_MAKE_FAST_ALLOCATED;
     
    158159    Timer m_programDestroyedTimer;
    159160
     161    HashSet<String> m_recordingCanvasIdentifiers;
     162
    160163    Optional<size_t> m_recordingAutoCaptureFrameCount;
    161164};
Note: See TracChangeset for help on using the changeset viewer.