diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 8b9a1db7..44237e94 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -146,6 +146,7 @@ 4C6F228C19A4AA700012310C /* MPAutotypeDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228B19A4AA700012310C /* MPAutotypeDelay.m */; }; 4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C701CBB178618A000581B88 /* 12_RemoteTemplate.pdf */; }; 4C7155D81A10DB6D00979307 /* IconSelection.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C7155DA1A10DB6D00979307 /* IconSelection.xib */; }; + 4C735FC02035FCBF00708D53 /* MPPluginEntryActionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */; }; 4C76155C1764C04C0015A1A6 /* GeneralSettings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76155E1764C04C0015A1A6 /* GeneralSettings.xib */; }; 4C7615681764C0C40015A1A6 /* PasswordInputView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76156A1764C0C40015A1A6 /* PasswordInputView.xib */; }; 4C76156D1764C0E20015A1A6 /* InspectorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76156F1764C0E20015A1A6 /* InspectorView.xib */; }; @@ -562,6 +563,8 @@ 4C7155E81A10DB7700979307 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IconSelection.strings; sourceTree = ""; }; 4C7155EA1A10DB7800979307 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IconSelection.strings; sourceTree = ""; }; 4C7155EC1A10DB7900979307 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IconSelection.strings; sourceTree = ""; }; + 4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginEntryActionContext.h; sourceTree = ""; }; + 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginEntryActionContext.m; sourceTree = ""; }; 4C73EB941FBB58730033000F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/DatabaseSettingsWindow.strings; sourceTree = ""; }; 4C73EB951FBB5A8F0033000F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/AutotypeCandidateSelectionView.strings; sourceTree = ""; }; 4C73EB961FBB5A910033000F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/AutotypeBuilderView.strings; sourceTree = ""; }; @@ -1617,6 +1620,8 @@ 4C8F0C6D1FCEE9B900BE157F /* MPPluginConstants.m */, 4CA78BFE1FD58C92003C8560 /* MPPluginRepository.h */, 4CA78BFF1FD58C92003C8560 /* MPPluginRepository.m */, + 4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */, + 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */, ); name = Plugin; path = MacPass; @@ -1896,6 +1901,7 @@ 4C3BD51516D276F800389F1F /* MPToolbarDelegate.m in Sources */, 4C7B63731C0CB51F00D7038C /* TTTDataTransformer.m in Sources */, 4C8F0C711FCEF91400BE157F /* MPPickcharsParser.m in Sources */, + 4C735FC02035FCBF00708D53 /* MPPluginEntryActionContext.m in Sources */, 4C61EA0316D2FD0800AC519E /* MPOutlineViewController.m in Sources */, 4C65C79C16DD283900E32CFF /* MPToolbarButton.m in Sources */, 4C431BCD16E2A82800700A81 /* MPPasteBoardController.m in Sources */, diff --git a/MacPass/MPPluginEntryActionContext.h b/MacPass/MPPluginEntryActionContext.h new file mode 100644 index 00000000..632a25f1 --- /dev/null +++ b/MacPass/MPPluginEntryActionContext.h @@ -0,0 +1,22 @@ +// +// MPPluginEntryActionContext.h +// MacPass +// +// Created by Michael Starke on 15.02.18. +// Copyright © 2018 HicknHack Software GmbH. All rights reserved. +// + +#import + +@class MPPlugin; +@class KPKEntry; +@protocol MPEntryActionPlugin; + +@interface MPPluginEntryActionContext : NSObject + +@property (strong) MPPlugin *plugin; +@property (copy) NSArray *entries; + +- (instancetype)initWithPlugin:(MPPlugin *)plugin entries:(NSArray *)entries NS_DESIGNATED_INITIALIZER; + +@end diff --git a/MacPass/MPPluginEntryActionContext.m b/MacPass/MPPluginEntryActionContext.m new file mode 100644 index 00000000..1a4fe8e4 --- /dev/null +++ b/MacPass/MPPluginEntryActionContext.m @@ -0,0 +1,26 @@ +// +// MPPluginEntryActionContext.m +// MacPass +// +// Created by Michael Starke on 15.02.18. +// Copyright © 2018 HicknHack Software GmbH. All rights reserved. +// + +#import "MPPluginEntryActionContext.h" + +@implementation MPPluginEntryActionContext + +- (instancetype)init { + return [self initWithPlugin:nil entries:nil]; +} + +- (instancetype)initWithPlugin:(MPPlugin *)plugin entries:(NSArray *)entries { + self = [super init]; + if(self) { + _plugin = plugin; + _entries = [entries copy]; + } + return self; +} + +@end diff --git a/MacPass/MPPluginHost.m b/MacPass/MPPluginHost.m index e6e3c245..84868b42 100644 --- a/MacPass/MPPluginHost.m +++ b/MacPass/MPPluginHost.m @@ -25,6 +25,8 @@ #import "MPPlugin.h" #import "MPPlugin_Private.h" #import "MPPluginConstants.h" +#import "MPPluginEntryActionContext.h" + #import "NSApplication+MPAdditions.h" #import "MPSettingsHelper.h" @@ -40,8 +42,8 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun @interface MPPluginHost () @property (strong) NSMutableArray *mutablePlugins; -@property (strong) NSPointerArray *entryActionPlugins; -@property (strong) NSPointerArray *customAttributePlugins; +@property (strong) NSMutableArray *entryActionPluginIdentifiers; +@property (strong) NSMutableArray *customAttributePluginIdentifiers; @property (nonatomic) BOOL loadUnsecurePlugins; @@ -74,8 +76,8 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun _mutablePlugins = [[NSMutableArray alloc] init]; _disabledPlugins = [[NSUserDefaults standardUserDefaults] arrayForKey:kMPSettingsKeyLoadUnsecurePlugins]; _loadUnsecurePlugins = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyLoadUnsecurePlugins]; - _entryActionPlugins = [NSPointerArray weakObjectsPointerArray]; - _customAttributePlugins = [NSPointerArray weakObjectsPointerArray]; + _entryActionPluginIdentifiers = [[NSMutableArray alloc] init]; + _customAttributePluginIdentifiers = [[NSMutableArray alloc] init]; [self _loadPlugins]; @@ -296,25 +298,52 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun - (void)_addPlugin:(MPPlugin *)plugin { [self.mutablePlugins addObject:plugin]; if([plugin conformsToProtocol:@protocol(MPEntryActionPlugin)]) { - [self.entryActionPlugins addPointer:(__bridge void * _Nullable)(plugin)]; + NSAssert(![self.entryActionPluginIdentifiers containsObject:plugin.identifier], @"Internal inconsitency. Duplicate bundle identifier used %@!", plugin.identifier); + [self.entryActionPluginIdentifiers addObject:plugin.identifier]; } if([plugin conformsToProtocol:@protocol(MPCustomAttributePlugin)]) { - [self.customAttributePlugins addPointer:(__bridge void * _Nullable)(plugin)]; + NSAssert(![self.customAttributePluginIdentifiers containsObject:plugin.identifier], @"Internal inconsitency. Duplicate bundle identifier used %@!", plugin.identifier); + [self.customAttributePluginIdentifiers addObject:plugin.identifier]; } } +- (MPPlugin *)_pluginWithIdentifier:(NSString *)bundleIdentifier { + for(MPPlugin *plugin in self.mutablePlugins) { + if([plugin.identifier isEqualToString:bundleIdentifier]) { + return plugin; + } + } + return nil; +} + #pragma mark Action Plugins - (NSArray *)avilableMenuItemsForEntries:(NSArray *)entries { NSMutableArray *items = [[NSMutableArray alloc] init]; - for(id plugin in self.entryActionPlugins) { + for(NSString *identifier in self.entryActionPluginIdentifiers) { + MPPlugin *plugin = (MPPlugin *)[self _pluginWithIdentifier:identifier]; if(plugin) { - [items addObjectsFromArray:[plugin menuItemsForEntries:entries]]; + NSArray *tmpItems = [plugin menuItemsForEntries:entries]; + for(NSMenuItem *item in tmpItems) { + item.representedObject = [[MPPluginEntryActionContext alloc] initWithPlugin:plugin entries:entries]; + item.target = self; + item.action = @selector(_performEntryAction:); + } + [items addObjectsFromArray:tmpItems]; } } return [items copy]; } +- (void)_performEntryAction:(id)sender { + if(![sender isKindOfClass:NSMenuItem.class]) { + return; + } + NSMenuItem *item = sender; + MPPluginEntryActionContext *context = item.representedObject; + [context.plugin performActionForMenuItem:item withEntries:context.entries]; +} + @end