Flutter macOS Embedder
FlutterNSBundleUtils.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include <Foundation/Foundation.h>
8 
10 
12 
13 NSString* const kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
14 
15 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath);
16 
17 NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
18  NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
19  enumeratorAtURL:searchURL
20  includingPropertiesForKeys:nil
21  options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
22  NSDirectoryEnumerationSkipsHiddenFiles
23  // Skip directories where errors are encountered.
24  errorHandler:nil];
25 
26  for (NSURL* candidate in frameworkEnumerator) {
27  NSBundle* flutterFrameworkBundle = [NSBundle bundleWithURL:candidate];
28  if ([flutterFrameworkBundle.bundleIdentifier isEqualToString:flutterFrameworkBundleID]) {
29  return flutterFrameworkBundle;
30  }
31  }
32  return nil;
33 }
34 
36  NSBundle* mainBundle = NSBundle.mainBundle;
37  // App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
38  if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
39  // Up two levels.
40  return [NSBundle bundleWithURL:mainBundle.bundleURL.URLByDeletingLastPathComponent
41  .URLByDeletingLastPathComponent];
42  }
43  return mainBundle;
44 }
45 
46 NSBundle* FLTFrameworkBundleWithIdentifier(NSString* flutterFrameworkBundleID) {
47  NSBundle* appBundle = FLTGetApplicationBundle();
48  NSBundle* flutterFrameworkBundle =
49  FLTFrameworkBundleInternal(flutterFrameworkBundleID, appBundle.privateFrameworksURL);
50  if (flutterFrameworkBundle == nil) {
51  // Fallback to slow implementation.
52  flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
53  }
54  if (flutterFrameworkBundle == nil) {
55  flutterFrameworkBundle = NSBundle.mainBundle;
56  }
57  return flutterFrameworkBundle;
58 }
59 
60 NSString* FLTAssetPath(NSBundle* bundle) {
61  return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: kDefaultAssetPath;
62 }
63 
64 NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
65  NSString* relativeAssetsPath = FLTAssetPath(bundle);
66  NSString* flutterAssetsPath = GetFlutterAssetsPathFromBundle(bundle, relativeAssetsPath);
67  if (flutterAssetsPath.length == 0) {
68  flutterAssetsPath = GetFlutterAssetsPathFromBundle(NSBundle.mainBundle, relativeAssetsPath);
69  }
70  return flutterAssetsPath;
71 }
72 
73 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath) {
74  // Use the raw path solution so that asset path can be returned from unloaded bundles.
75  // See https://github.com/flutter/engine/pull/46073
76  NSString* assetsPath = [bundle pathForResource:relativeAssetsPath ofType:nil];
77  if (assetsPath.length == 0) {
78  // In app extension, using full relative path (kDefaultAssetPath)
79  // returns nil when the app bundle is not loaded. Try to use
80  // the sub folder name, which can successfully return a valid path.
81  assetsPath = [bundle pathForResource:@"flutter_assets" ofType:nil];
82  }
83  return assetsPath;
84 }
FLUTTER_ASSERT_ARC
#define FLUTTER_ASSERT_ARC
Definition: FlutterMacros.h:44
FLTFrameworkBundleWithIdentifier
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
Definition: FlutterNSBundleUtils.mm:46
kDefaultAssetPath
FLUTTER_ASSERT_ARC NSString *const kDefaultAssetPath
Definition: FlutterNSBundleUtils.mm:13
FLTFrameworkBundleInternal
NSBundle * FLTFrameworkBundleInternal(NSString *flutterFrameworkBundleID, NSURL *searchURL)
Definition: FlutterNSBundleUtils.mm:17
GetFlutterAssetsPathFromBundle
static NSString * GetFlutterAssetsPathFromBundle(NSBundle *bundle, NSString *relativeAssetsPath)
Definition: FlutterNSBundleUtils.mm:73
FlutterMacros.h
FLTAssetPath
NSString * FLTAssetPath(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:60
FlutterNSBundleUtils.h
FLTAssetsPathFromBundle
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:64
FLTGetApplicationBundle
NSBundle * FLTGetApplicationBundle()
Definition: FlutterNSBundleUtils.mm:35