diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 447d732..5c1b29be 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -606,6 +606,8 @@ "paint/display_item_list_unittest.cc", "paint/paint_image_unittest.cc", "paint/paint_op_buffer_unittest.cc", + "paint/paint_shader_unittest.cc", + "paint/scoped_image_flags_unittest.cc", "paint/solid_color_analyzer_unittest.cc", "raster/playback_image_provider_unittest.cc", "raster/raster_buffer_provider_unittest.cc",
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index 387800c5..037891d4 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -45,6 +45,8 @@ "paint_shader.h", "record_paint_canvas.cc", "record_paint_canvas.h", + "scoped_image_flags.cc", + "scoped_image_flags.h", "skia_paint_canvas.cc", "skia_paint_canvas.h", "skia_paint_image_generator.cc",
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc index 0d23dd3..05dbe8b 100644 --- a/cc/paint/discardable_image_map.cc +++ b/cc/paint/discardable_image_map.cc
@@ -27,6 +27,8 @@ return dst; } +// This canvas is used only for tracking transform/clip/filter state from the +// non-drawing ops. class PaintTrackingCanvas final : public SkNoDrawCanvas { public: PaintTrackingCanvas(int width, int height) : SkNoDrawCanvas(width, height) {} @@ -75,51 +77,13 @@ class DiscardableImageGenerator { public: - DiscardableImageGenerator(int width, int height) : canvas_(width, height) {} - ~DiscardableImageGenerator() = default; - - void GatherDiscardableImages(const PaintOpBuffer* buffer) { - if (!buffer->HasDiscardableImages()) - return; - - PlaybackParams params(nullptr, canvas_.getTotalMatrix()); - canvas_.save(); - // TODO(khushalsagar): Optimize out save/restore blocks if there are no - // images in the draw ops between them. - for (auto* op : PaintOpBuffer::Iterator(buffer)) { - if (op->IsDrawOp()) { - SkRect op_rect; - if (op->IsPaintOpWithFlags() && PaintOp::GetBounds(op, &op_rect)) { - AddImageFromFlags(op_rect, - static_cast<const PaintOpWithFlags*>(op)->flags); - } - - PaintOpType op_type = static_cast<PaintOpType>(op->type); - if (op_type == PaintOpType::DrawImage) { - auto* image_op = static_cast<DrawImageOp*>(op); - auto* sk_image = image_op->image.GetSkImage().get(); - AddImage(image_op->image, - SkRect::MakeIWH(sk_image->width(), sk_image->height()), - SkRect::MakeXYWH(image_op->left, image_op->top, - sk_image->width(), sk_image->height()), - nullptr, image_op->flags); - } else if (op_type == PaintOpType::DrawImageRect) { - auto* image_rect_op = static_cast<DrawImageRectOp*>(op); - SkMatrix matrix; - matrix.setRectToRect(image_rect_op->src, image_rect_op->dst, - SkMatrix::kFill_ScaleToFit); - AddImage(image_rect_op->image, image_rect_op->src, image_rect_op->dst, - &matrix, image_rect_op->flags); - } else if (op_type == PaintOpType::DrawRecord) { - GatherDiscardableImages( - static_cast<const DrawRecordOp*>(op)->record.get()); - } - } else { - op->Raster(&canvas_, params); - } - } - canvas_.restore(); + DiscardableImageGenerator(int width, + int height, + const PaintOpBuffer* buffer) { + PaintTrackingCanvas canvas(width, height); + GatherDiscardableImages(buffer, nullptr, &canvas); } + ~DiscardableImageGenerator() = default; std::vector<std::pair<DrawImage, gfx::Rect>> TakeImages() { return std::move(image_set_); @@ -153,48 +117,112 @@ } private: - void AddImageFromFlags(const SkRect& rect, const PaintFlags& flags) { - if (!flags.HasShader() || - flags.getShader()->shader_type() != PaintShader::Type::kImage) + // Adds discardable images from |buffer| to the set of images tracked by + // this generator. If |buffer| is being used in a DrawOp that requires + // rasterization of the buffer as a pre-processing step for execution of the + // op (for instance, with PaintRecord backed PaintShaders), + // |top_level_op_rect| is set to the rect for that op. If provided, the + // |top_level_op_rect| will be used as the rect for tracking the position of + // this image in the top-level buffer. + void GatherDiscardableImages(const PaintOpBuffer* buffer, + const gfx::Rect* top_level_op_rect, + PaintTrackingCanvas* canvas) { + if (!buffer->HasDiscardableImages()) return; - const PaintImage& paint_image = flags.getShader()->paint_image(); - SkMatrix local_matrix = flags.getShader()->GetLocalMatrix(); - AddImage(paint_image, - SkRect::MakeWH(paint_image.width(), paint_image.height()), rect, - &local_matrix, flags); + // Prevent PaintOpBuffers from having side effects back into the canvas. + SkAutoCanvasRestore save_restore(canvas, true); + + PlaybackParams params(nullptr, canvas->getTotalMatrix()); + // TODO(khushalsagar): Optimize out save/restore blocks if there are no + // images in the draw ops between them. + for (auto* op : PaintOpBuffer::Iterator(buffer)) { + if (!op->IsDrawOp()) { + op->Raster(canvas, params); + continue; + } else if (!PaintOp::OpHasDiscardableImages(op)) { + continue; + } + + gfx::Rect op_rect; + base::Optional<gfx::Rect> local_op_rect; + + if (top_level_op_rect) { + op_rect = *top_level_op_rect; + } else { + local_op_rect = ComputePaintRect(op, canvas); + if (local_op_rect.value().IsEmpty()) + continue; + + op_rect = local_op_rect.value(); + } + + const SkMatrix& ctm = canvas->getTotalMatrix(); + if (op->IsPaintOpWithFlags()) { + AddImageFromFlags(op_rect, + static_cast<const PaintOpWithFlags*>(op)->flags, ctm); + } + + PaintOpType op_type = static_cast<PaintOpType>(op->type); + if (op_type == PaintOpType::DrawImage) { + auto* image_op = static_cast<DrawImageOp*>(op); + auto* sk_image = image_op->image.GetSkImage().get(); + AddImage(image_op->image, + SkRect::MakeIWH(sk_image->width(), sk_image->height()), + op_rect, ctm, image_op->flags.getFilterQuality()); + } else if (op_type == PaintOpType::DrawImageRect) { + auto* image_rect_op = static_cast<DrawImageRectOp*>(op); + SkMatrix matrix = ctm; + matrix.postConcat(SkMatrix::MakeRectToRect(image_rect_op->src, + image_rect_op->dst, + SkMatrix::kFill_ScaleToFit)); + AddImage(image_rect_op->image, image_rect_op->src, op_rect, matrix, + image_rect_op->flags.getFilterQuality()); + } else if (op_type == PaintOpType::DrawRecord) { + GatherDiscardableImages( + static_cast<const DrawRecordOp*>(op)->record.get(), + top_level_op_rect, canvas); + } + } } - void AddImage(PaintImage paint_image, - const SkRect& src_rect, - const SkRect& rect, - const SkMatrix* local_matrix, - const PaintFlags& flags) { - if (!paint_image.IsLazyGenerated()) - return; + // Given the |op_rect|, which is the rect for the draw op, returns the + // transformed rect accounting for the current transform, clip and paint + // state on |canvas_|. + gfx::Rect ComputePaintRect(const PaintOp* op, PaintTrackingCanvas* canvas) { + const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds()); + const SkMatrix& ctm = canvas->getTotalMatrix(); - const SkRect& clip_rect = SkRect::Make(canvas_.getDeviceClipBounds()); - const SkMatrix& ctm = canvas_.getTotalMatrix(); + gfx::Rect transformed_rect; + SkRect op_rect; + if (!PaintOp::GetBounds(op, &op_rect)) { + // If we can't provide a conservative bounding rect for the op, assume it + // covers the complete current clip. + transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(clip_rect)); + } else { + const PaintFlags* flags = + op->IsPaintOpWithFlags() + ? &static_cast<const PaintOpWithFlags*>(op)->flags + : nullptr; + SkPaint paint; + if (flags) + paint = flags->ToSkPaint(); - SkRect paint_rect = MapRect(ctm, rect); - SkPaint paint = flags.ToSkPaint(); - bool computed_paint_bounds = - canvas_.ComputePaintBounds(paint_rect, &paint, &paint_rect); - if (!computed_paint_bounds) { - // TODO(vmpstr): UMA this case. - paint_rect = clip_rect; + SkRect paint_rect = MapRect(ctm, op_rect); + bool computed_paint_bounds = + canvas->ComputePaintBounds(paint_rect, &paint, &paint_rect); + if (!computed_paint_bounds) { + // TODO(vmpstr): UMA this case. + paint_rect = clip_rect; + } + + // Clamp the image rect by the current clip rect. + if (!paint_rect.intersect(clip_rect)) + return gfx::Rect(); + + transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect)); } - // Clamp the image rect by the current clip rect. - if (!paint_rect.intersect(clip_rect)) - return; - - SkFilterQuality filter_quality = flags.getFilterQuality(); - - SkIRect src_irect; - src_rect.roundOut(&src_irect); - gfx::Rect image_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect)); - // During raster, we use the device clip bounds on the canvas, which outsets // the actual clip by 1 due to the possibility of antialiasing. Account for // this here by outsetting the image rect by 1. Note that this only affects @@ -205,7 +233,52 @@ // raster time, since we might be sending a larger-than-one-item display // item to skia, which means that skia will internally determine whether to // raster the picture (using device clip bounds that are outset). - image_rect.Inset(-1, -1); + transformed_rect.Inset(-1, -1); + return transformed_rect; + } + + void AddImageFromFlags(const gfx::Rect& op_rect, + const PaintFlags& flags, + const SkMatrix& ctm) { + if (!flags.getShader()) + return; + + if (flags.getShader()->shader_type() == PaintShader::Type::kImage) { + const PaintImage& paint_image = flags.getShader()->paint_image(); + SkMatrix matrix = ctm; + matrix.postConcat(flags.getShader()->GetLocalMatrix()); + AddImage(paint_image, + SkRect::MakeWH(paint_image.width(), paint_image.height()), + op_rect, matrix, flags.getFilterQuality()); + } else if (flags.getShader()->shader_type() == + PaintShader::Type::kPaintRecord && + flags.getShader()->paint_record()->HasDiscardableImages()) { + SkRect scaled_tile_rect; + if (!flags.getShader()->GetRasterizationTileRect(ctm, + &scaled_tile_rect)) { + return; + } + + PaintTrackingCanvas canvas(scaled_tile_rect.width(), + scaled_tile_rect.height()); + canvas.setMatrix(SkMatrix::MakeRectToRect(flags.getShader()->tile(), + scaled_tile_rect, + SkMatrix::kFill_ScaleToFit)); + GatherDiscardableImages(flags.getShader()->paint_record().get(), &op_rect, + &canvas); + } + } + + void AddImage(PaintImage paint_image, + const SkRect& src_rect, + const gfx::Rect& image_rect, + const SkMatrix& matrix, + SkFilterQuality filter_quality) { + if (!paint_image.IsLazyGenerated()) + return; + + SkIRect src_irect; + src_rect.roundOut(&src_irect); // Make a note if any image was originally specified in a non-sRGB color // space. @@ -217,10 +290,6 @@ color_stats_srgb_image_count_++; } - SkMatrix matrix = ctm; - if (local_matrix) - matrix.postConcat(*local_matrix); - image_id_to_rect_[paint_image.stable_id()].Union(image_rect); if (paint_image.ShouldAnimate()) { @@ -235,9 +304,6 @@ image_rect); } - // This canvas is used only for tracking transform/clip/filter state from the - // non-drawing ops. - PaintTrackingCanvas canvas_; std::vector<std::pair<DrawImage, gfx::Rect>> image_set_; base::flat_map<PaintImage::Id, gfx::Rect> image_id_to_rect_; std::vector<DiscardableImageMap::AnimatedImageMetadata> @@ -263,8 +329,8 @@ if (!paint_op_buffer->HasDiscardableImages()) return; - DiscardableImageGenerator generator(bounds.right(), bounds.bottom()); - generator.GatherDiscardableImages(paint_op_buffer); + DiscardableImageGenerator generator(bounds.right(), bounds.bottom(), + paint_op_buffer); generator.RecordColorHistograms(); image_id_to_rect_ = generator.TakeImageIdToRectMap(); animated_images_metadata_ = generator.TakeAnimatedImagesMetadata();
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc index 0e8a6d20e..4530746 100644 --- a/cc/paint/discardable_image_map_unittest.cc +++ b/cc/paint/discardable_image_map_unittest.cc
@@ -747,6 +747,43 @@ EXPECT_DCHECK_DEATH(images[2]->frame_index()); } +TEST_F(DiscardableImageMapTest, CapturesImagesInPaintRecordShaders) { + // Create the record to use in the shader. + auto shader_record = sk_make_sp<PaintOpBuffer>(); + shader_record->push<ScaleOp>(2.0f, 2.0f); + PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(100, 100)); + shader_record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + + gfx::Rect visible_rect(500, 500); + scoped_refptr<DisplayItemList> display_list = new DisplayItemList(); + display_list->StartPaint(); + display_list->push<ScaleOp>(2.0f, 2.0f); + PaintFlags flags; + SkRect tile = SkRect::MakeWH(100, 100); + flags.setShader(PaintShader::MakePaintRecord( + shader_record, tile, SkShader::TileMode::kClamp_TileMode, + SkShader::TileMode::kClamp_TileMode, nullptr)); + display_list->push<DrawRectOp>(SkRect::MakeWH(200, 200), flags); + display_list->EndPaintOfUnpaired(visible_rect); + display_list->Finalize(); + + display_list->GenerateDiscardableImagesMetadata(); + const auto& image_map = display_list->discardable_image_map(); + + // The image rect is set to the rect for the DrawRectOp. + std::vector<PositionScaleDrawImage> draw_images = + GetDiscardableImagesInRect(image_map, visible_rect); + std::vector<gfx::Rect> inset_rects = InsetImageRects(draw_images); + ASSERT_EQ(draw_images.size(), 1u); + EXPECT_EQ(draw_images[0].image, paint_image); + // The position of the image is the position of the DrawRectOp that uses the + // shader. + EXPECT_EQ(gfx::Rect(400, 400), inset_rects[0]); + // The scale of the image includes the scale at which the shader record is + // rasterized. + EXPECT_EQ(SkSize::Make(4.f, 4.f), draw_images[0].scale); +} + class DiscardableImageMapColorSpaceTest : public DiscardableImageMapTest, public testing::WithParamInterface<gfx::ColorSpace> {};
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 4631780..ab441cd 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -13,6 +13,7 @@ #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" +#include "cc/paint/scoped_image_flags.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRegion.h" @@ -25,22 +26,6 @@ return result; } -bool IsImageShader(const PaintFlags& flags) { - return flags.HasShader() && - flags.getShader()->shader_type() == PaintShader::Type::kImage; -} - -bool IsImageOp(const PaintOp* op) { - if (op->GetType() == PaintOpType::DrawImage) - return true; - else if (op->GetType() == PaintOpType::DrawImageRect) - return true; - else if (op->IsDrawOp() && op->IsPaintOpWithFlags()) - return IsImageShader(static_cast<const PaintOpWithFlags*>(op)->flags); - - return false; -} - bool QuickRejectDraw(const PaintOp* op, const SkCanvas* canvas) { DCHECK(op->IsDrawOp()); @@ -58,65 +43,6 @@ return canvas->quickReject(rect); } -// Encapsulates a ImageProvider::DecodedImageHolder and a SkPaint. Use of -// this class ensures that the DecodedImageHolder outlives the dependent -// SkPaint. -class ScopedImageFlags { - public: - ScopedImageFlags(ImageProvider* image_provider, - const PaintFlags& flags, - const SkMatrix& ctm) { - DCHECK(IsImageShader(flags)); - - const PaintImage& paint_image = flags.getShader()->paint_image(); - SkMatrix matrix = flags.getShader()->GetLocalMatrix(); - - SkMatrix total_image_matrix = matrix; - total_image_matrix.preConcat(ctm); - SkRect src_rect = - SkRect::MakeIWH(paint_image.width(), paint_image.height()); - DrawImage draw_image(paint_image, RoundOutRect(src_rect), - flags.getFilterQuality(), total_image_matrix); - scoped_decoded_draw_image_ = - image_provider->GetDecodedDrawImage(draw_image); - - if (!scoped_decoded_draw_image_) - return; - const auto& decoded_image = scoped_decoded_draw_image_.decoded_image(); - DCHECK(decoded_image.image()); - - bool need_scale = !decoded_image.is_scale_adjustment_identity(); - if (need_scale) { - matrix.preScale(1.f / decoded_image.scale_adjustment().width(), - 1.f / decoded_image.scale_adjustment().height()); - } - - sk_sp<SkImage> sk_image = - sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get())); - PaintImage decoded_paint_image = PaintImageBuilder() - .set_id(paint_image.stable_id()) - .set_image(std::move(sk_image)) - .TakePaintImage(); - decoded_flags_.emplace(flags); - decoded_flags_.value().setFilterQuality(decoded_image.filter_quality()); - decoded_flags_.value().setShader( - PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(), - flags.getShader()->ty(), &matrix)); - } - - PaintFlags* decoded_flags() { - return decoded_flags_ ? &decoded_flags_.value() : nullptr; - } - - ~ScopedImageFlags() = default; - - private: - base::Optional<PaintFlags> decoded_flags_; - ImageProvider::ScopedDecodedDrawImage scoped_decoded_draw_image_; - - DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags); -}; - void RasterWithAlpha(const PaintOp* op, SkCanvas* canvas, const PlaybackParams& params, @@ -133,7 +59,7 @@ // ImageProvider if it consists of an image shader. base::Optional<ScopedImageFlags> scoped_flags; const PaintFlags* decoded_flags = &flags_op->flags; - if (params.image_provider && IsImageShader(flags_op->flags)) { + if (params.image_provider && flags_op->HasDiscardableImagesFromFlags()) { scoped_flags.emplace(params.image_provider, flags_op->flags, canvas->getTotalMatrix()); decoded_flags = scoped_flags.value().decoded_flags(); @@ -1457,12 +1383,47 @@ return false; } +// static +bool PaintOp::OpHasDiscardableImages(const PaintOp* op) { + if (op->IsPaintOpWithFlags() && static_cast<const PaintOpWithFlags*>(op) + ->HasDiscardableImagesFromFlags()) { + return true; + } + + if (op->GetType() == PaintOpType::DrawImage && + static_cast<const DrawImageOp*>(op)->HasDiscardableImages()) { + return true; + } else if (op->GetType() == PaintOpType::DrawImageRect && + static_cast<const DrawImageRectOp*>(op)->HasDiscardableImages()) { + return true; + } else if (op->GetType() == PaintOpType::DrawRecord && + static_cast<const DrawRecordOp*>(op)->HasDiscardableImages()) { + return true; + } + + return false; +} + void PaintOp::DestroyThis() { auto func = g_destructor_functions[type]; if (func) func(this); } +bool PaintOpWithFlags::HasDiscardableImagesFromFlags() const { + if (!IsDrawOp()) + return false; + + if (!flags.HasShader()) + return false; + else if (flags.getShader()->shader_type() == PaintShader::Type::kImage) + return flags.getShader()->paint_image().IsLazyGenerated(); + else if (flags.getShader()->shader_type() == PaintShader::Type::kPaintRecord) + return flags.getShader()->paint_record()->HasDiscardableImages(); + + return false; +} + void PaintOpWithFlags::RasterWithFlags(SkCanvas* canvas, const PaintFlags* flags, const PlaybackParams& params) const { @@ -1740,7 +1701,8 @@ // general case we defer this to the SkCanvas but if we will be // using an ImageProvider for pre-decoding images, we can save // performing an expensive decode that will never be rasterized. - const bool skip_op = params.image_provider && IsImageOp(draw_op) && + const bool skip_op = params.image_provider && + PaintOp::OpHasDiscardableImages(draw_op) && QuickRejectDraw(draw_op, canvas); if (skip_op) { // Now that we know this op will be skipped, we can push the save @@ -1770,15 +1732,15 @@ } } - if (params.image_provider && IsImageOp(op)) { + if (params.image_provider && PaintOp::OpHasDiscardableImages(op)) { if (QuickRejectDraw(op, canvas)) continue; auto* flags_op = op->IsPaintOpWithFlags() ? static_cast<const PaintOpWithFlags*>(op) : nullptr; - if (flags_op && IsImageShader(flags_op->flags)) { - ScopedImageFlags scoped_flags(image_provider, flags_op->flags, + if (flags_op && flags_op->HasDiscardableImagesFromFlags()) { + ScopedImageFlags scoped_flags(params.image_provider, flags_op->flags, canvas->getTotalMatrix()); // Only rasterize the op if we successfully decoded the image.
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 17405ec..96eb7f7 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -15,6 +15,7 @@ #include "base/memory/aligned_memory.h" #include "base/optional.h" #include "cc/base/math_util.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_flags.h" @@ -29,7 +30,6 @@ namespace cc { class ImageDecodeCache; -class ImageProvider; class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix { public: @@ -137,6 +137,10 @@ // for the op. static bool GetBounds(const PaintOp* op, SkRect* rect); + // Returns true if executing this op will require decoding of any lazy + // generated images. + static bool OpHasDiscardableImages(const PaintOp* op); + int CountSlowPaths() const { return 0; } int CountSlowPathsFromFlags() const { return 0; } @@ -195,14 +199,7 @@ int CountSlowPathsFromFlags() const { return flags.getPathEffect() ? 1 : 0; } bool HasNonAAPaint() const { return !flags.isAntiAlias(); } - bool HasDiscardableImagesFromFlags() const { - if (!IsDrawOp()) - return false; - - SkShader* shader = flags.getSkShader(); - SkImage* image = shader ? shader->isAImage(nullptr, nullptr) : nullptr; - return image && image->isLazyGenerated(); - } + bool HasDiscardableImagesFromFlags() const; void RasterWithFlags(SkCanvas* canvas, const PaintFlags* flags, @@ -981,6 +978,7 @@ friend class DisplayItemList; friend class PaintOpBufferOffsetsTest; friend class SolidColorAnalyzer; + friend class ScopedImageFlags; // Replays the paint op buffer into the canvas. If |indices| is specified, it // contains indices in an increasing order and only the indices specified in
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc index 7d0b8cf..6f0767086 100644 --- a/cc/paint/paint_shader.cc +++ b/cc/paint/paint_shader.cc
@@ -6,9 +6,25 @@ #include "base/memory/ptr_util.h" #include "cc/paint/paint_record.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/effects/SkGradientShader.h" namespace cc { +namespace { + +sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, + const SkRect& bounds, + const SkMatrix* matrix, + ImageProvider* image_provider) { + SkPictureRecorder recorder; + SkCanvas* canvas = recorder.beginRecording(bounds); + if (matrix) + canvas->setMatrix(*matrix); + record->Playback(canvas, image_provider); + return recorder.finishRecordingAsPicture(); +} + +} // namespace sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) { sk_sp<PaintShader> shader(new PaintShader(Type::kColor)); @@ -139,6 +155,96 @@ PaintShader::PaintShader(Type type) : shader_type_(type) {} PaintShader::~PaintShader() = default; +bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm, + SkRect* tile_rect) const { + DCHECK_EQ(shader_type_, Type::kPaintRecord); + + // If we are using a fixed scale, the record is rasterized with the original + // tile size and scaling is applied to the generated output. + if (scaling_behavior_ == ScalingBehavior::kFixedScale) { + *tile_rect = tile_; + return true; + } + + SkMatrix matrix = ctm; + if (local_matrix_.has_value()) + matrix.preConcat(local_matrix_.value()); + + SkSize scale; + if (!matrix.decomposeScale(&scale)) { + // Decomposition failed, use an approximation. + scale.set(SkScalarSqrt(matrix.getScaleX() * matrix.getScaleX() + + matrix.getSkewX() * matrix.getSkewX()), + SkScalarSqrt(matrix.getScaleY() * matrix.getScaleY() + + matrix.getSkewY() * matrix.getSkewY())); + } + SkSize scaled_size = + SkSize::Make(SkScalarAbs(scale.width() * tile_.width()), + SkScalarAbs(scale.height() * tile_.height())); + + // Clamp the tile size to about 4M pixels. + // TODO(khushalsagar): We need to consider the max texture size as well. + static const SkScalar kMaxTileArea = 2048 * 2048; + SkScalar tile_area = scaled_size.width() * scaled_size.height(); + if (tile_area > kMaxTileArea) { + SkScalar clamp_scale = SkScalarSqrt(kMaxTileArea / tile_area); + scaled_size.set(scaled_size.width() * clamp_scale, + scaled_size.height() * clamp_scale); + } + + scaled_size = scaled_size.toCeil(); + if (scaled_size.isEmpty()) + return false; + + *tile_rect = SkRect::MakeWH(scaled_size.width(), scaled_size.height()); + return true; +} + +sk_sp<PaintShader> PaintShader::CreateDecodedPaintRecord( + const SkMatrix& ctm, + ImageProvider* image_provider) const { + DCHECK_EQ(shader_type_, Type::kPaintRecord); + + // For creating a decoded PaintRecord shader, we need to do the following: + // 1) Figure out the scale at which the record should be rasterization given + // the ctm and local_matrix on the shader. + // 2) Transform this record to an SkPicture with this scale and replace + // encoded images in this record with decodes from the ImageProvider. This + // is done by setting the rasterization_matrix_ for this shader to be used + // in GetSkShader. + // 3) Since the SkShader will use a scaled SkPicture, we use a kFixedScale for + // the decoded shader which creates an SkPicture backed SkImage for + // creating the decoded SkShader. + // Note that the scaling logic here is replicated from + // SkPictureShader::refBitmapShader. + SkRect tile_rect; + if (!GetRasterizationTileRect(ctm, &tile_rect)) + return nullptr; + + sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); + shader->record_ = record_; + shader->tile_ = tile_rect; + // Use a fixed scale since we have already scaled the tile rect and fixed the + // raster scale. + shader->scaling_behavior_ = ScalingBehavior::kFixedScale; + shader->rasterization_matrix_.emplace(); + shader->rasterization_matrix_.value().setRectToRect( + tile_, tile_rect, SkMatrix::kFill_ScaleToFit); + shader->tx_ = tx_; + shader->ty_ = ty_; + + const SkSize tile_scale = + SkSize::Make(SkIntToScalar(tile_rect.width()) / tile_.width(), + SkIntToScalar(tile_rect.height()) / tile_.height()); + shader->local_matrix_ = GetLocalMatrix(); + shader->local_matrix_->preScale(1 / tile_scale.width(), + 1 / tile_scale.height()); + + shader->image_provider_ = image_provider; + + return shader; +} + sk_sp<SkShader> PaintShader::GetSkShader() const { if (cached_shader_) return cached_shader_; @@ -182,7 +288,12 @@ tx_, ty_, local_matrix_ ? &*local_matrix_ : nullptr); break; case Type::kPaintRecord: { - auto picture = ToSkPicture(record_, tile_); + // Create a recording at the desired scale if this record has images which + // have been decoded before raster. + auto picture = ToSkPicture( + record_, tile_, + rasterization_matrix_ ? &rasterization_matrix_.value() : nullptr, + image_provider_); switch (scaling_behavior_) { // For raster scale, we create a picture shader directly. @@ -191,7 +302,7 @@ std::move(picture), tx_, ty_, local_matrix_ ? &*local_matrix_ : nullptr, nullptr); break; - // For fixed scale, we create an image shader with and image backed by + // For fixed scale, we create an image shader with an image backed by // the picture. case ScalingBehavior::kFixedScale: { auto image = SkImage::MakeFromPicture(
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h index 8a133709..42ec44be 100644 --- a/cc/paint/paint_shader.h +++ b/cc/paint/paint_shader.h
@@ -16,7 +16,7 @@ #include "third_party/skia/include/core/SkShader.h" namespace cc { - +class ImageProvider; class PaintOpBuffer; using PaintRecord = PaintOpBuffer; @@ -111,8 +111,12 @@ return image_; } + const sk_sp<PaintRecord>& paint_record() const { return record_; } + bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const; + SkShader::TileMode tx() const { return tx_; } SkShader::TileMode ty() const { return ty_; } + SkRect tile() const { return tile_; } bool IsOpaque() const; @@ -127,11 +131,17 @@ friend class PaintOpReader; friend class PaintOpSerializationTestUtils; friend class PaintOpWriter; + friend class ScopedImageFlags; + FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord); explicit PaintShader(Type type); sk_sp<SkShader> GetSkShader() const; + sk_sp<PaintShader> CreateDecodedPaintRecord( + const SkMatrix& ctm, + ImageProvider* image_provider) const; + void SetColorsAndPositions(const SkColor* colors, const SkScalar* positions, int count); @@ -166,6 +176,12 @@ std::vector<SkColor> colors_; std::vector<SkScalar> positions_; + // The following are only used during raster to replace the decoded images in + // the record for this shader. The |image_provider_| and + // |decoded_image_stash_| must outlive this shader. + ImageProvider* image_provider_ = nullptr; + base::Optional<SkMatrix> rasterization_matrix_; + mutable sk_sp<SkShader> cached_shader_; DISALLOW_COPY_AND_ASSIGN(PaintShader);
diff --git a/cc/paint/paint_shader_unittest.cc b/cc/paint/paint_shader_unittest.cc new file mode 100644 index 0000000..bda3fb6 --- /dev/null +++ b/cc/paint/paint_shader_unittest.cc
@@ -0,0 +1,119 @@ +// Copyright 2015 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 "cc/paint/paint_shader.h" + +#include "cc/paint/draw_image.h" +#include "cc/paint/image_provider.h" +#include "cc/paint/paint_image_builder.h" +#include "cc/paint/paint_op_buffer.h" +#include "cc/test/fake_paint_image_generator.h" +#include "cc/test/skia_common.h" +#include "cc/test/test_skcanvas.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkSurface.h" + +namespace cc { +namespace { + +class MockImageGenerator : public FakePaintImageGenerator { + public: + explicit MockImageGenerator(const gfx::Size& size) + : FakePaintImageGenerator( + SkImageInfo::MakeN32Premul(size.width(), size.height())) {} + + MOCK_METHOD5(GetPixels, + bool(const SkImageInfo&, void*, size_t, size_t, uint32_t)); +}; + +class MockImageProvider : public ImageProvider { + public: + MockImageProvider() = default; + ~MockImageProvider() override = default; + + ScopedDecodedDrawImage GetDecodedDrawImage( + const DrawImage& draw_image) override { + draw_image_ = draw_image; + + SkBitmap bitmap; + bitmap.allocN32Pixels(10, 10); + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + return ScopedDecodedDrawImage( + DecodedDrawImage(image, SkSize::MakeEmpty(), SkSize::Make(1.0f, 1.0f), + draw_image.filter_quality())); + } + + const DrawImage& draw_image() const { return draw_image_; } + + private: + DrawImage draw_image_; +}; + +} // namespace + +TEST(PaintShaderTest, RasterizationRectForRecordShaders) { + SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f); + auto record_shader = PaintShader::MakePaintRecord( + sk_make_sp<PaintOpBuffer>(), SkRect::MakeWH(100, 100), + SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode, + &local_matrix); + + SkRect tile_rect; + SkMatrix ctm = SkMatrix::MakeScale(0.5f, 0.5f); + EXPECT_TRUE(record_shader->GetRasterizationTileRect(ctm, &tile_rect)); + EXPECT_EQ(tile_rect, SkRect::MakeWH(25, 25)); +} + +TEST(PaintShaderTest, DecodePaintRecord) { + auto record = sk_make_sp<PaintOpBuffer>(); + + // Use a strict mock for the generator. It should never be used when + // rasterizing this shader, since the decode should be done by the + // ImageProvider. + auto generator = + sk_make_sp<testing::StrictMock<MockImageGenerator>>(gfx::Size(100, 100)); + PaintImage paint_image = PaintImageBuilder() + .set_id(PaintImage::GetNextId()) + .set_paint_image_generator(generator) + .TakePaintImage(); + + record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); + SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f); + auto record_shader = PaintShader::MakePaintRecord( + record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode, + SkShader::TileMode::kClamp_TileMode, &local_matrix); + + PaintOpBuffer buffer; + PaintFlags flags; + flags.setShader(record_shader); + buffer.push<ScaleOp>(0.5f, 0.5f); + buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags); + + MockImageProvider image_provider; + SaveCountingCanvas canvas; + buffer.Playback(&canvas, &image_provider); + + EXPECT_EQ(canvas.draw_rect_, SkRect::MakeWH(100, 100)); + SkShader* shader = canvas.paint_.getShader(); + ASSERT_TRUE(shader); + SkMatrix decoded_local_matrix; + SkShader::TileMode xy[2]; + SkImage* skia_image = shader->isAImage(&decoded_local_matrix, xy); + ASSERT_TRUE(skia_image); + EXPECT_TRUE(skia_image->isLazyGenerated()); + EXPECT_EQ(xy[0], record_shader->tx()); + EXPECT_EQ(xy[1], record_shader->ty()); + EXPECT_EQ(decoded_local_matrix, SkMatrix::MakeScale(2.f, 2.f)); + + // The rasterization of the shader is internal to skia, so use a raster canvas + // to verify that the decoded paint does not have the encoded image. + auto surface = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100)); + surface->getCanvas()->drawPaint(canvas.paint_); + + // Using the shader requests decode for images at the correct scale. + EXPECT_EQ(image_provider.draw_image().paint_image(), paint_image); + EXPECT_EQ(image_provider.draw_image().scale(), SkSize::Make(0.25f, 0.25f)); +} + +} // namespace cc
diff --git a/cc/paint/scoped_image_flags.cc b/cc/paint/scoped_image_flags.cc new file mode 100644 index 0000000..cadb1da --- /dev/null +++ b/cc/paint/scoped_image_flags.cc
@@ -0,0 +1,103 @@ +// Copyright 2017 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 "cc/paint/scoped_image_flags.h" + +#include "cc/paint/image_provider.h" +#include "cc/paint/paint_image_builder.h" + +namespace cc { +namespace { +SkIRect RoundOutRect(const SkRect& rect) { + SkIRect result; + rect.roundOut(&result); + return result; +} +} // namespace + +ScopedImageFlags::DecodeStashingImageProvider::DecodeStashingImageProvider( + ImageProvider* source_provider) + : source_provider_(source_provider) {} +ScopedImageFlags::DecodeStashingImageProvider::~DecodeStashingImageProvider() = + default; + +ImageProvider::ScopedDecodedDrawImage +ScopedImageFlags::DecodeStashingImageProvider::GetDecodedDrawImage( + const DrawImage& draw_image) { + auto decode = source_provider_->GetDecodedDrawImage(draw_image); + if (!decode) + return ScopedDecodedDrawImage(); + + // No need to add any destruction callback to the returned image. The images + // decoded here match the lifetime of this provider. + auto image_to_return = ScopedDecodedDrawImage(decode.decoded_image()); + decoded_images_.push_back(std::move(decode)); + return image_to_return; +} + +ScopedImageFlags::ScopedImageFlags(ImageProvider* image_provider, + const PaintFlags& flags, + const SkMatrix& ctm) + : decode_stashing_image_provider_(image_provider) { + if (flags.getShader()->shader_type() == PaintShader::Type::kImage) { + DecodeImageShader(flags, ctm); + } else { + DCHECK_EQ(flags.getShader()->shader_type(), + PaintShader::Type::kPaintRecord); + DecodeRecordShader(flags, ctm); + } +} + +ScopedImageFlags::~ScopedImageFlags() = default; + +void ScopedImageFlags::DecodeImageShader(const PaintFlags& flags, + const SkMatrix& ctm) { + const PaintImage& paint_image = flags.getShader()->paint_image(); + SkMatrix matrix = flags.getShader()->GetLocalMatrix(); + + SkMatrix total_image_matrix = matrix; + total_image_matrix.preConcat(ctm); + SkRect src_rect = SkRect::MakeIWH(paint_image.width(), paint_image.height()); + DrawImage draw_image(paint_image, RoundOutRect(src_rect), + flags.getFilterQuality(), total_image_matrix); + auto decoded_draw_image = + decode_stashing_image_provider_.GetDecodedDrawImage(draw_image); + + if (!decoded_draw_image) + return; + + const auto& decoded_image = decoded_draw_image.decoded_image(); + DCHECK(decoded_image.image()); + + bool need_scale = !decoded_image.is_scale_adjustment_identity(); + if (need_scale) { + matrix.preScale(1.f / decoded_image.scale_adjustment().width(), + 1.f / decoded_image.scale_adjustment().height()); + } + + sk_sp<SkImage> sk_image = + sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get())); + PaintImage decoded_paint_image = PaintImageBuilder() + .set_id(paint_image.stable_id()) + .set_image(std::move(sk_image)) + .TakePaintImage(); + decoded_flags_.emplace(flags); + decoded_flags_.value().setFilterQuality(decoded_image.filter_quality()); + decoded_flags_.value().setShader( + PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(), + flags.getShader()->ty(), &matrix)); +} + +void ScopedImageFlags::DecodeRecordShader(const PaintFlags& flags, + const SkMatrix& ctm) { + auto decoded_shader = flags.getShader()->CreateDecodedPaintRecord( + ctm, &decode_stashing_image_provider_); + if (!decoded_shader) + return; + + decoded_flags_.emplace(flags); + decoded_flags_.value().setShader(std::move(decoded_shader)); +} + +} // namespace cc
diff --git a/cc/paint/scoped_image_flags.h b/cc/paint/scoped_image_flags.h new file mode 100644 index 0000000..9c39bf8 --- /dev/null +++ b/cc/paint/scoped_image_flags.h
@@ -0,0 +1,66 @@ +// Copyright 2017 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 CC_PAINT_SCOPED_IMAGE_FLAGS_H_ +#define CC_PAINT_SCOPED_IMAGE_FLAGS_H_ + +#include "base/macros.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_op_buffer.h" + +namespace cc { +class ImageProvider; + +// A helper class to decode images inside the provided |flags| and provide a +// PaintFlags with the decoded images that can directly be used for +// rasterization. +// This class should only be used if |flags| has any discardable images. +class CC_PAINT_EXPORT ScopedImageFlags { + public: + // |image_provider| must outlive this class. + ScopedImageFlags(ImageProvider* image_provider, + const PaintFlags& flags, + const SkMatrix& ctm); + ~ScopedImageFlags(); + + // The usage of these flags should not extend beyond the lifetime of this + // object. + PaintFlags* decoded_flags() { + return decoded_flags_ ? &decoded_flags_.value() : nullptr; + } + + private: + // An ImageProvider that passes decode requests through to the + // |source_provider| but keeps the decode cached throughtout its lifetime, + // instead of passing the ref to the caller. + class DecodeStashingImageProvider : public ImageProvider { + public: + // |source_provider| must outlive this class. + explicit DecodeStashingImageProvider(ImageProvider* source_provider); + ~DecodeStashingImageProvider() override; + + // ImageProvider implementation. + ScopedDecodedDrawImage GetDecodedDrawImage( + const DrawImage& draw_image) override; + + private: + ImageProvider* source_provider_; + std::vector<ScopedDecodedDrawImage> decoded_images_; + + DISALLOW_COPY_AND_ASSIGN(DecodeStashingImageProvider); + }; + + void DecodeImageShader(const PaintFlags& flags, const SkMatrix& ctm); + + void DecodeRecordShader(const PaintFlags& flags, const SkMatrix& ctm); + + base::Optional<PaintFlags> decoded_flags_; + DecodeStashingImageProvider decode_stashing_image_provider_; + + DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags); +}; + +} // namespace cc + +#endif // CC_PAINT_SCOPED_IMAGE_FLAGS_H_
diff --git a/cc/paint/scoped_image_flags_unittest.cc b/cc/paint/scoped_image_flags_unittest.cc new file mode 100644 index 0000000..b8e919a9 --- /dev/null +++ b/cc/paint/scoped_image_flags_unittest.cc
@@ -0,0 +1,70 @@ +// Copyright 2017 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 "cc/paint/scoped_image_flags.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "cc/test/skia_common.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { +class MockImageProvider : public ImageProvider { + public: + MockImageProvider() = default; + ~MockImageProvider() override { EXPECT_EQ(ref_count_, 0); } + + ScopedDecodedDrawImage GetDecodedDrawImage( + const DrawImage& draw_image) override { + ref_count_++; + + SkBitmap bitmap; + bitmap.allocN32Pixels(10, 10); + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + + return ScopedDecodedDrawImage( + DecodedDrawImage(image, SkSize::MakeEmpty(), SkSize::Make(1.0f, 1.0f), + draw_image.filter_quality()), + base::BindOnce(&MockImageProvider::UnrefImage, base::Unretained(this))); + } + + void UnrefImage(DecodedDrawImage decoded_image) { + ref_count_--; + CHECK_GE(ref_count_, 0); + } + + int ref_count() const { return ref_count_; } + + private: + int ref_count_ = 0; +}; +} // namespace + +TEST(ScopedImageFlagsTest, KeepsDecodesAlive) { + auto record = sk_make_sp<PaintOpBuffer>(); + record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, + 0.f, nullptr); + record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, + 0.f, nullptr); + record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, + 0.f, nullptr); + auto record_shader = PaintShader::MakePaintRecord( + record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode, + SkShader::TileMode::kClamp_TileMode, &SkMatrix::I()); + + MockImageProvider provider; + PaintFlags flags; + flags.setShader(record_shader); + { + ScopedImageFlags scoped_flags(&provider, flags, SkMatrix::I()); + ASSERT_TRUE(scoped_flags.decoded_flags()); + SkPaint paint = scoped_flags.decoded_flags()->ToSkPaint(); + ASSERT_TRUE(paint.getShader()); + EXPECT_EQ(provider.ref_count(), 3); + } + EXPECT_EQ(provider.ref_count(), 0); +} + +} // namespace cc
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc index aad7ee0943..26e1d99 100644 --- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc +++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -241,8 +241,8 @@ codecs, std::string(1, kCdmSupportedCodecsValueDelimiter), base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); CdmRegistry::GetInstance()->RegisterCdm( - content::CdmInfo(kWidevineCdmType, cdm_version, cdm_path, - supported_codecs, kWidevineKeySystem, false)); + content::CdmInfo(kWidevineCdmType, kWidevineCdmGuid, cdm_version, + cdm_path, supported_codecs, kWidevineKeySystem, false)); } } // namespace
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc index 41af191..d44710f4 100644 --- a/chrome/browser/media/encrypted_media_browsertest.cc +++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -881,6 +881,16 @@ TestNonPlaybackCases(kExternalClearKeyStorageIdTestKeySystem, kUnitTestSuccess); } + +IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, MultipleCdmTypes) { + if (!IsUsingMojoCdm()) { + DVLOG(0) << "Skipping test; Mojo CDM specific."; + return; + } + + base::StringPairs empty_query_params; + RunMediaTestPage("multiple_cdm_types.html", empty_query_params, kEnded, true); +} #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) } // namespace chrome
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index 75242d3..82f3aa08a 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc
@@ -551,26 +551,40 @@ // same directory as the installed adapter. const base::Version version(WIDEVINE_CDM_VERSION_STRING); DCHECK(version.IsValid()); - cdms->push_back(content::CdmInfo(kWidevineCdmType, version, cdm_path, - codecs_supported, kWidevineKeySystem, - false)); + cdms->push_back(content::CdmInfo(kWidevineCdmType, kWidevineCdmGuid, + version, cdm_path, codecs_supported, + kWidevineKeySystem, false)); } #endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) #if BUILDFLAG(ENABLE_LIBRARY_CDMS) // Register Clear Key CDM if specified in command line. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - std::string clear_key_cdm_path = - command_line->GetSwitchValueASCII(switches::kClearKeyCdmPathForTesting); + base::FilePath clear_key_cdm_path = + command_line->GetSwitchValuePath(switches::kClearKeyCdmPathForTesting); if (!clear_key_cdm_path.empty()) { - // TODO(crbug.com/764480): Remove this after we have a central place for + // TODO(crbug.com/764480): Remove these after we have a central place for // External Clear Key (ECK) related information. + // Normal External Clear Key key system. const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; + // A variant of ECK key system that has a different GUID. + const char kExternalClearKeyDifferentGuidTestKeySystem[] = + "org.chromium.externalclearkey.differentguid"; + + // Register kExternalClearKeyDifferentGuidTestKeySystem first separately. + // Otherwise, it'll be treated as a sub-key-system of normal + // kExternalClearKeyKeySystem. See MultipleCdmTypes test in + // ECKEncryptedMediaTest. + cdms->push_back(content::CdmInfo( + media::kClearKeyCdmType, media::kClearKeyCdmDifferentGuid, + base::Version("0.1.0.0"), clear_key_cdm_path, {}, + kExternalClearKeyDifferentGuidTestKeySystem, false)); + // Supported codecs are hard-coded in ExternalClearKeyProperties. cdms->push_back( - content::CdmInfo(media::kClearKeyCdmType, base::Version("0.1.0.0"), - base::FilePath::FromUTF8Unsafe(clear_key_cdm_path), - {}, kExternalClearKeyKeySystem, true)); + content::CdmInfo(media::kClearKeyCdmType, media::kClearKeyCdmGuid, + base::Version("0.1.0.0"), clear_key_cdm_path, {}, + kExternalClearKeyKeySystem, true)); } #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) }
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc index 51f24da..0c6eb3f 100644 --- a/chrome/renderer/media/chrome_key_systems.cc +++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -84,6 +84,8 @@ "org.chromium.externalclearkey.verifycdmhosttest"; static const char kExternalClearKeyStorageIdTestKeySystem[] = "org.chromium.externalclearkey.storageidtest"; + static const char kExternalClearKeyDifferentGuidTestKeySystem[] = + "org.chromium.externalclearkey.differentguid"; std::vector<base::string16> additional_param_names; std::vector<base::string16> additional_param_values; @@ -133,6 +135,10 @@ // A key system that fetches the Storage ID in ClearKeyCdm. concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( kExternalClearKeyStorageIdTestKeySystem)); + + // A key system that is registered with a different CDM GUID. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyDifferentGuidTestKeySystem)); } #if defined(WIDEVINE_CDM_AVAILABLE)
diff --git a/chromeos/cryptohome/system_salt_getter.cc b/chromeos/cryptohome/system_salt_getter.cc index 45461458..09d120b6 100644 --- a/chromeos/cryptohome/system_salt_getter.cc +++ b/chromeos/cryptohome/system_salt_getter.cc
@@ -6,6 +6,8 @@ #include <stdint.h> +#include <utility> + #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" @@ -76,13 +78,11 @@ void SystemSaltGetter::DidGetSystemSalt( const GetSystemSaltCallback& callback, - DBusMethodCallStatus call_status, - const std::vector<uint8_t>& system_salt) { - if (call_status == DBUS_METHOD_CALL_SUCCESS && - !system_salt.empty() && - system_salt.size() % 2 == 0U) { - raw_salt_ = system_salt; - system_salt_ = ConvertRawSaltToHexString(system_salt); + base::Optional<std::vector<uint8_t>> system_salt) { + if (system_salt.has_value() && !system_salt->empty() && + system_salt->size() % 2 == 0U) { + raw_salt_ = std::move(system_salt).value(); + system_salt_ = ConvertRawSaltToHexString(raw_salt_); std::vector<base::Closure> callbacks; callbacks.swap(on_system_salt_ready_);
diff --git a/chromeos/cryptohome/system_salt_getter.h b/chromeos/cryptohome/system_salt_getter.h index a77d85c..57cb91b7 100644 --- a/chromeos/cryptohome/system_salt_getter.h +++ b/chromeos/cryptohome/system_salt_getter.h
@@ -13,8 +13,8 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "chromeos/chromeos_export.h" -#include "chromeos/dbus/dbus_method_call_status.h" namespace chromeos { @@ -59,8 +59,7 @@ void DidWaitForServiceToBeAvailable(const GetSystemSaltCallback& callback, bool service_is_available); void DidGetSystemSalt(const GetSystemSaltCallback& callback, - DBusMethodCallStatus call_status, - const RawSalt& system_salt); + base::Optional<std::vector<uint8_t>> system_salt); RawSalt raw_salt_; std::string system_salt_;
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc index c49cefa5..f84b7f7 100644 --- a/chromeos/dbus/cryptohome_client.cc +++ b/chromeos/dbus/cryptohome_client.cc
@@ -178,13 +178,14 @@ } // CryptohomeClient override. - void GetSystemSalt(const GetSystemSaltCallback& callback) override { + void GetSystemSalt( + DBusMethodCallback<std::vector<uint8_t>> callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSystemSalt); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnGetSystemSalt, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } // CryptohomeClient override, @@ -1020,21 +1021,20 @@ } // Handles the result of GetSystemSalt(). - void OnGetSystemSalt(const GetSystemSaltCallback& callback, + void OnGetSystemSalt(DBusMethodCallback<std::vector<uint8_t>> callback, dbus::Response* response) { if (!response) { - callback.Run(DBUS_METHOD_CALL_FAILURE, std::vector<uint8_t>()); + std::move(callback).Run(base::nullopt); return; } dbus::MessageReader reader(response); - const uint8_t* bytes = NULL; + const uint8_t* bytes = nullptr; size_t length = 0; if (!reader.PopArrayOfBytes(&bytes, &length)) { - callback.Run(DBUS_METHOD_CALL_FAILURE, std::vector<uint8_t>()); + std::move(callback).Run(base::nullopt); return; } - callback.Run(DBUS_METHOD_CALL_SUCCESS, - std::vector<uint8_t>(bytes, bytes + length)); + std::move(callback).Run(std::vector<uint8_t>(bytes, bytes + length)); } // Calls a method without result values.
diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h index 1d712b4..79ef865 100644 --- a/chromeos/dbus/cryptohome_client.h +++ b/chromeos/dbus/cryptohome_client.h
@@ -63,10 +63,6 @@ // handler invocation later. using AsyncMethodCallback = DBusMethodCallback<int /* async_id */>; - // A callback for GetSystemSalt(). - typedef base::Callback<void(DBusMethodCallStatus call_status, - const std::vector<uint8_t>& system_salt)> - GetSystemSaltCallback; // A callback to handle LowDiskSpace signals. typedef base::Callback<void(uint64_t disk_free_bytes)> LowDiskSpaceHandler; // A callback to handle responses of Pkcs11GetTpmTokenInfo method. The result @@ -183,7 +179,8 @@ // Calls GetSystemSalt method. |callback| is called after the method call // succeeds. - virtual void GetSystemSalt(const GetSystemSaltCallback& callback) = 0; + virtual void GetSystemSalt( + DBusMethodCallback<std::vector<uint8_t>> callback) = 0; // Calls GetSanitizedUsername method. |callback| is called after the method // call succeeds.
diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc index 9ccb5722..0048bce 100644 --- a/chromeos/dbus/fake_cryptohome_client.cc +++ b/chromeos/dbus/fake_cryptohome_client.cc
@@ -140,9 +140,9 @@ } void FakeCryptohomeClient::GetSystemSalt( - const GetSystemSaltCallback& callback) { + DBusMethodCallback<std::vector<uint8_t>> callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, system_salt_)); + FROM_HERE, base::BindOnce(std::move(callback), system_salt_)); } void FakeCryptohomeClient::GetSanitizedUsername(
diff --git a/chromeos/dbus/fake_cryptohome_client.h b/chromeos/dbus/fake_cryptohome_client.h index c94a254..e92390d 100644 --- a/chromeos/dbus/fake_cryptohome_client.h +++ b/chromeos/dbus/fake_cryptohome_client.h
@@ -51,7 +51,8 @@ const ProtobufMethodCallback& callback) override; void GetAccountDiskUsage(const cryptohome::Identification& account_id, const ProtobufMethodCallback& callback) override; - void GetSystemSalt(const GetSystemSaltCallback& callback) override; + void GetSystemSalt( + DBusMethodCallback<std::vector<uint8_t>> callback) override; void GetSanitizedUsername(const cryptohome::Identification& cryptohome_id, DBusMethodCallback<std::string> callback) override; std::string BlockingGetSanitizedUsername(
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc index 260a9678..066d5bd 100644 --- a/content/browser/media/cdm_registry_impl_unittest.cc +++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -19,7 +19,8 @@ namespace content { -const char kTestCdmType[] = "test"; +const char kTestCdmType[] = "Test CDM"; +const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC"; const char kTestPath[] = "/aa/bb"; const char kVersion1[] = "1.1.1.1"; const char kVersion2[] = "1.1.1.2"; @@ -44,9 +45,10 @@ const std::vector<std::string> codecs = base::SplitString(supported_codecs, kCodecDelimiter, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - cdm_registry_.RegisterCdm(CdmInfo( - type, base::Version(version), base::FilePath::FromUTF8Unsafe(path), - codecs, supported_key_system, supports_sub_key_systems)); + cdm_registry_.RegisterCdm( + CdmInfo(type, kTestCdmGuid, base::Version(version), + base::FilePath::FromUTF8Unsafe(path), codecs, + supported_key_system, supports_sub_key_systems)); } bool IsRegistered(const std::string& type, const std::string& version) {
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc index 7505e28..31ce607a 100644 --- a/content/browser/media/media_interface_proxy.cc +++ b/content/browser/media/media_interface_proxy.cc
@@ -27,6 +27,7 @@ #endif #if BUILDFLAG(ENABLE_LIBRARY_CDMS) +#include "base/guid.h" #include "content/public/browser/cdm_registry.h" #include "content/public/common/cdm_info.h" #include "media/base/key_system_names.h" @@ -46,7 +47,7 @@ binding_.set_connection_error_handler(error_handler); - // |interface_factory_ptr_| and |cdm_interface_factory_ptr_| will be lazily + // |interface_factory_ptr_| and |cdm_interface_factory_map_| will be lazily // connected in GetMediaInterfaceFactory() and GetCdmInterfaceFactory(). } @@ -58,7 +59,7 @@ void MediaInterfaceProxy::CreateAudioDecoder( media::mojom::AudioDecoderRequest request) { DCHECK(thread_checker_.CalledOnValidThread()); - media::mojom::InterfaceFactory* factory = GetMediaInterfaceFactory(); + InterfaceFactory* factory = GetMediaInterfaceFactory(); if (factory) factory->CreateAudioDecoder(std::move(request)); } @@ -66,7 +67,7 @@ void MediaInterfaceProxy::CreateVideoDecoder( media::mojom::VideoDecoderRequest request) { DCHECK(thread_checker_.CalledOnValidThread()); - media::mojom::InterfaceFactory* factory = GetMediaInterfaceFactory(); + InterfaceFactory* factory = GetMediaInterfaceFactory(); if (factory) factory->CreateVideoDecoder(std::move(request)); } @@ -75,7 +76,7 @@ const std::string& audio_device_id, media::mojom::RendererRequest request) { DCHECK(thread_checker_.CalledOnValidThread()); - media::mojom::InterfaceFactory* factory = GetMediaInterfaceFactory(); + InterfaceFactory* factory = GetMediaInterfaceFactory(); if (factory) factory->CreateRenderer(audio_device_id, std::move(request)); } @@ -84,48 +85,18 @@ const std::string& key_system, media::mojom::ContentDecryptionModuleRequest request) { DCHECK(thread_checker_.CalledOnValidThread()); - media::mojom::InterfaceFactory* factory = GetCdmInterfaceFactory(key_system); + + InterfaceFactory* factory = +#if !BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) + GetMediaInterfaceFactory(); +#else + GetCdmInterfaceFactory(key_system); +#endif + if (factory) factory->CreateCdm(key_system, std::move(request)); } -media::mojom::InterfaceFactory* -MediaInterfaceProxy::GetMediaInterfaceFactory() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!interface_factory_ptr_) - ConnectToMediaService(); - - return interface_factory_ptr_.get(); -} - -media::mojom::InterfaceFactory* MediaInterfaceProxy::GetCdmInterfaceFactory( - const std::string& key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); -#if !BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) - return GetMediaInterfaceFactory(); -#else - if (!cdm_interface_factory_ptr_) - ConnectToCdmService(key_system); - - return cdm_interface_factory_ptr_.get(); -#endif -} - -void MediaInterfaceProxy::OnMediaServiceConnectionError() { - DVLOG(1) << __func__; - DCHECK(thread_checker_.CalledOnValidThread()); - - interface_factory_ptr_.reset(); -} - -void MediaInterfaceProxy::OnCdmServiceConnectionError() { - DVLOG(1) << __func__; - DCHECK(thread_checker_.CalledOnValidThread()); - - cdm_interface_factory_ptr_.reset(); -} - service_manager::mojom::InterfaceProviderPtr MediaInterfaceProxy::GetFrameServices() { // Register frame services. @@ -154,6 +125,16 @@ return interfaces; } +media::mojom::InterfaceFactory* +MediaInterfaceProxy::GetMediaInterfaceFactory() { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!interface_factory_ptr_) + ConnectToMediaService(); + + return interface_factory_ptr_.get(); +} + void MediaInterfaceProxy::ConnectToMediaService() { DVLOG(1) << __func__; DCHECK(!interface_factory_ptr_); @@ -173,7 +154,18 @@ base::Unretained(this))); } +void MediaInterfaceProxy::OnMediaServiceConnectionError() { + DVLOG(1) << __func__; + DCHECK(thread_checker_.CalledOnValidThread()); + + interface_factory_ptr_.reset(); +} + +#if BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) + #if BUILDFLAG(ENABLE_LIBRARY_CDMS) +// Returns CdmInfo registered for |key_system|. Returns null if no CdmInfo is +// registered for |key_system|, or if the CdmInfo registered is invalid. static std::unique_ptr<CdmInfo> GetCdmInfoForKeySystem( const std::string& key_system) { DVLOG(2) << __func__ << ": key_system = " << key_system; @@ -189,45 +181,84 @@ } #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) -void MediaInterfaceProxy::ConnectToCdmService(const std::string& key_system) { - DVLOG(1) << __func__ << ": key_system = " << key_system; - DCHECK(!cdm_interface_factory_ptr_); +media::mojom::InterfaceFactory* MediaInterfaceProxy::GetCdmInterfaceFactory( + const std::string& key_system) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Set the CDM GUID to be the default user ID used when connecting to mojo + // services. This is needed when ENABLE_STANDALONE_CDM_SERVICE is true but + // ENABLE_LIBRARY_CDMS is false. + std::string cdm_guid = service_manager::mojom::kInheritUserID; + + base::FilePath cdm_path; #if BUILDFLAG(ENABLE_LIBRARY_CDMS) - // The |key_system| comes from the render process which we cannot fully trust. - // Handle failure cases gracefully! - auto cdm_info = GetCdmInfoForKeySystem(key_system); + std::unique_ptr<CdmInfo> cdm_info = GetCdmInfoForKeySystem(key_system); if (!cdm_info) { - NOTREACHED() << "Key system " << key_system << " not registered."; - return; + NOTREACHED() << "No valid CdmInfo for " << key_system; + return nullptr; } - base::FilePath cdm_path = cdm_info->path; - if (cdm_path.empty()) { + if (cdm_info->path.empty()) { NOTREACHED() << "CDM path for " << key_system << " is empty."; - return; + return nullptr; } + if (!base::IsValidGUID(cdm_info->guid)) { + NOTREACHED() << "Invalid CDM GUID " << cdm_info->guid; + return nullptr; + } + cdm_guid = cdm_info->guid; + cdm_path = cdm_info->path; #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + auto found = cdm_interface_factory_map_.find(cdm_guid); + if (found != cdm_interface_factory_map_.end()) + return found->second.get(); + + return ConnectToCdmService(cdm_guid, cdm_path); +} + +media::mojom::InterfaceFactory* MediaInterfaceProxy::ConnectToCdmService( + const std::string& cdm_guid, + const base::FilePath& cdm_path) { + DVLOG(1) << __func__ << ": cdm_guid = " << cdm_guid; + + DCHECK(!cdm_interface_factory_map_.count(cdm_guid)); + service_manager::Identity identity(media::mojom::kCdmServiceName, cdm_guid); + // TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950. service_manager::Connector* connector = ServiceManagerConnection::GetForProcess()->GetConnector(); - // TODO(crbug.com/510604): Use different "User ID" for different CDM types to - // run each type of CDM in its own process. media::mojom::MediaServicePtr media_service; - connector->BindInterface(media::mojom::kCdmServiceName, &media_service); + connector->BindInterface(identity, &media_service); #if BUILDFLAG(ENABLE_LIBRARY_CDMS) // LoadCdm() should always be called before CreateInterfaceFactory(). media_service->LoadCdm(cdm_path); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) - media_service->CreateInterfaceFactory( - MakeRequest(&cdm_interface_factory_ptr_), GetFrameServices()); - - cdm_interface_factory_ptr_.set_connection_error_handler( + InterfaceFactoryPtr interface_factory_ptr; + media_service->CreateInterfaceFactory(MakeRequest(&interface_factory_ptr), + GetFrameServices()); + interface_factory_ptr.set_connection_error_handler( base::BindOnce(&MediaInterfaceProxy::OnCdmServiceConnectionError, - base::Unretained(this))); + base::Unretained(this), cdm_guid)); + + InterfaceFactory* cdm_interface_factory = interface_factory_ptr.get(); + cdm_interface_factory_map_.emplace(cdm_guid, + std::move(interface_factory_ptr)); + return cdm_interface_factory; } +void MediaInterfaceProxy::OnCdmServiceConnectionError( + const std::string& cdm_guid) { + DVLOG(1) << __func__; + DCHECK(thread_checker_.CalledOnValidThread()); + + DCHECK(cdm_interface_factory_map_.count(cdm_guid)); + cdm_interface_factory_map_.erase(cdm_guid); +} + +#endif // BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) + } // namespace content
diff --git a/content/browser/media/media_interface_proxy.h b/content/browser/media/media_interface_proxy.h index 859fb07..431a3ba0 100644 --- a/content/browser/media/media_interface_proxy.h +++ b/content/browser/media/media_interface_proxy.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_BROWSER_MEDIA_MEDIA_INTERFACE_PROXY_H_ #define CONTENT_BROWSER_MEDIA_MEDIA_INTERFACE_PROXY_H_ +#include <map> #include <memory> #include <vector> @@ -23,9 +24,13 @@ class RenderFrameHost; -// This implements the media::mojom::InterfaceFactory interface for -// RenderFrameHostImpl. Upon media::mojom::InterfaceFactory calls, it will -// figure out where to forward to the interface requests. +// This implements the media::mojom::InterfaceFactory interface for a +// RenderFrameHostImpl. Upon InterfaceFactory calls, it will +// figure out where to forward to the interface requests. For example, +// - When |enable_standalone_cdm_service| is true, forward CDM request to a +// standalone CDM service rather than the general media service. +// - Forward CDM requests to different CDM service instances based on library +// CDM types. class MediaInterfaceProxy : public media::mojom::InterfaceFactory { public: // Constructs MediaInterfaceProxy and bind |this| to the |request|. When @@ -45,42 +50,59 @@ media::mojom::ContentDecryptionModuleRequest request) final; private: - // Get the |interface_factory_ptr_|. Returns null if expected error happened. - media::mojom::InterfaceFactory* GetMediaInterfaceFactory(); + using InterfaceFactoryPtr = media::mojom::InterfaceFactoryPtr; - // Get the |cdm_interface_factory_ptr_|. Returns null if expected error - // happened. - media::mojom::InterfaceFactory* GetCdmInterfaceFactory( - const std::string& key_system); - - // Callback for connection error from |interface_factory_ptr_| or - // |cdm_interface_factory_ptr_|. - void OnMediaServiceConnectionError(); - void OnCdmServiceConnectionError(); - + // Gets services provided by the browser (at RenderFrameHost level) to the + // mojo media (or CDM) service running remotely. service_manager::mojom::InterfaceProviderPtr GetFrameServices(); + // Gets the MediaService |interface_factory_ptr_|. Returns null if unexpected + // error happened. + InterfaceFactory* GetMediaInterfaceFactory(); + void ConnectToMediaService(); - void ConnectToCdmService(const std::string& key_system); + + // Callback for connection error from |interface_factory_ptr_|. + void OnMediaServiceConnectionError(); + +#if BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) + // Gets a CDM InterfaceFactory pointer for |key_system|. Returns null if + // unexpected error happened. + InterfaceFactory* GetCdmInterfaceFactory(const std::string& key_system); + + // Connects to the CDM service associated with |key_system|, adds the new + // InterfaceFactoryPtr to the |cdm_interface_factory_map_|, and returns the + // newly created InterfaceFactory pointer. Returns nullptr if unexpected error + // happened. + InterfaceFactory* ConnectToCdmService(const std::string& cdm_guid, + const base::FilePath& cdm_path); + + // Callback for connection error from the InterfaceFactoryPtr in the + // |cdm_interface_factory_map_| associated with |cdm_guid|. + void OnCdmServiceConnectionError(const std::string& cdm_guid); +#endif // BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) // Safe to hold a raw pointer since |this| is owned by RenderFrameHostImpl. - RenderFrameHost* render_frame_host_; + RenderFrameHost* const render_frame_host_; + + // Binding for incoming InterfaceFactoryRequest from the the RenderFrameImpl. + mojo::Binding<InterfaceFactory> binding_; // TODO(xhwang): Replace InterfaceProvider with a dedicated host interface. // See http://crbug.com/660573 std::vector<std::unique_ptr<media::MediaInterfaceProvider>> media_registries_; - mojo::Binding<media::mojom::InterfaceFactory> binding_; - - // InterfacePtr to the remote media::mojom::InterfaceFactory implementation + // InterfacePtr to the remote InterfaceFactory implementation // in the service named kMediaServiceName hosted in the process specified by // the "mojo_media_host" gn argument. Available options are browser, GPU and // utility processes. - media::mojom::InterfaceFactoryPtr interface_factory_ptr_; + InterfaceFactoryPtr interface_factory_ptr_; - // InterfacePtr to the remote media::mojom::InterfaceFactory implementation - // in the service named kCdmServiceName hosted in the utility process. - media::mojom::InterfaceFactoryPtr cdm_interface_factory_ptr_; +#if BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) + // CDM GUID to CDM InterfaceFactoryPtr mapping, where the InterfaceFactory + // instances live in the standalone kCdmServiceName service instances. + std::map<std::string, InterfaceFactoryPtr> cdm_interface_factory_map_; +#endif // BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE) base::ThreadChecker thread_checker_;
diff --git a/content/child/service_worker/service_worker_subresource_loader_unittest.cc b/content/child/service_worker/service_worker_subresource_loader_unittest.cc index 833d1249..bfa5b48 100644 --- a/content/child/service_worker/service_worker_subresource_loader_unittest.cc +++ b/content/child/service_worker/service_worker_subresource_loader_unittest.cc
@@ -12,14 +12,62 @@ #include "content/public/common/content_features.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_url_loader_client.h" +#include "mojo/common/data_pipe_utils.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "net/http/http_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "storage/browser/blob/blob_data_builder.h" +#include "storage/browser/blob/blob_data_handle.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { namespace { +// This class need to set ChildURLLoaderFactoryGetter. CreateLoaderAndStart() +// need to implement. todo(emim): Merge this and the one in +// service_worker_url_loader_job_unittest.cc. +class FakeNetworkURLLoaderFactory final : public mojom::URLLoaderFactory { + public: + FakeNetworkURLLoaderFactory() = default; + + // mojom::URLLoaderFactory implementation. + void CreateLoaderAndStart(mojom::URLLoaderRequest request, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const ResourceRequest& url_request, + mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag& + traffic_annotation) override { + std::string headers = "HTTP/1.1 200 OK\n\n"; + net::HttpResponseInfo info; + info.headers = new net::HttpResponseHeaders( + net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length())); + ResourceResponseHead response; + response.headers = info.headers; + response.headers->GetMimeType(&response.mime_type); + client->OnReceiveResponse(response, base::nullopt, nullptr); + + std::string body = "this body came from the network"; + uint32_t bytes_written = body.size(); + mojo::DataPipe data_pipe; + data_pipe.producer_handle->WriteData(body.data(), &bytes_written, + MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); + client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle)); + + ResourceRequestCompletionStatus status; + status.error_code = net::OK; + client->OnComplete(status); + } + + void Clone(mojom::URLLoaderFactoryRequest factory) override { NOTREACHED(); } + + private: + DISALLOW_COPY_AND_ASSIGN(FakeNetworkURLLoaderFactory); +}; + class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { public: FakeControllerServiceWorker() = default; @@ -31,6 +79,22 @@ void CloseAllBindings() { bindings_.CloseAllBindings(); } + // Tells this controller to respond to fetch events with network fallback. + // i.e., simulate the service worker not calling respondWith(). + void RespondWithFallback() { + response_mode_ = ResponseMode::kFallbackResponse; + } + + // Tells this controller to respond to fetch events with the specified stream. + void RespondWithStream( + blink::mojom::ServiceWorkerStreamCallbackRequest callback_request, + mojo::ScopedDataPipeConsumerHandle consumer_handle) { + response_mode_ = ResponseMode::kStream; + stream_handle_ = blink::mojom::ServiceWorkerStreamHandle::New(); + stream_handle_->callback_request = std::move(callback_request); + stream_handle_->stream = std::move(consumer_handle); + } + // mojom::ControllerServiceWorker: void DispatchFetchEvent( const ServiceWorkerFetchRequest& request, @@ -38,7 +102,31 @@ DispatchFetchEventCallback callback) override { fetch_event_count_++; fetch_event_request_ = request; - std::move(callback).Run(SERVICE_WORKER_OK, base::Time()); + switch (response_mode_) { + case ResponseMode::kDefault: + std::move(callback).Run(SERVICE_WORKER_OK, base::Time()); + return; + case ResponseMode::kStream: + response_callback->OnResponseStream( + ServiceWorkerResponse( + base::MakeUnique<std::vector<GURL>>(), 200, "OK", + network::mojom::FetchResponseType::kDefault, + base::MakeUnique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */, + 0 /* blob_size */, nullptr /* blob */, + blink::kWebServiceWorkerResponseErrorUnknown, base::Time(), + false /* response_is_in_cache_storage */, + std::string() /* response_cache_storage_cache_name */, + base::MakeUnique< + ServiceWorkerHeaderList>() /* cors_exposed_header_names */), + std::move(stream_handle_), base::Time::Now()); + std::move(callback).Run(SERVICE_WORKER_OK, base::Time()); + return; + case ResponseMode::kFallbackResponse: + response_callback->OnFallback(base::Time::Now()); + std::move(callback).Run(SERVICE_WORKER_OK, base::Time::Now()); + return; + } + NOTREACHED(); } int fetch_event_count() const { return fetch_event_count_; } @@ -47,9 +135,16 @@ } private: + enum class ResponseMode { kDefault, kStream, kFallbackResponse }; + + ResponseMode response_mode_ = ResponseMode::kDefault; + int fetch_event_count_ = 0; ServiceWorkerFetchRequest fetch_event_request_; mojo::BindingSet<mojom::ControllerServiceWorker> bindings_; + // For ResponseMode::kStream. + blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_; + DISALLOW_COPY_AND_ASSIGN(FakeControllerServiceWorker); }; @@ -97,8 +192,26 @@ } // namespace +// Returns typical response info for a resource load that went through a service +// worker. +std::unique_ptr<ResourceResponseHead> CreateResponseInfoFromServiceWorker() { + auto head = std::make_unique<ResourceResponseHead>(); + head->was_fetched_via_service_worker = true; + head->was_fallback_required_by_service_worker = false; + head->url_list_via_service_worker = std::vector<GURL>(); + head->response_type_via_service_worker = + network::mojom::FetchResponseType::kDefault; + // TODO(emim): start and ready time should be set. + head->service_worker_start_time = base::TimeTicks(); + head->service_worker_ready_time = base::TimeTicks(); + head->is_in_cache_storage = false; + head->cache_storage_cache_name = std::string(); + head->did_service_worker_navigation_preload = false; + return head; +} + class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { - public: + protected: ServiceWorkerSubresourceLoaderTest() : fake_container_host_(&fake_controller_) {} ~ServiceWorkerSubresourceLoaderTest() override = default; @@ -106,8 +219,12 @@ void SetUp() override { feature_list_.InitAndEnableFeature(features::kNetworkService); + mojom::URLLoaderFactoryPtr fake_loader_factory; + mojo::MakeStrongBinding(base::MakeUnique<FakeNetworkURLLoaderFactory>(), + MakeRequest(&fake_loader_factory)); loader_factory_getter_ = - base::MakeRefCounted<ChildURLLoaderFactoryGetterImpl>(); + base::MakeRefCounted<ChildURLLoaderFactoryGetterImpl>( + std::move(fake_loader_factory), nullptr); controller_connector_ = base::MakeRefCounted<ControllerServiceWorkerConnector>( &fake_container_host_); @@ -123,7 +240,6 @@ request.method = method; mojom::URLLoaderPtr url_loader; - TestURLLoaderClient url_loader_client; ServiceWorkerSubresourceLoaderFactory loader_factory( controller_connector_, loader_factory_getter_, request.url.GetOrigin(), @@ -131,7 +247,7 @@ base::RefCountedData<storage::mojom::BlobRegistryPtr>>()); loader_factory.CreateLoaderAndStart( mojo::MakeRequest(&url_loader), 0, 0, mojom::kURLLoadOptionNone, - request, url_loader_client.CreateInterfacePtr(), + request, url_loader_client_.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); base::RunLoop().RunUntilIdle(); @@ -139,7 +255,27 @@ EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method); } - protected: + void ExpectResponseInfo(const ResourceResponseHead& info, + const ResourceResponseHead& expected_info) { + EXPECT_EQ(expected_info.was_fetched_via_service_worker, + info.was_fetched_via_service_worker); + EXPECT_EQ(expected_info.was_fallback_required_by_service_worker, + info.was_fallback_required_by_service_worker); + EXPECT_EQ(expected_info.url_list_via_service_worker, + info.url_list_via_service_worker); + EXPECT_EQ(expected_info.response_type_via_service_worker, + info.response_type_via_service_worker); + EXPECT_EQ(expected_info.service_worker_start_time, + info.service_worker_start_time); + EXPECT_EQ(expected_info.service_worker_ready_time, + info.service_worker_ready_time); + EXPECT_EQ(expected_info.is_in_cache_storage, info.is_in_cache_storage); + EXPECT_EQ(expected_info.cache_storage_cache_name, + info.cache_storage_cache_name); + EXPECT_EQ(expected_info.did_service_worker_navigation_preload, + info.did_service_worker_navigation_preload); + } + TestBrowserThreadBundle thread_bundle_; scoped_refptr<ChildURLLoaderFactoryGetter> loader_factory_getter_; @@ -148,6 +284,8 @@ scoped_refptr<ControllerServiceWorkerConnector> controller_connector_; base::test::ScopedFeatureList feature_list_; + TestURLLoaderClient url_loader_client_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSubresourceLoaderTest); }; @@ -159,9 +297,11 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, DropController) { TestRequest(GURL("https://www.example.com/foo.html"), "GET"); + url_loader_client_.Unbind(); EXPECT_EQ(1, fake_controller_.fetch_event_count()); EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count()); TestRequest(GURL("https://www.example.com/foo2.html"), "GET"); + url_loader_client_.Unbind(); EXPECT_EQ(2, fake_controller_.fetch_event_count()); EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count()); @@ -175,6 +315,52 @@ EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count()); } +TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse) { + // Construct the Stream to respond with. + const char kResponseBody[] = "Here is sample text for the Stream."; + blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback; + mojo::DataPipe data_pipe; + fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback), + std::move(data_pipe.consumer_handle)); + + // Perform the request. + TestRequest(GURL("https://www.example.com/foo.html"), "GET"); + + const ResourceResponseHead& info = url_loader_client_.response_head(); + EXPECT_EQ(200, info.headers->response_code()); + ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker()); + + // Write the body stream. + uint32_t written_bytes = sizeof(kResponseBody) - 1; + MojoResult mojo_result = data_pipe.producer_handle->WriteData( + kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE); + ASSERT_EQ(MOJO_RESULT_OK, mojo_result); + EXPECT_EQ(sizeof(kResponseBody) - 1, written_bytes); + stream_callback->OnCompleted(); + data_pipe.producer_handle.reset(); + + url_loader_client_.RunUntilComplete(); + EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code); + + // Test the body. + std::string response; + EXPECT_TRUE(url_loader_client_.response_body().is_valid()); + EXPECT_TRUE(mojo::common::BlockingCopyToString( + url_loader_client_.response_body_release(), &response)); + EXPECT_EQ(kResponseBody, response); +} + +// Test when the service worker responds with network fallback. +// i.e., does not call respondWith(). +TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) { + fake_controller_.RespondWithFallback(); + + // Perform the request. + TestRequest(GURL("https://www.example.com/foo.html"), "GET"); + // TODO(emim): It should add some expression to check whether this actually + // performed the fallback. +} + // TODO(kinuko): Add more tests. } // namespace content
diff --git a/content/common/media/cdm_info.cc b/content/common/media/cdm_info.cc index fb03e84..3d8fdc3 100644 --- a/content/common/media/cdm_info.cc +++ b/content/common/media/cdm_info.cc
@@ -4,20 +4,27 @@ #include "content/public/common/cdm_info.h" +#include "base/guid.h" +#include "base/logging.h" + namespace content { CdmInfo::CdmInfo(const std::string& type, + const std::string& guid, const base::Version& version, const base::FilePath& path, const std::vector<std::string>& supported_codecs, const std::string& supported_key_system, bool supports_sub_key_systems) : type(type), + guid(guid), version(version), path(path), supported_codecs(supported_codecs), supported_key_system(supported_key_system), - supports_sub_key_systems(supports_sub_key_systems) {} + supports_sub_key_systems(supports_sub_key_systems) { + DCHECK(base::IsValidGUID(guid)); +} CdmInfo::CdmInfo(const CdmInfo& other) = default;
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h index ba61eeb..cd4f1d4f9 100644 --- a/content/public/common/cdm_info.h +++ b/content/public/common/cdm_info.h
@@ -17,6 +17,7 @@ // Represents a Content Decryption Module implementation and its capabilities. struct CONTENT_EXPORT CdmInfo { CdmInfo(const std::string& type, + const std::string& guid, const base::Version& version, const base::FilePath& path, const std::vector<std::string>& supported_codecs, @@ -28,6 +29,9 @@ // Type of the CDM (e.g. Widevine). std::string type; + // A version 4 GUID to uniquely identify this type of CDM. + std::string guid; + // Version of the CDM. May be empty if the version is not known. base::Version version;
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc index 2534d2b..e89d74b 100644 --- a/content/utility/utility_service_factory.cc +++ b/content/utility/utility_service_factory.cc
@@ -4,6 +4,8 @@ #include "content/utility/utility_service_factory.h" +#include <memory> + #include "base/bind.h" #include "base/command_line.h" #include "content/child/child_process.h" @@ -24,18 +26,12 @@ #include "services/video_capture/service_impl.h" #if BUILDFLAG(ENABLE_LIBRARY_CDMS) -#include "base/memory/ptr_util.h" -#include "media/base/scoped_callback_runner.h" #include "media/cdm/cdm_adapter_factory.h" // nogncheck -#include "media/cdm/cdm_helpers.h" // nogncheck #include "media/mojo/features.h" // nogncheck #include "media/mojo/interfaces/constants.mojom.h" // nogncheck -#include "media/mojo/interfaces/output_protection.mojom.h" // nogncheck -#include "media/mojo/interfaces/platform_verification.mojom.h" // nogncheck #include "media/mojo/services/media_service.h" // nogncheck -#include "media/mojo/services/mojo_cdm_allocator.h" // nogncheck +#include "media/mojo/services/mojo_cdm_helper.h" // nogncheck #include "media/mojo/services/mojo_media_client.h" // nogncheck -#include "services/service_manager/public/cpp/connect.h" #endif namespace { @@ -55,112 +51,9 @@ static_assert(BUILDFLAG(ENABLE_STANDALONE_CDM_SERVICE), ""); static_assert(BUILDFLAG(ENABLE_MOJO_CDM), ""); -// Helper class that connects the CDM to various auxiliary services. All -// additional services (FileIO, memory allocation, output protection, and -// platform verification) are lazily created. -class MojoCdmHelper : public media::CdmAuxiliaryHelper { - public: - explicit MojoCdmHelper( - service_manager::mojom::InterfaceProvider* interface_provider) - : interface_provider_(interface_provider) {} - ~MojoCdmHelper() override = default; - - // CdmAuxiliaryHelper implementation. - std::unique_ptr<media::CdmFileIO> CreateCdmFileIO( - cdm::FileIOClient* client) override { - // TODO(jrummell): Hook up File IO. http://crbug.com/479923. - return nullptr; - } - - cdm::Buffer* CreateCdmBuffer(size_t capacity) override { - return GetAllocator()->CreateCdmBuffer(capacity); - } - - std::unique_ptr<media::VideoFrameImpl> CreateCdmVideoFrame() override { - return GetAllocator()->CreateCdmVideoFrame(); - } - - void QueryStatus(QueryStatusCB callback) override { - QueryStatusCB scoped_callback = - media::ScopedCallbackRunner(std::move(callback), false, 0, 0); - if (!ConnectToOutputProtection()) - return; - - output_protection_->QueryStatus(std::move(scoped_callback)); - } - - void EnableProtection(uint32_t desired_protection_mask, - EnableProtectionCB callback) override { - EnableProtectionCB scoped_callback = - media::ScopedCallbackRunner(std::move(callback), false); - if (!ConnectToOutputProtection()) - return; - - output_protection_->EnableProtection(desired_protection_mask, - std::move(scoped_callback)); - } - - void ChallengePlatform(const std::string& service_id, - const std::string& challenge, - ChallengePlatformCB callback) override { - ChallengePlatformCB scoped_callback = - media::ScopedCallbackRunner(std::move(callback), false, "", "", ""); - if (!ConnectToPlatformVerification()) - return; - - platform_verification_->ChallengePlatform(service_id, challenge, - std::move(scoped_callback)); - } - - void GetStorageId(uint32_t version, StorageIdCB callback) override { - StorageIdCB scoped_callback = media::ScopedCallbackRunner( - std::move(callback), version, std::vector<uint8_t>()); - // TODO(jrummell): Hook up GetStorageId() once added to the mojo interface. - // http://crbug.com/478960. - } - - private: - // All services are created lazily. - media::CdmAllocator* GetAllocator() { - if (!allocator_) - allocator_ = base::MakeUnique<media::MojoCdmAllocator>(); - return allocator_.get(); - } - - bool ConnectToOutputProtection() { - if (!output_protection_attempted_) { - output_protection_attempted_ = true; - service_manager::GetInterface<media::mojom::OutputProtection>( - interface_provider_, &output_protection_); - } - return output_protection_.is_bound(); - } - - bool ConnectToPlatformVerification() { - if (!platform_verification_attempted_) { - platform_verification_attempted_ = true; - service_manager::GetInterface<media::mojom::PlatformVerification>( - interface_provider_, &platform_verification_); - } - return platform_verification_.is_bound(); - } - - // Provides interfaces when needed. - service_manager::mojom::InterfaceProvider* interface_provider_; - - // Keep track if connection to the Mojo service has been attempted once. - // The service may not exist, or may fail later. - bool output_protection_attempted_ = false; - bool platform_verification_attempted_ = false; - - std::unique_ptr<media::CdmAllocator> allocator_; - media::mojom::OutputProtectionPtr output_protection_; - media::mojom::PlatformVerificationPtr platform_verification_; -}; - std::unique_ptr<media::CdmAuxiliaryHelper> CreateCdmHelper( service_manager::mojom::InterfaceProvider* interface_provider) { - return base::MakeUnique<MojoCdmHelper>(interface_provider); + return std::make_unique<media::MojoCdmHelper>(interface_provider); } class CdmMojoMediaClient final : public media::MojoMediaClient { @@ -170,7 +63,7 @@ std::unique_ptr<media::CdmFactory> CreateCdmFactory( service_manager::mojom::InterfaceProvider* host_interfaces) override { - return base::MakeUnique<media::CdmAdapterFactory>( + return std::make_unique<media::CdmAdapterFactory>( base::Bind(&CreateCdmHelper, host_interfaces)); } }; @@ -204,7 +97,7 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) service_manager::EmbeddedServiceInfo info; info.factory = base::Bind(&CreateCdmService); - services->insert(std::make_pair(media::mojom::kCdmServiceName, info)); + services->emplace(media::mojom::kCdmServiceName, info); #endif service_manager::EmbeddedServiceInfo shape_detection_info;
diff --git a/gpu/ipc/service/gpu_vsync_provider_win.cc b/gpu/ipc/service/gpu_vsync_provider_win.cc index 9adfece..9fec2d2 100644 --- a/gpu/ipc/service/gpu_vsync_provider_win.cc +++ b/gpu/ipc/service/gpu_vsync_provider_win.cc
@@ -25,6 +25,14 @@ // Default v-sync interval used when there is no history of v-sync timestamps. const int kDefaultInterval = 16666; +// Occasionally DWM stops advancing qpcVBlank timestamp. The existing +// implementation can cope with that by adjusting the qpcVBlank value forward +// by a number of v-sync intervals, although the accuracy of adjustment depends +// on accuracy of the calculated v-sync interval. To avoid accumulating the +// error, any DWM values that are more than the threshold number of intervals +// in the past are ignored. +const int kMissingDwmTimestampsThreshold = 7; + // from <D3dkmthk.h> typedef LONG NTSTATUS; typedef UINT D3DKMT_HANDLE; @@ -93,7 +101,7 @@ void AddTimestamp(base::TimeTicks timestamp); void AddInterval(base::TimeDelta interval); base::TimeDelta GetAverageInterval() const; - void ClearIntervalHistory(); + void ClearHistory(); bool GetDisplayFrequency(const wchar_t* device_name, DWORD* frequency); void UpdateCurrentDisplayFrequency(); @@ -139,15 +147,59 @@ base::TimeDelta min_accepted_interval_; base::TimeDelta max_accepted_interval_; - // History of recent deltas between timestamps which is used to calculate the - // average v-sync interval and organized as a circular buffer. - static const size_t kIntervalHistorySize = 60; - base::TimeDelta interval_history_[kIntervalHistorySize]; - size_t history_index_ = 0; - size_t history_size_ = 0; + // A simple circular buffer for storing a number of recent v-sync intervals + // or DWM adjustment deltas and finding an average of them. + class TimeDeltaRingBuffer { + public: + TimeDeltaRingBuffer() = default; + ~TimeDeltaRingBuffer() = default; - // Rolling sum of intervals in the circular buffer above. - base::TimeDelta rolling_interval_sum_; + void Add(base::TimeDelta value) { + if (size_ == kMaxSize) { + rolling_sum_ -= values_[next_index_]; + } else { + size_++; + } + + values_[next_index_] = value; + rolling_sum_ += value; + next_index_ = (next_index_ + 1) % kMaxSize; + } + + void Clear() { + rolling_sum_ = base::TimeDelta(); + next_index_ = 0; + size_ = 0; + } + + base::TimeDelta GetAverage() const { + if (size_ == 0) + return base::TimeDelta(); + + return rolling_sum_ / size_; + } + + private: + enum { kMaxSize = 60 }; + + base::TimeDelta values_[kMaxSize]; + size_t next_index_ = 0; + size_t size_ = 0; + + // Rolling sum of TimeDelta values in the circular buffer above. + base::TimeDelta rolling_sum_; + + DISALLOW_COPY_AND_ASSIGN(TimeDeltaRingBuffer); + }; + + // History of recent deltas between timestamps used to calculate the average + // v-sync interval. + TimeDeltaRingBuffer recent_intervals_; + + // History of recent DWM adjustments used to calculate the average adjustment. + TimeDeltaRingBuffer recent_adjustments_; + + DISALLOW_COPY_AND_ASSIGN(GpuVSyncWorker); }; GpuVSyncWorker::GpuVSyncWorker( @@ -289,27 +341,19 @@ if (interval < min_accepted_interval_ || interval > max_accepted_interval_) return; - if (history_size_ == kIntervalHistorySize) { - rolling_interval_sum_ -= interval_history_[history_index_]; - } else { - history_size_++; - } - - interval_history_[history_index_] = interval; - rolling_interval_sum_ += interval; - history_index_ = (history_index_ + 1) % kIntervalHistorySize; + recent_intervals_.Add(interval); } -void GpuVSyncWorker::ClearIntervalHistory() { +void GpuVSyncWorker::ClearHistory() { last_timestamp_ = base::TimeTicks(); - rolling_interval_sum_ = base::TimeDelta(); - history_index_ = 0; - history_size_ = 0; + recent_intervals_.Clear(); + recent_adjustments_.Clear(); } base::TimeDelta GpuVSyncWorker::GetAverageInterval() const { - return !rolling_interval_sum_.is_zero() - ? rolling_interval_sum_ / history_size_ + base::TimeDelta average_interval = recent_intervals_.GetAverage(); + return !average_interval.is_zero() + ? average_interval : base::TimeDelta::FromMicroseconds(kDefaultInterval); } @@ -341,11 +385,10 @@ current_display_frequency_ = frequency; base::TimeDelta interval = base::TimeDelta::FromMicroseconds( base::Time::kMicrosecondsPerSecond / static_cast<double>(frequency)); - ClearIntervalHistory(); + ClearHistory(); min_accepted_interval_ = interval * 0.8; max_accepted_interval_ = interval * 1.2; - AddInterval(interval); } } @@ -366,14 +409,22 @@ base::TimeDelta adjustment; if (use_dwm && GetDwmVBlankTimestamp(×tamp)) { - // Timestamp comes from DwmGetCompositionTimingInfo and apparently it might - // be up to 2-3 vsync cycles in the past or in the future. - // The adjustment formula was suggested here: - // http://www.vsynctester.com/firefoxisbroken.html base::TimeDelta interval = GetAverageInterval(); - adjustment = - ((now - timestamp + interval / 8) % interval + interval) % interval - - interval / 8; + if (now - timestamp > interval * kMissingDwmTimestampsThreshold) { + // DWM timestamp is too far in the past. Ignore it and use average + // historical adjustment to be applied to |now| time to estimate + // the v-sync timestamp. + adjustment = recent_adjustments_.GetAverage(); + } else { + // Timestamp comes from DwmGetCompositionTimingInfo and apparently it + // might be a few v-sync cycles in the past or in the future. + // The adjustment formula was suggested here: + // http://www.vsynctester.com/firefoxisbroken.html + adjustment = + ((now - timestamp + interval / 8) % interval + interval) % interval - + interval / 8; + recent_adjustments_.Add(adjustment); + } timestamp = now - adjustment; } else { // Not using DWM. @@ -382,11 +433,13 @@ AddTimestamp(timestamp); - TRACE_EVENT1("gpu", "GpuVSyncWorker::SendGpuVSyncUpdate", "adjustment", - adjustment.ToInternalValue()); + base::TimeDelta average_interval = GetAverageInterval(); + TRACE_EVENT2("gpu", "GpuVSyncWorker::SendGpuVSyncUpdate", "adjustment", + adjustment.InMicroseconds(), "interval", + average_interval.InMicroseconds()); - DCHECK_GT(GetAverageInterval().InMillisecondsF(), 0); - InvokeCallbackAndReschedule(timestamp, GetAverageInterval()); + DCHECK_GT(average_interval.InMillisecondsF(), 0); + InvokeCallbackAndReschedule(timestamp, average_interval); } void GpuVSyncWorker::InvokeCallbackAndReschedule(base::TimeTicks timestamp, @@ -461,7 +514,7 @@ current_adapter_handle_ = 0; current_device_name_.clear(); - ClearIntervalHistory(); + ClearHistory(); } }
diff --git a/ios/tools/coverage/coverage.py b/ios/tools/coverage/coverage.py index 3bb3bf5d..5706d30 100755 --- a/ios/tools/coverage/coverage.py +++ b/ios/tools/coverage/coverage.py
@@ -40,6 +40,10 @@ import subprocess import webbrowser +sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, + os.path.pardir, os.path.pardir, 'third_party')) +import jinja2 + BUILD_DIRECTORY = 'out/Coverage-iphonesimulator' DEFAULT_GOMA_JOBS = 50 @@ -64,6 +68,95 @@ # TODO(crbug.com/763957): Make test file identifiers configurable. TEST_FILES_POSTFIXES = ['unittest.mm', 'unittest.cc', 'egtest.mm'] +# The default name of the html coverage report for a directory. +DIRECTORY_COVERAGE_HTML_REPORT_NAME = 'coverage.html' + + +class _DirectoryCoverageReportHtmlGenerator(object): + """Excapsulates code coverage html report generation for a directory. + + The generated html has a table that contains all the code coverage of its + sub-directories and files. Please refer to ./example.html for an example of + the generated html file. + """ + + def __init__(self, css_path): + """Initializes _DirectoryCoverageReportHtmlGenerator object. + + This class assumes that the css file generated by 'llvm-cov show' is reused. + + Args: + css_path: A path to the css file. + """ + assert os.path.exists(css_path), ('css file: {} doesn\'t exist.' + .format(css_path)) + self._css_path = css_path + self._table_entries = [] + template_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), + 'html_templates') + + jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir), + trim_blocks=True) + self._header_template = jinja_env.get_template('header.html') + self._table_template = jinja_env.get_template('table.html') + self._footer_template = jinja_env.get_template('footer.html') + + def AddTableEntry(self, html_report_path, name, total_lines, executed_lines): + """Adds a file or directory entry to the directory html coverage report. + + Args: + html_report_path: A path to the file or directory's html report. + name: Base name of the file or directory. + total_lines: total number of lines. + executed_lines: executed number of lines. + """ + coverage = float(executed_lines) / total_lines + if coverage < 0.8: + color_class = 'column-entry-red' + elif coverage < 1: + color_class = 'column-entry-yellow' + elif coverage == 1: + color_class = 'column-entry-green' + else: + assert False, ('coverage cannot be greater than 100%, however, {} has ' + 'coverage: {}').format(html_report_path, coverage) + percentage_coverage = round(coverage * 100, 2) + + self._table_entries.append({'href': html_report_path, + 'name': name, + 'color_class': color_class, + 'total_lines': total_lines, + 'executed_lines': executed_lines, + 'percentage_coverage': percentage_coverage}) + + def WriteHtmlCoverageReport(self, output_path): + """Write html coverage report for the directory. + + In the report, sub-directories are displayed before files and within each + category, entries are sorted by coverage in ascending order. + + Args: + output_path: A path to the html report. + """ + dir_entries = [entry for entry in self._table_entries + if os.path.basename(entry['href']) == + DIRECTORY_COVERAGE_HTML_REPORT_NAME] + file_entries = [entry for entry in self._table_entries + if entry not in dir_entries] + + file_entries.sort( + key=lambda entry: float(entry['executed_lines']) / entry['total_lines']) + dir_entries.sort( + key=lambda entry: float(entry['executed_lines']) / entry['total_lines']) + + html_header = self._header_template.render(css_path=self._css_path) + html_table = self._table_template.render(dir_entries=dir_entries, + file_entries=file_entries) + html_footer = self._footer_template.render() + + with open(output_path, 'w') as html_file: + html_file.write(html_header + html_table + html_footer) + class _FileLineCoverageReport(object): """Encapsulates coverage calculations for files.""" @@ -165,7 +258,10 @@ def _CalculateCoverageForDirectory(self, path, line_coverage_result, file_line_coverage_report): - """Recursively calculate the line coverage for a directory. + """Recursively calculates the line coverage for a directory. + + Only directories that have non-zero number of total lines are included in + the report. Args: path: path to the directory. @@ -188,7 +284,7 @@ self._CalculateCoverageForDirectory(sub_path, line_coverage_result, file_line_coverage_report) - if os.path.isdir(sub_path): + if sub_path in line_coverage_result: sum_total_lines += line_coverage_result[sub_path]['total'] sum_executed_lines += line_coverage_result[sub_path]['executed'] elif file_line_coverage_report.ContainsFile(sub_path): @@ -197,8 +293,28 @@ sum_total_lines += total_lines sum_executed_lines += executed_lines - line_coverage_result[path] = {'total': sum_total_lines, - 'executed': sum_executed_lines} + if sum_total_lines != 0: + line_coverage_result[path] = {'total': sum_total_lines, + 'executed': sum_executed_lines} + + def GetListOfDirectories(self): + """Returns a list of directories in the report. + + Returns: + A list of directories. + """ + return self._coverage.keys() + + def ContainsDirectory(self, path): + """Returns True if the path is in the report. + + Args: + path: path to the directory. + + Returns: + True if the path is in the report. + """ + return path in self._coverage def GetCoverageForDirectory(self, path): """Returns tuple representing coverage for a directory. @@ -215,10 +331,10 @@ def _GenerateLineByLineFileCoverageInHtml( target, profdata_path, file_line_coverage_report, output_dir): - """Generate per file line-by-line coverage in html using 'llvm-cov show'. + """Generates per file line-by-line coverage in html using 'llvm-cov show'. For a file with absolute path /a/b/x.cc, a html report is generated as: - output_dir/a/b/x.cc.html. An index html file is also generated as: + output_dir/coverage/a/b/x.cc.html. An index html file is also generated as: output_dir/index.html. Args: @@ -226,8 +342,9 @@ profdata_path: A string representing the path to the profdata file. file_line_coverage_report: A FileLineCoverageReport object. output_dir: output directory for generated html files, the path needs to be - absolute or relative to the root of checkout. + an absolute path. """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' application_path = _GetApplicationBundlePath(target) binary_path = os.path.join(application_path, target) cmd = ['xcrun', 'llvm-cov', 'show', '-instr-profile', profdata_path, @@ -238,6 +355,113 @@ subprocess.check_call(cmd) +def _GeneratePerDirectoryCoverageHtmlReport(dir_line_coverage_report, + file_line_coverage_report, + output_dir): + """Generates per directory coverage report in html. + + For each directory, all its files or sub-directories that has non-zero number + of total lines are displayed. + + Args: + dir_line_coverage_report: A DirectoryLineCoverageReport object. + file_line_coverage_report: A FileLineCoverageReport object. + output_dir: output directory for generated html files, the path needs to be + an absolute path. + """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' + for dir_path in dir_line_coverage_report.GetListOfDirectories(): + _GenerateCoverageHtmlReportForDirectory(dir_path, dir_line_coverage_report, + file_line_coverage_report, + output_dir) + + +def _GenerateCoverageHtmlReportForDirectory(dir_path, dir_line_coverage_report, + file_line_coverage_report, + output_dir): + """Generates coverage report for directory in html. + + Args: + dir_path: A path to the directory. + dir_line_coverage_report: A DirectoryLineCoverageReport object. + file_line_coverage_report: A FileLineCoverageReport object. + output_dir: output directory for generated html files, the path needs to be + an absolute path. + """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' + css_path = os.path.join(output_dir, 'style.css') + html_generator = _DirectoryCoverageReportHtmlGenerator(css_path) + + for sub_name in os.listdir(dir_path): + sub_path = os.path.join(dir_path, sub_name) + sub_path_html_report_path = _GetCoverageHtmlReportPath( + sub_path, output_dir) + + if dir_line_coverage_report.ContainsDirectory(sub_path): + total_lines, executed_lines = ( + dir_line_coverage_report.GetCoverageForDirectory(sub_path)) + html_generator.AddTableEntry(sub_path_html_report_path, + os.path.basename(sub_path), + total_lines, + executed_lines) + elif file_line_coverage_report.ContainsFile(sub_path): + total_lines, executed_lines = ( + file_line_coverage_report.GetCoverageForFile(sub_path)) + html_generator.AddTableEntry(sub_path_html_report_path, + os.path.basename(sub_path), + total_lines, + executed_lines) + + html_generator.WriteHtmlCoverageReport( + _GetCoverageHtmlReportPath(dir_path, output_dir)) + + +def _GetCoverageHtmlReportPath(file_or_dir_path, output_dir): + """Given a file or directory, returns the corresponding html report path. + + Args: + file_or_dir_path: os path to a file or directory. + output_dir: output directory for generated html files, the path needs to be + an absolute path. + Returns: + A path to the corresponding coverage html report. + """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' + html_path = (os.path.join(os.path.abspath(output_dir), 'coverage') + + os.path.abspath(file_or_dir_path)) + if os.path.isdir(file_or_dir_path): + return os.path.join(html_path, DIRECTORY_COVERAGE_HTML_REPORT_NAME) + else: + return html_path + '.html' + + +def _OverwriteHtmlReportsIndexFile(top_level_dir, dir_line_coverage_report, + output_dir): + """Overwrites the index file to link to the report of the top level directory. + + Args: + top_level_dir: The top level directory to generate code coverage for. + dir_line_coverage_report: A DirectoryLineCoverageReport object. + output_dir: output directory for generated html files, the path needs to be + an absolute path. + """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' + css_path = os.path.join(output_dir, 'style.css') + index_html_generator = _DirectoryCoverageReportHtmlGenerator(css_path) + + html_report_path = _GetCoverageHtmlReportPath(top_level_dir, + output_dir) + total_lines, executed_lines = ( + dir_line_coverage_report.GetCoverageForDirectory(top_level_dir)) + index_html_generator.AddTableEntry( + html_report_path, os.path.basename(top_level_dir), total_lines, + executed_lines) + + index_file_path = os.path.join(output_dir, + 'index.html') + index_html_generator.WriteHtmlCoverageReport(index_file_path) + + def _CreateCoverageProfileDataForTarget(target, output_dir, jobs_count=None, gtest_filter=None): """Builds and runs target to generate the coverage profile data. @@ -245,7 +469,7 @@ Args: target: A string representing the name of the target to be tested. output_dir: A directory to store created coverage profile data file, the - path needs to be absolute or relative to the root of checkout. + path needs to be an absolute path. jobs_count: Number of jobs to run in parallel for building. If None, a default value is derived based on CPUs availability. gtest_filter: If present, only run unit tests whose full name matches the @@ -254,6 +478,7 @@ Returns: A string representing the absolute path to the generated profdata file. """ + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' _BuildTargetWithCoverageConfiguration(target, jobs_count) profraw_path = _GetProfileRawDataPathByRunningTarget(target, gtest_filter) profdata_path = _CreateCoverageProfileDataFromProfRawData(profraw_path, @@ -286,6 +511,9 @@ ------------------------------------------------------------------------------ In Total\t89\t85\t4.49%\t7\t6\t14.29%\t7\t6\t14.29%\t107\t99\t7.48% + NOTE: This method only includes files with non-zero total number of lines to + the report. + Args: target: A string representing the name of the target to be tested. profdata_path: A string representing the path to the profdata file. @@ -326,8 +554,9 @@ except ValueError: continue - executed_lines = total_lines - missed_lines - file_line_coverage_report.AddFile(file_name, total_lines, executed_lines) + if total_lines > 0: + executed_lines = total_lines - missed_lines + file_line_coverage_report.AddFile(file_name, total_lines, executed_lines) return file_line_coverage_report @@ -442,7 +671,7 @@ profraw_path: A string representing the absolute path to the profraw data file that is to be merged. output_dir: A directory to store created coverage profile data file, the - path needs to be absolute or relative to the root of checkout. + path needs to be an absolute path. Returns: A string representing the absolute path to the generated profdata file. @@ -452,6 +681,7 @@ """ print 'Creating the profile data file' + assert os.path.isabs(output_dir), 'output_dir must be an absolute path.' if not os.path.exists(output_dir): os.makedirs(output_dir) profdata_path = os.path.join(output_dir, PROFDATA_FILE_NAME) @@ -471,8 +701,8 @@ Returns: A string representing the absolute path to the root of checkout. """ - return os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, - os.pardir, os.pardir)) + return os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, + os.path.pardir, os.path.pardir)) def _GetApplicationBundlePath(target): @@ -808,14 +1038,15 @@ include_sources = include_paths + _GetSourcesOfBuildTargets(include_targets) exclude_sources = exclude_paths + _GetSourcesOfBuildTargets(exclude_targets) + output_dir_abspath = os.path.abspath(args.output_dir) profdata_path = args.reuse_profdata if profdata_path: assert os.path.exists(profdata_path), ('The provided profile data file: {} ' 'doesn\'t exist.').format( profdata_path) else: - profdata_path = _CreateCoverageProfileDataForTarget(target, args.output_dir, - jobs, args.gtest_filter) + profdata_path = _CreateCoverageProfileDataForTarget( + target, output_dir_abspath, jobs, args.gtest_filter) print 'Generating code coverge report' file_line_coverage_report = _GeneratePerFileLineCoverageReport( @@ -835,15 +1066,19 @@ _PrintLineCoverageStats(total, executed) _GenerateLineByLineFileCoverageInHtml( - target, profdata_path, file_line_coverage_report, args.output_dir) + target, profdata_path, file_line_coverage_report, output_dir_abspath) + _GeneratePerDirectoryCoverageHtmlReport( + dir_line_coverage_report, file_line_coverage_report, output_dir_abspath) + # The default index file is generated only for the list of source files, needs + # to overwrite it to display per directory code coverage breakdown. + _OverwriteHtmlReportsIndexFile(top_level_dir, dir_line_coverage_report, + output_dir_abspath) html_index_file_path = 'file://' + os.path.abspath( os.path.join(args.output_dir, 'index.html')) print 'index file for html report is generated as: {}'.format( html_index_file_path) - webbrowser.open(html_index_file_path) - if __name__ == '__main__': sys.exit(Main())
diff --git a/ios/tools/coverage/example.html b/ios/tools/coverage/example.html new file mode 100644 index 0000000..a5a3b3d3 --- /dev/null +++ b/ios/tools/coverage/example.html
@@ -0,0 +1,40 @@ +<!doctype html> +<html> + <head> + <meta name='viewport' content='width=device-width,initial-scale=1'> + <meta charset='UTF-8'> + <link rel='stylesheet' type='text/css' href='/Users/liaoyuke/bling/src/out/Coverage-iphonesimulator/html/style.css'> + </head> + <body> + <h2>Coverage Report</h2> + <p>Click <a href='http://clang.llvm.org/docs/SourceBasedCodeCoverage.html#interpreting-reports'>here</a> for information about interpreting this report.</p> + <div class='centered'> + <table> + <tr> + <td class='column-entry-left'>Directory Name</td> + <td class='column-entry'>Line Coverage</td> + </tr> + <tr class='light-row'> + <td> + <pre><a href='/Users/liaoyuke/bling/src/out/Coverage-iphonesimulator/html/coverage/Users/liaoyuke/bling/src/url/third_party/coverage.html'>third_party</a></pre> + </td> + <td class='column-entry-yellow'> + <pre> 90.31% (699/774)</pre> + </td> + </tr> + <tr> + <td class='column-entry-left'>File Name</td> + <td class='column-entry'>Line Coverage</td> + </tr> + <tr class='light-row'> + <td> + <pre><a href='/Users/liaoyuke/bling/src/out/Coverage-iphonesimulator/html/coverage/Users/liaoyuke/bling/src/url/url_canon_stdurl.cc.html'>url_canon_stdurl.cc</a></pre> + </td> + <td class='column-entry-yellow'> + <pre> 93.94% (124/132)</pre> + </td> + </tr> + </table> + </div> + </body> +</html> \ No newline at end of file
diff --git a/ios/tools/coverage/html_templates/footer.html b/ios/tools/coverage/html_templates/footer.html new file mode 100644 index 0000000..79532637 --- /dev/null +++ b/ios/tools/coverage/html_templates/footer.html
@@ -0,0 +1,4 @@ + </table> + </div> + </body> +</html> \ No newline at end of file
diff --git a/ios/tools/coverage/html_templates/header.html b/ios/tools/coverage/html_templates/header.html new file mode 100644 index 0000000..0d16a2fd --- /dev/null +++ b/ios/tools/coverage/html_templates/header.html
@@ -0,0 +1,12 @@ +<!doctype html> +<html> + <head> + <meta name='viewport' content='width=device-width,initial-scale=1'> + <meta charset='UTF-8'> + <link rel='stylesheet' type='text/css' href='{{ css_path }}'> + </head> + <body> + <h2>Coverage Report</h2> + <p>Click <a href='http://clang.llvm.org/docs/SourceBasedCodeCoverage.html#interpreting-reports'>here</a> for information about interpreting this report.</p> + <div class='centered'> + <table> \ No newline at end of file
diff --git a/ios/tools/coverage/html_templates/table.html b/ios/tools/coverage/html_templates/table.html new file mode 100644 index 0000000..3fcdfaa --- /dev/null +++ b/ios/tools/coverage/html_templates/table.html
@@ -0,0 +1,30 @@ +<table> + <tr> + <td class='column-entry-left'>Directory Name</td> + <td class='column-entry'>Line Coverage</td> + </tr> + {% for dir_entry in dir_entries %} + <tr class='light-row'> + <td> + <pre><a href='{{ dir_entry.href }}'>{{ dir_entry.name }}</a></pre> + </td> + <td class='{{ dir_entry.color_class }}'> + <pre> {{ dir_entry.percentage_coverage }}% ({{ dir_entry.executed_lines }}/{{ dir_entry.total_lines }})</pre> + </td> + </tr> + {% endfor %} + <tr> + <td class='column-entry-left'>File Name</td> + <td class='column-entry'>Line Coverage</td> + </tr> + {% for file_entry in file_entries %} + <tr class='light-row'> + <td> + <pre><a href='{{ file_entry.href }}'>{{ file_entry.name }}</a></pre> + </td> + <td class='{{ file_entry.color_class }}'> + <pre> {{ file_entry.percentage_coverage }}% ({{ file_entry.executed_lines }}/{{ file_entry.total_lines }})</pre> + </td> + </tr> + {% endfor %} +</table> \ No newline at end of file
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 0d8c66f..8aab9bd 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -281,7 +281,7 @@ // supported platforms. On platforms that do not support ECK, this feature has // no effect. const base::Feature kExternalClearKeyForTesting{ - "external-clear-key-for-testing", base::FEATURE_DISABLED_BY_DEFAULT}; + "ExternalClearKeyForTesting", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kSupportExperimentalCdmInterface{ "SupportExperimentalCdmInterface", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc index 0c1bdb9..c72f49f 100644 --- a/media/cdm/cdm_paths.cc +++ b/media/cdm/cdm_paths.cc
@@ -25,9 +25,9 @@ #endif const char kClearKeyCdmDisplayName[] = "Clear Key CDM"; - const char kClearKeyCdmType[] = "Clear Key CDM"; - +const char kClearKeyCdmGuid[] = "C1A6B4E3-FE48-4D53-9F52-244AEEAD5335"; +const char kClearKeyCdmDifferentGuid[] = "747C565D-34EE-4B0D-AC1E-4F9FB17DDB40"; const char kClearKeyCdmPepperMimeType[] = "application/x-ppapi-clearkey-cdm"; // Note: This file must be in sync with cdm_paths.gni.
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h index 0e6b9be5c..06e4985 100644 --- a/media/cdm/cdm_paths.h +++ b/media/cdm/cdm_paths.h
@@ -25,6 +25,13 @@ // The CDM type used to register Clear Key CDM. extern const char kClearKeyCdmType[]; +// The default GUID for Clear Key Cdm. +extern const char kClearKeyCdmGuid[]; + +// A different GUID for Clear Key Cdm for testing running different types of +// CDMs in the system. +extern const char kClearKeyCdmDifferentGuid[]; + // Pepper type for Clear Key CDM. // TODO(xhwang): Remove after switching to mojo CDM. extern const char kClearKeyCdmPepperMimeType[];
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index d96df62..22f1994 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -70,6 +70,8 @@ "org.chromium.externalclearkey.verifycdmhosttest"; const char kExternalClearKeyStorageIdTestKeySystem[] = "org.chromium.externalclearkey.storageidtest"; +const char kExternalClearKeyDifferentGuidTestKeySystem[] = + "org.chromium.externalclearkey.differentguid"; const int64_t kSecondsPerMinute = 60; const int64_t kMsPerSecond = 1000; @@ -256,7 +258,8 @@ key_system_string != kExternalClearKeyPlatformVerificationTestKeySystem && key_system_string != kExternalClearKeyCrashKeySystem && key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem && - key_system_string != kExternalClearKeyStorageIdTestKeySystem) { + key_system_string != kExternalClearKeyStorageIdTestKeySystem && + key_system_string != kExternalClearKeyDifferentGuidTestKeySystem) { DVLOG(1) << "Unsupported key system:" << key_system_string; return nullptr; } @@ -693,7 +696,7 @@ // that the session is properly closed. if (!last_session_id_.empty() && key_system_ == kExternalClearKeyCrashKeySystem) { - CHECK(false); + CHECK(false) << "Crash in decrypt-and-decode with crash key system."; } scoped_refptr<media::DecoderBuffer> buffer; @@ -857,6 +860,13 @@ CdmKeysInfo keys_info) { DVLOG(1) << __func__ << ": size = " << keys_info.size(); + // Crash if the special key ID "crash" is present. + const std::vector<uint8_t> kCrashKeyId{'c', 'r', 'a', 's', 'h'}; + for (const auto& key_info : keys_info) { + if (key_info->key_id == kCrashKeyId) + CHECK(false) << "Crash on special crash key ID."; + } + std::vector<cdm::KeyInformation> keys_vector; ConvertCdmKeysInfo(keys_info, &keys_vector); host_->OnSessionKeysChange(session_id.data(), session_id.length(),
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 533ac35..b4c22eb 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -112,6 +112,8 @@ sources += [ "mojo_cdm_allocator.cc", "mojo_cdm_allocator.h", + "mojo_cdm_helper.cc", + "mojo_cdm_helper.h", ] deps += [ "//media/cdm:cdm_api" ] }
diff --git a/media/mojo/services/mojo_cdm_helper.cc b/media/mojo/services/mojo_cdm_helper.cc new file mode 100644 index 0000000..0bb4836e --- /dev/null +++ b/media/mojo/services/mojo_cdm_helper.cc
@@ -0,0 +1,97 @@ +// Copyright 2017 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 "media/mojo/services/mojo_cdm_helper.h" + +#include "media/base/scoped_callback_runner.h" +#include "media/cdm/cdm_helpers.h" +#include "media/mojo/services/mojo_cdm_allocator.h" +#include "services/service_manager/public/cpp/connect.h" + +namespace media { + +MojoCdmHelper::MojoCdmHelper( + service_manager::mojom::InterfaceProvider* interface_provider) + : interface_provider_(interface_provider) {} + +MojoCdmHelper::~MojoCdmHelper() {} + +std::unique_ptr<CdmFileIO> MojoCdmHelper::CreateCdmFileIO( + cdm::FileIOClient* client) { + // TODO(jrummell): Hook up File IO. http://crbug.com/479923. + return nullptr; +} + +cdm::Buffer* MojoCdmHelper::CreateCdmBuffer(size_t capacity) { + return GetAllocator()->CreateCdmBuffer(capacity); +} + +std::unique_ptr<VideoFrameImpl> MojoCdmHelper::CreateCdmVideoFrame() { + return GetAllocator()->CreateCdmVideoFrame(); +} + +void MojoCdmHelper::QueryStatus(QueryStatusCB callback) { + QueryStatusCB scoped_callback = + ScopedCallbackRunner(std::move(callback), false, 0, 0); + if (!ConnectToOutputProtection()) + return; + + output_protection_->QueryStatus(std::move(scoped_callback)); +} + +void MojoCdmHelper::EnableProtection(uint32_t desired_protection_mask, + EnableProtectionCB callback) { + EnableProtectionCB scoped_callback = + ScopedCallbackRunner(std::move(callback), false); + if (!ConnectToOutputProtection()) + return; + + output_protection_->EnableProtection(desired_protection_mask, + std::move(scoped_callback)); +} + +void MojoCdmHelper::ChallengePlatform(const std::string& service_id, + const std::string& challenge, + ChallengePlatformCB callback) { + ChallengePlatformCB scoped_callback = + ScopedCallbackRunner(std::move(callback), false, "", "", ""); + if (!ConnectToPlatformVerification()) + return; + + platform_verification_->ChallengePlatform(service_id, challenge, + std::move(scoped_callback)); +} + +void MojoCdmHelper::GetStorageId(uint32_t version, StorageIdCB callback) { + StorageIdCB scoped_callback = ScopedCallbackRunner( + std::move(callback), version, std::vector<uint8_t>()); + // TODO(jrummell): Hook up GetStorageId() once added to the mojo interface. + // http://crbug.com/478960. +} + +CdmAllocator* MojoCdmHelper::GetAllocator() { + if (!allocator_) + allocator_ = base::MakeUnique<MojoCdmAllocator>(); + return allocator_.get(); +} + +bool MojoCdmHelper::ConnectToOutputProtection() { + if (!output_protection_attempted_) { + output_protection_attempted_ = true; + service_manager::GetInterface<mojom::OutputProtection>(interface_provider_, + &output_protection_); + } + return output_protection_.is_bound(); +} + +bool MojoCdmHelper::ConnectToPlatformVerification() { + if (!platform_verification_attempted_) { + platform_verification_attempted_ = true; + service_manager::GetInterface<mojom::PlatformVerification>( + interface_provider_, &platform_verification_); + } + return platform_verification_.is_bound(); +} + +} // namespace media
diff --git a/media/mojo/services/mojo_cdm_helper.h b/media/mojo/services/mojo_cdm_helper.h new file mode 100644 index 0000000..167fdfd --- /dev/null +++ b/media/mojo/services/mojo_cdm_helper.h
@@ -0,0 +1,68 @@ +// Copyright 2017 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 MEDIA_MOJO_SERVICES_MOJO_CDM_HELPER_H_ +#define MEDIA_MOJO_SERVICES_MOJO_CDM_HELPER_H_ + +#include <memory> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "media/cdm/cdm_auxiliary_helper.h" +#include "media/mojo/interfaces/output_protection.mojom.h" +#include "media/mojo/interfaces/platform_verification.mojom.h" +#include "media/mojo/services/media_mojo_export.h" + +namespace service_manager { +namespace mojom { +class InterfaceProvider; +} +} // namespace service_manager + +namespace media { + +// Helper class that connects the CDM to various auxiliary services. All +// additional services (FileIO, memory allocation, output protection, and +// platform verification) are lazily created. +class MEDIA_MOJO_EXPORT MojoCdmHelper final : public CdmAuxiliaryHelper { + public: + explicit MojoCdmHelper( + service_manager::mojom::InterfaceProvider* interface_provider); + ~MojoCdmHelper() final; + + // CdmAuxiliaryHelper implementation. + std::unique_ptr<media::CdmFileIO> CreateCdmFileIO( + cdm::FileIOClient* client) final; + cdm::Buffer* CreateCdmBuffer(size_t capacity) final; + std::unique_ptr<VideoFrameImpl> CreateCdmVideoFrame() final; + void QueryStatus(QueryStatusCB callback) final; + void EnableProtection(uint32_t desired_protection_mask, + EnableProtectionCB callback) final; + void ChallengePlatform(const std::string& service_id, + const std::string& challenge, + ChallengePlatformCB callback) final; + void GetStorageId(uint32_t version, StorageIdCB callback) final; + + private: + // All services are created lazily. + CdmAllocator* GetAllocator(); + bool ConnectToOutputProtection(); + bool ConnectToPlatformVerification(); + + // Provides interfaces when needed. + service_manager::mojom::InterfaceProvider* interface_provider_; + + // Keep track if connection to the Mojo service has been attempted once. + // The service may not exist, or may fail later. + bool output_protection_attempted_ = false; + bool platform_verification_attempted_ = false; + + std::unique_ptr<media::CdmAllocator> allocator_; + media::mojom::OutputProtectionPtr output_protection_; + media::mojom::PlatformVerificationPtr platform_verification_; +}; + +} // namespace media + +#endif // MEDIA_MOJO_SERVICES_MOJO_CDM_HELPER_H_
diff --git a/media/test/data/multiple_cdm_types.html b/media/test/data/multiple_cdm_types.html new file mode 100644 index 0000000..ad313ea6 --- /dev/null +++ b/media/test/data/multiple_cdm_types.html
@@ -0,0 +1,103 @@ +<!DOCTYPE html> +<title>Test running different types of CDM in the system</title> +<div id="console"></div> +<script src='eme_player_js/app_loader.js' type='text/javascript'></script> +<script type='text/javascript'> + + function log(message) { + let consoleElement = document.getElementById('console'); + let entry = document.createElement('div'); + entry.appendChild(document.createTextNode(message)); + consoleElement.appendChild(entry); + console.log(message); + } + + const EXTERNAL_CLEARKEY_DIFFERENTGUID + = 'org.chromium.externalclearkey.differentguid'; + const crashKeyId = 'crash'; + const normalJwkSet = Utils.createJWKData(KEY_ID, KEY); + const crashJwkSet = Utils.createJWKData(crashKeyId, KEY); + + var config = { + initDataTypes : [ 'keyids' ], + videoCapabilities: [{contentType: 'video/webm; codecs="vp8"'}], + persistentState: 'optional', + sessionTypes: ['temporary'], + }; + + function createMediaKeySession(key_system) { + var mediaKeySession; + return navigator.requestMediaKeySystemAccess(key_system, [config]) + .then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = Utils.createKeyIdsInitializationData(KEY_ID) + return access.createMediaKeys(); + }).then(function(result) { + log('CDM created'); + var mediaKeys = result; + mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + mediaKeySession.update(normalJwkSet); + }).then(function() { + return mediaKeySession; + }); + } + + log('Start test'); + + // Using EXTERNAL_CLEARKEY + var session1; + + // Both using EXTERNAL_CLEARKEY_DIFFERENTGUID + var session2; + var session3; + + // The following creates 3 MediaKeys instances each with a MediaKeySession. + // MediaKeys using different CDM GUID will run in different processes. + // |session1| uses EXTERNAL_CLEARKEY that is registered with the default GUID + // for Clear Key CDM. |session2/3| use EXTERNAL_CLEARKEY_DIFFERENTGUID that is + // registered with a different GUID. So |session1| will run in process1, and + // |session2/3| will run in process2. + // + // Then we send a special response |crashJwkSet| to session2 which will cause + // the process2 to crash. This will close both |session2/3| as they run in the + // same process. |session1| should not be affected. Then we try to create + // another MediaKeySession using EXTERNAL_CLEARKEY_DIFFERENTGUID, and the + // creation should work as a new process should be started. + + createMediaKeySession(EXTERNAL_CLEARKEY).then(function(session) { + log('Session1 created'); + session1 = session; + return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID); + }).then(function(session) { + log('Session2 created'); + session2 = session; + return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID); + }).then(function(session) { + log('Session3 created'); + session3 = session; + log('Crash session2'); + return session.update(crashJwkSet); + }).then(function() { + log('Session2 crashed'); + return session2.closed; + }).then(function() { + log('Session2 closed'); + return session3.closed; + }).then(function() { + log('Session3 also closed'); + return session1.update(normalJwkSet); + }).then(function() { + log('Session1 still works'); + return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID); + }).then(function(session) { + log('Can still create a session after crash'); + Utils.setResultInTitle('ENDED'); + }).catch(function(error) { + log('Error: ' + error); + Utils.failTest('Test failed: ' + error); + }); + +</script> +</html>
diff --git a/third_party/WebKit/LayoutTests/compositing/squashing/selection-repaint-with-gaps.html b/third_party/WebKit/LayoutTests/compositing/squashing/selection-repaint-with-gaps.html index b6fd71d9..192b55d21 100644 --- a/third_party/WebKit/LayoutTests/compositing/squashing/selection-repaint-with-gaps.html +++ b/third_party/WebKit/LayoutTests/compositing/squashing/selection-repaint-with-gaps.html
@@ -36,7 +36,7 @@ </div> <script> if (window.testRunner) { - testRunner.dumpAsText(); + testRunner.dumpAsTextWithPixelResults(); testRunner.waitUntilDone(); }
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png index a811512..c5d0b0f0 100644 --- a/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png +++ b/third_party/WebKit/LayoutTests/images/color-profile-background-image-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-composited-scrolling-container.html b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-composited-scrolling-container.html index 54afdb7..d4afee2 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-composited-scrolling-container.html +++ b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-composited-scrolling-container.html
@@ -1,9 +1,9 @@ -<!DOCTYPE html> +<!DOCTYPE html> <script src="../resources/text-based-repaint.js"></script> <input id="target" size="5" value="test test test"> <script> window.testIsAsync = true; -onload = runRepaintTest; +onload = runRepaintAndPixelTest; if (window.internals) window.internals.settings.setPreferCompositingToLCDTextEnabled(true);
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-non-composited-scrolling-container.html b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-non-composited-scrolling-container.html index be54fc7..53da250 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-non-composited-scrolling-container.html +++ b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-in-non-composited-scrolling-container.html
@@ -1,9 +1,9 @@ -<!DOCTYPE html> +<!DOCTYPE html> <script src="../resources/text-based-repaint.js"></script> <input id="target"size="5" value="test test test"> <script> window.testIsAsync = true; -onload = runRepaintTest; +onload = runRepaintAndPixelTest; if (window.internals) window.internals.settings.setPreferCompositingToLCDTextEnabled(false);
diff --git a/third_party/WebKit/LayoutTests/platform/android/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/android/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..4525ea5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/squashing/selection-repaint-with-gaps-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/squashing/selection-repaint-with-gaps-expected.png new file mode 100644 index 0000000..cf84bf13 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/squashing/selection-repaint-with-gaps-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png index 424b4db..cabe47b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png index c7e1f7b..5d8eaeae 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..effd75a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..044e2c9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index 66498a7..9c73ba8 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png index 424b4db..cabe47b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/compositing/squashing/selection-repaint-with-gaps-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/compositing/squashing/selection-repaint-with-gaps-expected.png new file mode 100644 index 0000000..1bbbef8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/compositing/squashing/selection-repaint-with-gaps-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png index a773132..08343bfa 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..e2c6c700 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..da7762af --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index 07a3c2c..05ebe12 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..74794c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..dd74d55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png index 47ed2d1..eedee93 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/masking/mask-repeat-space-padding-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png index cde34596..b2aeb5a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..d2cc6b04 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..4fcaf52 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index 0f4a16b..1df1cd43 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..74794c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..dd74d55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/squashing/selection-repaint-with-gaps-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/squashing/selection-repaint-with-gaps-expected.png new file mode 100644 index 0000000..4f49e56 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/squashing/selection-repaint-with-gaps-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png index eb90563..636b74b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/css3/masking/mask-repeat-space-padding-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png index 4dba2a8b..6f502775 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/background-repeat-with-background-color-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png index d8181498..5c897cc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png index 75c356c..5773e7e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png index 13c9b2e..3359ed2 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..02490f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..80def35 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png new file mode 100644 index 0000000..7b65507 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index 41f9297..8cde405 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png index f268586..73cbaf7a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png index 94f1612..e138bc81 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png index d8181498..5c897cc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/squashing/selection-repaint-with-gaps-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/squashing/selection-repaint-with-gaps-expected.png new file mode 100644 index 0000000..6db86be --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/squashing/selection-repaint-with-gaps-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png index 391076d..6dd1e66 100644 --- a/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/css3/masking/mask-repeat-space-padding-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png index f6ab2241..47bfe99 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/background-repeat-with-background-color-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png index 2304502..fe19eb5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png index 15b2a7c8..7d0f474 100644 --- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png index 6dd3d20b..af34a7c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png new file mode 100644 index 0000000..59ebd4a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png new file mode 100644 index 0000000..209e87d --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png index 8b8e6e0a..a8f389c6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index e6b8478..6a319b8 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png index 6965947..2699d76 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png index 54806de..0123a81 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-background-size-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png index 2304502..fe19eb5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/http/tests/misc/slow-loading-image-in-pattern-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-fallback.html b/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-fallback.html new file mode 100644 index 0000000..f84b925b --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-fallback.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<script src='../resources/testharness.js'></script> +<script src='../resources/testharnessreport.js'></script> +<script src='resources/shadow-dom.js'></script> +<script src='resources/focus-utils.js'></script> +<div id="log"></div> + +<input id="i0" tabindex=0 value="i0"> +<div id="fallback"> + <template data-mode="open"> + <slot id="s0" name="s0"> + <div id="x-foo"> + <template data-mode="open"> + <input id="a2" tabindex=3 value="a2"> + <slot id="s1" name="s1" tabindex=2> + <slot id="s2" name="s2"> + <input id="a1" slot="s2" value="a1"> + </slot> + </slot> + <input id="a0" tabindex=1 value="a0"> + </template> + </div> + </slot> + </template> +</div> + +<script> +'use strict'; + +test(() => { + let fallback = document.getElementById('fallback'); + convertTemplatesToShadowRootsWithin(fallback); + + let elements = [ + 'i0', + 'fallback/x-foo/a0', + 'fallback/x-foo/a1', + 'fallback/x-foo/a2' + ]; + + assert_focus_navigation_forward(elements); + elements.reverse(); + assert_focus_navigation_backward(elements); +}, 'Focus should cover assigned elements of an assigned slot, as well as elements that are directly assigned to a slot.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-slot.html b/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-slot.html new file mode 100644 index 0000000..48811e6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-slot-shadow-in-slot.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<script src='../resources/testharness.js'></script> +<script src='../resources/testharnessreport.js'></script> +<script src='resources/shadow-dom.js'></script> +<script src='resources/focus-utils.js'></script> +<div id="log"></div> + +<input id="i0" tabindex=0 value="i0"> +<div id="assigned"> + <template data-mode="open"> + <slot id="s0" name="s0"> + <div id="x-foo"> + <input id="a1" slot="s2" value="a1"> + <template data-mode="open"> + <input id="a2" tabindex=3 value="a2"> + <slot id="s1" name="s1" tabindex=2> + <slot id="s2" name="s2"></slot> + </slot> + <input id="a0" tabindex=1 value="a0"> + </template> + </div> + </slot> + </template> +</div> + +<script> +'use strict'; + +test(() => { + let assigned = document.getElementById('assigned'); + convertTemplatesToShadowRootsWithin(assigned); + + let elements = [ + 'i0', + 'assigned/x-foo/a0', + 'assigned/a1', + 'assigned/x-foo/a2' + ]; + + assert_focus_navigation_forward(elements); + elements.reverse(); + assert_focus_navigation_backward(elements); +}, 'Focus should cover assigned elements of an assigned slot, as well as elements that are directly assigned to a slot.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png deleted file mode 100644 index 9e5603dc..0000000 --- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-background-image-space-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index 0afb30b..66bfe74 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -61,6 +61,7 @@ #include "platform/loader/fetch/AccessControlStatus.h" #include "platform/runtime_enabled_features.h" #include "platform/scheduler/child/web_scheduler.h" +#include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityViolationReportingPolicy.h" #include "platform/wtf/AddressSanitizer.h" #include "platform/wtf/Assertions.h" @@ -395,9 +396,12 @@ String specifier = ToCoreStringWithNullCheck(v8_specifier); v8::Local<v8::Value> v8_referrer_url = v8_referrer->GetResourceName(); - String referrer_url; - if (v8_referrer_url->IsString()) - referrer_url = ToCoreString(v8::Local<v8::String>::Cast(v8_referrer_url)); + KURL referrer_url; + if (v8_referrer_url->IsString()) { + String referrer_url_str = + ToCoreString(v8::Local<v8::String>::Cast(v8_referrer_url)); + referrer_url = KURL(NullURL(), referrer_url_str); + } ReferrerScriptInfo referrer_info = ReferrerScriptInfo::FromV8HostDefinedOptions( context, v8_referrer->GetHostDefinedOptions());
diff --git a/third_party/WebKit/Source/core/CoreInitializer.h b/third_party/WebKit/Source/core/CoreInitializer.h index 2c99ec4..9b9d7c5 100644 --- a/third_party/WebKit/Source/core/CoreInitializer.h +++ b/third_party/WebKit/Source/core/CoreInitializer.h
@@ -31,6 +31,7 @@ #ifndef CoreInitializer_h #define CoreInitializer_h +#include "base/macros.h" #include "core/CoreExport.h" #include "platform/wtf/Allocator.h" @@ -60,7 +61,7 @@ class CORE_EXPORT CoreInitializer { USING_FAST_MALLOC(CoreInitializer); - WTF_MAKE_NONCOPYABLE(CoreInitializer); + DISALLOW_COPY_AND_ASSIGN(CoreInitializer); public: // Initialize must be called before GetInstance.
diff --git a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp index 8176720..90cea65 100644 --- a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp +++ b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp
@@ -142,7 +142,7 @@ void DynamicModuleResolver::ResolveDynamically( const String& specifier, - const String& referrer_url_str, + const KURL& referrer_url, const ReferrerScriptInfo& referrer_info, ScriptPromiseResolver* promise_resolver) { DCHECK(modulator_->GetScriptState()->GetIsolate()->InContext()) @@ -157,7 +157,6 @@ // Step 2.1. "Let url be the result of resolving a module specifier // given referencing script and specifier." [spec text] - KURL referrer_url = KURL(NullURL(), referrer_url_str); DCHECK(referrer_url.IsValid()); KURL url = Modulator::ResolveModuleSpecifier(specifier, referrer_url); if (!url.IsValid()) {
diff --git a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.h b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.h index 912a105..9bddfe2a 100644 --- a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.h +++ b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.h
@@ -8,6 +8,7 @@ #include "core/CoreExport.h" #include "platform/heap/Handle.h" #include "platform/heap/Visitor.h" +#include "platform/weborigin/KURL.h" #include "platform/wtf/text/WTFString.h" namespace blink { @@ -31,7 +32,7 @@ // Implements "HostImportModuleDynamically" semantics. // Should be called w/ a valid V8 context. void ResolveDynamically(const String& specifier, - const String& referrer_url, + const KURL& referrer_url, const ReferrerScriptInfo& referrer_info, ScriptPromiseResolver*);
diff --git a/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp b/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp index f60a51fbf..cb90687 100644 --- a/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp +++ b/third_party/WebKit/Source/core/dom/DynamicModuleResolverTest.cpp
@@ -23,6 +23,13 @@ constexpr const char* kTestReferrerURL = "https://example.com/referrer.js"; constexpr const char* kTestDependencyURL = "https://example.com/dependency.js"; +const KURL TestReferrerURL() { + return KURL(kParsedURLString, kTestReferrerURL); +} +const KURL TestDependencyURL() { + return KURL(kParsedURLString, kTestDependencyURL); +} + class DynamicModuleResolverTestModulator final : public DummyModulator { public: explicit DynamicModuleResolverTestModulator(ScriptState* script_state) @@ -42,7 +49,7 @@ ScriptState* GetScriptState() final { return script_state_.get(); } ModuleScript* GetFetchedModuleScript(const KURL& url) final { - EXPECT_EQ(kTestReferrerURL, url.GetString()); + EXPECT_EQ(TestReferrerURL(), url); ModuleScript* module_script = ModuleScript::CreateForTest( this, ScriptModule(), url, "nonce", kParserInserted, WebURLRequest::kFetchCredentialsModeOmit); @@ -51,7 +58,7 @@ void FetchTree(const ModuleScriptFetchRequest& request, ModuleTreeClient* client) final { - EXPECT_EQ(kTestDependencyURL, request.Url().GetString()); + EXPECT_EQ(TestDependencyURL(), request.Url()); pending_client_ = client; } @@ -194,19 +201,18 @@ NotReached::CreateFunction(scope.GetScriptState())); auto resolver = DynamicModuleResolver::Create(modulator); - resolver->ResolveDynamically("./dependency.js", kTestReferrerURL, + resolver->ResolveDynamically("./dependency.js", TestReferrerURL(), ReferrerScriptInfo(), promise_resolver); v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate()); EXPECT_FALSE(capture->WasCalled()); - KURL url(kParsedURLString, kTestDependencyURL); ScriptModule record = ScriptModule::Compile( - scope.GetIsolate(), "export const foo = 'hello';", url.GetString(), + scope.GetIsolate(), "export const foo = 'hello';", TestReferrerURL(), kSharableCrossOrigin, WebURLRequest::kFetchCredentialsModeOmit, "", kParserInserted, TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION); ModuleScript* module_script = ModuleScript::CreateForTest( - modulator, record, url, "nonce", kNotParserInserted, + modulator, record, TestDependencyURL(), "nonce", kNotParserInserted, WebURLRequest::kFetchCredentialsModeOmit); record.Instantiate(scope.GetScriptState()); EXPECT_FALSE(module_script->IsErrored()); @@ -230,7 +236,7 @@ capture->Bind()); auto resolver = DynamicModuleResolver::Create(modulator); - resolver->ResolveDynamically("invalid-specifier", kTestReferrerURL, + resolver->ResolveDynamically("invalid-specifier", TestReferrerURL(), ReferrerScriptInfo(), promise_resolver); v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate()); @@ -252,7 +258,7 @@ capture->Bind()); auto resolver = DynamicModuleResolver::Create(modulator); - resolver->ResolveDynamically("./dependency.js", kTestReferrerURL, + resolver->ResolveDynamically("./dependency.js", TestReferrerURL(), ReferrerScriptInfo(), promise_resolver); EXPECT_FALSE(capture->WasCalled()); @@ -278,18 +284,17 @@ capture->Bind()); auto resolver = DynamicModuleResolver::Create(modulator); - resolver->ResolveDynamically("./dependency.js", kTestReferrerURL, + resolver->ResolveDynamically("./dependency.js", TestReferrerURL(), ReferrerScriptInfo(), promise_resolver); EXPECT_FALSE(capture->WasCalled()); - KURL url(kParsedURLString, kTestDependencyURL); ScriptModule record = ScriptModule::Compile( - scope.GetIsolate(), "throw Error('bar')", url.GetString(), + scope.GetIsolate(), "throw Error('bar')", TestReferrerURL(), kSharableCrossOrigin, WebURLRequest::kFetchCredentialsModeOmit, "", kParserInserted, TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION); ModuleScript* module_script = ModuleScript::CreateForTest( - modulator, record, url, "nonce", kNotParserInserted, + modulator, record, TestDependencyURL(), "nonce", kNotParserInserted, WebURLRequest::kFetchCredentialsModeOmit); record.Instantiate(scope.GetScriptState()); EXPECT_FALSE(module_script->IsErrored());
diff --git a/third_party/WebKit/Source/core/dom/Modulator.h b/third_party/WebKit/Source/core/dom/Modulator.h index 0003b4bd..c7931fe 100644 --- a/third_party/WebKit/Source/core/dom/Modulator.h +++ b/third_party/WebKit/Source/core/dom/Modulator.h
@@ -111,7 +111,7 @@ // https://tc39.github.io/proposal-dynamic-import/#sec-hostimportmoduledynamically virtual void ResolveDynamically(const String& specifier, - const String& referrer_url, + const KURL&, const ReferrerScriptInfo&, ScriptPromiseResolver*) = 0;
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp b/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp index 24d8fcdf..5f50bcde 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp +++ b/third_party/WebKit/Source/core/dom/ModulatorImplBase.cpp
@@ -108,7 +108,7 @@ void ModulatorImplBase::ResolveDynamically( const String& specifier, - const String& referrer_url, + const KURL& referrer_url, const ReferrerScriptInfo& referrer_info, ScriptPromiseResolver* resolver) { dynamic_module_resolver_->ResolveDynamically(specifier, referrer_url,
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImplBase.h b/third_party/WebKit/Source/core/dom/ModulatorImplBase.h index 3c6c9fe..f751ddf 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImplBase.h +++ b/third_party/WebKit/Source/core/dom/ModulatorImplBase.h
@@ -60,7 +60,7 @@ ModuleGraphLevel, ModuleScriptLoaderClient*) override; void ResolveDynamically(const String& specifier, - const String& referrer_url, + const KURL&, const ReferrerScriptInfo&, ScriptPromiseResolver*) override; ScriptModule CompileModule(const String& script,
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.h b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.h index 85142d09..c6e93b6e 100644 --- a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.h +++ b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.h
@@ -5,6 +5,7 @@ #ifndef ObjectPaintInvalidator_h #define ObjectPaintInvalidator_h +#include "base/macros.h" #include "core/CoreExport.h" #include "platform/graphics/PaintInvalidationReason.h" #include "platform/wtf/Allocator.h" @@ -114,7 +115,7 @@ // will always invalidate raster after paint. class DisablePaintInvalidationStateAsserts { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(DisablePaintInvalidationStateAsserts); + DISALLOW_COPY_AND_ASSIGN(DisablePaintInvalidationStateAsserts); public: DisablePaintInvalidationStateAsserts();
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.cpp b/third_party/WebKit/Source/core/testing/DummyModulator.cpp index d2fb721..18a21b5 100644 --- a/third_party/WebKit/Source/core/testing/DummyModulator.cpp +++ b/third_party/WebKit/Source/core/testing/DummyModulator.cpp
@@ -95,7 +95,7 @@ } void DummyModulator::ResolveDynamically(const String&, - const String&, + const KURL&, const ReferrerScriptInfo&, ScriptPromiseResolver*) { NOTREACHED();
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.h b/third_party/WebKit/Source/core/testing/DummyModulator.h index d9c235e..3a49e25 100644 --- a/third_party/WebKit/Source/core/testing/DummyModulator.h +++ b/third_party/WebKit/Source/core/testing/DummyModulator.h
@@ -49,7 +49,7 @@ ModuleScriptLoaderClient*) override; bool HasValidContext() override; void ResolveDynamically(const String& specifier, - const String& referrer_url, + const KURL&, const ReferrerScriptInfo&, ScriptPromiseResolver*) override; ScriptModule CompileModule(const String& script,
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp index 6fe83ad..f2a9abe 100644 --- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
@@ -57,14 +57,14 @@ DedicatedWorkerThread::~DedicatedWorkerThread() {} +void DedicatedWorkerThread::ClearWorkerBackingThread() { + worker_backing_thread_ = nullptr; +} + WorkerOrWorkletGlobalScope* DedicatedWorkerThread::CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params) { return DedicatedWorkerGlobalScope::Create(this, std::move(creation_params), time_origin_); } -void DedicatedWorkerThread::ClearWorkerBackingThread() { - worker_backing_thread_ = nullptr; -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h index a827208..a0bccd4 100644 --- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h +++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h
@@ -53,14 +53,13 @@ return worker_object_proxy_; } - protected: + private: + friend class DedicatedWorkerThreadForTest; + DedicatedWorkerThread(ThreadableLoadingContext*, InProcessWorkerObjectProxy&); WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) override; - private: - friend class DedicatedWorkerThreadForTest; - std::unique_ptr<WorkerBackingThread> worker_backing_thread_; InProcessWorkerObjectProxy& worker_object_proxy_; };
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerThread.h b/third_party/WebKit/Source/core/workers/SharedWorkerThread.h index e8c6083..f14365e 100644 --- a/third_party/WebKit/Source/core/workers/SharedWorkerThread.h +++ b/third_party/WebKit/Source/core/workers/SharedWorkerThread.h
@@ -51,11 +51,10 @@ } void ClearWorkerBackingThread() override; - protected: + private: WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) override; - private: std::unique_ptr<WorkerBackingThread> worker_backing_thread_; String name_; };
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp index f6c5bc7d..e43e274 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp +++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -65,18 +65,6 @@ void ClearWorkerBackingThread() override {} - WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( - std::unique_ptr<GlobalScopeCreationParams> creation_params) final { - RefPtr<SecurityOrigin> security_origin = - SecurityOrigin::Create(creation_params->script_url); - return new ThreadedWorkletGlobalScope( - creation_params->script_url, creation_params->user_agent, - std::move(security_origin), this->GetIsolate(), this, - creation_params->worker_clients); - } - - bool IsOwningBackingThread() const final { return false; } - static void EnsureSharedBackingThread() { DCHECK(IsMainThread()); WorkletThreadHolder<ThreadedWorkletThreadForTest>::CreateForTest( @@ -121,6 +109,19 @@ ->Get(TaskType::kUnspecedTimer) ->PostTask(BLINK_FROM_HERE, CrossThreadBind(&testing::ExitRunLoop)); } + + private: + WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( + std::unique_ptr<GlobalScopeCreationParams> creation_params) final { + RefPtr<SecurityOrigin> security_origin = + SecurityOrigin::Create(creation_params->script_url); + return new ThreadedWorkletGlobalScope( + creation_params->script_url, creation_params->user_agent, + std::move(security_origin), this->GetIsolate(), this, + creation_params->worker_clients); + } + + bool IsOwningBackingThread() const final { return false; } }; class ThreadedWorkletMessagingProxyForTest
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.h b/third_party/WebKit/Source/core/workers/WorkerThread.h index e75af1c..72e29b95 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.h +++ b/third_party/WebKit/Source/core/workers/WorkerThread.h
@@ -184,18 +184,6 @@ protected: WorkerThread(ThreadableLoadingContext*, WorkerReportingProxy&); - // Factory method for creating a new worker context for the thread. - // Called on the worker thread. - virtual WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( - std::unique_ptr<GlobalScopeCreationParams>) = 0; - - // Returns true when this WorkerThread owns the associated - // WorkerBackingThread exclusively. If this function returns true, the - // WorkerThread initializes / shutdowns the backing thread. Otherwise - // workerBackingThread() should be initialized / shutdown properly - // out of this class. - virtual bool IsOwningBackingThread() const { return true; } - // Official moment of creation of worker: when the worker thread is created. // (https://w3c.github.io/hr-time/#time-origin) const double time_origin_; @@ -220,6 +208,18 @@ kReadyToShutdown, }; + // Factory method for creating a new worker context for the thread. + // Called on the worker thread. + virtual WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( + std::unique_ptr<GlobalScopeCreationParams>) = 0; + + // Returns true when this WorkerThread owns the associated + // WorkerBackingThread exclusively. If this function returns true, the + // WorkerThread initializes / shutdowns the backing thread. Otherwise + // the backing thread should be initialized / shutdown properly out of this + // class. + virtual bool IsOwningBackingThread() const { return true; } + // Posts a delayed task to forcibly terminate script execution in case the // normal shutdown sequence does not start within a certain time period. void ScheduleToTerminateScriptExecution();
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp index ac2d9b6..ee3c221 100644 --- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp
@@ -39,24 +39,6 @@ AnimationWorkletThread::~AnimationWorkletThread() {} -WorkerOrWorkletGlobalScope* AnimationWorkletThread::CreateWorkerGlobalScope( - std::unique_ptr<GlobalScopeCreationParams> creation_params) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"), - "AnimationWorkletThread::createWorkerGlobalScope"); - - RefPtr<SecurityOrigin> security_origin = - SecurityOrigin::Create(creation_params->script_url); - if (creation_params->starter_origin_privilege_data) { - security_origin->TransferPrivilegesFrom( - std::move(creation_params->starter_origin_privilege_data)); - } - - return AnimationWorkletGlobalScope::Create( - creation_params->script_url, creation_params->user_agent, - std::move(security_origin), this->GetIsolate(), this, - creation_params->worker_clients); -} - WorkerBackingThread& AnimationWorkletThread::GetWorkerBackingThread() { return *WorkletThreadHolder<AnimationWorkletThread>::GetInstance() ->GetThread(); @@ -95,4 +77,22 @@ Platform::Current()->CompositorThread()); } +WorkerOrWorkletGlobalScope* AnimationWorkletThread::CreateWorkerGlobalScope( + std::unique_ptr<GlobalScopeCreationParams> creation_params) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"), + "AnimationWorkletThread::createWorkerGlobalScope"); + + RefPtr<SecurityOrigin> security_origin = + SecurityOrigin::Create(creation_params->script_url); + if (creation_params->starter_origin_privilege_data) { + security_origin->TransferPrivilegesFrom( + std::move(creation_params->starter_origin_privilege_data)); + } + + return AnimationWorkletGlobalScope::Create( + creation_params->script_url, creation_params->user_agent, + std::move(security_origin), this->GetIsolate(), this, + creation_params->worker_clients); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h index 263b4a8..6e5a82c 100644 --- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h +++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h
@@ -34,14 +34,13 @@ static void CreateSharedBackingThreadForTest(); - protected: + private: + AnimationWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&); + WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) final; bool IsOwningBackingThread() const override { return false; } - - private: - AnimationWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h index 379e3ab..10bcb7c 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h
@@ -57,13 +57,12 @@ } void ClearWorkerBackingThread() override; - protected: + private: WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) override; InstalledScriptsManager* GetInstalledScriptsManager() override; - private: Persistent<ServiceWorkerGlobalScopeProxy> global_scope_proxy_; std::unique_ptr<WorkerBackingThread> worker_backing_thread_; std::unique_ptr<ServiceWorkerInstalledScriptsManager>
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h index f8cd5a9..477cd13b 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h
@@ -43,15 +43,14 @@ // the customers. static WebThread* GetSharedBackingThread(); - protected: + private: + AudioWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&); + WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) final; bool IsOwningBackingThread() const override { return false; } - private: - AudioWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&); - // This raw pointer gets assigned in EnsureSharedBackingThread() and manually // released by ClearSharedBackingThread(). static WebThread* s_backing_thread_;
diff --git a/third_party/WebKit/Source/platform/EventDispatchForbiddenScope.h b/third_party/WebKit/Source/platform/EventDispatchForbiddenScope.h index 6a384841..7486b0a 100644 --- a/third_party/WebKit/Source/platform/EventDispatchForbiddenScope.h +++ b/third_party/WebKit/Source/platform/EventDispatchForbiddenScope.h
@@ -5,6 +5,7 @@ #ifndef EventDispatchForbiddenScope_h #define EventDispatchForbiddenScope_h +#include "base/macros.h" #include "platform/PlatformExport.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Assertions.h" @@ -16,7 +17,7 @@ class EventDispatchForbiddenScope { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(EventDispatchForbiddenScope); + DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope); public: EventDispatchForbiddenScope() { @@ -55,7 +56,7 @@ class EventDispatchForbiddenScope { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(EventDispatchForbiddenScope); + DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope); public: EventDispatchForbiddenScope() {}
diff --git a/third_party/WebKit/Source/platform/ScriptForbiddenScope.h b/third_party/WebKit/Source/platform/ScriptForbiddenScope.h index f2bfd70..cdeb2c05 100644 --- a/third_party/WebKit/Source/platform/ScriptForbiddenScope.h +++ b/third_party/WebKit/Source/platform/ScriptForbiddenScope.h
@@ -5,6 +5,7 @@ #ifndef ScriptForbiddenScope_h #define ScriptForbiddenScope_h +#include "base/macros.h" #include "platform/PlatformExport.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/AutoReset.h" @@ -16,7 +17,7 @@ // and only to be used by the main thread. class PLATFORM_EXPORT ScriptForbiddenScope final { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptForbiddenScope); + DISALLOW_COPY_AND_ASSIGN(ScriptForbiddenScope); public: ScriptForbiddenScope() { Enter(); } @@ -24,7 +25,7 @@ class PLATFORM_EXPORT AllowUserAgentScript final { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(AllowUserAgentScript); + DISALLOW_COPY_AND_ASSIGN(AllowUserAgentScript); public: AllowUserAgentScript() { @@ -64,7 +65,7 @@ // its behalf. class PLATFORM_EXPORT ScriptForbiddenIfMainThreadScope final { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(ScriptForbiddenIfMainThreadScope); + DISALLOW_COPY_AND_ASSIGN(ScriptForbiddenIfMainThreadScope); public: ScriptForbiddenIfMainThreadScope() {
diff --git a/third_party/WebKit/Source/platform/audio/AudioSourceProvider.h b/third_party/WebKit/Source/platform/audio/AudioSourceProvider.h index 0034dc8..6f20c5b 100644 --- a/third_party/WebKit/Source/platform/audio/AudioSourceProvider.h +++ b/third_party/WebKit/Source/platform/audio/AudioSourceProvider.h
@@ -30,6 +30,7 @@ #define AudioSourceProvider_h #include <cstddef> +#include "base/macros.h" #include "platform/PlatformExport.h" #include "platform/wtf/Allocator.h" @@ -41,7 +42,7 @@ // Abstract base-class for a pull-model client. class PLATFORM_EXPORT AudioSourceProvider { USING_FAST_MALLOC(AudioSourceProvider); - WTF_MAKE_NONCOPYABLE(AudioSourceProvider); + DISALLOW_COPY_AND_ASSIGN(AudioSourceProvider); public: AudioSourceProvider() {}
diff --git a/third_party/WebKit/Source/platform/graphics/Path.h b/third_party/WebKit/Source/platform/graphics/Path.h index b9e1463..c44c2ae 100644 --- a/third_party/WebKit/Source/platform/graphics/Path.h +++ b/third_party/WebKit/Source/platform/graphics/Path.h
@@ -29,6 +29,7 @@ #ifndef Path_h #define Path_h +#include "base/macros.h" #include "platform/PlatformExport.h" #include "platform/geometry/FloatRoundedRect.h" #include "platform/graphics/GraphicsTypes.h" @@ -98,7 +99,7 @@ // vary depending on curvature and number of segments, but should never be // worse than that of the state-less method on Path. class PLATFORM_EXPORT PositionCalculator { - WTF_MAKE_NONCOPYABLE(PositionCalculator); + DISALLOW_COPY_AND_ASSIGN(PositionCalculator); USING_FAST_MALLOC(PositionCalculator); public:
diff --git a/third_party/WebKit/Source/platform/graphics/PathTraversalState.h b/third_party/WebKit/Source/platform/graphics/PathTraversalState.h index 26251c9..912d8044 100644 --- a/third_party/WebKit/Source/platform/graphics/PathTraversalState.h +++ b/third_party/WebKit/Source/platform/graphics/PathTraversalState.h
@@ -26,6 +26,7 @@ #ifndef PathTraversalState_h #define PathTraversalState_h +#include "base/macros.h" #include "platform/PlatformExport.h" #include "platform/geometry/FloatPoint.h" #include "platform/wtf/Allocator.h" @@ -34,7 +35,7 @@ class PLATFORM_EXPORT PathTraversalState final { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(PathTraversalState); + DISALLOW_COPY_AND_ASSIGN(PathTraversalState); public: enum PathTraversalAction {
diff --git a/third_party/WebKit/Source/platform/heap/StackFrameDepth.h b/third_party/WebKit/Source/platform/heap/StackFrameDepth.h index 4e0d5678..47ed658 100644 --- a/third_party/WebKit/Source/platform/heap/StackFrameDepth.h +++ b/third_party/WebKit/Source/platform/heap/StackFrameDepth.h
@@ -7,6 +7,7 @@ #include <stdint.h> #include <cstddef> +#include "base/macros.h" #include "build/build_config.h" #include "platform/PlatformExport.h" #include "platform/wtf/Allocator.h" @@ -86,7 +87,7 @@ class StackFrameDepthScope { STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(StackFrameDepthScope); + DISALLOW_COPY_AND_ASSIGN(StackFrameDepthScope); public: explicit StackFrameDepthScope(StackFrameDepth* depth) : depth_(depth) {
diff --git a/third_party/WebKit/Source/platform/wtf/Assertions.h b/third_party/WebKit/Source/platform/wtf/Assertions.h index 506fb0d8..9b81828 100644 --- a/third_party/WebKit/Source/platform/wtf/Assertions.h +++ b/third_party/WebKit/Source/platform/wtf/Assertions.h
@@ -31,7 +31,6 @@ #include "base/compiler_specific.h" #include "base/logging.h" -#include "platform/wtf/Noncopyable.h" #include "platform/wtf/WTFExport.h" // New code shouldn't use this function. This function will be deprecated. @@ -74,25 +73,13 @@ // Allow equality comparisons of Objects by reference or pointer, // interchangeably. This can be only used on types whose equality makes no // other sense than pointer equality. -#define DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(thisType) \ - inline bool operator==(const thisType& a, const thisType& b) { \ - return &a == &b; \ - } \ - inline bool operator==(const thisType& a, const thisType* b) { \ - return &a == b; \ - } \ - inline bool operator==(const thisType* a, const thisType& b) { \ - return a == &b; \ - } \ - inline bool operator!=(const thisType& a, const thisType& b) { \ - return !(a == b); \ - } \ - inline bool operator!=(const thisType& a, const thisType* b) { \ - return !(a == b); \ - } \ - inline bool operator!=(const thisType* a, const thisType& b) { \ - return !(a == b); \ - } +#define DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(Type) \ + inline bool operator==(const Type& a, const Type& b) { return &a == &b; } \ + inline bool operator==(const Type& a, const Type* b) { return &a == b; } \ + inline bool operator==(const Type* a, const Type& b) { return a == &b; } \ + inline bool operator!=(const Type& a, const Type& b) { return !(a == b); } \ + inline bool operator!=(const Type& a, const Type* b) { return !(a == b); } \ + inline bool operator!=(const Type* a, const Type& b) { return !(a == b); } // DEFINE_TYPE_CASTS // @@ -108,68 +95,68 @@ // * it's hard to prevent from passing unexpected objects, // * proceeding with the following code doesn't make sense, and // * cost of runtime type check is acceptable. -#define DEFINE_TYPE_CASTS(thisType, argumentType, argument, pointerPredicate, \ - referencePredicate) \ - inline thisType* To##thisType(argumentType* argument) { \ - SECURITY_DCHECK(!argument || (pointerPredicate)); \ - return static_cast<thisType*>(argument); \ - } \ - inline const thisType* To##thisType(const argumentType* argument) { \ - SECURITY_DCHECK(!argument || (pointerPredicate)); \ - return static_cast<const thisType*>(argument); \ - } \ - inline thisType& To##thisType(argumentType& argument) { \ - SECURITY_DCHECK(referencePredicate); \ - return static_cast<thisType&>(argument); \ - } \ - inline const thisType& To##thisType(const argumentType& argument) { \ - SECURITY_DCHECK(referencePredicate); \ - return static_cast<const thisType&>(argument); \ - } \ - void To##thisType(const thisType*); \ - void To##thisType(const thisType&); \ - \ - inline thisType* To##thisType##OrNull(argumentType* argument) { \ - if (!(argument) || !(pointerPredicate)) \ - return nullptr; \ - return static_cast<thisType*>(argument); \ - } \ - inline const thisType* To##thisType##OrNull(const argumentType* argument) { \ - if (!(argument) || !(pointerPredicate)) \ - return nullptr; \ - return static_cast<const thisType*>(argument); \ - } \ - inline thisType* To##thisType##OrNull(argumentType& argument) { \ - if (!(referencePredicate)) \ - return nullptr; \ - return static_cast<thisType*>(&argument); \ - } \ - inline const thisType* To##thisType##OrNull(const argumentType& argument) { \ - if (!(referencePredicate)) \ - return nullptr; \ - return static_cast<const thisType*>(&argument); \ - } \ - void To##thisType##OrNull(const thisType*); \ - void To##thisType##OrNull(const thisType&); \ - \ - inline thisType* To##thisType##OrDie(argumentType* argument) { \ - CHECK(!argument || (pointerPredicate)); \ - return static_cast<thisType*>(argument); \ - } \ - inline const thisType* To##thisType##OrDie(const argumentType* argument) { \ - CHECK(!argument || (pointerPredicate)); \ - return static_cast<const thisType*>(argument); \ - } \ - inline thisType& To##thisType##OrDie(argumentType& argument) { \ - CHECK(referencePredicate); \ - return static_cast<thisType&>(argument); \ - } \ - inline const thisType& To##thisType##OrDie(const argumentType& argument) { \ - CHECK(referencePredicate); \ - return static_cast<const thisType&>(argument); \ - } \ - void To##thisType##OrDie(const thisType*); \ - void To##thisType##OrDie(const thisType&) +#define DEFINE_TYPE_CASTS(Type, ArgType, argument, pointerPredicate, \ + referencePredicate) \ + inline Type* To##Type(ArgType* argument) { \ + SECURITY_DCHECK(!argument || (pointerPredicate)); \ + return static_cast<Type*>(argument); \ + } \ + inline const Type* To##Type(const ArgType* argument) { \ + SECURITY_DCHECK(!argument || (pointerPredicate)); \ + return static_cast<const Type*>(argument); \ + } \ + inline Type& To##Type(ArgType& argument) { \ + SECURITY_DCHECK(referencePredicate); \ + return static_cast<Type&>(argument); \ + } \ + inline const Type& To##Type(const ArgType& argument) { \ + SECURITY_DCHECK(referencePredicate); \ + return static_cast<const Type&>(argument); \ + } \ + void To##Type(const Type*); \ + void To##Type(const Type&); \ + \ + inline Type* To##Type##OrNull(ArgType* argument) { \ + if (!(argument) || !(pointerPredicate)) \ + return nullptr; \ + return static_cast<Type*>(argument); \ + } \ + inline const Type* To##Type##OrNull(const ArgType* argument) { \ + if (!(argument) || !(pointerPredicate)) \ + return nullptr; \ + return static_cast<const Type*>(argument); \ + } \ + inline Type* To##Type##OrNull(ArgType& argument) { \ + if (!(referencePredicate)) \ + return nullptr; \ + return static_cast<Type*>(&argument); \ + } \ + inline const Type* To##Type##OrNull(const ArgType& argument) { \ + if (!(referencePredicate)) \ + return nullptr; \ + return static_cast<const Type*>(&argument); \ + } \ + void To##Type##OrNull(const Type*); \ + void To##Type##OrNull(const Type&); \ + \ + inline Type* To##Type##OrDie(ArgType* argument) { \ + CHECK(!argument || (pointerPredicate)); \ + return static_cast<Type*>(argument); \ + } \ + inline const Type* To##Type##OrDie(const ArgType* argument) { \ + CHECK(!argument || (pointerPredicate)); \ + return static_cast<const Type*>(argument); \ + } \ + inline Type& To##Type##OrDie(ArgType& argument) { \ + CHECK(referencePredicate); \ + return static_cast<Type&>(argument); \ + } \ + inline const Type& To##Type##OrDie(const ArgType& argument) { \ + CHECK(referencePredicate); \ + return static_cast<const Type&>(argument); \ + } \ + void To##Type##OrDie(const Type*); \ + void To##Type##OrDie(const Type&) // Check at compile time that related enums stay in sync. #define STATIC_ASSERT_ENUM(a, b) \
diff --git a/third_party/widevine/cdm/widevine_cdm_common.h b/third_party/widevine/cdm/widevine_cdm_common.h index 8ab44bdb..84179fd 100644 --- a/third_party/widevine/cdm/widevine_cdm_common.h +++ b/third_party/widevine/cdm/widevine_cdm_common.h
@@ -18,6 +18,8 @@ // This type is used to register the Widevine CDM. const char kWidevineCdmType[] = "Widevine"; +const char kWidevineCdmGuid[] = "AD87877A-0213-49A8-8849-9E93B075E477"; + // Widevine CDM files are in a directory with this name. const char kWidevineCdmBaseDirectory[] = "WidevineCdm";