1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 05:30:01 +00:00
Files
browser/apps/desktop/desktop_native/objc/src/native/interop.m
Andreas Coroiu f16bfa4cd2 [PM-9035] desktop build logic to provide credentials to os on sync (#10181)
* feat: scaffold desktop_objc

* feat: rename fido2 to autofill

* feat: scaffold electron autofill

* feat: auto call hello world on init

* feat: scaffold call to basic objc function

* feat: simple log that checks if autofill is enabled

* feat: adding some availability guards

* feat: scaffold services and allow calls from inspector

* feat: create custom type for returning strings across rust/objc boundary

* chore: clean up comments

* feat: enable ARC

* feat: add util function `c_string_to_nsstring`

* chore: refactor and rename to `run_command`

* feat: add try-catch around command execution

* feat: properly implement command calling

Add static typing. Add proper error handling.

* feat: add autoreleasepool to avoid memory leaks

* chore: change objc names to camelCase

* fix: error returning

* feat: extract some helper functions into utils class

* feat: scaffold status command

* feat: implement status command

* feat: implement password credential mapping

* wip: implement sync command

This crashes because we are not properly handling the fact that `saveCredentialIdentities` uses callbacks, resulting in a race condition where we try to access a variable (result) that has already gotten dealloc'd.

* feat: first version of callback

* feat: make run_command async

* feat: functioning callback returns

* chore: refactor to make objc code easier to read and use

* feat: refactor everything to use new callback return method

* feat: re-implement status command with callback

* fix: warning about CommandContext not being FFI-safe

* feat: implement sync command using callbacks

* feat: implement manual password credential sync

* feat: add auto syncing

* docs: add todo

* feat: add support for passkeys

* chore: move desktop autofill service to init service

* feat: auto-add all .m files to builder

* fix: native build on unix and windows

* fix: unused compiler warnings

* fix: napi type exports

* feat: add corresponding dist command

* feat: comment signing profile until we fix signing

* fix: build breaking on non-macOS platforms

* chore: cargo lock update

* chore: revert accidental version change

* feat: put sync behind feature flag

* chore: put files in autofill folder

* fix: obj-c code not recompiling on changes

* feat: add `namespace` to commands

* fix: linting complaining about flag

* feat: add autofill as owner of their objc code

* chore: make autofill owner of run_command in core crate

* fix: re-add napi annotation

* fix: remove dev bypass
2024-12-06 16:31:30 +01:00

72 lines
2.3 KiB
Objective-C

#import "interop.h"
#import "utils.h"
/// [Callable from Rust]
/// Frees the memory allocated for an ObjCString
void freeObjCString(struct ObjCString *value) {
free(value->value);
}
// --- Helper functions to convert between Objective-C and Rust types ---
NSString *_success(NSDictionary *value) {
NSDictionary *wrapper = @{@"type": @"success", @"value": value};
NSError *jsonError = nil;
NSString *toReturn = serializeJson(wrapper, jsonError);
if (jsonError) {
// Manually format message since there seems to be an issue with the JSON serialization
return [NSString stringWithFormat:@"{\"type\": \"error\", \"error\": \"Error occurred while serializing error: %@\"}", jsonError];
}
return toReturn;
}
NSString *_error(NSString *error) {
NSDictionary *errorDictionary = @{@"type": @"error", @"error": error};
NSError *jsonError = nil;
NSString *toReturn = serializeJson(errorDictionary, jsonError);
if (jsonError) {
// Manually format message since there seems to be an issue with the JSON serialization
return [NSString stringWithFormat:@"{\"type\": \"error\", \"error\": \"Error occurred while serializing error: %@\"}", jsonError];
}
return toReturn;
}
NSString *_error_er(NSError *error) {
return _error([error localizedDescription]);
}
NSString *_error_ex(NSException *error) {
return _error([NSString stringWithFormat:@"%@ (%@): %@", error.name, error.reason, [error callStackSymbols]]);
}
void _return(void* context, NSString *output) {
if (!commandReturn(context, nsStringToObjCString(output))) {
NSLog(@"Error: Failed to return command output");
// NOTE: This will most likely crash the application
@throw [NSException exceptionWithName:@"CommandReturnError" reason:@"Failed to return command output" userInfo:nil];
}
}
/// Converts an NSString to an ObjCString struct
struct ObjCString nsStringToObjCString(NSString* string) {
size_t size = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
char *value = malloc(size);
[string getCString:value maxLength:size encoding:NSUTF8StringEncoding];
struct ObjCString objCString;
objCString.value = value;
objCString.size = size;
return objCString;
}
/// Converts a C-string to an NSString
NSString* cStringToNSString(char* string) {
return [[NSString alloc] initWithUTF8String:string];
}