diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/csspaint')
25 files changed, 619 insertions, 183 deletions
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn b/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn index 9cd50f82315..fe5e78782e5 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn +++ b/chromium/third_party/blink/renderer/modules/csspaint/BUILD.gn @@ -23,7 +23,11 @@ blink_modules_sources("csspaint") { "paint_worklet_global_scope.h", "paint_worklet_global_scope_proxy.cc", "paint_worklet_global_scope_proxy.h", + "paint_worklet_messaging_proxy.cc", + "paint_worklet_messaging_proxy.h", "paint_worklet_pending_generator_registry.cc", "paint_worklet_pending_generator_registry.h", + "paint_worklet_proxy_client.cc", + "paint_worklet_proxy_client.h", ] } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/DEPS b/chromium/third_party/blink/renderer/modules/csspaint/DEPS index 6281a008ed3..25a8971a4af 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/DEPS +++ b/chromium/third_party/blink/renderer/modules/csspaint/DEPS @@ -3,4 +3,5 @@ include_rules = [ "+third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h", "+third_party/blink/renderer/modules/csspaint", "+third_party/blink/renderer/modules/modules_export.h", + "+third_party/blink/renderer/modules/worklet", ] diff --git a/chromium/third_party/blink/renderer/modules/csspaint/README.md b/chromium/third_party/blink/renderer/modules/csspaint/README.md index 26614d50b05..8f5fa0b4ea6 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/README.md +++ b/chromium/third_party/blink/renderer/modules/csspaint/README.md @@ -58,5 +58,5 @@ paint. ## Testing -Tests live [here](../../../LayoutTests/csspaint/). +Tests live [here](../../../web_tests/csspaint/). diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc index ffd88e09052..e27b374024f 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc @@ -21,13 +21,12 @@ namespace blink { namespace { -FloatSize GetSpecifiedSize(const IntSize& size, float zoom) { +FloatSize GetSpecifiedSize(const FloatSize& size, float zoom) { float un_zoom_factor = 1 / zoom; auto un_zoom_fn = [un_zoom_factor](float a) -> float { return a * un_zoom_factor; }; - return FloatSize(un_zoom_fn(static_cast<float>(size.Width())), - un_zoom_fn(static_cast<float>(size.Height()))); + return FloatSize(un_zoom_fn(size.Width()), un_zoom_fn(size.Height())); } } // namespace @@ -39,8 +38,8 @@ CSSPaintDefinition* CSSPaintDefinition::Create( const Vector<CSSPropertyID>& native_invalidation_properties, const Vector<AtomicString>& custom_invalidation_properties, const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings& context_settings) { - return new CSSPaintDefinition( + const PaintRenderingContext2DSettings* context_settings) { + return MakeGarbageCollected<CSSPaintDefinition>( script_state, constructor, paint, native_invalidation_properties, custom_invalidation_properties, input_argument_types, context_settings); } @@ -52,7 +51,7 @@ CSSPaintDefinition::CSSPaintDefinition( const Vector<CSSPropertyID>& native_invalidation_properties, const Vector<AtomicString>& custom_invalidation_properties, const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings& context_settings) + const PaintRenderingContext2DSettings* context_settings) : script_state_(script_state), constructor_(script_state->GetIsolate(), constructor), paint_(script_state->GetIsolate(), paint), @@ -67,7 +66,7 @@ CSSPaintDefinition::~CSSPaintDefinition() = default; scoped_refptr<Image> CSSPaintDefinition::Paint( const ImageResourceObserver& client, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector* paint_arguments) { // TODO: Break dependency on LayoutObject. Passing the Node should work. const LayoutObject& layout_object = static_cast<const LayoutObject&>(client); @@ -89,15 +88,16 @@ scoped_refptr<Image> CSSPaintDefinition::Paint( DCHECK(layout_object.GetNode()); CanvasColorParams color_params; - if (!context_settings_.alpha()) { + if (!context_settings_->alpha()) { color_params.SetOpacityMode(kOpaque); } + // Do subpixel snapping for the |container_size|. PaintRenderingContext2D* rendering_context = PaintRenderingContext2D::Create( - container_size, color_params, context_settings_, zoom); + RoundedIntSize(container_size), color_params, context_settings_, zoom); PaintSize* paint_size = PaintSize::Create(specified_size); StylePropertyMapReadOnly* style_map = - new PrepopulatedComputedStylePropertyMap( + MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>( layout_object.GetDocument(), layout_object.StyleRef(), layout_object.GetNode(), native_invalidation_properties_, custom_invalidation_properties_); @@ -131,7 +131,7 @@ scoped_refptr<Image> CSSPaintDefinition::Paint( } return PaintGeneratedImage::Create(rendering_context->GetRecord(), - FloatSize(container_size)); + container_size); } void CSSPaintDefinition::MaybeCreatePaintInstance() { @@ -157,6 +157,7 @@ void CSSPaintDefinition::Trace(Visitor* visitor) { visitor->Trace(constructor_.Cast<v8::Value>()); visitor->Trace(paint_.Cast<v8::Value>()); visitor->Trace(instance_); + visitor->Trace(context_settings_); visitor->Trace(script_state_); } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h index 4622a7b84a1..c282c561b1b 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h @@ -5,15 +5,15 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_CSS_PAINT_DEFINITION_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_CSS_PAINT_DEFINITION_H_ +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_syntax_descriptor.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_settings.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" -#include "third_party/blink/renderer/platform/geometry/int_size.h" +#include "third_party/blink/renderer/platform/geometry/float_size.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "v8/include/v8.h" @@ -37,7 +37,16 @@ class MODULES_EXPORT CSSPaintDefinition final const Vector<CSSPropertyID>&, const Vector<AtomicString>& custom_invalidation_properties, const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings&); + const PaintRenderingContext2DSettings*); + + CSSPaintDefinition( + ScriptState*, + v8::Local<v8::Function> constructor, + v8::Local<v8::Function> paint, + const Vector<CSSPropertyID>& native_invalidation_properties, + const Vector<AtomicString>& custom_invalidation_properties, + const Vector<CSSSyntaxDescriptor>& input_argument_types, + const PaintRenderingContext2DSettings*); virtual ~CSSPaintDefinition(); // Invokes the javascript 'paint' callback on an instance of the javascript @@ -47,9 +56,9 @@ class MODULES_EXPORT CSSPaintDefinition final // This may return a nullptr (representing an invalid image) if javascript // throws an error. // - // The |container_size| is the container size with subpixel snapping. + // The |container_size| is without subpixel snapping. scoped_refptr<Image> Paint(const ImageResourceObserver&, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector*); const Vector<CSSPropertyID>& NativeInvalidationProperties() const { return native_invalidation_properties_; @@ -60,13 +69,16 @@ class MODULES_EXPORT CSSPaintDefinition final const Vector<CSSSyntaxDescriptor>& InputArgumentTypes() const { return input_argument_types_; } - const PaintRenderingContext2DSettings& GetPaintRenderingContext2DSettings() + const PaintRenderingContext2DSettings* GetPaintRenderingContext2DSettings() const { return context_settings_; } ScriptState* GetScriptState() const { return script_state_; } + v8::Local<v8::Function> ConstructorForTesting(v8::Isolate* isolate) { + return constructor_.NewLocal(isolate); + } v8::Local<v8::Function> PaintFunctionForTesting(v8::Isolate* isolate) { return paint_.NewLocal(isolate); } @@ -77,15 +89,6 @@ class MODULES_EXPORT CSSPaintDefinition final } private: - CSSPaintDefinition( - ScriptState*, - v8::Local<v8::Function> constructor, - v8::Local<v8::Function> paint, - const Vector<CSSPropertyID>& native_invalidation_properties, - const Vector<AtomicString>& custom_invalidation_properties, - const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings&); - void MaybeCreatePaintInstance(); Member<ScriptState> script_state_; @@ -105,7 +108,7 @@ class MODULES_EXPORT CSSPaintDefinition final Vector<AtomicString> custom_invalidation_properties_; // Input argument types, if applicable. Vector<CSSSyntaxDescriptor> input_argument_types_; - PaintRenderingContext2DSettings context_settings_; + Member<const PaintRenderingContext2DSettings> context_settings_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc index 6ede956cba9..b088fc61bf3 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc @@ -22,9 +22,11 @@ CSSPaintImageGenerator* CSSPaintImageGeneratorImpl::Create( DCHECK(paint_worklet); CSSPaintImageGeneratorImpl* generator; if (paint_worklet->GetDocumentDefinitionMap().Contains(name)) { - generator = new CSSPaintImageGeneratorImpl(paint_worklet, name); + generator = + MakeGarbageCollected<CSSPaintImageGeneratorImpl>(paint_worklet, name); } else { - generator = new CSSPaintImageGeneratorImpl(observer, paint_worklet, name); + generator = MakeGarbageCollected<CSSPaintImageGeneratorImpl>( + observer, paint_worklet, name); paint_worklet->AddPendingGenerator(name, generator); } @@ -51,7 +53,7 @@ void CSSPaintImageGeneratorImpl::NotifyGeneratorReady() { scoped_refptr<Image> CSSPaintImageGeneratorImpl::Paint( const ImageResourceObserver& observer, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector* data) { return paint_worklet_->Paint(name_, observer, container_size, data); } @@ -107,7 +109,7 @@ bool CSSPaintImageGeneratorImpl::HasAlpha() const { DocumentPaintDefinition* definition; if (!GetValidDocumentDefinition(definition)) return false; - return definition->GetPaintRenderingContext2DSettings().alpha(); + return definition->GetPaintRenderingContext2DSettings()->alpha(); } const Vector<CSSSyntaxDescriptor>& diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h index 0ef758380e0..6fa7f01c307 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h @@ -9,7 +9,7 @@ #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" -#include "third_party/blink/renderer/platform/geometry/int_size.h" +#include "third_party/blink/renderer/platform/geometry/float_size.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "v8/include/v8.h" @@ -27,11 +27,14 @@ class MODULES_EXPORT CSSPaintImageGeneratorImpl final static CSSPaintImageGenerator* Create(const String& name, const Document&, Observer*); + + CSSPaintImageGeneratorImpl(Observer*, PaintWorklet*, const String&); + CSSPaintImageGeneratorImpl(PaintWorklet*, const String&); ~CSSPaintImageGeneratorImpl() override; - // The |container_size| is the container size with subpixel snapping. + // The |container_size| is without subpixel snapping. scoped_refptr<Image> Paint(const ImageResourceObserver&, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector*) final; const Vector<CSSPropertyID>& NativeInvalidationProperties() const final; const Vector<AtomicString>& CustomInvalidationProperties() const final; @@ -52,9 +55,6 @@ class MODULES_EXPORT CSSPaintImageGeneratorImpl final void Trace(blink::Visitor*) override; private: - CSSPaintImageGeneratorImpl(Observer*, PaintWorklet*, const String&); - CSSPaintImageGeneratorImpl(PaintWorklet*, const String&); - bool HasDocumentDefinition() const; // This function first checks whether the document definition with |name_| // exists or not. If it does exist, the function fetches the document diff --git a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.cc b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.cc index 89395f1aaf6..ebddd9afe4c 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.cc @@ -15,8 +15,8 @@ DocumentPaintDefinition::~DocumentPaintDefinition() = default; bool DocumentPaintDefinition::RegisterAdditionalPaintDefinition( const CSSPaintDefinition& other) { - if (GetPaintRenderingContext2DSettings().alpha() != - other.GetPaintRenderingContext2DSettings().alpha() || + if (GetPaintRenderingContext2DSettings()->alpha() != + other.GetPaintRenderingContext2DSettings()->alpha() || NativeInvalidationProperties() != other.NativeInvalidationProperties() || CustomInvalidationProperties() != other.CustomInvalidationProperties() || InputArgumentTypes() != other.InputArgumentTypes()) diff --git a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.h index 3ff2730611e..894b52e3a4c 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/document_paint_definition.h @@ -38,7 +38,8 @@ class DocumentPaintDefinition final const Vector<CSSSyntaxDescriptor>& InputArgumentTypes() const { return paint_definition_->InputArgumentTypes(); } - PaintRenderingContext2DSettings GetPaintRenderingContext2DSettings() const { + const PaintRenderingContext2DSettings* GetPaintRenderingContext2DSettings() + const { return paint_definition_->GetPaintRenderingContext2DSettings(); } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc index 085161d5550..890529308fc 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc @@ -12,7 +12,7 @@ namespace blink { PaintRenderingContext2D::PaintRenderingContext2D( const IntSize& container_size, const CanvasColorParams& color_params, - const PaintRenderingContext2DSettings& context_settings, + const PaintRenderingContext2DSettings* context_settings, float zoom) : container_size_(container_size), color_params_(color_params), @@ -23,8 +23,8 @@ PaintRenderingContext2D::PaintRenderingContext2D( clip_antialiasing_ = kAntiAliased; ModifiableState().SetShouldAntialias(true); - Canvas()->clear(context_settings.alpha() ? SK_ColorTRANSPARENT - : SK_ColorBLACK); + Canvas()->clear(context_settings->alpha() ? SK_ColorTRANSPARENT + : SK_ColorBLACK); did_record_draw_commands_in_paint_recorder_ = true; Canvas()->scale(zoom, zoom); } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h index a23889682d7..ddfbde175a4 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h @@ -28,13 +28,19 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable, static PaintRenderingContext2D* Create( const IntSize& container_size, const CanvasColorParams& color_params, - const PaintRenderingContext2DSettings& context_settings, + const PaintRenderingContext2DSettings* context_settings, float zoom) { - return new PaintRenderingContext2D(container_size, color_params, - context_settings, zoom); + return MakeGarbageCollected<PaintRenderingContext2D>( + container_size, color_params, context_settings, zoom); } + PaintRenderingContext2D(const IntSize& container_size, + const CanvasColorParams&, + const PaintRenderingContext2DSettings*, + float zoom); + void Trace(blink::Visitor* visitor) override { + visitor->Trace(context_settings_); ScriptWrappable::Trace(visitor); BaseRenderingContext2D::Trace(visitor); } @@ -73,7 +79,7 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable, void ValidateStateStack() const final; - bool HasAlpha() const final { return context_settings_.alpha(); } + bool HasAlpha() const final { return context_settings_->alpha(); } // PaintRenderingContext2D cannot lose it's context. bool isContextLost() const final { return false; } @@ -90,11 +96,6 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable, void WillOverwriteCanvas() override; private: - PaintRenderingContext2D(const IntSize& container_size, - const CanvasColorParams&, - const PaintRenderingContext2DSettings&, - float zoom); - void InitializePaintRecorder(); cc::PaintCanvas* Canvas() const; @@ -102,7 +103,7 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable, sk_sp<PaintRecord> previous_frame_; IntSize container_size_; const CanvasColorParams& color_params_; - PaintRenderingContext2DSettings context_settings_; + Member<const PaintRenderingContext2DSettings> context_settings_; bool did_record_draw_commands_in_paint_recorder_; float effective_zoom_; }; diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc index 0bddc0fd094..116fd8262c7 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc @@ -21,8 +21,9 @@ class PaintRenderingContext2DTest : public testing::Test { }; void PaintRenderingContext2DTest::SetUp() { - PaintRenderingContext2DSettings context_settings; - context_settings.setAlpha(false); + PaintRenderingContext2DSettings* context_settings = + PaintRenderingContext2DSettings::Create(); + context_settings->setAlpha(false); ctx_ = PaintRenderingContext2D::Create( IntSize(kWidth, kHeight), CanvasColorParams(), context_settings, kZoom); } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_size.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_size.h index 40f9c4689d7..283cb805838 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_size.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_size.h @@ -16,15 +16,17 @@ class PaintSize : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static PaintSize* Create(FloatSize size) { return new PaintSize(size); } + static PaintSize* Create(FloatSize size) { + return MakeGarbageCollected<PaintSize>(size); + } + + explicit PaintSize(FloatSize size) : size_(size) {} ~PaintSize() override = default; float width() const { return size_.Width(); } float height() const { return size_.Height(); } private: - explicit PaintSize(FloatSize size) : size_(size) {} - FloatSize size_; }; diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.cc index b668a6f2623..62ef724e5d4 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.cc @@ -11,11 +11,13 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" #include "third_party/blink/renderer/platform/graphics/image.h" namespace blink { -const size_t PaintWorklet::kNumGlobalScopes = 2u; +const wtf_size_t PaintWorklet::kNumGlobalScopes = 2u; const size_t kMaxPaintCountToSwitch = 30u; DocumentPaintDefinition* const kInvalidDocumentPaintDefinition = nullptr; @@ -32,7 +34,7 @@ PaintWorklet* PaintWorklet::From(LocalDOMWindow& window) { // static PaintWorklet* PaintWorklet::Create(LocalFrame* frame) { - return new PaintWorklet(frame); + return MakeGarbageCollected<PaintWorklet>(frame); } PaintWorklet::PaintWorklet(LocalFrame* frame) @@ -52,7 +54,7 @@ void PaintWorklet::AddPendingGenerator(const String& name, // calls (rand(kMaxPaintCountToSwitch)). // This approach ensures non-deterministic of global scope selecting, and that // there is a max of one switching within one frame. -size_t PaintWorklet::SelectGlobalScope() { +wtf_size_t PaintWorklet::SelectGlobalScope() { size_t current_paint_frame_count = GetFrame()->View()->PaintFrameCount(); // Whether a new frame starts or not. bool frame_changed = current_paint_frame_count != active_frame_count_; @@ -82,14 +84,17 @@ int PaintWorklet::GetPaintsBeforeSwitching() { return base::RandInt(0, kMaxPaintCountToSwitch - 1); } -size_t PaintWorklet::SelectNewGlobalScope() { - return static_cast<size_t>(base::RandGenerator(kNumGlobalScopes)); +wtf_size_t PaintWorklet::SelectNewGlobalScope() { + return static_cast<wtf_size_t>(base::RandGenerator(kNumGlobalScopes)); } scoped_refptr<Image> PaintWorklet::Paint(const String& name, const ImageResourceObserver& observer, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector* data) { + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) + return nullptr; + if (!document_definition_map_.Contains(name)) return nullptr; @@ -123,9 +128,20 @@ bool PaintWorklet::NeedsToCreateGlobalScope() { WorkletGlobalScopeProxy* PaintWorklet::CreateGlobalScope() { DCHECK(NeedsToCreateGlobalScope()); - return new PaintWorkletGlobalScopeProxy( - To<Document>(GetExecutionContext())->GetFrame(), ModuleResponsesMap(), - pending_generator_registry_, GetNumberOfGlobalScopes() + 1); + if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + return MakeGarbageCollected<PaintWorkletGlobalScopeProxy>( + To<Document>(GetExecutionContext())->GetFrame(), ModuleResponsesMap(), + pending_generator_registry_, GetNumberOfGlobalScopes() + 1); + } + + PaintWorkletProxyClient* proxy_client = PaintWorkletProxyClient::Create(); + WorkerClients* worker_clients = WorkerClients::Create(); + ProvidePaintWorkletProxyClientTo(worker_clients, proxy_client); + + PaintWorkletMessagingProxy* proxy = + new PaintWorkletMessagingProxy(GetExecutionContext()); + proxy->Initialize(worker_clients, ModuleResponsesMap()); + return proxy; } } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.h index aa6459aa17a..791459e8440 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet.h @@ -29,17 +29,18 @@ class MODULES_EXPORT PaintWorklet : public Worklet, static const char kSupplementName[]; // At this moment, paint worklet allows at most two global scopes at any time. - static const size_t kNumGlobalScopes; + static const wtf_size_t kNumGlobalScopes; static PaintWorklet* From(LocalDOMWindow&); static PaintWorklet* Create(LocalFrame*); + explicit PaintWorklet(LocalFrame*); ~PaintWorklet() override; void AddPendingGenerator(const String& name, CSSPaintImageGeneratorImpl*); - // The |container_size| is the container size with subpixel snapping. + // The |container_size| is without subpixel snapping. scoped_refptr<Image> Paint(const String& name, const ImageResourceObserver&, - const IntSize& container_size, + const FloatSize& container_size, const CSSStyleValueVector*); typedef HeapHashMap<String, Member<DocumentPaintDefinition>> @@ -50,12 +51,10 @@ class MODULES_EXPORT PaintWorklet : public Worklet, void Trace(blink::Visitor*) override; protected: - explicit PaintWorklet(LocalFrame*); - // Since paint worklet has more than one global scope, we MUST override this // function and provide our own selection logic. - size_t SelectGlobalScope() final; - size_t GetActiveGlobalScopeForTesting() { return active_global_scope_; } + wtf_size_t SelectGlobalScope() final; + wtf_size_t GetActiveGlobalScopeForTesting() { return active_global_scope_; } private: friend class PaintWorkletTest; @@ -68,7 +67,7 @@ class MODULES_EXPORT PaintWorklet : public Worklet, // global scopes. virtual int GetPaintsBeforeSwitching(); // This function calculates the next global scope to switch to. - virtual size_t SelectNewGlobalScope(); + virtual wtf_size_t SelectNewGlobalScope(); Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_; DocumentDefinitionMap document_definition_map_; @@ -77,7 +76,7 @@ class MODULES_EXPORT PaintWorklet : public Worklet, // tell when we begin painting on a new frame. size_t active_frame_count_ = 0u; // The current global scope being used for painting. - size_t active_global_scope_ = 0u; + wtf_size_t active_global_scope_ = 0u; // The number of paint calls remaining before Paint will select a new global // scope. SelectGlobalScope resets this at the beginning of each frame. int paints_before_switching_global_scope_; diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc index 7e2bbcf3193..fd6e0bad961 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc @@ -9,18 +9,20 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_paint_rendering_context_2d_settings.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_syntax_descriptor.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" +#include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_worklet.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" #include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h" namespace blink { @@ -63,10 +65,9 @@ bool ParseInputArguments(v8::Local<v8::Context> context, return true; } -bool ParsePaintRenderingContext2DSettings( +PaintRenderingContext2DSettings* ParsePaintRenderingContext2DSettings( v8::Local<v8::Context> context, v8::Local<v8::Function> constructor, - PaintRenderingContext2DSettings* context_settings, ExceptionState* exception_state) { v8::Isolate* isolate = context->GetIsolate(); v8::TryCatch block(isolate); @@ -75,13 +76,14 @@ bool ParsePaintRenderingContext2DSettings( if (!constructor->Get(context, V8AtomicString(isolate, "contextOptions")) .ToLocal(&context_settings_value)) { exception_state->RethrowV8Exception(block.Exception()); - return false; + return nullptr; } - V8PaintRenderingContext2DSettings::ToImpl( - isolate, context_settings_value, *context_settings, *exception_state); + auto* context_settings = + NativeValueTraits<PaintRenderingContext2DSettings>::NativeValue( + isolate, context_settings_value, *exception_state); if (exception_state->HadException()) - return false; - return true; + return nullptr; + return context_settings; } } // namespace @@ -93,9 +95,10 @@ PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create( WorkerReportingProxy& reporting_proxy, PaintWorkletPendingGeneratorRegistry* pending_generator_registry, size_t global_scope_number) { - auto* global_scope = - new PaintWorkletGlobalScope(frame, std::move(creation_params), - reporting_proxy, pending_generator_registry); + DCHECK(!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()); + auto* global_scope = MakeGarbageCollected<PaintWorkletGlobalScope>( + frame, std::move(creation_params), reporting_proxy, + pending_generator_registry); String context_name("PaintWorklet #"); context_name.append(String::Number(global_scope_number)); global_scope->ScriptController()->InitializeContextIfNeeded(context_name, @@ -106,6 +109,15 @@ PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create( return global_scope; } +// static +PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create( + std::unique_ptr<GlobalScopeCreationParams> creation_params, + WorkerThread* thread) { + DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()); + return MakeGarbageCollected<PaintWorkletGlobalScope>( + std::move(creation_params), thread); +} + PaintWorkletGlobalScope::PaintWorkletGlobalScope( LocalFrame* frame, std::unique_ptr<GlobalScopeCreationParams> creation_params, @@ -114,12 +126,26 @@ PaintWorkletGlobalScope::PaintWorkletGlobalScope( : WorkletGlobalScope(std::move(creation_params), reporting_proxy, frame), pending_generator_registry_(pending_generator_registry) {} +PaintWorkletGlobalScope::PaintWorkletGlobalScope( + std::unique_ptr<GlobalScopeCreationParams> creation_params, + WorkerThread* thread) + : WorkletGlobalScope(std::move(creation_params), + thread->GetWorkerReportingProxy(), + thread) {} + PaintWorkletGlobalScope::~PaintWorkletGlobalScope() = default; void PaintWorkletGlobalScope::Dispose() { - MainThreadDebugger::Instance()->ContextWillBeDestroyed( - ScriptController()->GetScriptState()); - pending_generator_registry_ = nullptr; + DCHECK(IsContextThread()); + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + if (PaintWorkletProxyClient* proxy_client = + PaintWorkletProxyClient::From(Clients())) + proxy_client->Dispose(); + } else { + MainThreadDebugger::Instance()->ContextWillBeDestroyed( + ScriptController()->GetScriptState()); + pending_generator_registry_ = nullptr; + } WorkletGlobalScope::Dispose(); } @@ -127,6 +153,8 @@ void PaintWorkletGlobalScope::registerPaint( const String& name, const ScriptValue& constructor_value, ExceptionState& exception_state) { + RegisterWithProxyClientIfNeeded(); + if (name.IsEmpty()) { exception_state.ThrowTypeError("The empty string is not a valid name."); return; @@ -161,9 +189,10 @@ void PaintWorkletGlobalScope::registerPaint( &exception_state)) return; - PaintRenderingContext2DSettings context_settings; - if (!ParsePaintRenderingContext2DSettings( - context, constructor, &context_settings, &exception_state)) + PaintRenderingContext2DSettings* context_settings = + ParsePaintRenderingContext2DSettings(context, constructor, + &exception_state); + if (!context_settings) return; v8::Local<v8::Object> prototype; @@ -184,34 +213,36 @@ void PaintWorkletGlobalScope::registerPaint( // TODO(xidachen): the following steps should be done with a postTask when // we move PaintWorklet off main thread. - PaintWorklet* paint_worklet = - PaintWorklet::From(*GetFrame()->GetDocument()->domWindow()); - PaintWorklet::DocumentDefinitionMap& document_definition_map = - paint_worklet->GetDocumentDefinitionMap(); - if (document_definition_map.Contains(name)) { - DocumentPaintDefinition* existing_document_definition = - document_definition_map.at(name); - if (existing_document_definition == kInvalidDocumentPaintDefinition) - return; - if (!existing_document_definition->RegisterAdditionalPaintDefinition( - *definition)) { - document_definition_map.Set(name, kInvalidDocumentPaintDefinition); - exception_state.ThrowDOMException( - DOMExceptionCode::kNotSupportedError, - "A class with name:'" + name + - "' was registered with a different definition."); - return; + if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + PaintWorklet* paint_worklet = + PaintWorklet::From(*GetFrame()->GetDocument()->domWindow()); + PaintWorklet::DocumentDefinitionMap& document_definition_map = + paint_worklet->GetDocumentDefinitionMap(); + if (document_definition_map.Contains(name)) { + DocumentPaintDefinition* existing_document_definition = + document_definition_map.at(name); + if (existing_document_definition == kInvalidDocumentPaintDefinition) + return; + if (!existing_document_definition->RegisterAdditionalPaintDefinition( + *definition)) { + document_definition_map.Set(name, kInvalidDocumentPaintDefinition); + exception_state.ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + "A class with name:'" + name + + "' was registered with a different definition."); + return; + } + // Notify the generator ready only when register paint is called the + // second time with the same |name| (i.e. there is already a document + // definition associated with |name| + if (existing_document_definition->GetRegisteredDefinitionCount() == + PaintWorklet::kNumGlobalScopes) + pending_generator_registry_->NotifyGeneratorReady(name); + } else { + DocumentPaintDefinition* document_definition = + MakeGarbageCollected<DocumentPaintDefinition>(definition); + document_definition_map.Set(name, document_definition); } - // Notify the generator ready only when register paint is called the second - // time with the same |name| (i.e. there is already a document definition - // associated with |name| - if (existing_document_definition->GetRegisteredDefinitionCount() == - PaintWorklet::kNumGlobalScopes) - pending_generator_registry_->NotifyGeneratorReady(name); - } else { - DocumentPaintDefinition* document_definition = - new DocumentPaintDefinition(definition); - document_definition_map.Set(name, document_definition); } } @@ -221,7 +252,11 @@ CSSPaintDefinition* PaintWorkletGlobalScope::FindDefinition( } double PaintWorkletGlobalScope::devicePixelRatio() const { - return GetFrame()->DevicePixelRatio(); + // TODO(smcgruer): Implement |devicePixelRatio| for worklet-thread bound + // PaintWorkletGlobalScope. + return RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled() + ? 1.0 + : GetFrame()->DevicePixelRatio(); } void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) { @@ -230,4 +265,15 @@ void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) { WorkletGlobalScope::Trace(visitor); } +void PaintWorkletGlobalScope::RegisterWithProxyClientIfNeeded() { + if (registered_ || !RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) + return; + + if (PaintWorkletProxyClient* proxy_client = + PaintWorkletProxyClient::From(Clients())) { + proxy_client->SetGlobalScope(this); + registered_ = true; + } +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h index 6bd200d8dde..958840fc5a2 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h @@ -11,6 +11,7 @@ #include "third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -23,12 +24,25 @@ class MODULES_EXPORT PaintWorkletGlobalScope final : public WorkletGlobalScope { USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletGlobalScope); public: + // Creates a main-thread bound PaintWorkletGlobalScope. static PaintWorkletGlobalScope* Create( LocalFrame*, std::unique_ptr<GlobalScopeCreationParams>, WorkerReportingProxy&, PaintWorkletPendingGeneratorRegistry*, size_t global_scope_number); + + // Creates an worklet-thread bound PaintWorkletGlobalScope. + static PaintWorkletGlobalScope* Create( + std::unique_ptr<GlobalScopeCreationParams>, + WorkerThread*); + + PaintWorkletGlobalScope(LocalFrame*, + std::unique_ptr<GlobalScopeCreationParams>, + WorkerReportingProxy&, + PaintWorkletPendingGeneratorRegistry*); + PaintWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>, + WorkerThread*); ~PaintWorkletGlobalScope() override; void Dispose() final; @@ -43,10 +57,9 @@ class MODULES_EXPORT PaintWorkletGlobalScope final : public WorkletGlobalScope { void Trace(blink::Visitor*) override; private: - PaintWorkletGlobalScope(LocalFrame*, - std::unique_ptr<GlobalScopeCreationParams>, - WorkerReportingProxy&, - PaintWorkletPendingGeneratorRegistry*); + // Registers the global scope with a proxy client, if not already done. Only + // used for worklet-thread bound PaintWorkletGlobalScopes. + void RegisterWithProxyClientIfNeeded(); // The implementation of the "paint definition" concept: // https://drafts.css-houdini.org/css-paint-api/#paint-definition @@ -54,14 +67,24 @@ class MODULES_EXPORT PaintWorkletGlobalScope final : public WorkletGlobalScope { DefinitionMap; DefinitionMap paint_definitions_; - Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_; + // Only used for main-thread bound PaintWorkletGlobalScopes. + // TODO(smcgruer): Move elsewhere for worklet-thread bound + // PaintWorkletGlobalScope. + Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_ = + nullptr; + + // Tracks whether this PaintWorkletGlobalScope has been registered with a + // PaintWorkletProxyClient. Only used in worklet-thread bound + // PaintWorkletGlobalScopes. + bool registered_ = false; }; -DEFINE_TYPE_CASTS(PaintWorkletGlobalScope, - ExecutionContext, - context, - context->IsPaintWorkletGlobalScope(), - context.IsPaintWorkletGlobalScope()); +template <> +struct DowncastTraits<PaintWorkletGlobalScope> { + static bool AllowFrom(const ExecutionContext& context) { + return context.IsPaintWorkletGlobalScope(); + } +}; } // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc index d4c9ec466ab..833e8272875 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc @@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h" +#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -36,13 +37,12 @@ PaintWorkletGlobalScopeProxy::PaintWorkletGlobalScopeProxy( std::make_unique<MainThreadWorkletReportingProxy>(document); WorkerClients* worker_clients = WorkerClients::Create(); - ProvideWorkerFetchContextToWorker( - worker_clients, frame->Client()->CreateWorkerFetchContext()); ProvideContentSettingsClientToWorker( worker_clients, frame->Client()->CreateWorkerContentSettingsClient()); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - document->Url(), ScriptType::kModule, document->UserAgent(), + document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + frame->Client()->CreateWorkerFetchContext(), document->GetContentSecurityPolicy()->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), document->IsSecureContext(), document->GetHttpsState(), worker_clients, diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc new file mode 100644 index 00000000000..8efc3188a48 --- /dev/null +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc @@ -0,0 +1,183 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" + +#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" +#include "third_party/blink/renderer/core/inspector/worker_devtools_params.h" +#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" +#include "third_party/blink/renderer/core/script/script.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" +#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" +#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" +#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" +#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" + +namespace blink { +namespace { + +class MockPaintWorkletProxyClient : public PaintWorkletProxyClient { + public: + MockPaintWorkletProxyClient() + : PaintWorkletProxyClient(), did_set_global_scope_(false) {} + void SetGlobalScope(WorkletGlobalScope*) override { + did_set_global_scope_ = true; + } + bool did_set_global_scope() { return did_set_global_scope_; } + + private: + bool did_set_global_scope_; +}; + +} // namespace + +// TODO(smcgruer): Extract a common base class between this and +// AnimationWorkletGlobalScope. +class PaintWorkletGlobalScopeTest : public PageTestBase { + public: + PaintWorkletGlobalScopeTest() = default; + + void SetUp() override { + PageTestBase::SetUp(IntSize()); + Document* document = &GetDocument(); + document->SetURL(KURL("https://example.com/")); + document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url())); + reporting_proxy_ = std::make_unique<WorkerReportingProxy>(); + } + + std::unique_ptr<AnimationAndPaintWorkletThread> + CreateAnimationAndPaintWorkletThread(PaintWorkletProxyClient* proxy_client) { + std::unique_ptr<AnimationAndPaintWorkletThread> thread = + AnimationAndPaintWorkletThread::CreateForPaintWorklet( + *reporting_proxy_); + + WorkerClients* clients = WorkerClients::Create(); + if (proxy_client) + ProvidePaintWorkletProxyClientTo(clients, proxy_client); + + Document* document = &GetDocument(); + thread->Start( + std::make_unique<GlobalScopeCreationParams>( + document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), + document->GetReferrerPolicy(), document->GetSecurityOrigin(), + document->IsSecureContext(), document->GetHttpsState(), clients, + document->AddressSpace(), + OriginTrialContext::GetTokens(document).get(), + base::UnguessableToken::Create(), nullptr /* worker_settings */, + kV8CacheOptionsDefault, new WorkletModuleResponsesMap), + base::nullopt, std::make_unique<WorkerDevToolsParams>(), + ParentExecutionContextTaskRunners::Create()); + return thread; + } + + using TestCalback = void (PaintWorkletGlobalScopeTest::*)(WorkerThread*, + WaitableEvent*); + + // Create a new paint worklet and run the callback task on it. Terminate the + // worklet once the task completion is signaled. + void RunTestOnWorkletThread(TestCalback callback) { + std::unique_ptr<WorkerThread> worklet = + CreateAnimationAndPaintWorkletThread(nullptr); + WaitableEvent waitable_event; + PostCrossThreadTask( + *worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBind(callback, CrossThreadUnretained(this), + CrossThreadUnretained(worklet.get()), + CrossThreadUnretained(&waitable_event))); + waitable_event.Wait(); + + worklet->Terminate(); + worklet->WaitForShutdownForTesting(); + } + + void RunScriptOnWorklet(String source_code, + WorkerThread* thread, + WaitableEvent* waitable_event) { + ASSERT_TRUE(thread->IsCurrentThread()); + auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope()); + ScriptState* script_state = + global_scope->ScriptController()->GetScriptState(); + ASSERT_TRUE(script_state); + v8::Isolate* isolate = script_state->GetIsolate(); + ASSERT_TRUE(isolate); + ScriptState::Scope scope(script_state); + ASSERT_TRUE(EvaluateScriptModule(global_scope, source_code)); + waitable_event->Signal(); + } + + void RunBasicParsingTestOnWorklet(WorkerThread* thread, + WaitableEvent* waitable_event) { + ASSERT_TRUE(thread->IsCurrentThread()); + auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope()); + ScriptState* script_state = + global_scope->ScriptController()->GetScriptState(); + ASSERT_TRUE(script_state); + v8::Isolate* isolate = script_state->GetIsolate(); + ASSERT_TRUE(isolate); + + ScriptState::Scope scope(script_state); + + { + // registerPaint() with a valid class definition should define an + // animator. + String source_code = + R"JS( + registerPaint('test', class { + constructor () {} + paint (ctx, size) {} + }); + )JS"; + ASSERT_TRUE(EvaluateScriptModule(global_scope, source_code)); + + CSSPaintDefinition* definition = global_scope->FindDefinition("test"); + ASSERT_TRUE(definition); + + EXPECT_TRUE(definition->ConstructorForTesting(isolate)->IsFunction()); + EXPECT_TRUE(definition->PaintFunctionForTesting(isolate)->IsFunction()); + } + + { + // registerPaint() with a null class definition should fail to define + // an painter. + String source_code = "registerPaint('null', null);"; + ASSERT_FALSE(EvaluateScriptModule(global_scope, source_code)); + EXPECT_FALSE(global_scope->FindDefinition("null")); + } + + EXPECT_FALSE(global_scope->FindDefinition("non-existent")); + + waitable_event->Signal(); + } + + private: + bool EvaluateScriptModule(PaintWorkletGlobalScope* global_scope, + const String& source_code) { + ScriptState* script_state = + global_scope->ScriptController()->GetScriptState(); + EXPECT_TRUE(script_state); + const KURL js_url("https://example.com/worklet.js"); + ScriptModule module = ScriptModule::Compile( + script_state->GetIsolate(), source_code, js_url, js_url, + ScriptFetchOptions(), TextPosition::MinimumPosition(), + ASSERT_NO_EXCEPTION); + EXPECT_FALSE(module.IsNull()); + ScriptValue exception = module.Instantiate(script_state); + EXPECT_TRUE(exception.IsEmpty()); + ScriptValue value = module.Evaluate(script_state); + return value.IsEmpty(); + } + + std::unique_ptr<WorkerReportingProxy> reporting_proxy_; +}; + +TEST_F(PaintWorkletGlobalScopeTest, BasicParsing) { + ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true); + RunTestOnWorkletThread( + &PaintWorkletGlobalScopeTest::RunBasicParsingTestOnWorklet); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.cc new file mode 100644 index 00000000000..17c2f4c6907 --- /dev/null +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.cc @@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h" + +#include "third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h" +#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h" + +namespace blink { + +PaintWorkletMessagingProxy::PaintWorkletMessagingProxy( + ExecutionContext* execution_context) + : ThreadedWorkletMessagingProxy(execution_context) {} + +void PaintWorkletMessagingProxy::Trace(blink::Visitor* visitor) { + ThreadedWorkletMessagingProxy::Trace(visitor); +} + +PaintWorkletMessagingProxy::~PaintWorkletMessagingProxy() = default; + +std::unique_ptr<WorkerThread> PaintWorkletMessagingProxy::CreateWorkerThread() { + return AnimationAndPaintWorkletThread::CreateForPaintWorklet( + WorkletObjectProxy()); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h new file mode 100644 index 00000000000..7ffb584f2d5 --- /dev/null +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h @@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_MESSAGING_PROXY_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_MESSAGING_PROXY_H_ + +#include <memory> +#include "third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h" + +namespace blink { + +class ExecutionContext; +class WorkerThread; + +// Acts as a proxy for worklet-thread bound PaintWorkletGlobalScopes. The logic +// to actually proxy an off thread global scope is implemented in the parent. +// The main contribution of this class is to create an appropriate worklet +// thread type as part of the the worklet initialization process. +class PaintWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy { + public: + explicit PaintWorkletMessagingProxy(ExecutionContext*); + + void Trace(blink::Visitor*) override; + + private: + ~PaintWorkletMessagingProxy() override; + + std::unique_ptr<WorkerThread> CreateWorkerThread() override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_OFF_THREAD_PAINT_WORKLET_MESSAGING_PROXY_H_ diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc index 6aa143838b6..0243f55a685 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.cc @@ -26,7 +26,7 @@ void PaintWorkletPendingGeneratorRegistry::AddPendingGenerator( Member<GeneratorHashSet>& set = pending_generators_.insert(name, nullptr).stored_value->value; if (!set) - set = new GeneratorHashSet; + set = MakeGarbageCollected<GeneratorHashSet>(); set->insert(generator); } diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc new file mode 100644 index 00000000000..a46565a9c5c --- /dev/null +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc @@ -0,0 +1,69 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" + +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" +#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" +#include "third_party/blink/renderer/core/workers/worker_thread.h" +#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/graphics/image.h" + +namespace blink { + +const char PaintWorkletProxyClient::kSupplementName[] = + "PaintWorkletProxyClient"; + +// static +PaintWorkletProxyClient* PaintWorkletProxyClient::Create() { + return new PaintWorkletProxyClient; +} + +PaintWorkletProxyClient::PaintWorkletProxyClient() + : state_(RunState::kUninitialized) { + DCHECK(IsMainThread()); +} + +void PaintWorkletProxyClient::Trace(blink::Visitor* visitor) { + Supplement<WorkerClients>::Trace(visitor); +} + +void PaintWorkletProxyClient::SetGlobalScope(WorkletGlobalScope* global_scope) { + DCHECK(global_scope); + DCHECK(global_scope->IsContextThread()); + if (state_ == RunState::kDisposed) + return; + DCHECK(state_ == RunState::kUninitialized); + + global_scope_ = static_cast<PaintWorkletGlobalScope*>(global_scope); + state_ = RunState::kWorking; +} + +void PaintWorkletProxyClient::Dispose() { + if (state_ == RunState::kWorking) { + DCHECK(global_scope_); + DCHECK(global_scope_->IsContextThread()); + + // At worklet scope termination break the reference cycle between + // PaintWorkletGlobalScope and PaintWorkletProxyClient. + global_scope_ = nullptr; + } + + DCHECK(state_ != RunState::kDisposed); + state_ = RunState::kDisposed; +} + +// static +PaintWorkletProxyClient* PaintWorkletProxyClient::From(WorkerClients* clients) { + return Supplement<WorkerClients>::From<PaintWorkletProxyClient>(clients); +} + +void ProvidePaintWorkletProxyClientTo(WorkerClients* clients, + PaintWorkletProxyClient* client) { + clients->ProvideSupplement(client); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h new file mode 100644 index 00000000000..78248601c42 --- /dev/null +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h @@ -0,0 +1,59 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_ + +#include "base/macros.h" +#include "base/single_thread_task_runner.h" +#include "third_party/blink/renderer/core/workers/worker_clients.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" +#include "third_party/blink/renderer/modules/modules_export.h" + +namespace blink { + +class WorkletGlobalScope; + +// Mediates between a worklet-thread bound PaintWorkletGlobalScope and its +// associated dispatchers. A PaintWorkletProxyClient is associated with a single +// global scope and one dispatcher to the compositor thread. +// +// This is constructed on the main thread but it is used in the worklet backing +// thread. +// +// TODO(smcgruer): Add the dispatcher logic. +class MODULES_EXPORT PaintWorkletProxyClient + : public GarbageCollectedFinalized<PaintWorkletProxyClient>, + public Supplement<WorkerClients> { + USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletProxyClient); + DISALLOW_COPY_AND_ASSIGN(PaintWorkletProxyClient); + + public: + static const char kSupplementName[]; + + static PaintWorkletProxyClient* Create(); + virtual ~PaintWorkletProxyClient() = default; + + void Trace(blink::Visitor*) override; + + virtual void SetGlobalScope(WorkletGlobalScope*); + void Dispose(); + + static PaintWorkletProxyClient* From(WorkerClients*); + + protected: + PaintWorkletProxyClient(); + + private: + CrossThreadPersistent<PaintWorkletGlobalScope> global_scope_; + + enum RunState { kUninitialized, kWorking, kDisposed } state_; +}; + +void MODULES_EXPORT ProvidePaintWorkletProxyClientTo(WorkerClients*, + PaintWorkletProxyClient*); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_ diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc index a58249d1bd6..3d6790bba79 100644 --- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc +++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc @@ -23,13 +23,13 @@ class TestPaintWorklet : public PaintWorklet { public: explicit TestPaintWorklet(LocalFrame* frame) : PaintWorklet(frame) {} - void SetPaintsToSwitch(size_t num) { paints_to_switch_ = num; } + void SetPaintsToSwitch(int num) { paints_to_switch_ = num; } int GetPaintsBeforeSwitching() override { return paints_to_switch_; } // We always switch to another global scope so that we can tell how often it // was switched in the test. - size_t SelectNewGlobalScope() override { + wtf_size_t SelectNewGlobalScope() override { return (GetActiveGlobalScopeForTesting() + 1) % PaintWorklet::kNumGlobalScopes; } @@ -37,15 +37,15 @@ class TestPaintWorklet : public PaintWorklet { size_t GetActiveGlobalScope() { return GetActiveGlobalScopeForTesting(); } private: - size_t paints_to_switch_; + int paints_to_switch_; }; class PaintWorkletTest : public PageTestBase { public: void SetUp() override { PageTestBase::SetUp(IntSize()); - test_paint_worklet_ = - new TestPaintWorklet(GetDocument().domWindow()->GetFrame()); + test_paint_worklet_ = MakeGarbageCollected<TestPaintWorklet>( + GetDocument().domWindow()->GetFrame()); proxy_ = test_paint_worklet_->CreateGlobalScope(); } @@ -66,10 +66,11 @@ class PaintWorkletTest : public PageTestBase { // Helper function used in GlobalScopeSelection test. void ExpectSwitchGlobalScope(bool expect_switch_within_frame, size_t num_paint_calls, - size_t paint_cnt_to_switch, + int paint_cnt_to_switch, size_t expected_num_paints_before_switch, TestPaintWorklet* paint_worklet_to_test) { - paint_worklet_to_test->GetFrame()->View()->UpdateAllLifecyclePhases(); + paint_worklet_to_test->GetFrame()->View()->UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); paint_worklet_to_test->SetPaintsToSwitch(paint_cnt_to_switch); size_t previously_selected_global_scope = paint_worklet_to_test->GetActiveGlobalScope(); @@ -103,43 +104,6 @@ class PaintWorkletTest : public PageTestBase { Persistent<TestPaintWorklet> test_paint_worklet_; }; -TEST_F(PaintWorkletTest, GarbageCollectionOfCSSPaintDefinition) { - PaintWorkletGlobalScope* global_scope = GetProxy()->global_scope(); - global_scope->ScriptController()->Evaluate( - ScriptSourceCode("registerPaint('foo', class { paint() { } });"), - kSharableCrossOrigin); - - CSSPaintDefinition* definition = global_scope->FindDefinition("foo"); - DCHECK(definition); - - v8::Isolate* isolate = - global_scope->ScriptController()->GetScriptState()->GetIsolate(); - DCHECK(isolate); - - // Set our ScopedPersistent to the paint function, and make weak. - ScopedPersistent<v8::Function> handle; - { - v8::HandleScope handle_scope(isolate); - handle.Set(isolate, definition->PaintFunctionForTesting(isolate)); - handle.SetPhantom(); - } - DCHECK(!handle.IsEmpty()); - DCHECK(handle.IsWeak()); - - // Run a GC, persistent shouldn't have been collected yet. - ThreadState::Current()->CollectAllGarbage(); - V8GCController::CollectAllGarbageForTesting(isolate); - DCHECK(!handle.IsEmpty()); - - // Delete the page & associated objects. - Terminate(); - - // Run a GC, the persistent should have been collected. - ThreadState::Current()->CollectAllGarbage(); - V8GCController::CollectAllGarbageForTesting(isolate); - DCHECK(handle.IsEmpty()); -} - // This is a crash test for crbug.com/803026. At some point, we shipped the // CSSPaintAPI without shipping the CSSPaintAPIArguments, the result of it is // that the |paint_arguments| in the CSSPaintDefinition::Paint() becomes @@ -149,7 +113,7 @@ TEST_F(PaintWorkletTest, PaintWithNullPaintArguments) { PaintWorkletGlobalScope* global_scope = GetProxy()->global_scope(); global_scope->ScriptController()->Evaluate( ScriptSourceCode("registerPaint('foo', class { paint() { } });"), - kSharableCrossOrigin); + SanitizeScriptErrors::kDoNotSanitize); CSSPaintDefinition* definition = global_scope->FindDefinition("foo"); ASSERT_TRUE(definition); @@ -157,7 +121,7 @@ TEST_F(PaintWorkletTest, PaintWithNullPaintArguments) { ImageResourceObserver* observer = GetImageResourceObserver(); ASSERT_TRUE(observer); - const IntSize container_size(100, 100); + const FloatSize container_size(100, 100); scoped_refptr<Image> image = definition->Paint(*observer, container_size, nullptr); EXPECT_NE(image, nullptr); @@ -171,7 +135,7 @@ TEST_F(PaintWorkletTest, SinglyRegisteredDocumentDefinitionNotUsed) { PaintWorkletGlobalScope* global_scope = GetProxy()->global_scope(); global_scope->ScriptController()->Evaluate( ScriptSourceCode("registerPaint('foo', class { paint() { } });"), - kSharableCrossOrigin); + SanitizeScriptErrors::kDoNotSanitize); CSSPaintImageGeneratorImpl* generator = static_cast<CSSPaintImageGeneratorImpl*>( |