Skip to content

Commit 9a9926c

Browse files
committed
[Model] Handle the error case when the model asset cannot be loaded
https://bugs.webkit.org/show_bug.cgi?id=290244 rdar://147635013 Reviewed by Mike Wyrzykowski. If the model asset cannot be loaded for some reason (e.g. invalid format), we should reject the ready promise on the model element. * LayoutTests/model-element/model-element-ready-expected.txt: * LayoutTests/model-element/model-element-ready.html: Check ready promise is rejected when the model source points to an asset that can't be loaded. * LayoutTests/model-element/resources/error-case.usdz: Added. A bad usdz example that doesn't have the expected content. * Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm: (WebKit::toResourceError): (WebKit::RKModelLoaderUSD::load): If no entity is loaded, treat this as a failed case. (WebKit::ModelProcessModelPlayerProxy::didFailLoading): Notify the web content side about this failed load. * Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.cpp: (WebKit::ModelProcessModelPlayer::didFailLoading): Notify the client (HTMLModelElement) about the failed load. * Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.h: * Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.messages.in: Canonical link: https://commits.webkit.org/292547@main
1 parent f7073d5 commit 9a9926c

7 files changed

Lines changed: 43 additions & 6 deletions

File tree

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

2-
PASS <model> rejects the ready promise when provided with an unknown resoure.
2+
PASS <model> rejects the ready promise when provided with an unknown resource.
3+
PASS <model> rejects the ready promise when provided with a resource that can't be loaded.
34
PASS <model> rejects the ready promise when its resource load is aborted.
45
PASS <model> resolves the ready promise when provided with a known resource.
56

LayoutTests/model-element/model-element-ready.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@
1414
value => assert_unreached("Unexpected ready promise resolution."),
1515
reason => assert_true(reason.toString().includes("NetworkError"), "The ready promise is rejected with a NetworkError.")
1616
);
17-
}, `<model> rejects the ready promise when provided with an unknown resoure.`);
17+
}, `<model> rejects the ready promise when provided with an unknown resource.`);
18+
19+
promise_test(async t => {
20+
const [model, source] = createModelAndSource(t, "resources/error-case.usdz");
21+
return model.ready.then(
22+
value => assert_unreached("Unexpected ready promise resolution."),
23+
reason => assert_true(reason.toString().includes("AbortError"), "The ready promise is rejected with an AbortError.")
24+
);
25+
}, `<model> rejects the ready promise when provided with a resource that can't be loaded.`);
1826

1927
promise_test(async t => {
2028
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
@@ -25,7 +33,7 @@
2533

2634
return modelReady.then(
2735
value => assert_unreached("Unexpected ready promise resolution."),
28-
reason => assert_true(reason.toString().includes("AbortError"), "The ready promise is rejected with a NetworkError.")
36+
reason => assert_true(reason.toString().includes("AbortError"), "The ready promise is rejected with an AbortError.")
2937
);
3038
}, `<model> rejects the ready promise when its resource load is aborted.`);
3139

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus hendrerit felis et ex maximus condimentum. Vestibulum eget mattis dui, maximus convallis mi. Suspendisse pharetra id nibh ac volutpat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris commodo sed ipsum vel elementum. Nam dignissim velit ac neque gravida interdum. Duis eu pellentesque tortor, ac ornare nisi. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam elementum aliquet dignissim. In hac habitasse platea dictumst.

Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,27 @@ void didFail(ResourceError error)
177177
WeakPtr<REModelLoaderClient> m_client;
178178
};
179179

