From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Fri, 30 Mar 2018 10:09:03 +0200 Subject: Add fingerprinting mitigation for getClientRects, getBoundingClientRect Scale the result of Range::getClientRects and Element::getBoundingClientRect by a random +/-3% of the original value for each float in the Rect/Quad. The random value is generated once for each Document and re-used for all the attached elements. The rationale is that such value, albeit constant within the rendered Document, is within the same order of magniture of the floating point precision being used for fingerprinting and sufficient to poison the well. See also: http://www.gsd.inesc-id.pt/~mpc/pubs/fingerprinting-trustcom2016.pdf --- third_party/blink/renderer/core/dom/document.cc | 14 ++++++++++++++ third_party/blink/renderer/core/dom/document.h | 5 +++++ third_party/blink/renderer/core/dom/element.cc | 7 +++++++ third_party/blink/renderer/core/dom/range.cc | 8 +++++++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc @@ -279,6 +279,8 @@ #include "extensions/anti_amp_cure.h" +#include "base/rand_util.h" + #ifndef NDEBUG using WeakDocumentSet = blink::PersistentHeapHashSet>; @@ -740,6 +742,10 @@ Document::Document(const DocumentInit& initializer, #ifndef NDEBUG liveDocumentSet().insert(this); #endif + + // add +/- 3% noise against fingerprinting + shuffleFactorX_ = 1 + (base::RandDouble() - 0.5) * 0.03; + shuffleFactorY_ = 1 + (base::RandDouble() - 0.5) * 0.03; } Document::~Document() { @@ -766,6 +772,14 @@ Range* Document::CreateRangeAdjustedToTreeScope(const TreeScope& tree_scope, Position::BeforeNode(*shadow_host)); } +double Document::GetShuffleFactorX() { + return shuffleFactorX_; +} + +double Document::GetShuffleFactorY() { + return shuffleFactorY_; +} + SelectorQueryCache& Document::GetSelectorQueryCache() { if (!selector_query_cache_) selector_query_cache_ = std::make_unique(); diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h @@ -408,6 +408,9 @@ class CORE_EXPORT Document : public ContainerNode, String origin() const; + double GetShuffleFactorX(); + double GetShuffleFactorY(); + String visibilityState() const; mojom::PageVisibilityState GetPageVisibilityState() const; bool hidden() const; @@ -1670,6 +1673,8 @@ class CORE_EXPORT Document : public ContainerNode, double start_time_; + double shuffleFactorX_, shuffleFactorY_; + TraceWrapperMember script_runner_; HeapVector> current_script_stack_; diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc @@ -1348,6 +1348,11 @@ DOMRectList* Element::getClientRects() { DCHECK(element_layout_object); GetDocument().AdjustFloatQuadsForScrollAndAbsoluteZoom( quads, *element_layout_object); + + for (FloatQuad& quad : quads) { + quad.Scale(GetDocument().GetShuffleFactorX(), GetDocument().GetShuffleFactorY()); + } + return DOMRectList::Create(quads); } @@ -1365,6 +1370,8 @@ DOMRect* Element::getBoundingClientRect() { DCHECK(element_layout_object); GetDocument().AdjustFloatRectForScrollAndAbsoluteZoom(result, *element_layout_object); + result.Scale(GetDocument().GetShuffleFactorX(), GetDocument().GetShuffleFactorY()); + return DOMRect::FromFloatRect(result); } diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc --- a/third_party/blink/renderer/core/dom/range.cc +++ b/third_party/blink/renderer/core/dom/range.cc @@ -1575,11 +1575,17 @@ DOMRectList* Range::getClientRects() const { Vector quads; GetBorderAndTextQuads(quads); + for (FloatQuad& quad : quads) { + quad.Scale(owner_document_->GetShuffleFactorX(), owner_document_->GetShuffleFactorY()); + } + return DOMRectList::Create(quads); } DOMRect* Range::getBoundingClientRect() const { - return DOMRect::FromFloatRect(BoundingRect()); + auto rect = BoundingRect(); + rect.Scale(owner_document_->GetShuffleFactorX(), owner_document_->GetShuffleFactorY()); + return DOMRect::FromFloatRect(rect); } // TODO(editing-dev): We should make -- 2.7.4 From: SergeyZhukovsky Date: Tue, 15 Aug 2017 15:33:16 -0400 Subject: Remove google account access permission on reboot --- chrome/android/BUILD.gn | 3 +-- chrome/android/java/AndroidManifest.xml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn @@ -784,8 +784,7 @@ jinja_template_resources("chrome_public_apk_template_resources") { resources = [ "java/res_template/xml/file_paths.xml", "java/res_template/xml/launchershortcuts.xml", - "java/res_template/xml/searchable.xml", - "java/res_template/xml/syncadapter.xml", + "java/res_template/xml/searchable.xml" ] res_dir = "java/res_template" variables = chrome_public_jinja_variables diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml @@ -804,14 +804,14 @@ by a child template that "extends" this file. - - + --> -- 2.7.4 From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Wed, 25 Apr 2018 10:23:51 +0200 Subject: Disable metrics on all I/O threads -- 2.7.4 From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Thu, 22 Mar 2018 22:38:00 +0100 Subject: Disable plugins enumeration --- third_party/blink/renderer/core/frame/local_frame.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc @@ -1175,10 +1175,8 @@ FrameResourceCoordinator* LocalFrame::GetFrameResourceCoordinator() { } PluginData* LocalFrame::GetPluginData() const { - if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) - return nullptr; - return GetPage()->GetPluginData( - Tree().Top().GetSecurityContext()->GetSecurityOrigin()); + // what about no + return nullptr; } DEFINE_WEAK_IDENTIFIER_MAP(LocalFrame); -- 2.7.4 From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Sun, 25 Mar 2018 21:49:37 +0200 Subject: AudioBuffer, AnalyserNode: fingerprinting mitigations via IDL Return fixed base latency --- third_party/blink/renderer/modules/webaudio/analyser_node.idl | 8 ++++---- third_party/blink/renderer/modules/webaudio/audio_buffer.idl | 4 ++-- third_party/blink/renderer/modules/webaudio/audio_context.cc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/third_party/blink/renderer/modules/webaudio/analyser_node.idl b/third_party/blink/renderer/modules/webaudio/analyser_node.idl --- a/third_party/blink/renderer/modules/webaudio/analyser_node.idl +++ b/third_party/blink/renderer/modules/webaudio/analyser_node.idl @@ -42,10 +42,10 @@ interface AnalyserNode : AudioNode { // Copies the current frequency data into the passed array. // If the array has fewer elements than the frequencyBinCount, the excess elements will be dropped. - void getFloatFrequencyData(Float32Array array); - void getByteFrequencyData(Uint8Array array); + //void getFloatFrequencyData(Float32Array array); + //void getByteFrequencyData(Uint8Array array); // Real-time waveform data - void getFloatTimeDomainData(Float32Array array); - void getByteTimeDomainData(Uint8Array array); + //void getFloatTimeDomainData(Float32Array array); + //void getByteTimeDomainData(Uint8Array array); }; diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.idl b/third_party/blink/renderer/modules/webaudio/audio_buffer.idl --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.idl +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.idl @@ -38,7 +38,7 @@ // Channel access readonly attribute unsigned long numberOfChannels; - [RaisesException] Float32Array getChannelData(unsigned long channelIndex); - [RaisesException] void copyFromChannel(Float32Array destination, long channelNumber, optional unsigned long startInChannel = 0); + //[RaisesException] Float32Array getChannelData(unsigned long channelIndex); + //[RaisesException] void copyFromChannel(Float32Array destination, long channelNumber, optional unsigned long startInChannel = 0); [RaisesException] void copyToChannel(Float32Array source, long channelNumber, optional unsigned long startInChannel = 0); }; diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc @@ -312,18 +312,7 @@ } double AudioContext::baseLatency() const { - DCHECK(IsMainThread()); - DCHECK(destination()); - - // TODO(hongchan): Due to the incompatible constructor between - // AudioDestinationNode and DefaultAudioDestinationNode, casting directly from - // |destination()| is impossible. This is a temporary workaround until the - // refactoring is completed. - DefaultAudioDestinationHandler& destination_handler = - static_cast( - destination()->GetAudioDestinationHandler()); - return destination_handler.GetFramesPerBuffer() / - static_cast(sampleRate()); + return 0.04; } void AudioContext::NotifySourceNodeStart() { -- 2.7.4 From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Thu, 22 Mar 2018 22:11:57 +0100 Subject: Battery API: return nothing --- services/device/battery/battery_status_service.cc | 2 +- .../renderer/modules/battery/battery_manager.cc | 25 ++++------------------ 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/services/device/battery/battery_status_service.cc b/services/device/battery/battery_status_service.cc --- a/services/device/battery/battery_status_service.cc +++ b/services/device/battery/battery_status_service.cc @@ -41,7 +41,7 @@ BatteryStatusService::AddCallback(const BatteryUpdateCallback& callback) { if (!battery_fetcher_) battery_fetcher_ = BatteryStatusManager::Create(update_callback_); -#if 0 +#if !defined(OS_ANDROID) if (callback_list_.empty()) { bool success = battery_fetcher_->StartListeningBatteryChange(); // On failure pass the default values back. diff --git a/third_party/blink/renderer/modules/battery/battery_manager.cc b/third_party/blink/renderer/modules/battery/battery_manager.cc --- a/third_party/blink/renderer/modules/battery/battery_manager.cc +++ b/third_party/blink/renderer/modules/battery/battery_manager.cc @@ -42,26 +42,24 @@ } bool BatteryManager::charging() { - return battery_status_.Charging(); + return false; } double BatteryManager::chargingTime() { - return battery_status_.charging_time(); + return false; } double BatteryManager::dischargingTime() { - return battery_status_.discharging_time(); + return false; } double BatteryManager::level() { - return battery_status_.Level(); + return false; } void BatteryManager::DidUpdateData() { DCHECK(battery_property_); - BatteryStatus old_status = battery_status_; - battery_status_ = *BatteryDispatcher::Instance().LatestData(); if (battery_property_->GetState() == ScriptPromisePropertyBase::kPending) { battery_property_->Resolve(this); @@ -73,14 +71,6 @@ if (document->IsContextPaused() || document->IsContextDestroyed()) return; - if (battery_status_.Charging() != old_status.Charging()) - DispatchEvent(*Event::Create(event_type_names::kChargingchange)); - if (battery_status_.charging_time() != old_status.charging_time()) - DispatchEvent(*Event::Create(event_type_names::kChargingtimechange)); - if (battery_status_.discharging_time() != old_status.discharging_time()) - DispatchEvent(*Event::Create(event_type_names::kDischargingtimechange)); - if (battery_status_.Level() != old_status.Level()) - DispatchEvent(*Event::Create(event_type_names::kLevelchange)); } void BatteryManager::RegisterWithDispatcher() { -- 2.7.4 From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Sat, 24 Mar 2018 05:18:03 +0100 Subject: Canvas: fingerprinting mitigations for image data, font metrics and webGL Disable webGL renderering info, add shuffling to TextMetrics; additionally, the color data returned by ToBlob and ToDataURL will contain randomly manipulated pixels (maximum 10) that slightly change the color R,G,B components without visibly altering the rendering. Credits to Slaviro (https://github.com/Slaviro) for coming up with a better approach to change color components. --- .../renderer/core/html/canvas/text_metrics.cc | 20 +++ .../blink/renderer/core/html/canvas/text_metrics.h | 2 + .../canvas/canvas2d/base_rendering_context_2d.cc | 3 + .../canvas/canvas2d/canvas_rendering_context_2d.cc | 6 +- .../modules/webgl/webgl_debug_renderer_info.cc | 4 +- .../platform/graphics/image_data_buffer.cc | 137 +++++++++++++++++++++ .../renderer/platform/graphics/image_data_buffer.h | 2 + 7 files changed, 171 insertions(+), 3 deletions(-) diff --git a/third_party/blink/renderer/core/html/canvas/text_metrics.cc b/third_party/blink/renderer/core/html/canvas/text_metrics.cc --- a/third_party/blink/renderer/core/html/canvas/text_metrics.cc +++ b/third_party/blink/renderer/core/html/canvas/text_metrics.cc @@ -49,6 +49,24 @@ return 0; } +void TextMetrics::Shuffle(const double amt) { + double adjusted = 1 + amt; + + // x-direction + width_ *= adjusted; + actual_bounding_box_left_ *= adjusted; + actual_bounding_box_right_ *= adjusted; + + // y-direction + font_bounding_box_ascent_ *= adjusted; + font_bounding_box_descent_ *= adjusted; + actual_bounding_box_ascent_ *= adjusted; + actual_bounding_box_descent_ *= adjusted; + em_height_ascent_ *= adjusted; + em_height_descent_ *= adjusted; +} + + void TextMetrics::Update(const Font& font, const TextDirection& direction, const TextBaseline& baseline, diff --git a/third_party/blink/renderer/core/html/canvas/text_metrics.h b/third_party/blink/renderer/core/html/canvas/text_metrics.h --- a/third_party/blink/renderer/core/html/canvas/text_metrics.h +++ b/third_party/blink/renderer/core/html/canvas/text_metrics.h @@ -67,6 +67,8 @@ class CORE_EXPORT TextMetrics final : public ScriptWrappable { static float GetFontBaseline(const TextBaseline&, const FontMetrics&); + void Shuffle(const double amt); + private: void Update(const Font&, const TextDirection&, diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc @@ -1620,6 +1620,9 @@ ImageData* BaseRenderingContext2D::getImageData( const CanvasColorParams& color_params = ColorParams(); scoped_refptr snapshot = GetImage(kPreferNoAcceleration); + //TODO: calculate some random value and use it to shuffle pixel data in 'snapshot' + // it should be a StaticBitmapImage somehow + if (!StaticBitmapImage::ConvertToArrayBufferContents( snapshot, contents, image_data_rect, color_params, IsAccelerated())) { exception_state.ThrowRangeError("Out of memory at ImageData creation"); diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc @@ -773,8 +773,12 @@ TextMetrics* CanvasRenderingContext2D::measureText(const String& text) { else direction = ToTextDirection(GetState().GetDirection(), canvas()); - return TextMetrics::Create(font, direction, GetState().GetTextBaseline(), + TextMetrics* textMetrics = TextMetrics::Create(font, direction, GetState().GetTextBaseline(), GetState().GetTextAlign(), text); + + textMetrics->Shuffle(canvas()->GetDocument().GetShuffleFactorX()); + + return textMetrics; } void CanvasRenderingContext2D::DrawTextInternal( diff --git a/third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.cc b/third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.cc --- a/third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.cc @@ -37,11 +37,11 @@ WebGLDebugRendererInfo* WebGLDebugRendererInfo::Create( WebGLRenderingContextBase* context) { - return MakeGarbageCollected(context); + return nullptr; } bool WebGLDebugRendererInfo::Supported(WebGLRenderingContextBase*) { - return true; + return false; } const char* WebGLDebugRendererInfo::ExtensionName() { diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc --- a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc @@ -35,6 +35,7 @@ #include #include "base/memory/ptr_util.h" +#include "base/rand_util.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/image-encoders/image_encoder.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -44,6 +45,7 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSwizzle.h" #include "third_party/skia/include/encode/SkJpegEncoder.h" +#include "../../include/private/SkColorData.h" namespace blink { @@ -116,6 +118,140 @@ return static_cast(pixmap_.addr()); } +#define shuffleComponent(color, max, delta) ((color) >= (max) ? -(delta) : (delta)) + +void ImageDataBuffer::shuffleSubchannelColorData() const { +auto w = pixmap_.width(), h = pixmap_.height(); + // generate the first random number here + double shuffleX = 0.5 + base::RandDouble() * 0.5; + + // cap maximum pixels to change + auto pixels = (w + h) / 128; + if (pixels > 10) { + pixels = 10; + } else if (pixels < 2) { + pixels = 2; + } + + auto colorType = pixmap_.colorType(); + + // second random number (for y/height) + double shuffleY = 0.5 + base::RandDouble() * 0.5; + + // calculate random coordinates using bisection + auto currentW = w, currentH = h; + for(;pixels >= 0; pixels--) { + int x = currentW * shuffleX, y = currentH * shuffleY; + + // calculate randomisation amounts for each RGB component + auto shuffleR = (uint8_t)base::RandInt(0, 4), shuffleG = (uint8_t)base::RandInt(0, 4), shuffleB = (uint8_t)base::RandInt(0, 4); + + // manipulate pixel data to slightly change the R, G, B components + switch (colorType) { + case kAlpha_8_SkColorType: + { + uint8_t *pixel = pixmap_.writable_addr8(x, y); + auto r = SkColorGetR(*pixel), g = SkColorGetG(*pixel), b = SkColorGetB(*pixel), a = SkColorGetA(*pixel); + + r += shuffleComponent(r, UINT8_MAX-1, shuffleR); + g += shuffleComponent(g, UINT8_MAX-1, shuffleG); + b += shuffleComponent(b, UINT8_MAX-1, shuffleB); + // alpha is left unchanged + + *pixel = SkColorSetARGB(a, r, g, b); + } + break; + case kGray_8_SkColorType: + { + uint8_t *pixel = pixmap_.writable_addr8(x, y); + *pixel += shuffleComponent(*pixel, UINT8_MAX-1, shuffleB); + } + break; + case kRGB_565_SkColorType: + { + uint16_t *pixel = pixmap_.writable_addr16(x, y); + unsigned r = SkPacked16ToR32(*pixel); + unsigned g = SkPacked16ToG32(*pixel); + unsigned b = SkPacked16ToB32(*pixel); + + r += shuffleComponent(r, 31, shuffleR); + g += shuffleComponent(g, 63, shuffleG); + b += shuffleComponent(b, 31, shuffleB); + + unsigned r16 = (r & SK_R16_MASK) << SK_R16_SHIFT; + unsigned g16 = (g & SK_G16_MASK) << SK_G16_SHIFT; + unsigned b16 = (b & SK_B16_MASK) << SK_B16_SHIFT; + + *pixel = r16 | g16 | b16; + } + break; + case kARGB_4444_SkColorType: + { + uint16_t *pixel = pixmap_.writable_addr16(x, y); + auto a = SkGetPackedA4444(*pixel), r = SkGetPackedR4444(*pixel), g = SkGetPackedG4444(*pixel), b = SkGetPackedB4444(*pixel); + + r += shuffleComponent(r, 15, shuffleR); + g += shuffleComponent(g, 15, shuffleG); + b += shuffleComponent(b, 15, shuffleB); + // alpha is left unchanged + + unsigned a4 = (a & 0xF) << SK_A4444_SHIFT; + unsigned r4 = (r & 0xF) << SK_R4444_SHIFT; + unsigned g4 = (g & 0xF) << SK_G4444_SHIFT; + unsigned b4 = (b & 0xF) << SK_B4444_SHIFT; + + *pixel = r4 | b4 | g4 | a4; + } + break; + case kRGBA_8888_SkColorType: + { + uint32_t *pixel = pixmap_.writable_addr32(x, y); + auto a = SkGetPackedA32(*pixel), r = SkGetPackedR32(*pixel), g = SkGetPackedG32(*pixel), b = SkGetPackedB32(*pixel); + + r += shuffleComponent(r, UINT8_MAX-1, shuffleR); + g += shuffleComponent(g, UINT8_MAX-1, shuffleG); + b += shuffleComponent(b, UINT8_MAX-1, shuffleB); + // alpha is left unchanged + + *pixel = (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | + (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); + } + break; + case kBGRA_8888_SkColorType: + { + uint32_t *pixel = pixmap_.writable_addr32(x, y); + auto a = SkGetPackedA32(*pixel), b = SkGetPackedR32(*pixel), g = SkGetPackedG32(*pixel), r = SkGetPackedB32(*pixel); + + r += shuffleComponent(r, UINT8_MAX-1, shuffleR); + g += shuffleComponent(g, UINT8_MAX-1, shuffleG); + b += shuffleComponent(b, UINT8_MAX-1, shuffleB); + // alpha is left unchanged + + *pixel = (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) | + (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT); + } + break; + default: + // the remaining formats are not expected to be used in Chromium + return; + } + + // keep bisecting or reset current width/height as needed + if (x == 0) { + currentW = w; + } else { + currentW = x; + } + if (y == 0) { + currentH = h; + } else { + currentH = y; + } + } +} + + + bool ImageDataBuffer::EncodeImage(const ImageEncodingMimeType mime_type, const double& quality, Vector* encoded_image) const { @@ -128,6 +264,11 @@ const SkPixmap& pixmap) const { DCHECK(is_valid_); + // shuffle subchannel color data within the pixmap + shuffleSubchannelColorData(); + + + if (mime_type == kMimeTypeJpeg) { SkJpegEncoder::Options options; options.fQuality = ImageEncoder::ComputeJpegQuality(quality); diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.h b/third_party/blink/renderer/platform/graphics/image_data_buffer.h --- a/third_party/blink/renderer/platform/graphics/image_data_buffer.h +++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.h @@ -65,6 +65,8 @@ class PLATFORM_EXPORT ImageDataBuffer { bool IsValid() { return is_valid_; } // Only used by Create() + void shuffleSubchannelColorData() const; + sk_sp retained_image_; SkPixmap pixmap_; bool is_valid_ = false; -- 2.7.4