Changeset 237670 in webkit


Ignore:
Timestamp:
Oct 31, 2018 9:13:41 PM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Canvas: create a setting for auto-recording newly created contexts
https://bugs.webkit.org/show_bug.cgi?id=190856

Reviewed by Brian Burg.

Source/JavaScriptCore:

  • inspector/protocol/Canvas.json:

Add setRecordingAutoCaptureFrameCount command for setting the number of frames to record
immediately after a context is created.

  • inspector/protocol/Recording.json:

Add creation value for Initiator enum.

Source/WebCore:

Test: inspector/canvas/setRecordingAutoCaptureFrameCount.html

  • inspector/agents/InspectorCanvasAgent.h:

(WebCore::InspectorCanvasAgent::RecordingOptions): Added.

  • inspector/agents/InspectorCanvasAgent.cpp:

(WebCore::InspectorCanvasAgent::enable):
(WebCore::InspectorCanvasAgent::disable):
(WebCore::InspectorCanvasAgent::setRecordingAutoCaptureFrameCount): Added.
(WebCore::InspectorCanvasAgent::startRecording):
(WebCore::InspectorCanvasAgent::didCreateCanvasRenderingContext):
(WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
(WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):
(WebCore::InspectorCanvasAgent::startRecording): Added.
Unify the different functions that are able to start a recording to use a single path.

  • inspector/InspectorCanvas.h:
  • inspector/InspectorCanvas.cpp:

(WebCore::InspectorCanvas::resetRecordingData):
(WebCore::InspectorCanvas::recordAction):
(WebCore::InspectorCanvas::setFrameCount): Added.
(WebCore::InspectorCanvas::overFrameCount const): Added.

Source/WebInspectorUI:

  • UserInterface/Controllers/CanvasManager.js:

(WI.CanvasManager.supportsRecordingAutoCapture): Added.
(WI.CanvasManager.prototype.setRecordingAutoCaptureFrameCount): Added.

  • UserInterface/Models/Canvas.js:

(WI.Canvas.prototype.startRecording):
(WI.Canvas.prototype.recordingStarted):
(WI.Canvas.prototype.recordingFinished):

  • UserInterface/Models/Recording.js:
  • UserInterface/Views/CanvasOverviewContentView.js:

(WI.CanvasOverviewContentView):
(WI.CanvasOverviewContentView.prototype.get navigationItems):
(WI.CanvasOverviewContentView.prototype.initialLayout): Added.
(WI.CanvasOverviewContentView.prototype.attached):
(WI.CanvasOverviewContentView.prototype.detached):
(WI.CanvasOverviewContentView.prototype._setRecordingAutoCaptureFrameCount): Added.
(WI.CanvasOverviewContentView.prototype._updateRecordingAutoCaptureInputElementSize): Added.
(WI.CanvasOverviewContentView.prototype._handleRecordingAutoCaptureInput): Added.
(WI.CanvasOverviewContentView.prototype._handleRecordingAutoCaptureCheckedDidChange): Added.
(WI.CanvasOverviewContentView.prototype._handleCanvasRecordingAutoCaptureEnabledChanged): Added.
(WI.CanvasOverviewContentView.prototype._handleCanvasRecordingAutoCaptureFrameCountChanged): Added.

  • UserInterface/Views/CanvasOverviewContentView.css:

(.navigation-bar > .item.canvas-recording-auto-capture > label): Added.
(.navigation-bar > .item.canvas-recording-auto-capture > label > input): Added.
(.navigation-bar > .item.canvas-recording-auto-capture > label > input::-webkit-inner-spin-button): Added.
(.popover-content > .tree-outline .item.recording > .icon): Deleted.
(.popover-content > .tree-outline .item.recording:hover): Deleted.
(.popover-content > .tree-outline .item.recording:hover > .icon): Deleted.
Drive-by: removed unused CSS rules.

  • UserInterface/Views/CanvasContentView.js:

(WI.CanvasContentView.prototype.initialLayout):
(WI.CanvasContentView.prototype._updateProgressView):
(WI.CanvasContentView.prototype._updateViewRelatedItems):

  • UserInterface/Views/CanvasTabContentView.js:

(WI.CanvasTabContentView.prototype._recordingImportedOrStopped):

  • UserInterface/Views/CheckboxNavigationItem.js:

(WI.CheckboxNavigationItem):
(WI.CheckboxNavigationItem.prototype._handleLabelClick): Added.

  • UserInterface/Base/Setting.js:
  • Localizations/en.lproj/localizedStrings.js:

LayoutTests:

  • inspector/canvas/resources/recording-utilities.js:

(TestPage.registerInitializer.window.startRecording):
(TestPage.registerInitializer.handleRecordingProgress):

  • inspector/canvas/recording-2d.html:
  • inspector/canvas/recording-bitmaprenderer.html:
  • inspector/canvas/recording-webgl-snapshots.html:
  • inspector/canvas/recording-webgl.html:
  • inspector/canvas/setRecordingAutoCaptureFrameCount-expected.txt: Added.
  • inspector/canvas/setRecordingAutoCaptureFrameCount.html: Added.
Location:
trunk
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r237665 r237670  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=190856
     5
     6        Reviewed by Brian Burg.
     7
     8        * inspector/canvas/resources/recording-utilities.js:
     9        (TestPage.registerInitializer.window.startRecording):
     10        (TestPage.registerInitializer.handleRecordingProgress):
     11        * inspector/canvas/recording-2d.html:
     12        * inspector/canvas/recording-bitmaprenderer.html:
     13        * inspector/canvas/recording-webgl-snapshots.html:
     14        * inspector/canvas/recording-webgl.html:
     15
     16        * inspector/canvas/setRecordingAutoCaptureFrameCount-expected.txt: Added.
     17        * inspector/canvas/setRecordingAutoCaptureFrameCount.html: Added.
     18
    1192018-10-31  Devin Rousso  <drousso@apple.com>
    220
  • trunk/LayoutTests/inspector/canvas/recording-2d.html

    r237198 r237670  
    437437        description: "Check that the recording is stopped after a single frame.",
    438438        test(resolve, reject) {
    439             startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {singleFrame: true});
     439            startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {frameCount: 1});
    440440        },
    441441    });
     
    445445        description: "Check that recording data is serialized correctly for multiple frames.",
    446446        test(resolve, reject) {
    447             startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {singleFrame: false});
     447            startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject);
    448448        },
    449449    });
     
    494494            });
    495495
    496             const singleFrame = true;
    497             CanvasAgent.startRecording(canvas.identifier, singleFrame)
     496            const frameCount = 1;
     497            CanvasAgent.startRecording(canvas.identifier, frameCount)
    498498            .catch(reject);
    499499        },
     
    539539            InspectorTest.evaluateInPage(`performSavePreActions()`)
    540540            .then(() => {
    541                 const singleFrame = true;
    542                 CanvasAgent.startRecording(canvas.identifier, singleFrame).catch(reject);
     541                const frameCount = 1;
     542                CanvasAgent.startRecording(canvas.identifier, frameCount).catch(reject);
    543543            }, reject);
    544544        },
  • trunk/LayoutTests/inspector/canvas/recording-bitmaprenderer.html

    r237010 r237670  
    8888        description: "Check that the recording is stopped after a single frame.",
    8989        test(resolve, reject) {
    90             startRecording(WI.Canvas.ContextType.BitmapRenderer, resolve, reject, {singleFrame: true});
     90            startRecording(WI.Canvas.ContextType.BitmapRenderer, resolve, reject, {frameCount: 1});
    9191        },
    9292    });
     
    9696        description: "Check that recording data is serialized correctly for multiple frames.",
    9797        test(resolve, reject) {
    98             startRecording(WI.Canvas.ContextType.BitmapRenderer, resolve, reject, {singleFrame: false});
     98            startRecording(WI.Canvas.ContextType.BitmapRenderer, resolve, reject);
    9999        },
    100100    });
  • trunk/LayoutTests/inspector/canvas/recording-webgl-snapshots.html

    r237010 r237670  
    101101        description: "Check that the snapshot taken after each visual action is different.",
    102102        test(resolve, reject) {
    103             startRecording(WI.Canvas.ContextType.WebGL, resolve, reject, {singleFrame: true});
     103            startRecording(WI.Canvas.ContextType.WebGL, resolve, reject, {frameCount: 1});
    104104        },
    105105    });
  • trunk/LayoutTests/inspector/canvas/recording-webgl.html

    r237010 r237670  
    514514        description: "Check that the recording is stopped after a single frame.",
    515515        test(resolve, reject) {
    516             startRecording(WI.Canvas.ContextType.WebGL, resolve, reject, {singleFrame: true});
     516            startRecording(WI.Canvas.ContextType.WebGL, resolve, reject, {frameCount: 1});
    517517        },
    518518    });
     
    522522        description: "Check that recording data is serialized correctly for multiple frames.",
    523523        test(resolve, reject) {
    524             startRecording(WI.Canvas.ContextType.WebGL, resolve, reject, {singleFrame: false});
     524            startRecording(WI.Canvas.ContextType.WebGL, resolve, reject);
    525525        },
    526526    });
  • trunk/LayoutTests/inspector/canvas/resources/recording-utilities.js

    r237198 r237670  
    8484    };
    8585
    86     window.startRecording = function(type, resolve, reject, {singleFrame, memoryLimit} = {}) {
     86    window.startRecording = function(type, resolve, reject, {frameCount, memoryLimit} = {}) {
    8787        let canvas = getCanvas(type);
    8888        if (!canvas) {
     
    111111
    112112        let bufferUsed = 0;
    113         let frameCount = 0;
     113        let recordingFrameCount = 0;
    114114        function handleRecordingProgress(event) {
    115             InspectorTest.assert(canvas.recordingFrameCount > frameCount, "Additional frames were captured for this progress event.");
    116             frameCount = canvas.recordingFrameCount;
     115            InspectorTest.assert(canvas.recordingFrameCount > recordingFrameCount, "Additional frames were captured for this progress event.");
     116            recordingFrameCount = canvas.recordingFrameCount;
    117117
    118118            InspectorTest.assert(canvas.recordingBufferUsed > bufferUsed, "Total memory usage increases with each progress event.");
     
    130130            InspectorTest.assert(recording.source.contextType === type, `Recording should be of a canvas with type "${type}".`);
    131131            InspectorTest.assert(recording.source.recordingCollection.has(recording), "Recording should be in the canvas' list of recordings.");
    132             InspectorTest.assert(recording.frames.length === frameCount, `Recording should have ${frameCount} frames.`)
     132            InspectorTest.assert(recording.frames.length === recordingFrameCount, `Recording should have ${recordingFrameCount} frames.`)
     133
     134            if (frameCount)
     135                InspectorTest.assert(recording.frames.length === frameCount, `Recording frame count should match the provided value ${frameCount}.`)
    133136
    134137            Promise.all(recording.actions.map((action) => action.swizzle(recording))).then(() => {
     
    149152        });
    150153
    151         CanvasAgent.startRecording(canvas.identifier, singleFrame, memoryLimit).catch(reject);
     154        CanvasAgent.startRecording(canvas.identifier, frameCount, memoryLimit).catch(reject);
    152155    };
    153156
  • trunk/Source/JavaScriptCore/ChangeLog

    r237669 r237670  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=190856
     5
     6        Reviewed by Brian Burg.
     7
     8        * inspector/protocol/Canvas.json:
     9        Add `setRecordingAutoCaptureFrameCount` command for setting the number of frames to record
     10        immediately after a context is created.
     11
     12        * inspector/protocol/Recording.json:
     13        Add `creation` value for `Initiator` enum.
     14
    1152018-10-31  Devin Rousso  <drousso@apple.com>
    216
  • trunk/Source/JavaScriptCore/inspector/protocol/Canvas.json

    r237010 r237670  
    106106        },
    107107        {
     108            "name": "setRecordingAutoCaptureFrameCount",
     109            "description": "Tells the backend to record `count` frames whenever a new context is created.",
     110            "parameters": [
     111                { "name": "count", "type": "integer", "description": "Number of frames to record (0 means don't record anything)." }
     112            ]
     113        },
     114        {
    108115            "name": "startRecording",
    109116            "description": "Record the next frame, or up to the given number of bytes of data, for the given canvas.",
    110117            "parameters": [
    111118                { "name": "canvasId", "$ref": "CanvasId" },
    112                 { "name": "singleFrame", "type": "boolean", "optional": true, "description": "Whether to record a single frame or until the memory limit is reached." },
    113                 { "name": "memoryLimit", "type": "integer", "optional": true, "description": "Memory limit of recorded data." }
     119                { "name": "frameCount", "type": "integer", "optional": true, "description": "Number of frames to record (unlimited when not specified)." },
     120                { "name": "memoryLimit", "type": "integer", "optional": true, "description": "Memory limit of recorded data (100MB when not specified)." }
    114121            ]
    115122        },
  • trunk/Source/JavaScriptCore/inspector/protocol/Recording.json

    r237198 r237670  
    1212            "id": "Initiator",
    1313            "type": "string",
    14             "enum": ["frontend", "console"]
     14            "enum": ["frontend", "console", "auto-capture"]
    1515        },
    1616        {
  • trunk/Source/WebCore/ChangeLog

    r237669 r237670  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=190856
     5
     6        Reviewed by Brian Burg.
     7
     8        Test: inspector/canvas/setRecordingAutoCaptureFrameCount.html
     9
     10        * inspector/agents/InspectorCanvasAgent.h:
     11        (WebCore::InspectorCanvasAgent::RecordingOptions): Added.
     12        * inspector/agents/InspectorCanvasAgent.cpp:
     13        (WebCore::InspectorCanvasAgent::enable):
     14        (WebCore::InspectorCanvasAgent::disable):
     15        (WebCore::InspectorCanvasAgent::setRecordingAutoCaptureFrameCount): Added.
     16        (WebCore::InspectorCanvasAgent::startRecording):
     17        (WebCore::InspectorCanvasAgent::didCreateCanvasRenderingContext):
     18        (WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame):
     19        (WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas):
     20        (WebCore::InspectorCanvasAgent::startRecording): Added.
     21        Unify the different functions that are able to start a recording to use a single path.
     22
     23        * inspector/InspectorCanvas.h:
     24        * inspector/InspectorCanvas.cpp:
     25        (WebCore::InspectorCanvas::resetRecordingData):
     26        (WebCore::InspectorCanvas::recordAction):
     27        (WebCore::InspectorCanvas::setFrameCount): Added.
     28        (WebCore::InspectorCanvas::overFrameCount const): Added.
     29
    1302018-10-31  Devin Rousso  <drousso@apple.com>
    231
  • trunk/Source/WebCore/inspector/InspectorCanvas.cpp

    r237198 r237670  
    106106    m_bufferLimit = 100 * 1024 * 1024;
    107107    m_bufferUsed = 0;
    108     m_singleFrame = true;
     108    m_frameCount = std::nullopt;
     109    m_framesCaptured = 0;
    109110
    110111    m_context.setCallTracingActive(false);
     
    151152
    152153        m_frames->addItem(WTFMove(frame));
     154        ++m_framesCaptured;
    153155
    154156        m_currentFrameStartTime = MonotonicTime::now();
     
    215217{
    216218    return m_bufferUsed < m_bufferLimit;
     219}
     220
     221void InspectorCanvas::setFrameCount(long frameCount)
     222{
     223    if (frameCount > 0)
     224        m_frameCount = std::min<long>(frameCount, std::numeric_limits<int>::max());
     225    else
     226        m_frameCount = std::nullopt;
     227}
     228
     229bool InspectorCanvas::overFrameCount() const
     230{
     231    return m_frameCount && m_framesCaptured >= m_frameCount.value();
    217232}
    218233
  • trunk/Source/WebCore/inspector/InspectorCanvas.h

    r237198 r237670  
    7272    long bufferUsed() const { return m_bufferUsed; }
    7373
    74     bool singleFrame() const { return m_singleFrame; }
    75     void setSingleFrame(bool singleFrame) { m_singleFrame = singleFrame; }
     74    void setFrameCount(long);
     75    bool overFrameCount() const;
    7676
    7777    Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(bool captureBacktrace);
     
    118118    size_t m_bufferLimit { 100 * 1024 * 1024 };
    119119    size_t m_bufferUsed { 0 };
    120     bool m_singleFrame { false };
     120    std::optional<size_t> m_frameCount;
     121    size_t m_framesCaptured { 0 };
    121122};
    122123
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

    r237409 r237670  
    9696        return;
    9797
     98    m_recordingAutoCaptureFrameCount = std::nullopt;
     99
    98100    m_enabled = true;
    99101
     
    138140    for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values())
    139141        inspectorCanvas->resetRecordingData();
     142
     143    m_recordingAutoCaptureFrameCount = std::nullopt;
    140144
    141145    m_enabled = false;
     
    262266}
    263267
    264 void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const bool* singleFrame, const int* memoryLimit)
     268void InspectorCanvasAgent::setRecordingAutoCaptureFrameCount(ErrorString&, int count)
     269{
     270    if (count > 0)
     271        m_recordingAutoCaptureFrameCount = count;
     272    else
     273        m_recordingAutoCaptureFrameCount = std::nullopt;
     274}
     275
     276void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const int* frameCount, const int* memoryLimit)
    265277{
    266278    auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId);
     
    273285    }
    274286
    275     inspectorCanvas->resetRecordingData();
    276     if (singleFrame)
    277         inspectorCanvas->setSingleFrame(*singleFrame);
     287    RecordingOptions recordingOptions;
     288    if (frameCount)
     289        recordingOptions.frameCount = *frameCount;
    278290    if (memoryLimit)
    279         inspectorCanvas->setBufferLimit(*memoryLimit);
    280 
    281     inspectorCanvas->context().setCallTracingActive(true);
    282 
    283     m_frontendDispatcher->recordingStarted(inspectorCanvas->identifier(), Inspector::Protocol::Recording::Initiator::Frontend);
     291        recordingOptions.memoryLimit = *memoryLimit;
     292    startRecording(*inspectorCanvas, Inspector::Protocol::Recording::Initiator::Frontend, WTFMove(recordingOptions));
    284293}
    285294
     
    430439    context.canvasBase().addObserver(*this);
    431440
    432     auto inspectorCanvas = InspectorCanvas::create(context);
    433 
    434     if (m_enabled) {
    435         const bool captureBacktrace = true;
    436         m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(captureBacktrace));
    437     }
    438 
    439     m_identifierToInspectorCanvas.set(inspectorCanvas->identifier(), WTFMove(inspectorCanvas));
     441    RefPtr<InspectorCanvas> inspectorCanvas = InspectorCanvas::create(context);
     442    m_identifierToInspectorCanvas.set(inspectorCanvas->identifier(), inspectorCanvas);
     443
     444    if (!m_enabled)
     445        return;
     446
     447    const bool captureBacktrace = true;
     448    m_frontendDispatcher->canvasAdded(inspectorCanvas->buildObjectForCanvas(captureBacktrace));
     449
     450    if (m_recordingAutoCaptureFrameCount) {
     451        RecordingOptions recordingOptions;
     452        recordingOptions.frameCount = m_recordingAutoCaptureFrameCount.value();
     453        startRecording(*inspectorCanvas, Inspector::Protocol::Recording::Initiator::AutoCapture, WTFMove(recordingOptions));
     454    }
    440455}
    441456
     
    524539        m_frontendDispatcher->recordingProgress(inspectorCanvas->identifier(), inspectorCanvas->releaseFrames(), inspectorCanvas->bufferUsed());
    525540
    526     if (!forceDispatch && !inspectorCanvas->singleFrame())
     541    if (!forceDispatch && !inspectorCanvas->overFrameCount())
    527542        return;
    528543
     
    566581        return;
    567582
    568     if (inspectorCanvas->context().callTracingActive())
    569         return;
    570 
    571     inspectorCanvas->resetRecordingData();
    572 
     583    RecordingOptions recordingOptions;
    573584    if (options) {
     585        if (JSC::JSValue optionSingleFrame = options->get(&exec, JSC::Identifier::fromString(&exec, "singleFrame")))
     586            recordingOptions.frameCount = optionSingleFrame.toBoolean(&exec) ? 1 : 0;
     587        if (JSC::JSValue optionFrameCount = options->get(&exec, JSC::Identifier::fromString(&exec, "frameCount")))
     588            recordingOptions.frameCount = optionFrameCount.toNumber(&exec);
     589        if (JSC::JSValue optionMemoryLimit = options->get(&exec, JSC::Identifier::fromString(&exec, "memoryLimit")))
     590            recordingOptions.memoryLimit = optionMemoryLimit.toNumber(&exec);
    574591        if (JSC::JSValue optionName = options->get(&exec, JSC::Identifier::fromString(&exec, "name")))
    575             inspectorCanvas->setRecordingName(optionName.toWTFString(&exec));
    576         if (JSC::JSValue optionSingleFrame = options->get(&exec, JSC::Identifier::fromString(&exec, "singleFrame")))
    577             inspectorCanvas->setSingleFrame(optionSingleFrame.toBoolean(&exec));
    578         if (JSC::JSValue optionMemoryLimit = options->get(&exec, JSC::Identifier::fromString(&exec, "memoryLimit")))
    579             inspectorCanvas->setBufferLimit(optionMemoryLimit.toNumber(&exec));
    580     }
    581 
    582     inspectorCanvas->context().setCallTracingActive(true);
    583 
    584     m_frontendDispatcher->recordingStarted(inspectorCanvas->identifier(), Inspector::Protocol::Recording::Initiator::Console);
     592            recordingOptions.name = optionName.toWTFString(&exec);
     593    }
     594    startRecording(*inspectorCanvas, Inspector::Protocol::Recording::Initiator::Console, WTFMove(recordingOptions));
    585595}
    586596
     
    640650}
    641651#endif
     652
     653void InspectorCanvasAgent::startRecording(InspectorCanvas& inspectorCanvas, Inspector::Protocol::Recording::Initiator initiator, RecordingOptions&& recordingOptions)
     654{
     655    auto& canvasRenderingContext = inspectorCanvas.context();
     656
     657    if (!is<CanvasRenderingContext2D>(canvasRenderingContext)
     658#if ENABLE(WEBGL)
     659        && !is<WebGLRenderingContext>(canvasRenderingContext)
     660#endif
     661        && !is<ImageBitmapRenderingContext>(canvasRenderingContext))
     662        return;
     663
     664    if (canvasRenderingContext.callTracingActive())
     665        return;
     666
     667    inspectorCanvas.resetRecordingData();
     668    if (recordingOptions.frameCount)
     669        inspectorCanvas.setFrameCount(recordingOptions.frameCount.value());
     670    if (recordingOptions.memoryLimit)
     671        inspectorCanvas.setBufferLimit(recordingOptions.memoryLimit.value());
     672    if (recordingOptions.name)
     673        inspectorCanvas.setRecordingName(recordingOptions.name.value());
     674    canvasRenderingContext.setCallTracingActive(true);
     675
     676    m_frontendDispatcher->recordingStarted(inspectorCanvas.identifier(), initiator);
     677}
    642678
    643679void InspectorCanvasAgent::canvasDestroyedTimerFired()
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.h

    r230127 r237670  
    7474    void requestCSSCanvasClientNodes(ErrorString&, const String& canvasId, RefPtr<JSON::ArrayOf<int>>&) override;
    7575    void resolveCanvasContext(ErrorString&, const String& canvasId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>&) override;
    76     void startRecording(ErrorString&, const String& canvasId, const bool* singleFrame, const int* memoryLimit) override;
     76    void setRecordingAutoCaptureFrameCount(ErrorString&, int count) override;
     77    void startRecording(ErrorString&, const String& canvasId, const int* frameCount, const int* memoryLimit) override;
    7778    void stopRecording(ErrorString&, const String& canvasId) override;
    7879    void requestShaderSource(ErrorString&, const String& programId, const String& shaderType, String*) override;
     
    104105
    105106private:
     107    struct RecordingOptions {
     108        std::optional<long> frameCount;
     109        std::optional<long> memoryLimit;
     110        std::optional<String> name;
     111    };
     112    void startRecording(InspectorCanvas&, Inspector::Protocol::Recording::Initiator, RecordingOptions&& = { });
     113
    106114    void canvasDestroyedTimerFired();
    107115    void canvasRecordingTimerFired();
     
    125133    Timer m_canvasDestroyedTimer;
    126134    Timer m_canvasRecordingTimer;
     135    std::optional<size_t> m_recordingAutoCaptureFrameCount;
    127136
    128137    bool m_enabled { false };
  • trunk/Source/WebInspectorUI/ChangeLog

    r237669 r237670  
     12018-10-31  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Canvas: create a setting for auto-recording newly created contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=190856
     5
     6        Reviewed by Brian Burg.
     7
     8        * UserInterface/Controllers/CanvasManager.js:
     9        (WI.CanvasManager.supportsRecordingAutoCapture): Added.
     10        (WI.CanvasManager.prototype.setRecordingAutoCaptureFrameCount): Added.
     11
     12        * UserInterface/Models/Canvas.js:
     13        (WI.Canvas.prototype.startRecording):
     14        (WI.Canvas.prototype.recordingStarted):
     15        (WI.Canvas.prototype.recordingFinished):
     16
     17        * UserInterface/Models/Recording.js:
     18
     19        * UserInterface/Views/CanvasOverviewContentView.js:
     20        (WI.CanvasOverviewContentView):
     21        (WI.CanvasOverviewContentView.prototype.get navigationItems):
     22        (WI.CanvasOverviewContentView.prototype.initialLayout): Added.
     23        (WI.CanvasOverviewContentView.prototype.attached):
     24        (WI.CanvasOverviewContentView.prototype.detached):
     25        (WI.CanvasOverviewContentView.prototype._setRecordingAutoCaptureFrameCount): Added.
     26        (WI.CanvasOverviewContentView.prototype._updateRecordingAutoCaptureInputElementSize): Added.
     27        (WI.CanvasOverviewContentView.prototype._handleRecordingAutoCaptureInput): Added.
     28        (WI.CanvasOverviewContentView.prototype._handleRecordingAutoCaptureCheckedDidChange): Added.
     29        (WI.CanvasOverviewContentView.prototype._handleCanvasRecordingAutoCaptureEnabledChanged): Added.
     30        (WI.CanvasOverviewContentView.prototype._handleCanvasRecordingAutoCaptureFrameCountChanged): Added.
     31        * UserInterface/Views/CanvasOverviewContentView.css:
     32        (.navigation-bar > .item.canvas-recording-auto-capture > label): Added.
     33        (.navigation-bar > .item.canvas-recording-auto-capture > label > input): Added.
     34        (.navigation-bar > .item.canvas-recording-auto-capture > label > input::-webkit-inner-spin-button): Added.
     35        (.popover-content > .tree-outline .item.recording > .icon): Deleted.
     36        (.popover-content > .tree-outline .item.recording:hover): Deleted.
     37        (.popover-content > .tree-outline .item.recording:hover > .icon): Deleted.
     38        Drive-by: removed unused CSS rules.
     39
     40        * UserInterface/Views/CanvasContentView.js:
     41        (WI.CanvasContentView.prototype.initialLayout):
     42        (WI.CanvasContentView.prototype._updateProgressView):
     43        (WI.CanvasContentView.prototype._updateViewRelatedItems):
     44
     45        * UserInterface/Views/CanvasTabContentView.js:
     46        (WI.CanvasTabContentView.prototype._recordingImportedOrStopped):
     47
     48        * UserInterface/Views/CheckboxNavigationItem.js:
     49        (WI.CheckboxNavigationItem):
     50        (WI.CheckboxNavigationItem.prototype._handleLabelClick): Added.
     51
     52        * UserInterface/Base/Setting.js:
     53
     54        * Localizations/en.lproj/localizedStrings.js:
     55
    1562018-10-31  Devin Rousso  <drousso@apple.com>
    257
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r237669 r237670  
    679679localizedStrings["Reasons for compositing"] = "Reasons for compositing";
    680680localizedStrings["Reasons for compositing:"] = "Reasons for compositing:";
     681localizedStrings["Record first %s frames"] = "Record first %s frames";
    681682localizedStrings["Recording"] = "Recording";
    682683localizedStrings["Recording %d"] = "Recording %d";
  • trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js

    r237661 r237670  
    104104
    105105WI.settings = {
     106    canvasRecordingAutoCaptureEnabled: new WI.Setting("canvas-recording-auto-capture-enabled", false),
     107    canvasRecordingAutoCaptureFrameCount: new WI.Setting("canvas-recording-auto-capture-frame-count", 1),
    106108    clearLogOnNavigate: new WI.Setting("clear-log-on-navigate", true),
    107109    clearNetworkOnNavigate: new WI.Setting("clear-network-on-navigate", true),
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js

    r237652 r237670  
    4747    }
    4848
     49    // Static
     50
     51    static supportsRecordingAutoCapture()
     52    {
     53        return window.CanvasAgent && CanvasAgent.setRecordingAutoCaptureFrameCount;
     54    }
     55
    4956    // Public
    5057
     
    9299    }
    93100
     101    setRecordingAutoCaptureFrameCount(enabled, count)
     102    {
     103        console.assert(!isNaN(count) && count >= 0);
     104
     105        return CanvasAgent.setRecordingAutoCaptureFrameCount(enabled ? count : 0)
     106        .then(() => {
     107            WI.settings.canvasRecordingAutoCaptureEnabled.value = enabled && count;
     108            WI.settings.canvasRecordingAutoCaptureFrameCount.value = count;
     109        })
     110        .catch((error) => {
     111            console.error(error);
     112        });
     113    }
     114
    94115    canvasAdded(canvasPayload)
    95116    {
  • trunk/Source/WebInspectorUI/UserInterface/Models/Canvas.js

    r237010 r237670  
    270270    startRecording(singleFrame)
    271271    {
    272         CanvasAgent.startRecording(this._identifier, singleFrame, (error) => {
     272        let handleStartRecording = (error) => {
    273273            if (error) {
    274274                console.error(error);
     
    286286
    287287            this.dispatchEventToListeners(WI.Canvas.Event.RecordingStarted);
    288         });
     288        };
     289
     290        // COMPATIBILITY (iOS 12.1): `frameCount` did not exist yet.
     291        if (CanvasAgent.startRecording.supports("singleFrame")) {
     292            CanvasAgent.startRecording(this._identifier, singleFrame, handleStartRecording);
     293            return;
     294        }
     295
     296        if (singleFrame) {
     297            const frameCount = 1;
     298            CanvasAgent.startRecording(this._identifier, frameCount, handleStartRecording);
     299        } else
     300            CanvasAgent.startRecording(this._identifier, handleStartRecording);
    289301    }
    290302
     
    331343        // Called from WI.CanvasManager.
    332344
    333         if (initiator === WI.Recording.Initiator.Console)
     345        if (initiator === RecordingAgent.Initiator.Console)
    334346            this._recordingState = WI.Canvas.RecordingState.ActiveConsole;
     347        else if (initiator === RecordingAgent.Initiator.AutoCapture)
     348            this._recordingState = WI.Canvas.RecordingState.ActiveAutoCapture;
    335349        else {
    336             console.assert(initiator === WI.Recording.Initiator.Frontend);
     350            console.assert(initiator === RecordingAgent.Initiator.Frontend);
    337351            this._recordingState = WI.Canvas.RecordingState.ActiveFrontend;
    338352        }
     
    359373        // Called from WI.CanvasManager.
    360374
    361         let fromConsole = this._recordingState === WI.Canvas.RecordingState.ActiveConsole;
     375        let initiatedByUser = this._recordingState === WI.Canvas.RecordingState.ActiveFrontend;
    362376
    363377        // COMPATIBILITY (iOS 12.1): Canvas.event.recordingStarted did not exist yet
    364         if (!fromConsole && !CanvasAgent.hasEvent("recordingStarted"))
    365             fromConsole = !this.recordingActive;
     378        if (!initiatedByUser && !CanvasAgent.hasEvent("recordingStarted"))
     379            initiatedByUser = !!this.recordingActive;
    366380
    367381        let recording = recordingPayload ? WI.Recording.fromPayload(recordingPayload, this._recordingFrames) : null;
     
    377391        this._recordingBufferUsed = 0;
    378392
    379         this.dispatchEventToListeners(WI.Canvas.Event.RecordingStopped, {recording, fromConsole});
     393        this.dispatchEventToListeners(WI.Canvas.Event.RecordingStopped, {recording, initiatedByUser});
    380394    }
    381395
     
    406420    ActiveFrontend: "canvas-recording-state-active-frontend",
    407421    ActiveConsole: "canvas-recording-state-active-console",
     422    ActiveAutoCapture: "canvas-recording-state-active-auto-capture",
    408423};
    409424
  • trunk/Source/WebInspectorUI/UserInterface/Models/Recording.js

    r237198 r237670  
    540540};
    541541
    542 WI.Recording.Initiator = {
    543     Frontend: "frontend",
    544     Console: "console",
    545 };
    546 
    547542// Keep this in sync with WebCore::RecordingSwizzleTypes.
    548543WI.Recording.Swizzle = {
  • trunk/Source/WebInspectorUI/UserInterface/Views/CanvasContentView.js

    r236952 r237670  
    150150        if (this._errorElement)
    151151            this._showError();
     152
     153        this._updateProgressView();
    152154    }
    153155
     
    372374    _updateProgressView()
    373375    {
     376        if (!this._previewContainerElement)
     377            return;
     378
    374379        if (!this.representedObject.recordingActive) {
    375380            if (this._progressView && this._progressView.parentView) {
     
    399404    _updateViewRelatedItems()
    400405    {
     406        if (!this._viewRelatedItemsContainer)
     407            return;
     408
    401409        this._viewRelatedItemsContainer.removeChildren();
    402410
  • trunk/Source/WebInspectorUI/UserInterface/Views/CanvasOverviewContentView.css

    r236953 r237670  
    174174}
    175175
    176 .popover-content > .tree-outline .item.recording > .icon {
    177     content: url(../Images/Recording.svg);
    178 }
    179 
    180 .popover-content > .tree-outline .item.recording:hover {
    181     color: var(--selected-foreground-color);
    182     background-color: var(--selected-background-color);
    183     border-radius: 3px;
    184 }
    185 
    186 .popover-content > .tree-outline .item.recording:hover > .icon {
    187     filter: invert();
     176.navigation-bar > .item.canvas-recording-auto-capture > label {
     177    display: flex;
     178    align-items: center;
     179}
     180
     181.navigation-bar > .item.canvas-recording-auto-capture > label > input {
     182    width: 1.5em;
     183    min-width: 1.5em;
     184    margin: 0 4px;
     185    text-align: center;
     186}
     187
     188.navigation-bar > .item.canvas-recording-auto-capture > label > input::-webkit-inner-spin-button {
     189    -webkit-appearance: none;
    188190}
    189191
  • trunk/Source/WebInspectorUI/UserInterface/Views/CanvasOverviewContentView.js

    r236766 r237670  
    4646        this.element.classList.add("canvas-overview");
    4747
     48        if (WI.CanvasManager.supportsRecordingAutoCapture()) {
     49            this._recordingAutoCaptureFrameCountInputElement = document.createElement("input");
     50            this._recordingAutoCaptureFrameCountInputElement.type = "number";
     51            this._recordingAutoCaptureFrameCountInputElement.min = 0;
     52            this._recordingAutoCaptureFrameCountInputElement.value = WI.settings.canvasRecordingAutoCaptureFrameCount.value;
     53            this._recordingAutoCaptureFrameCountInputElement.addEventListener("input", this._handleRecordingAutoCaptureInput.bind(this));
     54
     55            let label = document.createDocumentFragment();
     56            String.format(WI.UIString("Record first %s frames"), [this._recordingAutoCaptureFrameCountInputElement], String.standardFormatters, label, (a, b) => {
     57                a.append(b);
     58                return a;
     59            });
     60
     61            this._recordingAutoCaptureNavigationItem = new WI.CheckboxNavigationItem("canvas-recording-auto-capture", label, !!WI.settings.canvasRecordingAutoCaptureEnabled.value);
     62            this._recordingAutoCaptureNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
     63            this._recordingAutoCaptureNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleRecordingAutoCaptureCheckedDidChange, this);
     64        }
     65
    4866        this._importButtonNavigationItem = new WI.ButtonNavigationItem("import-recording", WI.UIString("Import"), "Images/Import.svg", 15, 15);
    4967        this._importButtonNavigationItem.toolTip = WI.UIString("Import recording from file");
     
    6583    get navigationItems()
    6684    {
    67         return [this._importButtonNavigationItem, new WI.DividerNavigationItem, this._refreshButtonNavigationItem, this._showGridButtonNavigationItem];
     85        let navigationItems = [this._importButtonNavigationItem, new WI.DividerNavigationItem, this._refreshButtonNavigationItem, this._showGridButtonNavigationItem];
     86        if (WI.CanvasManager.supportsRecordingAutoCapture())
     87            navigationItems.unshift(this._recordingAutoCaptureNavigationItem, new WI.DividerNavigationItem);
     88        return navigationItems;
    6889    }
    6990
     
    7697
    7798    // Protected
     99
     100    initialLayout()
     101    {
     102        super.initialLayout();
     103
     104        if (WI.CanvasManager.supportsRecordingAutoCapture()) {
     105            this._updateRecordingAutoCaptureInputElementSize();
     106            this._setRecordingAutoCaptureFrameCount();
     107        }
     108    }
    78109
    79110    contentViewAdded(contentView)
     
    98129
    99130        WI.settings.showImageGrid.addEventListener(WI.Setting.Event.Changed, this._updateShowImageGrid, this);
     131        WI.settings.canvasRecordingAutoCaptureEnabled.addEventListener(WI.Setting.Event.Changed, this._handleCanvasRecordingAutoCaptureEnabledChanged, this);
     132        WI.settings.canvasRecordingAutoCaptureFrameCount.addEventListener(WI.Setting.Event.Changed, this._handleCanvasRecordingAutoCaptureFrameCountChanged, this);
    100133    }
    101134
    102135    detached()
    103136    {
     137        WI.settings.canvasRecordingAutoCaptureFrameCount.removeEventListener(null, null, this);
     138        WI.settings.canvasRecordingAutoCaptureEnabled.removeEventListener(null, null, this);
    104139        WI.settings.showImageGrid.removeEventListener(null, null, this);
    105140
     
    162197        WI.domManager.hideDOMNodeHighlight();
    163198    }
     199
     200    _setRecordingAutoCaptureFrameCount()
     201    {
     202        let frameCount = parseInt(this._recordingAutoCaptureFrameCountInputElement.value);
     203        console.assert(!isNaN(frameCount) && frameCount >= 0);
     204
     205        let enabled = frameCount && !!this._recordingAutoCaptureNavigationItem.checked;
     206
     207        WI.canvasManager.setRecordingAutoCaptureFrameCount(enabled, frameCount);
     208    }
     209
     210    _updateRecordingAutoCaptureInputElementSize()
     211    {
     212        let frameCount = parseInt(this._recordingAutoCaptureFrameCountInputElement.value);
     213        if (isNaN(frameCount) || frameCount < 0) {
     214            frameCount = 0;
     215            this._recordingAutoCaptureFrameCountInputElement.value = frameCount;
     216        }
     217
     218        WI.ImageUtilities.scratchCanvasContext2D((context) => {
     219            if (!this._recordingAutoCaptureFrameCountInputElement.__cachedFont) {
     220                let computedStyle = window.getComputedStyle(this._recordingAutoCaptureFrameCountInputElement);
     221                this._recordingAutoCaptureFrameCountInputElement.__cachedFont = computedStyle.font;
     222            }
     223
     224            context.font = this._recordingAutoCaptureFrameCountInputElement.__cachedFont;
     225            let textMetrics = context.measureText(this._recordingAutoCaptureFrameCountInputElement.value);
     226            this._recordingAutoCaptureFrameCountInputElement.style.setProperty("width", (textMetrics.width + 8) + "px");
     227        });
     228
     229        this._recordingAutoCaptureNavigationItem.checked = !!frameCount;
     230    }
     231
     232    _handleRecordingAutoCaptureInput(event)
     233    {
     234        this._updateRecordingAutoCaptureInputElementSize();
     235        this._setRecordingAutoCaptureFrameCount();
     236    }
     237
     238    _handleRecordingAutoCaptureCheckedDidChange(event)
     239    {
     240        this._setRecordingAutoCaptureFrameCount();
     241    }
     242
     243    _handleCanvasRecordingAutoCaptureEnabledChanged(event)
     244    {
     245        this._recordingAutoCaptureNavigationItem.checked = WI.settings.canvasRecordingAutoCaptureEnabled.value;
     246    }
     247
     248    _handleCanvasRecordingAutoCaptureFrameCountChanged(event)
     249    {
     250        this._recordingAutoCaptureFrameCountInputElement.value = WI.settings.canvasRecordingAutoCaptureFrameCount.value;
     251    }
    164252};
  • trunk/Source/WebInspectorUI/UserInterface/Views/CanvasTabContentView.js

    r237560 r237670  
    248248    _recordingImportedOrStopped(event)
    249249    {
    250         let recording = event.data.recording;
     250        let {recording, initiatedByUser} = event.data;
    251251        if (!recording)
    252252            return;
    253253
    254254        this._addRecording(recording, {
    255             suppressShowRecording: event.data.fromConsole || this.contentBrowser.currentRepresentedObjects.some((representedObject) => representedObject instanceof WI.Recording),
     255            suppressShowRecording: !initiatedByUser || this.contentBrowser.currentRepresentedObjects.some((representedObject) => representedObject instanceof WI.Recording),
    256256        });
    257257    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/CheckboxNavigationItem.js

    r225250 r237670  
    3434        this._checkboxElement.id = "checkbox-navigation-item-" + identifier;
    3535        this._checkboxElement.type = "checkbox";
    36 
    3736        this._checkboxElement.addEventListener("change", this._checkboxChanged.bind(this));
    3837
    3938        this._checkboxLabel = this.element.appendChild(document.createElement("label"));
    4039        this._checkboxLabel.className = "toggle";
    41         this._checkboxLabel.textContent = label;
     40        this._checkboxLabel.append(label);
    4241        this._checkboxLabel.setAttribute("for", this._checkboxElement.id);
     42        this._checkboxLabel.addEventListener("click", this._handleLabelClick.bind(this));
    4343    }
    4444
     
    6868        this.dispatchEventToListeners(WI.CheckboxNavigationItem.Event.CheckedDidChange);
    6969    }
     70
     71    _handleLabelClick(event)
     72    {
     73        if (WI.isEventTargetAnEditableField(event))
     74            event.stop();
     75    }
    7076};
    7177
Note: See TracChangeset for help on using the changeset viewer.