180+
static ResourceError toResourceError(String payload, Model& model)
181+
{
182+
return ResourceError { [NSError errorWithDomain:@"RKModelLoaderUSD" code:-1 userInfo:@{
183+
NSLocalizedDescriptionKey: (NSString *)payload,
184+
NSURLErrorFailingURLErrorKey: (NSURL *)model.url()
185+
}] };
186+
}
187+
180188
void RKModelLoaderUSD::load()
181189
{
182190
[getWKSRKEntityClass() loadFromData:m_model->data()->createNSData().get() completionHandler:makeBlockPtr([weakThis = WeakPtr { *this }] (WKSRKEntity *entity) mutable {
183-
if (RefPtr protectedThis = weakThis.get())
184-
protectedThis->didFinish(entity);
191+
RefPtr protectedThis = weakThis.get();
192+
if (!protectedThis)
193+
return;
194+
195+
if (!entity) {
196+
protectedThis->didFail(toResourceError("Failed to load the entity"_s, protectedThis->m_model));
197+
return;
198+
}
199+
200+
protectedThis->didFinish(entity);
185201
}).get()];
186202
}
187203

@@ -494,7 +510,7 @@ static CGFloat effectivePointsPerMeter(CALayer *caLayer)
494510

495511
RELEASE_LOG_ERROR(ModelElement, "%p - ModelProcessModelPlayerProxy failed to load model id=%" PRIu64 " error=\"%@\"", this, m_id.toUInt64(), error.nsError().localizedDescription);
496512

497-
// FIXME: Do something sensible in the failure case.
513+
send(Messages::ModelProcessModelPlayer::DidFailLoading());
498514
}
499515

500516
// MARK: - WebCore::ModelPlayer

Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "WebProcess.h"
3636
#include <WebCore/LayerHostingContextIdentifier.h>
3737
#include <WebCore/Page.h>
38+
#include <WebCore/ResourceError.h>
3839
#include <WebCore/TransformationMatrix.h>
3940

4041
namespace WebKit {
@@ -96,6 +97,14 @@ void ModelProcessModelPlayer::didFinishLoading(const WebCore::FloatPoint3D& boun
9697
m_client->didUpdateBoundingBox(*this, boundingBoxCenter, boundingBoxExtents);
9798
}
9899

100+
void ModelProcessModelPlayer::didFailLoading()
101+
{
102+
RELEASE_LOG(ModelElement, "%p - ModelProcessModelPlayer didFailLoading id=%" PRIu64, this, m_id.toUInt64());
103+
RELEASE_ASSERT(modelProcessEnabled());
104+
105+
m_client->didFailLoading(*this, WebCore::ResourceError { WebCore::errorDomainWebKitInternal, 0, { }, "Failed to load model data"_s });
106+
}
107+
99108
/// This comes from Model Process side, so that Web Process has the most up-to-date knowledge about the transform actually applied to the entity.
100109
/// Not to be confused with setEntityTransform().
101110
void ModelProcessModelPlayer::didUpdateEntityTransform(const WebCore::TransformationMatrix& transform)

Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class ModelProcessModelPlayer
6666
// Messages
6767
void didCreateLayer(WebCore::LayerHostingContextIdentifier);
6868
void didFinishLoading(const WebCore::FloatPoint3D&, const WebCore::FloatPoint3D&);
69+
void didFailLoading();
6970
void didUpdateEntityTransform(const WebCore::TransformationMatrix&);
7071
void didUpdateAnimationPlaybackState(bool isPaused, double playbackRate, Seconds duration, Seconds currentTime, MonotonicTime clockTimestamp);
7172
void didFinishEnvironmentMapLoading(bool succeeded);

Source/WebKit/WebProcess/Model/ModelProcessModelPlayer.messages.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
messages -> ModelProcessModelPlayer {
3131
DidCreateLayer(WebCore::LayerHostingContextIdentifier identifier)
3232
DidFinishLoading(WebCore::FloatPoint3D center, WebCore::FloatPoint3D extents)
33+
DidFailLoading()
3334
DidUpdateEntityTransform(WebCore::TransformationMatrix transform)
3435
DidUpdateAnimationPlaybackState(bool isPaused, double playbackRate, Seconds duration, Seconds currentTime, MonotonicTime clockTimestamp)
3536
DidFinishEnvironmentMapLoading(bool succeeded)

0 commit comments

Comments
 (0)