| /* |
| * Copyright (C) 2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "config.h" |
| |
| #if HAVE(SCENEKIT) |
| |
| #import "SceneKitModelLoader.h" |
| |
| #import "MIMETypeRegistry.h" |
| #import "Model.h" |
| #import "ResourceError.h" |
| #import "SceneKitModelLoaderClient.h" |
| #import "SceneKitModelLoaderUSD.h" |
| |
| namespace WebCore { |
| |
| // Defining trivial virtual destructor in implementation to pin vtable. |
| SceneKitModelLoader::~SceneKitModelLoader() = default; |
| |
| // No-op loader used for the cases where no loading actually happens (such as unsupported MIME type). |
| class SceneKitModelLoaderFailure final : public SceneKitModelLoader { |
| public: |
| static Ref<SceneKitModelLoaderFailure> create(ResourceError error) |
| { |
| return adoptRef(*new SceneKitModelLoaderFailure(WTFMove(error))); |
| } |
| |
| virtual ~SceneKitModelLoaderFailure() = default; |
| virtual void cancel() override { } |
| |
| const ResourceError& error() const |
| { |
| return m_error; |
| } |
| |
| private: |
| SceneKitModelLoaderFailure(ResourceError error) |
| : m_error { WTFMove(error) } |
| { |
| } |
| |
| ResourceError m_error; |
| }; |
| |
| |
| } |
| |
| namespace WebCore { |
| |
| static String mimeTypeUtilizingFileExtensionOverridingForLocalFiles(const Model& modelSource) |
| { |
| if (modelSource.url().isLocalFile() && (modelSource.mimeType().isEmpty() || modelSource.mimeType() == WebCore::defaultMIMEType())) { |
| // FIXME: Getting the file extension from a URL seems like it should be in shared code. |
| auto lastPathComponent = modelSource.url().lastPathComponent(); |
| auto position = lastPathComponent.reverseFind('.'); |
| if (position != WTF::notFound) { |
| auto extension = lastPathComponent.substring(position + 1); |
| |
| return MIMETypeRegistry::mediaMIMETypeForExtension(extension.toString()); |
| } |
| } |
| |
| return modelSource.mimeType(); |
| } |
| |
| enum class ModelType { |
| USD, |
| Unknown |
| }; |
| |
| static ModelType modelType(Model& modelSource) |
| { |
| auto mimeType = mimeTypeUtilizingFileExtensionOverridingForLocalFiles(modelSource); |
| |
| if (WebCore::MIMETypeRegistry::isUSDMIMEType(mimeType)) |
| return ModelType::USD; |
| |
| return ModelType::Unknown; |
| } |
| |
| Ref<SceneKitModelLoader> loadSceneKitModel(Model& modelSource, SceneKitModelLoaderClient& client) |
| { |
| switch (modelType(modelSource)) { |
| case ModelType::USD: |
| return loadSceneKitModelUsingUSDLoader(modelSource, client); |
| case ModelType::Unknown: |
| break; |
| } |
| |
| auto loader = SceneKitModelLoaderFailure::create([NSError errorWithDomain:@"SceneKitModelLoader" code:-1 userInfo:@{ |
| NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Unsupported MIME type: %s.", modelSource.mimeType().utf8().data()], |
| NSURLErrorFailingURLErrorKey: (NSURL *)modelSource.url() |
| }]); |
| |
| dispatch_async(dispatch_get_main_queue(), [weakClient = WeakPtr { client }, loader] { |
| auto strongClient = weakClient.get(); |
| if (!strongClient) |
| return; |
| |
| strongClient->didFailLoading(loader.get(), loader->error()); |
| }); |
| |
| return loader; |
| } |
| |
| } |
| |
| #endif |