Aucune description

FIRInstanceIDBackupExcludedPlist.m 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FIRInstanceIDBackupExcludedPlist.h"
  17. #import "FIRInstanceIDDefines.h"
  18. #import "FIRInstanceIDLogger.h"
  19. typedef enum : NSUInteger {
  20. FIRInstanceIDPlistDirectoryUnknown,
  21. FIRInstanceIDPlistDirectoryDocuments,
  22. FIRInstanceIDPlistDirectoryApplicationSupport,
  23. } FIRInstanceIDPlistDirectory;
  24. @interface FIRInstanceIDBackupExcludedPlist ()
  25. @property(nonatomic, readwrite, copy) NSString *fileName;
  26. @property(nonatomic, readwrite, copy) NSString *subDirectoryName;
  27. @property(nonatomic, readwrite, assign) BOOL fileInStandardDirectory;
  28. @property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents;
  29. @end
  30. @implementation FIRInstanceIDBackupExcludedPlist
  31. - (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory {
  32. self = [super init];
  33. if (self) {
  34. _fileName = [fileName copy];
  35. _subDirectoryName = [subDirectory copy];
  36. #if TARGET_OS_IOS
  37. _fileInStandardDirectory = [self moveToApplicationSupportSubDirectory:subDirectory];
  38. #else
  39. // For tvOS and macOS, we never store the content in document folder, so
  40. // the migration is unnecessary.
  41. _fileInStandardDirectory = YES;
  42. #endif
  43. }
  44. return self;
  45. }
  46. - (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error {
  47. NSString *path = [self plistPathInDirectory:[self plistDirectory]];
  48. if (![dict writeToFile:path atomically:YES]) {
  49. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000,
  50. @"Failed to write to %@.plist", self.fileName);
  51. return NO;
  52. }
  53. // Successfully wrote contents -- change the in-memory contents
  54. self.cachedPlistContents = [dict copy];
  55. _FIRInstanceIDDevAssert([[NSFileManager defaultManager] fileExistsAtPath:path],
  56. @"Error writing data to non-backed up plist %@.plist", self.fileName);
  57. NSURL *URL = [NSURL fileURLWithPath:path];
  58. if (error) {
  59. *error = nil;
  60. }
  61. NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ]
  62. error:error];
  63. if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) {
  64. return YES;
  65. }
  66. BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error];
  67. if (!success) {
  68. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001,
  69. @"Error excluding %@ from backup, %@", [URL lastPathComponent],
  70. error ? *error : @"");
  71. }
  72. return success;
  73. }
  74. - (BOOL)deleteFile:(NSError **)error {
  75. BOOL success = YES;
  76. NSString *path = [self plistPathInDirectory:[self plistDirectory]];
  77. if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
  78. success = [[NSFileManager defaultManager] removeItemAtPath:path error:error];
  79. }
  80. // remove the in-memory contents
  81. self.cachedPlistContents = nil;
  82. return success;
  83. }
  84. - (NSDictionary *)contentAsDictionary {
  85. if (!self.cachedPlistContents) {
  86. NSString *path = [self plistPathInDirectory:[self plistDirectory]];
  87. if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
  88. self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path];
  89. }
  90. }
  91. return self.cachedPlistContents;
  92. }
  93. - (BOOL)moveToApplicationSupportSubDirectory:(NSString *)subDirectoryName {
  94. NSArray *directoryPaths =
  95. NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES);
  96. // This only going to happen inside iOS so it is an applicationSupportDirectory.
  97. NSString *applicationSupportDirPath = directoryPaths.lastObject;
  98. NSArray *components = @[ applicationSupportDirPath, subDirectoryName ];
  99. NSString *subDirectoryPath = [NSString pathWithComponents:components];
  100. BOOL hasSubDirectory;
  101. if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath
  102. isDirectory:&hasSubDirectory]) {
  103. // Cannot move to non-existent directory
  104. return NO;
  105. }
  106. if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryDocuments]) {
  107. NSString *oldPlistPath = [self plistPathInDirectory:FIRInstanceIDPlistDirectoryDocuments];
  108. NSString *newPlistPath =
  109. [self plistPathInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport];
  110. if ([self doesFileExistInDirectory:FIRInstanceIDPlistDirectoryApplicationSupport]) {
  111. // File exists in both Documents and ApplicationSupport
  112. return NO;
  113. }
  114. NSError *moveError;
  115. if (![[NSFileManager defaultManager] moveItemAtPath:oldPlistPath
  116. toPath:newPlistPath
  117. error:&moveError]) {
  118. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist002,
  119. @"Failed to move file %@ from %@ to %@. Error: %@", self.fileName,
  120. oldPlistPath, newPlistPath, moveError);
  121. return NO;
  122. }
  123. }
  124. // We moved the file if it existed, otherwise we didn't need to do anything
  125. return YES;
  126. }
  127. - (BOOL)doesFileExist {
  128. return [self doesFileExistInDirectory:[self plistDirectory]];
  129. }
  130. #pragma mark - Private
  131. - (FIRInstanceIDPlistDirectory)plistDirectory {
  132. if (_fileInStandardDirectory) {
  133. return FIRInstanceIDPlistDirectoryApplicationSupport;
  134. } else {
  135. return FIRInstanceIDPlistDirectoryDocuments;
  136. };
  137. }
  138. - (NSString *)plistPathInDirectory:(FIRInstanceIDPlistDirectory)directory {
  139. return [self pathWithName:self.fileName inDirectory:directory];
  140. }
  141. - (NSString *)pathWithName:(NSString *)plistName
  142. inDirectory:(FIRInstanceIDPlistDirectory)directory {
  143. NSArray *directoryPaths;
  144. NSArray *components = @[];
  145. NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", plistName];
  146. switch (directory) {
  147. case FIRInstanceIDPlistDirectoryDocuments:
  148. directoryPaths =
  149. NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  150. components = @[ directoryPaths.lastObject, plistNameWithExtension ];
  151. break;
  152. case FIRInstanceIDPlistDirectoryApplicationSupport:
  153. directoryPaths =
  154. NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES);
  155. components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ];
  156. break;
  157. default:
  158. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlistInvalidPlistEnum,
  159. @"Invalid plist directory type: %lu", (unsigned long)directory);
  160. NSAssert(NO, @"Invalid plist directory type: %lu", (unsigned long)directory);
  161. break;
  162. }
  163. return [NSString pathWithComponents:components];
  164. }
  165. - (BOOL)doesFileExistInDirectory:(FIRInstanceIDPlistDirectory)directory {
  166. NSString *path = [self plistPathInDirectory:directory];
  167. return [[NSFileManager defaultManager] fileExistsAtPath:path];
  168. }
  169. - (NSSearchPathDirectory)supportedDirectory {
  170. #if TARGET_OS_TV
  171. return NSCachesDirectory;
  172. #else
  173. return NSApplicationSupportDirectory;
  174. #endif
  175. }
  176. @end