Skip to content

Commit

Permalink
- OCVault: add property and accessor for bookmarkMetadataURL folder
Browse files Browse the repository at this point in the history
- OCBookmark:
	- add `metaDataStorageURL` property for transitioning data from internal/memory to external/disk storage
	- if `metaDataStorageURL` is set, externalize avatar/avatarData and load it only on demand for as short as possible
	- keep track of whether an avatar has been stored via avatarDataURL
- OCBookmarkManager
	- add code to transition bookmarks from internal to external storage
	- add code to store changed and transitioned data to external storage
  • Loading branch information
felix-schwarz committed Oct 1, 2024
1 parent bca0bb5 commit fe346c6
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 5 deletions.
5 changes: 5 additions & 0 deletions ownCloudSDK/Bookmark/OCBookmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ NS_ASSUME_NONNULL_BEGIN
- (void)removeCapability:(OCBookmarkCapability)capability;
- (BOOL)hasCapability:(OCBookmarkCapability)capability;

#pragma mark - Metadata storage
@property(strong,nullable) NSURL *metaDataStorageURL; //!< URL to store bookmark data in (f.ex. certificates, avatar images, ..)

- (nullable NSError *)storeMetadata;

#pragma mark - Certificate approval
- (NSNotificationName)certificateUserApprovalUpdateNotificationName; //!< Notification that gets sent if the bookmark's certificate user-approved status changed
- (void)postCertificateUserApprovalUpdateNotification; //!< Posts a .certificateUserApprovalUpdateNotificationName notification
Expand Down
74 changes: 69 additions & 5 deletions ownCloudSDK/Bookmark/OCBookmark.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ @interface OCBookmark ()
OCIPCNotificationName _bookmarkAuthUpdateNotificationName;

id<OCViewProvider> _avatar;
NSURL *_avatarDataURL;
NSData *_avatarData;

NSString *_lastUsername;
Expand Down Expand Up @@ -246,19 +247,64 @@ - (OCCertificate *)primaryCertificate
return (primaryCertificate);
}

#pragma mark - Metadata storage
- (NSError *)storeMetadata
{
NSError *error = nil;

@synchronized(self)
{
if (_metaDataStorageURL != nil)
{
if ([NSFileManager.defaultManager createDirectoryAtURL:_metaDataStorageURL withIntermediateDirectories:YES attributes:nil error:&error])
{
if ((_avatarDataURL != nil) && (_avatarData != nil))
{
[_avatarData writeToURL:_avatarDataURL options:NSDataWritingAtomic error:&error];
}
}
}
}

return (error);
}

#pragma mark - Avatar
- (NSData *)avatarData
{
@synchronized(self)
{
if ((_avatarData == nil) && (_avatarDataURL != nil))
{
_avatarData = [[NSData alloc] initWithContentsOfURL:_avatarDataURL];
}
}

return (_avatarData);
}

- (id<OCViewProvider>)avatar
{
@synchronized(self)
{
if ((_avatar == nil) && (_avatarData != nil))
if (_avatar == nil)
{
@try
NSData *avatarData = _avatarData;

if ((avatarData == nil) && (_avatarDataURL != nil))
{
_avatar = [NSKeyedUnarchiver unarchiveObjectWithData:_avatarData];
avatarData = [[NSData alloc] initWithContentsOfURL:_avatarDataURL];
}
@catch (NSException *exception)

if (avatarData != nil)
{
@try
{
_avatar = [NSKeyedUnarchiver unarchiveObjectWithData:avatarData];
}
@catch (NSException *exception)
{
}
}
}

Expand Down Expand Up @@ -304,6 +350,15 @@ - (void)setAvatar:(id<OCViewProvider>)avatar

_avatar = (avatarData != nil) ? avatar : nil;
_avatarData = avatarData;

if ((avatarData != nil) && (_metaDataStorageURL != nil))
{
_avatarDataURL = [_metaDataStorageURL URLByAppendingPathComponent:@"avatarData"];
}
else
{
_avatarDataURL = nil;
}
}
}

