Commit b53ebdc3 authored by Olivier Yiptong's avatar Olivier Yiptong Committed by Chromium LUCI CQ

FontAccess: Fail concurrent font chooser requests

This changes the behavior from concurrent font chooser requests all
returning the same data from a single chooser invocation to failing a
subsequent request.

As implemented, the User Activation check will consume the activation,
failing any other in-flight requests.

Fixed: 1149621
Change-Id: If14e7e12ff52967e8dc49c383a66da94995c9134
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2568931
Commit-Queue: Olivier Yiptong <oyiptong@chromium.org>
Auto-Submit: Olivier Yiptong <oyiptong@chromium.org>
Reviewed-by: default avatarJoshua Bell <jsbell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#833129}
parent 69ed274d
...@@ -66,50 +66,45 @@ ScriptValue FontManager::query(ScriptState* script_state, ...@@ -66,50 +66,45 @@ ScriptValue FontManager::query(ScriptState* script_state,
ScriptPromise FontManager::showFontChooser(ScriptState* script_state, ScriptPromise FontManager::showFontChooser(ScriptState* script_state,
const QueryOptions* options) { const QueryOptions* options) {
// TODO(crbug.com/1149621): Queue up font chooser requests. auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
if (!pending_resolver_) { ScriptPromise promise = resolver->Promise();
remote_manager_->ChooseLocalFonts(
WTF::Bind(&FontManager::DidShowFontChooser, WrapWeakPersistent(this))); remote_manager_->ChooseLocalFonts(WTF::Bind(&FontManager::DidShowFontChooser,
pending_resolver_ = WrapWeakPersistent(this),
MakeGarbageCollected<ScriptPromiseResolver>(script_state); WrapPersistent(resolver)));
}
return pending_resolver_->Promise(); return promise;
} }
void FontManager::Trace(blink::Visitor* visitor) const { void FontManager::Trace(blink::Visitor* visitor) const {
ScriptWrappable::Trace(visitor); ScriptWrappable::Trace(visitor);
ContextLifecycleObserver::Trace(visitor); ContextLifecycleObserver::Trace(visitor);
visitor->Trace(pending_resolver_);
} }
void FontManager::DidShowFontChooser( void FontManager::DidShowFontChooser(
ScriptPromiseResolver* resolver,
mojom::blink::FontEnumerationStatus status, mojom::blink::FontEnumerationStatus status,
Vector<mojom::blink::FontMetadataPtr> fonts) { Vector<mojom::blink::FontMetadataPtr> fonts) {
switch (status) { switch (status) {
case mojom::blink::FontEnumerationStatus::kOk: case mojom::blink::FontEnumerationStatus::kOk:
break; break;
case mojom::blink::FontEnumerationStatus::kUnimplemented: case mojom::blink::FontEnumerationStatus::kUnimplemented:
pending_resolver_->Reject(MakeGarbageCollected<DOMException>( resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, DOMExceptionCode::kNotSupportedError,
"Not yet supported on this platform.")); "Not yet supported on this platform."));
pending_resolver_.Clear();
return; return;
case mojom::blink::FontEnumerationStatus::kCanceled: case mojom::blink::FontEnumerationStatus::kCanceled:
pending_resolver_->Reject(MakeGarbageCollected<DOMException>( resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "The user canceled the operation.")); DOMExceptionCode::kAbortError, "The user canceled the operation."));
pending_resolver_.Clear();
return; return;
case mojom::blink::FontEnumerationStatus::kNeedsUserActivation: case mojom::blink::FontEnumerationStatus::kNeedsUserActivation:
pending_resolver_->Reject(MakeGarbageCollected<DOMException>( resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, "User activation is required.")); DOMExceptionCode::kSecurityError, "User activation is required."));
pending_resolver_.Clear();
return; return;
case mojom::blink::FontEnumerationStatus::kUnexpectedError: case mojom::blink::FontEnumerationStatus::kUnexpectedError:
default: default:
pending_resolver_->Reject(MakeGarbageCollected<DOMException>( resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "An unexpected error occured.")); DOMExceptionCode::kUnknownError, "An unexpected error occured."));
pending_resolver_.Clear();
return; return;
} }
...@@ -119,8 +114,7 @@ void FontManager::DidShowFontChooser( ...@@ -119,8 +114,7 @@ void FontManager::DidShowFontChooser(
font->family}; font->family};
entries.push_back(FontMetadata::Create(std::move(entry))); entries.push_back(FontMetadata::Create(std::move(entry)));
} }
pending_resolver_->Resolve(std::move(entries)); resolver->Resolve(std::move(entries));
pending_resolver_.Clear();
} }
void FontManager::ContextDestroyed() { void FontManager::ContextDestroyed() {
......
...@@ -39,13 +39,13 @@ class FontManager final : public ScriptWrappable, ...@@ -39,13 +39,13 @@ class FontManager final : public ScriptWrappable,
void Trace(blink::Visitor*) const override; void Trace(blink::Visitor*) const override;
private: private:
void DidShowFontChooser(mojom::blink::FontEnumerationStatus status, void DidShowFontChooser(ScriptPromiseResolver* resolver,
mojom::blink::FontEnumerationStatus status,
Vector<mojom::blink::FontMetadataPtr> fonts); Vector<mojom::blink::FontMetadataPtr> fonts);
void ContextDestroyed() override; void ContextDestroyed() override;
void OnDisconnect(); void OnDisconnect();
mojo::Remote<mojom::blink::FontAccessManager> remote_manager_; mojo::Remote<mojom::blink::FontAccessManager> remote_manager_;
Member<ScriptPromiseResolver> pending_resolver_;
}; };
} // namespace blink } // namespace blink
......
...@@ -2214,8 +2214,10 @@ crbug.com/626703 [ Win ] external/wpt/html/editing/dnd/events/historical-manual. ...@@ -2214,8 +2214,10 @@ crbug.com/626703 [ Win ] external/wpt/html/editing/dnd/events/historical-manual.
external/wpt/font-access/font_access-blob.tentative.https.window.html [ Skip ] external/wpt/font-access/font_access-blob.tentative.https.window.html [ Skip ]
external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Skip ] external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Skip ]
external/wpt/font-access/font_access-chooser.tentative.manual.https.html [ Skip ] external/wpt/font-access/font_access-chooser.tentative.manual.https.html [ Skip ]
external/wpt/font-access/font_access-chooser-multiple.tentative.manual.https.html [ Skip ]
virtual/font-access/external/wpt/font-access/font_access-blob.tentative.https.window.html [ Pass ] virtual/font-access/external/wpt/font-access/font_access-blob.tentative.https.window.html [ Pass ]
virtual/font-access/external/wpt/font-access/font_access-chooser.tentative.manual.https.html [ Skip ] virtual/font-access/external/wpt/font-access/font_access-chooser.tentative.manual.https.html [ Skip ]
virtual/font-access/external/wpt/font-access/font_access-chooser-multiple.tentative.manual.https.html [ Skip ]
virtual/font-access/external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Pass ] virtual/font-access/external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Pass ]
# text-orientation:upright # text-orientation:upright
......
<!doctype html>
<title>Local Font Access: Multiple choosers</title>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script>
promise_test(async t => {
await new Promise(resolve => {
window.addEventListener('DOMContentLoaded', resolve);
});
// Small delay to give chrome's test automation a chance to actually install
// itself.
await new Promise(resolve => step_timeout(resolve, 100));
await window.test_driver.bless('show a font chooser.<br>Please select at least one font.');
const promise = navigator.fonts.showFontChooser()
promise_rejects_dom(t, 'SecurityError', navigator.fonts.showFontChooser());
const fonts = await promise;
}, 'showFontChooser multiple choosers');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment