Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(441)

Unified Diff: third_party/WebKit/Source/core/html/HTMLImageElement.cpp

Issue 2769823002: Add decode() functionality to image elements. (Closed)
Patch Set: rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/HTMLImageElement.cpp
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index 6ad492963e8641a36d0b0cc8211d58aa936076a0..c317ebb48308ff454edefee3eace24cd98a81255 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -31,6 +31,7 @@
#include "core/css/MediaValuesDynamic.h"
#include "core/css/parser/SizesAttributeParser.h"
#include "core/dom/Attribute.h"
+#include "core/dom/DOMException.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/Deprecation.h"
@@ -51,6 +52,7 @@
#include "core/layout/LayoutImage.h"
#include "core/layout/api/LayoutImageItem.h"
#include "core/loader/resource/ImageResourceContent.h"
+#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/style/ContentData.h"
#include "core/svg/graphics/SVGImageForContainer.h"
@@ -92,6 +94,7 @@ HTMLImageElement::HTMLImageElement(Document& document, bool created_by_parser)
image_device_pixel_ratio_(1.0f),
source_(nullptr),
layout_disposition_(LayoutDisposition::kPrimaryContent),
+ decode_sequence_id_(0),
form_was_set_by_parser_(false),
element_created_by_parser_(created_by_parser),
is_fallback_image_(false),
@@ -115,6 +118,7 @@ DEFINE_TRACE(HTMLImageElement) {
visitor->Trace(listener_);
visitor->Trace(form_);
visitor->Trace(source_);
+ visitor->Trace(decode_promise_resolvers_);
HTMLElement::Trace(visitor);
}
@@ -125,6 +129,45 @@ void HTMLImageElement::NotifyViewportChanged() {
SelectSourceURL(ImageLoader::kUpdateSizeChanged);
}
+void HTMLImageElement::RequestDecode() {
+ DCHECK(!decode_promise_resolvers_.IsEmpty());
+ LocalFrame* frame = GetDocument().GetFrame();
+ // If we don't have the image, or the document doesn't have a frame, then
+ // reject the decode, since we can't plumb the request to the correct place.
+ if (!GetImageLoader().GetImage() ||
+ !GetImageLoader().GetImage()->GetImage() || !frame) {
+ DecodeRequestFinished(decode_sequence_id_, false);
+ return;
+ }
+ Image* image = GetImageLoader().GetImage()->GetImage();
+ frame->GetChromeClient().RequestDecode(
+ frame, image->ImageForCurrentFrame(),
+ WTF::Bind(&HTMLImageElement::DecodeRequestFinished,
+ WrapWeakPersistent(this), decode_sequence_id_));
+}
+
+void HTMLImageElement::DecodeRequestFinished(uint32_t sequence_id,
+ bool success) {
+ // If the sequence id attached with this callback doesn't match our current
+ // sequence id, then the source of the image has changed. In other words, the
+ // decode resolved/rejected by this callback was already rejected. Since we
+ // could have had a new decode request, we have to make sure not to
+ // resolve/reject those using the stale callback.
+ if (sequence_id != decode_sequence_id_)
+ return;
+
+ if (success) {
+ for (auto& resolver : decode_promise_resolvers_)
+ resolver->Resolve();
+ } else {
+ for (auto& resolver : decode_promise_resolvers_) {
+ resolver->Reject(DOMException::Create(
+ kEncodingError, "The source image cannot be decoded"));
+ }
+ }
+ decode_promise_resolvers_.clear();
+}
+
HTMLImageElement* HTMLImageElement::CreateForJSConstructor(Document& document) {
HTMLImageElement* image = new HTMLImageElement(document);
image->element_created_by_parser_ = false;
@@ -260,6 +303,14 @@ void HTMLImageElement::ParseAttribute(
}
} else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) {
SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError);
+ // Ensure to fail any pending decodes on possible source changes.
+ if (!decode_promise_resolvers_.IsEmpty() &&
+ params.old_value != params.new_value) {
+ DecodeRequestFinished(decode_sequence_id_, false);
+ // Increment the sequence id so that any in flight decode completion tasks
+ // will not trigger promise resolution for new decode requests.
+ ++decode_sequence_id_;
+ }
} else if (name == usemapAttr) {
SetIsLink(!params.new_value.IsNull());
} else if (name == referrerpolicyAttr) {
@@ -597,6 +648,22 @@ int HTMLImageElement::y() const {
return abs_pos.Y();
}
+ScriptPromise HTMLImageElement::decode(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (!script_state->ContextIsValid()) {
+ exception_state.ThrowDOMException(kEncodingError,
+ "The source image cannot be decoded");
+ return ScriptPromise();
+ }
+ exception_state.ClearException();
+ decode_promise_resolvers_.push_back(
+ ScriptPromiseResolver::Create(script_state));
+ ScriptPromise promise = decode_promise_resolvers_.back()->Promise();
+ if (complete())
+ RequestDecode();
+ return promise;
+}
+
bool HTMLImageElement::complete() const {
return GetImageLoader().ImageComplete();
}
@@ -613,8 +680,8 @@ bool HTMLImageElement::IsServerMap() const {
const AtomicString& usemap = FastGetAttribute(usemapAttr);
- // If the usemap attribute starts with '#', it refers to a map element in the
- // document.
+ // If the usemap attribute starts with '#', it refers to a map element in
+ // the document.
if (usemap[0] == '#')
return false;
@@ -812,6 +879,15 @@ PassRefPtr<ComputedStyle> HTMLImageElement::CustomStyleForLayoutObject() {
}
}
+void HTMLImageElement::ImageNotifyFinished(bool success) {
+ if (decode_promise_resolvers_.IsEmpty())
+ return;
+ if (success)
+ RequestDecode();
+ else
+ DecodeRequestFinished(decode_sequence_id_, false);
+}
+
void HTMLImageElement::AssociateWith(HTMLFormElement* form) {
if (form && form->isConnected()) {
form_ = form;
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLImageElement.h ('k') | third_party/WebKit/Source/core/html/HTMLImageElement.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698