Expand Down Expand Up @@ -415,6 +470,8 @@ - (instancetype)initWithCoder:(NSCoder *)decoder

_originURL = [decoder decodeObjectOfClass:NSURL.class forKey:@"originURL"];

_metaDataStorageURL = [decoder decodeObjectOfClass:NSURL.class forKey:@"metaDataStorageURL"];

_capabilities = [decoder decodeObjectOfClasses:[NSSet setWithObjects:NSSet.class, NSString.class, nil] forKey:@"capabilities"];

_certificateStore = [decoder decodeObjectOfClass:OCCertificateStore.class forKey:@"certificateStore"];
Expand All @@ -435,6 +492,7 @@ - (instancetype)initWithCoder:(NSCoder *)decoder
_authenticationValidationDate = [decoder decodeObjectOfClass:NSDate.class forKey:@"authenticationValidationDate"];

_avatarData = [decoder decodeObjectOfClass:NSData.class forKey:@"avatarData"];
_avatarDataURL = [decoder decodeObjectOfClass:NSURL.class forKey:@"avatarDataURL"];

_databaseVersion = [decoder decodeIntegerForKey:@"databaseVersion"];

Expand Down Expand Up @@ -462,14 +520,20 @@ - (void)encodeWithCoder:(NSCoder *)coder

[coder encodeObject:_originURL forKey:@"originURL"];

[coder encodeObject:_metaDataStorageURL forKey:@"metaDataStorageURL"];

[coder encodeObject:_capabilities forKey:@"capabilities"];

[coder encodeObject:_certificateStore forKey:@"certificateStore"];

[coder encodeObject:_authenticationMethodIdentifier forKey:@"authenticationMethodIdentifier"];
[coder encodeObject:_authenticationValidationDate forKey:@"authenticationValidationDate"];

[coder encodeObject:_avatarData forKey:@"avatarData"];
if (_avatarDataURL == nil)
{
[coder encodeObject:_avatarData forKey:@"avatarData"];
}
[coder encodeObject:_avatarDataURL forKey:@"avatarDataURL"];

[coder encodeInteger:_databaseVersion forKey:@"databaseVersion"];

Expand Down
18 changes: 18 additions & 0 deletions ownCloudSDK/Resource Management/OCBookmarkManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#import "OCLogger.h"
#import "OCDataSourceArray.h"
#import "OCBookmark+DataItem.h"
#import "OCVault.h"

@implementation OCBookmarkManager
{
Expand Down Expand Up @@ -106,6 +107,13 @@ - (void)loadBookmarks
{
OCBookmark *existingBookmark = nil;

if (loadedBookmark.metaDataStorageURL == nil)
{
// Old-style bookmark with internal/memory metadata storage - transition it to external storage
loadedBookmark.metaDataStorageURL = [OCVault bookmarkMetadataURLForVaultUUID:loadedBookmark.uuid]; // Provide bookmark storage location
loadedBookmark.avatar = loadedBookmark.avatar; // Re-set avatar to force generation of _avatarDataURL
}

for (OCBookmark *bookmark in existingBookmarks)
{
if ([bookmark.uuid isEqual:loadedBookmark.uuid])
Expand Down Expand Up @@ -206,6 +214,16 @@ - (void)saveBookmarks
OCLogError(@"Error archiving bookmarks: %@", OCLogPrivate(exception));
}

for (OCBookmark *bookmark in _bookmarks)
{
NSError *error;

if ((error = [bookmark storeMetadata]) != nil)
{
OCLogError(@"Error storing metadata for bookmark: %@ (for %@)", error, bookmark);
}
}

[bookmarkData writeToURL:self.bookmarkStoreURL atomically:YES];
}
}
Expand Down
6 changes: 6 additions & 0 deletions ownCloudSDK/Vaults/OCVault.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
[Bookmark UUID].ockvs - OCVault.keyValueStoreURL
"BookmarkMetadata"/ - OCVault.bookmarkMetadataURL and +bookmarkMetadataURLForVaultUUID: (folder where (larger) bookmark metadata blobs are stored)
"Erasure"/ - OCVault.wipeContainerRootURL (folder whose contents should be erased)
"HTTPPipeline"/ - OCVault.httpPipelineRootURL
Expand All @@ -53,6 +54,7 @@
"TemporaryDownloads"/ - OCVault.temporaryDownloadURL
[Random UUID] (temporary files for downloads)
"messageQueue.dat" - OCMessageQueue.globalQueue KVS
"postBuildSettings.plist" - OCClassSettingsFlatSourcePostBuild storage
Expand Down Expand Up @@ -102,6 +104,7 @@ typedef BOOL(^OCVaultCompactSelector)(OCSyncAnchor _Nullable syncAnchor, OCItem
NSURL *_filesRootURL;
NSURL *_httpPipelineRootURL;
NSURL *_temporaryDownloadURL;
NSURL *_bookmarkMetadataURL;
NSURL *_wipeContainerRootURL;
NSURL *_wipeContainerFilesRootURL;

Expand Down Expand Up @@ -140,6 +143,7 @@ typedef BOOL(^OCVaultCompactSelector)(OCSyncAnchor _Nullable syncAnchor, OCItem
@property(nullable,readonly,nonatomic) NSURL *drivesRootURL; //!< The vault's root URL for drive folders
@property(nullable,readonly,nonatomic) NSURL *httpPipelineRootURL; //!< The vault's root URL for HTTP pipeline data
@property(nullable,readonly,nonatomic) NSURL *temporaryDownloadURL; //!< The vault's root URL for temporarily downloaded files.
@property(nullable,readonly,nonatomic) NSURL *bookmarkMetadataURL; //!< The vault's root URL for bookmark metadata files.

@property(nullable,readonly,nonatomic) NSURL *wipeContainerRootURL; //!< The vault's rootURL subfolder for items to erase.
@property(nullable,readonly,nonatomic) NSURL *wipeContainerFilesRootURL; //!< The vault's filesRootURL subfolder for items to erase.
Expand Down Expand Up @@ -200,6 +204,8 @@ typedef BOOL(^OCVaultCompactSelector)(OCSyncAnchor _Nullable syncAnchor, OCItem

+ (nullable NSString *)databaseFilePathRelativeToRootPathForVaultUUID:(NSUUID *)uuid;

+ (nullable NSURL *)bookmarkMetadataURLForVaultUUID:(NSUUID *)uuid;

@property(nullable,readonly,nonatomic,class) NSURL *httpPipelineRootURL;

#pragma mark - URL/path parser
Expand Down
14 changes: 14 additions & 0 deletions ownCloudSDK/Vaults/OCVault.m
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,15 @@ - (NSURL *)temporaryDownloadURL
return (_temporaryDownloadURL);
}

- (NSURL *)bookmarkMetadataURL
{
if (_bookmarkMetadataURL == nil)
{
_bookmarkMetadataURL = [self.class bookmarkMetadataURLForVaultUUID:self.uuid];
}
return (_bookmarkMetadataURL);
}

- (NSURL *)wipeContainerRootURL
{
if (_wipeContainerRootURL == nil)
Expand Down Expand Up @@ -1110,6 +1119,11 @@ + (NSString *)keyValueStoreFilePathRelativeToRootPathForVaultUUID:(NSUUID *)uuid
return ([uuid.UUIDString stringByAppendingString:@".ockvs"]);
}

+ (nullable NSURL *)bookmarkMetadataURLForVaultUUID:(NSUUID *)uuid
{
return ([[self rootURLForUUID:uuid] URLByAppendingPathComponent:@"BookmarkMetadata" isDirectory:YES]);
}

+ (NSURL *)httpPipelineRootURL
{
return [[[OCAppIdentity sharedAppIdentity] appGroupContainerURL] URLByAppendingPathComponent:OCVaultPathHTTPPipeline];
Expand Down

0 comments on commit fe346c6

Please sign in to comment.