205 lines
6.9 KiB
Plaintext
205 lines
6.9 KiB
Plaintext
// Copyright 2012 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/base/platform_mime_util.h"
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
|
|
|
|
#include <string>
|
|
|
|
#include "base/mac/foundation_util.h"
|
|
#include "base/mac/scoped_cftyperef.h"
|
|
#include "base/notreached.h"
|
|
#include "base/strings/sys_string_conversions.h"
|
|
#include "build/build_config.h"
|
|
|
|
#if BUILDFLAG(IS_IOS)
|
|
#include <MobileCoreServices/MobileCoreServices.h>
|
|
#else
|
|
#include <CoreServices/CoreServices.h>
|
|
#endif // BUILDFLAG(IS_IOS)
|
|
|
|
namespace net {
|
|
|
|
bool PlatformMimeUtil::GetPlatformMimeTypeFromExtension(
|
|
const base::FilePath::StringType& ext,
|
|
std::string* result) const {
|
|
std::string ext_nodot = ext;
|
|
if (ext_nodot.length() >= 1 && ext_nodot[0] == L'.') {
|
|
ext_nodot.erase(ext_nodot.begin());
|
|
}
|
|
|
|
// TODO(crbug.com/1227419): Remove iOS availability check when cronet
|
|
// deployment target is bumped to 14.
|
|
if (@available(macOS 11, iOS 14, *)) {
|
|
UTType* uttype =
|
|
[UTType typeWithFilenameExtension:base::SysUTF8ToNSString(ext_nodot)];
|
|
// Dynamic UTTypes are made by the system in the event that there's a
|
|
// non-identifiable mime type. For now, we should treat dynamic UTTypes as a
|
|
// nonstandard format.
|
|
if ([uttype isDynamic] || uttype.preferredMIMEType == nil) {
|
|
return false;
|
|
}
|
|
*result = base::SysNSStringToUTF8(uttype.preferredMIMEType);
|
|
return true;
|
|
}
|
|
#if (BUILDFLAG(IS_MAC) && \
|
|
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0) || \
|
|
(BUILDFLAG(IS_IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
else {
|
|
base::ScopedCFTypeRef<CFStringRef> ext_ref(
|
|
base::SysUTF8ToCFStringRef(ext_nodot));
|
|
if (!ext_ref) {
|
|
return false;
|
|
}
|
|
base::ScopedCFTypeRef<CFStringRef> uti(
|
|
UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
|
|
ext_ref, nullptr));
|
|
if (!uti) {
|
|
return false;
|
|
}
|
|
base::ScopedCFTypeRef<CFStringRef> mime_ref(
|
|
UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
|
|
if (!mime_ref) {
|
|
return false;
|
|
}
|
|
|
|
*result = base::SysCFStringRefToUTF8(mime_ref);
|
|
return true;
|
|
}
|
|
#else
|
|
NOTREACHED();
|
|
return false;
|
|
#endif // (BUILDFLAG(IS_MAC) && MAC_OS_X_VERSION_MIN_REQUIRED <
|
|
// MAC_OS_VERSION_11_0) || (BUILDFLAG(IS_IOS) &&
|
|
// __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
}
|
|
|
|
bool PlatformMimeUtil::GetPlatformPreferredExtensionForMimeType(
|
|
const std::string& mime_type,
|
|
base::FilePath::StringType* ext) const {
|
|
// TODO(crbug.com/1227419): Remove iOS availability check when cronet
|
|
// deployment target is bumped to 14.
|
|
if (@available(macOS 11, iOS 14, *)) {
|
|
UTType* uttype =
|
|
[UTType typeWithMIMEType:base::SysUTF8ToNSString(mime_type)];
|
|
if ([uttype isDynamic] || uttype.preferredFilenameExtension == nil) {
|
|
return false;
|
|
}
|
|
*ext = base::SysNSStringToUTF8(uttype.preferredFilenameExtension);
|
|
return true;
|
|
}
|
|
#if (BUILDFLAG(IS_MAC) && \
|
|
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0) || \
|
|
(BUILDFLAG(IS_IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
else {
|
|
base::ScopedCFTypeRef<CFStringRef> mime_ref(
|
|
base::SysUTF8ToCFStringRef(mime_type));
|
|
if (!mime_ref) {
|
|
return false;
|
|
}
|
|
base::ScopedCFTypeRef<CFStringRef> uti(
|
|
UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mime_ref,
|
|
nullptr));
|
|
if (!uti) {
|
|
return false;
|
|
}
|
|
base::ScopedCFTypeRef<CFStringRef> ext_ref(
|
|
UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension));
|
|
if (!ext_ref) {
|
|
return false;
|
|
}
|
|
|
|
*ext = base::SysCFStringRefToUTF8(ext_ref);
|
|
return true;
|
|
}
|
|
|
|
#else
|
|
NOTREACHED();
|
|
return false;
|
|
#endif // (BUILDFLAG(IS_MAC) && MAC_OS_X_VERSION_MIN_REQUIRED <
|
|
// MAC_OS_VERSION_11_0) || (BUILDFLAG(IS_IOS) &&
|
|
// __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
}
|
|
|
|
void PlatformMimeUtil::GetPlatformExtensionsForMimeType(
|
|
const std::string& mime_type,
|
|
std::unordered_set<base::FilePath::StringType>* extensions) const {
|
|
// TODO(crbug.com/1227419): Remove iOS availability check when cronet
|
|
// deployment target is bumped to 14.
|
|
if (@available(macOS 11, iOS 14, *)) {
|
|
NSArray<UTType*>* types =
|
|
[UTType typesWithTag:base::SysUTF8ToNSString(mime_type)
|
|
tagClass:UTTagClassMIMEType
|
|
conformingToType:nil];
|
|
bool extensions_found = false;
|
|
if (types) {
|
|
NSInteger numberOfTypes = (NSInteger)types.count;
|
|
for (NSInteger i = 0; i < numberOfTypes; ++i) {
|
|
UTType* type = types[i];
|
|
if (!type || type.preferredFilenameExtension == nil) {
|
|
continue;
|
|
}
|
|
extensions_found = true;
|
|
NSArray<NSString*>* extensions_list =
|
|
type.tags[UTTagClassFilenameExtension];
|
|
for (NSString* extension in extensions_list) {
|
|
extensions->insert(base::SysNSStringToUTF8(extension));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (extensions_found) {
|
|
return;
|
|
}
|
|
|
|
base::FilePath::StringType ext;
|
|
if (GetPlatformPreferredExtensionForMimeType(mime_type, &ext)) {
|
|
extensions->insert(ext);
|
|
}
|
|
}
|
|
#if (BUILDFLAG(IS_MAC) && \
|
|
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0) || \
|
|
(BUILDFLAG(IS_IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
else {
|
|
base::ScopedCFTypeRef<CFStringRef> mime_ref(
|
|
base::SysUTF8ToCFStringRef(mime_type));
|
|
if (mime_ref) {
|
|
bool extensions_found = false;
|
|
base::ScopedCFTypeRef<CFArrayRef> types(UTTypeCreateAllIdentifiersForTag(
|
|
kUTTagClassMIMEType, mime_ref, nullptr));
|
|
if (types) {
|
|
for (CFIndex i = 0; i < CFArrayGetCount(types); i++) {
|
|
base::ScopedCFTypeRef<CFArrayRef> extensions_list(
|
|
UTTypeCopyAllTagsWithClass(base::mac::CFCast<CFStringRef>(
|
|
CFArrayGetValueAtIndex(types, i)),
|
|
kUTTagClassFilenameExtension));
|
|
if (!extensions_list) {
|
|
continue;
|
|
}
|
|
extensions_found = true;
|
|
for (NSString* extension in base::mac::CFToNSCast(extensions_list)) {
|
|
extensions->insert(base::SysNSStringToUTF8(extension));
|
|
}
|
|
}
|
|
}
|
|
if (extensions_found) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Huh? Give up.
|
|
base::FilePath::StringType ext;
|
|
if (GetPlatformPreferredExtensionForMimeType(mime_type, &ext)) {
|
|
extensions->insert(ext);
|
|
}
|
|
}
|
|
#endif // (BUILDFLAG(IS_MAC) && MAC_OS_X_VERSION_MIN_REQUIRED <
|
|
// MAC_OS_VERSION_11_0) || (BUILDFLAG(IS_IOS) &&
|
|
// __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_14_0)
|
|
}
|
|
|
|
} // namespace net
|