summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorJason Wray <friedbunny@users.noreply.github.com>2016-07-07 12:11:08 -0400
committerGitHub <noreply@github.com>2016-07-07 12:11:08 -0400
commit3fa4f9379d1ec40b0c3e778b246ed6f88d3d3a76 (patch)
treeb3e0c06ba1dc899008fe68280733c0480b30215b /platform/darwin
parentc4bd946f9b39a71c44c7677c56e20c143f9f4dd6 (diff)
downloadqtlocation-mapboxgl-3fa4f9379d1ec40b0c3e778b246ed6f88d3d3a76.tar.gz
[ios] Move cache.db to a subdirectory (#5601)
We cannot guarantee that the offline/ambient tile cache (cache.db) will be created in a timely manner, so it's safer to set the backup exclusion key on its containing directory. But, because we placed cache.db in the base of the app's Application Support directory (where backups are expected to be allowed), we need to move cache.db into a directory that we control and can exclude from backups with impunity. This is an amalgam of https://github.com/mapbox/mapbox-gl-native/pull/5578 (directory exclusion) and https://github.com/mapbox/mapbox-gl-native/pull/5585 (refactored URL methods, but without the new database size method). Also: * Prefix mapbox subdirectory with dot, for extra safety * Update changelog entry with new ticket, less speculation
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm122
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.m11
2 files changed, 84 insertions, 49 deletions
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index a59fb69943..dd15920eab 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -40,58 +40,92 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount";
return sharedOfflineStorage;
}
+/**
+ Returns the file URL to the offline cache, with the option to omit the private
+ subdirectory for legacy (v3.2.0 - v3.2.3) migration purposes.
+
+ The cache is located in a directory specific to the application, so that packs
+ downloaded by other applications don’t count toward this application’s limits.
+
+ The cache is located at:
+ ~/Library/Application Support/tld.app.bundle.id/.mapbox/cache.db
+
+ The subdirectory-less cache was located at:
+ ~/Library/Application Support/tld.app.bundle.id/cache.db
+ */
++ (NSURL *)cacheURLIncludingSubdirectory:(BOOL)useSubdirectory {
+ NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
+ inDomain:NSUserDomainMask
+ appropriateForURL:nil
+ create:YES
+ error:nil];
+ NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+ if (!bundleIdentifier) {
+ // There’s no main bundle identifier when running in a unit test bundle.
+ bundleIdentifier = [NSBundle bundleForClass:self].bundleIdentifier;
+ }
+ cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
+ if (useSubdirectory) {
+ cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:@".mapbox"];
+ }
+ [[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nil];
+ if (useSubdirectory) {
+ // Avoid backing up the offline cache onto iCloud, because it can be
+ // redownloaded. Ideally, we’d even put the ambient cache in Caches, so
+ // it can be reclaimed by the system when disk space runs low. But
+ // unfortunately it has to live in the same file as offline resources.
+ [cacheDirectoryURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:NULL];
+ }
+ return [cacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName];
+}
+
+/**
+ Returns the absolute path to the location where v3.2.0-beta.1 placed the
+ offline cache.
+ */
++ (NSString *)legacyCachePath {
+#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+ // ~/Documents/offline.db
+ NSArray *legacyPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
+#elif TARGET_OS_MAC
+ // ~/Library/Caches/tld.app.bundle.id/offline.db
+ NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+ NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
+ inDomain:NSUserDomainMask
+ appropriateForURL:nil
+ create:NO
+ error:nil];
+ legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
+ NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
+ NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @"";
+#endif
+ return legacyCachePath;
+}
+
- (instancetype)init {
if (self = [super init]) {
- // Place the cache in a location specific to the application, so that
- // packs downloaded by other applications don’t count toward this
- // application’s limits.
- // ~/Library/Application Support/tld.app.bundle.id/cache.db
- NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
- inDomain:NSUserDomainMask
- appropriateForURL:nil
- create:YES
- error:nil];
- NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
- if (!bundleIdentifier) {
- // There’s no main bundle identifier when running in a unit test bundle.
- bundleIdentifier = [NSBundle bundleForClass:[self class]].bundleIdentifier;
- }
- cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
- [[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL
- withIntermediateDirectories:YES
- attributes:nil
- error:nil];
- NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName];
- NSString *cachePath = cacheURL ? cacheURL.path : @"";
-
+ NSURL *cacheURL = [[self class] cacheURLIncludingSubdirectory:YES];
+ NSString *cachePath = cacheURL.path ?: @"";
+
// Move the offline cache from v3.2.0-beta.1 to a location that can also
// be used for ambient caching.
-#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
- // ~/Documents/offline.db
- NSArray *legacyPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
-#elif TARGET_OS_MAC
- // ~/Library/Caches/tld.app.bundle.id/offline.db
- NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
- inDomain:NSUserDomainMask
- appropriateForURL:nil
- create:NO
- error:nil];
- legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
- NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
- NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @"";
-#endif
if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) {
+ NSString *legacyCachePath = [[self class] legacyCachePath];
[[NSFileManager defaultManager] moveItemAtPath:legacyCachePath toPath:cachePath error:NULL];
}
-
- _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);
- // Avoid backing up the offline cache onto iCloud, because it can be
- // redownloaded. Ideally, we’d even put the ambient cache in Caches, so
- // it can be reclaimed by the system when disk space runs low. But
- // unfortunately it has to live in the same file as offline resources.
- [cacheURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:NULL];
+ // Move the offline file cache from v3.2.x path to a subdirectory that
+ // can be reliably excluded from backups.
+ if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) {
+ NSURL *subdirectorylessCacheURL = [[self class] cacheURLIncludingSubdirectory:NO];
+ [[NSFileManager defaultManager] moveItemAtPath:subdirectorylessCacheURL.path toPath:cachePath error:NULL];
+ }
+
+ _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);
// Observe for changes to the global access token (and find out the current one).
[[MGLAccountManager sharedManager] addObserver:self
diff --git a/platform/darwin/test/MGLOfflineStorageTests.m b/platform/darwin/test/MGLOfflineStorageTests.m
index 415039c527..e2346c5f61 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.m
+++ b/platform/darwin/test/MGLOfflineStorageTests.m
@@ -106,17 +106,18 @@
// Unit tests don't use the main bundle; use com.mapbox.ios.sdk instead.
NSString *bundleIdentifier = [NSBundle bundleForClass:[MGLMapView class]].bundleIdentifier;
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
- XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheDirectoryURL.path], @"Cache directory should exist.");
+ cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:@".mapbox"];
+ XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheDirectoryURL.path], @"Cache subdirectory should exist.");
NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:@"cache.db"];
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheURL.path], @"Cache database should exist.");
NSError *error = nil;
NSNumber *exclusionFlag = nil;
- [cacheURL getResourceValue:&exclusionFlag
- forKey:NSURLIsExcludedFromBackupKey
- error:&error];
- XCTAssertTrue(exclusionFlag && [exclusionFlag boolValue], @"Backup exclusion flag should be set for cache database.");
+ [cacheDirectoryURL getResourceValue:&exclusionFlag
+ forKey:NSURLIsExcludedFromBackupKey
+ error:&error];
+ XCTAssertTrue(exclusionFlag && [exclusionFlag boolValue], @"Backup exclusion flag should be set for the directory containing the cache database.");
XCTAssertNil(error, @"No errors should be returned when checking backup exclusion flag.");
}