diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 6de29fa43a..d2138dd96a 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -165,8 +165,8 @@ export default class MainBackground { return promise.then((result) => result.response === 'unlocked'); } }); - this.storageService = new BrowserStorageService(this.platformUtilsService); - this.secureStorageService = new BrowserStorageService(this.platformUtilsService); + this.storageService = new BrowserStorageService(); + this.secureStorageService = new BrowserStorageService(); this.i18nService = new I18nService(BrowserApi.getUILanguage(window)); this.cryptoFunctionService = new WebCryptoFunctionService(window, this.platformUtilsService); this.cryptoService = new CryptoService(this.storageService, this.secureStorageService, @@ -249,17 +249,15 @@ export default class MainBackground { this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, this.platformUtilsService, this.analytics, this.vaultTimeoutService); - if (!this.isSafari) { - this.tabsBackground = new TabsBackground(this); - this.contextMenusBackground = new ContextMenusBackground(this, this.cipherService, - this.passwordGenerationService, this.analytics, this.platformUtilsService, this.vaultTimeoutService, - this.eventService, this.totpService); - this.idleBackground = new IdleBackground(this.vaultTimeoutService, this.storageService, - this.notificationsService); - this.webRequestBackground = new WebRequestBackground(this.platformUtilsService, this.cipherService, - this.vaultTimeoutService); - this.windowsBackground = new WindowsBackground(this); - } + this.tabsBackground = new TabsBackground(this); + this.contextMenusBackground = new ContextMenusBackground(this, this.cipherService, + this.passwordGenerationService, this.analytics, this.platformUtilsService, this.vaultTimeoutService, + this.eventService, this.totpService); + this.idleBackground = new IdleBackground(this.vaultTimeoutService, this.storageService, + this.notificationsService); + this.webRequestBackground = new WebRequestBackground(this.platformUtilsService, this.cipherService, + this.vaultTimeoutService); + this.windowsBackground = new WindowsBackground(this); } async bootstrap() { @@ -273,13 +271,11 @@ export default class MainBackground { await this.runtimeBackground.init(); await this.commandsBackground.init(); - if (!this.isSafari) { - await this.tabsBackground.init(); - await this.contextMenusBackground.init(); - await this.idleBackground.init(); - await this.webRequestBackground.init(); - await this.windowsBackground.init(); - } + await this.tabsBackground.init(); + await this.contextMenusBackground.init(); + await this.idleBackground.init(); + await this.webRequestBackground.init(); + await this.windowsBackground.init(); return new Promise((resolve) => { setTimeout(async () => { @@ -294,7 +290,7 @@ export default class MainBackground { } async setIcon() { - if (this.isSafari || (!chrome.browserAction && !this.sidebarAction)) { + if ((!chrome.browserAction && !this.sidebarAction)) { return; } @@ -313,7 +309,7 @@ export default class MainBackground { } async refreshBadgeAndMenu(forLocked: boolean = false) { - if (this.isSafari || !chrome.windows || !chrome.contextMenus) { + if (!chrome.windows || !chrome.contextMenus) { return; } @@ -444,7 +440,7 @@ export default class MainBackground { } private async buildContextMenu() { - if (this.isSafari || !chrome.contextMenus || this.buildingContextMenu) { + if (!chrome.contextMenus || this.buildingContextMenu) { return; } diff --git a/src/browser/browserApi.ts b/src/browser/browserApi.ts index 1ee54a45b1..c19f0059e3 100644 --- a/src/browser/browserApi.ts +++ b/src/browser/browserApi.ts @@ -4,20 +4,16 @@ import { Utils } from 'jslib/misc/utils'; export class BrowserApi { static isWebExtensionsApi: boolean = (typeof browser !== 'undefined'); - static isSafariApi: boolean = (window as any).safariAppExtension === true; + static isSafariApi: boolean = true; static isChromeApi: boolean = !BrowserApi.isSafariApi && (typeof chrome !== 'undefined'); static isFirefoxOnAndroid: boolean = navigator.userAgent.indexOf('Firefox/') !== -1 && navigator.userAgent.indexOf('Android') !== -1; static async getTabFromCurrentWindowId(): Promise { - if (BrowserApi.isChromeApi) { - return await BrowserApi.tabsQueryFirst({ - active: true, - windowId: chrome.windows.WINDOW_ID_CURRENT, - }); - } else if (BrowserApi.isSafariApi) { - return await BrowserApi.getTabFromCurrentWindow(); - } + return await BrowserApi.tabsQueryFirst({ + active: true, + windowId: chrome.windows.WINDOW_ID_CURRENT, + }); } static async getTabFromCurrentWindow(): Promise { @@ -34,16 +30,11 @@ export class BrowserApi { } static async tabsQuery(options: any): Promise { - if (BrowserApi.isChromeApi) { - return new Promise((resolve) => { - chrome.tabs.query(options, (tabs: any[]) => { - resolve(tabs); - }); + return new Promise((resolve) => { + chrome.tabs.query(options, (tabs: any[]) => { + resolve(tabs); }); - } else if (BrowserApi.isSafariApi) { - const tabs = await SafariApp.sendMessageToApp('tabs_query', JSON.stringify(options)); - return tabs != null ? JSON.parse(tabs) : null; - } + }); } static async tabsQueryFirst(options: any): Promise { @@ -72,81 +63,36 @@ export class BrowserApi { return; } - if (BrowserApi.isChromeApi) { - return new Promise((resolve) => { - chrome.tabs.sendMessage(tab.id, obj, options, () => { - if (chrome.runtime.lastError) { - // Some error happened - } - resolve(); - }); + return new Promise((resolve) => { + chrome.tabs.sendMessage(tab.id, obj, options, () => { + if (chrome.runtime.lastError) { + // Some error happened + } + resolve(); }); - } else if (BrowserApi.isSafariApi) { - if (options != null && options.frameId != null && obj.bitwardenFrameId == null) { - obj.bitwardenFrameId = options.frameId; - } - await SafariApp.sendMessageToApp('tabs_message', JSON.stringify({ - tab: tab, - obj: JSON.stringify(obj), - options: options, - }), true); - } + }); } static getBackgroundPage(): any { - if (BrowserApi.isChromeApi) { - return chrome.extension.getBackgroundPage(); - } else if (BrowserApi.isSafariApi) { - return window; - } else { - return null; - } + return chrome.extension.getBackgroundPage(); } static getApplicationVersion(): string { - if (BrowserApi.isChromeApi) { - return chrome.runtime.getManifest().version; - } else if (BrowserApi.isSafariApi) { - return (window as any).bitwardenApplicationVersion; - } else { - return null; - } + return chrome.runtime.getManifest().version; } static async isPopupOpen(): Promise { - if (BrowserApi.isChromeApi) { - return Promise.resolve(chrome.extension.getViews({ type: 'popup' }).length > 0); - } else if (BrowserApi.isSafariApi) { - const open = await SafariApp.sendMessageToApp('isPopoverOpen'); - return open === 'true'; - } else { - return Promise.resolve(false); - } + return Promise.resolve(chrome.extension.getViews({ type: 'popup' }).length > 0); } static createNewTab(url: string, extensionPage: boolean = false) { - if (BrowserApi.isChromeApi) { - chrome.tabs.create({ url: url }); - } else if (BrowserApi.isSafariApi) { - SafariApp.sendMessageToApp('createNewTab', url, true); - } + chrome.tabs.create({ url: url }); } static messageListener(name: string, callback: (message: any, sender: any, response: any) => void) { - if (BrowserApi.isChromeApi) { - chrome.runtime.onMessage.addListener((msg: any, sender: any, response: any) => { - callback(msg, sender, response); - }); - } else if (BrowserApi.isSafariApi) { - SafariApp.addMessageListener(name, (message: any, sender: any, response: any) => { - if (message.bitwardenFrameId != null) { - if (sender != null && typeof (sender) === 'object' && sender.frameId == null) { - sender.frameId = message.bitwardenFrameId; - } - } - callback(message, sender, response); - }); - } + chrome.runtime.onMessage.addListener((msg: any, sender: any, response: any) => { + callback(msg, sender, response); + }); } static closePopup(win: Window) { @@ -155,10 +101,8 @@ export class BrowserApi { // condition is only called if the popup wasn't already dismissed (future proofing). // ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1433604 browser.tabs.update({ active: true }).finally(win.close); - } else if (BrowserApi.isWebExtensionsApi || BrowserApi.isChromeApi) { + } else { win.close(); - } else if (BrowserApi.isSafariApi) { - SafariApp.sendMessageToApp('hidePopover'); } } @@ -196,30 +140,22 @@ export class BrowserApi { } static getUILanguage(win: Window) { - if (BrowserApi.isSafariApi) { - return win.navigator.language; - } else { - return chrome.i18n.getUILanguage(); - } + return chrome.i18n.getUILanguage(); } static reloadExtension(win: Window) { if (win != null) { return win.location.reload(true); - } else if (BrowserApi.isSafariApi) { - SafariApp.sendMessageToApp('reloadExtension'); - } else if (!BrowserApi.isSafariApi) { + } else { return chrome.runtime.reload(); } } static reloadOpenWindows() { - if (!BrowserApi.isSafariApi) { - const views = chrome.extension.getViews() as Window[]; - views.filter((w) => w.location.href != null).forEach((w) => { - w.location.reload(); - }); - } + const views = chrome.extension.getViews() as Window[]; + views.filter((w) => w.location.href != null).forEach((w) => { + w.location.reload(); + }); } static connectNative(application: string): browser.runtime.Port | chrome.runtime.Port { diff --git a/src/browser/safariApp.ts b/src/browser/safariApp.ts index 5593b069b8..3c9b887a1d 100644 --- a/src/browser/safariApp.ts +++ b/src/browser/safariApp.ts @@ -6,6 +6,7 @@ export class SafariApp { return; } (window as any).bitwardenSafariAppInited = true; + if (BrowserApi.isSafariApi) { (window as any).bitwardenSafariAppRequests = new Map void, timeoutDate: Date }>(); @@ -14,31 +15,25 @@ export class SafariApp { (window as any).bitwardenSafariAppMessageReceiver = (message: any) => { SafariApp.receiveMessageFromApp(message); }; - setInterval(() => SafariApp.cleanupOldRequests(), 5 * 60000); // every 5 mins } } static sendMessageToApp(command: string, data: any = null, resolveNow = false): Promise { + debugger; if (!BrowserApi.isSafariApi) { return Promise.resolve(null); } return new Promise((resolve) => { const now = new Date(); const messageId = now.getTime().toString() + '_' + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); - (window as any).webkit.messageHandlers.bitwardenApp.postMessage(JSON.stringify({ + (browser as any).runtime.sendNativeMessage("com.bitwarden.desktop", { id: messageId, command: command, data: data, responseData: null, - })); - if (resolveNow) { - resolve(); - } else { - (window as any).bitwardenSafariAppRequests.set(messageId, { - resolve: resolve, - timeoutDate: new Date(now.getTime() + 5 * 60000), - }); - } + }, (response: any) => { + resolve(response); + }); }); } @@ -56,30 +51,13 @@ export class SafariApp { } if ((message.id == null || message.id === '') && message.command === 'app_message') { try { + debugger; const msg = JSON.parse(message.data); SafariApp.sendMessageToListeners(msg, { id: 'app_message', tab: message.senderTab, }, null); } catch { } - } else if (message.id != null && (window as any).bitwardenSafariAppRequests.has(message.id)) { - const p = (window as any).bitwardenSafariAppRequests.get(message.id); - p.resolve(message.responseData); - (window as any).bitwardenSafariAppRequests.delete(message.id); } } - - private static cleanupOldRequests() { - const removeIds: string[] = []; - ((window as any).bitwardenSafariAppRequests as - Map void, timeoutDate: Date }>) - .forEach((v, key) => { - if (v.timeoutDate < new Date()) { - removeIds.push(key); - } - }); - removeIds.forEach((id) => { - (window as any).bitwardenSafariAppRequests.delete(id); - }); - } } diff --git a/src/popup/app-routing.animations.ts b/src/popup/app-routing.animations.ts index a852922b0c..05e3197605 100644 --- a/src/popup/app-routing.animations.ts +++ b/src/popup/app-routing.animations.ts @@ -185,8 +185,6 @@ export const routerTransition = trigger('routerTransition', [ transition('tabs => premium', inSlideLeft), transition('premium => tabs', outSlideRight), -]); -if (!BrowserApi.isSafariApi) { - routerTransition.definitions.push(transition('tabs => lock', inSlideDown)); -} + transition('tabs => lock', inSlideDown), +]); diff --git a/src/safari/desktop.xcodeproj/project.pbxproj b/src/safari/desktop.xcodeproj/project.pbxproj index b563d9d34e..7c38c7084d 100644 --- a/src/safari/desktop.xcodeproj/project.pbxproj +++ b/src/safari/desktop.xcodeproj/project.pbxproj @@ -7,37 +7,42 @@ objects = { /* Begin PBXBuildFile section */ - 27E5E98D22F3D5B2005EA1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E5E98C22F3D5B2005EA1D9 /* AppDelegate.swift */; }; - 27E5E98F22F3D5B2005EA1D9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E5E98E22F3D5B2005EA1D9 /* ViewController.swift */; }; - 27E5E99122F3D5B4005EA1D9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 27E5E99022F3D5B4005EA1D9 /* Assets.xcassets */; }; - 27E5E99422F3D5B4005EA1D9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 27E5E99222F3D5B4005EA1D9 /* Main.storyboard */; }; - 27E5E9A322F3D5FE005EA1D9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27E5E9A222F3D5FE005EA1D9 /* Cocoa.framework */; }; - 27E5E9A622F3D5FE005EA1D9 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E5E9A522F3D5FE005EA1D9 /* SafariExtensionHandler.swift */; }; - 27E5E9A822F3D5FE005EA1D9 /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E5E9A722F3D5FE005EA1D9 /* SafariExtensionViewController.swift */; }; - 27E5E9AB22F3D5FE005EA1D9 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 27E5E9A922F3D5FE005EA1D9 /* SafariExtensionViewController.xib */; }; - 27E5E9B022F3D5FE005EA1D9 /* ToolbarItemIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 27E5E9AF22F3D5FE005EA1D9 /* ToolbarItemIcon.pdf */; }; - 27E5E9B422F3D5FE005EA1D9 /* safari.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 27E5E9A022F3D5FE005EA1D9 /* safari.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 27E5E9BC22F4B9D5005EA1D9 /* app in Resources */ = {isa = PBXBuildFile; fileRef = 27E5E9BB22F4B9D5005EA1D9 /* app */; }; + 55E0374D2577FA6B00979016 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E0374C2577FA6B00979016 /* AppDelegate.swift */; }; + 55E037502577FA6B00979016 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55E0374E2577FA6B00979016 /* Main.storyboard */; }; + 55E037522577FA6B00979016 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E037512577FA6B00979016 /* ViewController.swift */; }; + 55E037542577FA6E00979016 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55E037532577FA6E00979016 /* Assets.xcassets */; }; + 55E0375B2577FA6F00979016 /* safari.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 55E0375A2577FA6F00979016 /* safari.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 55E037602577FA6F00979016 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55E0375F2577FA6F00979016 /* Cocoa.framework */; }; + 55E037632577FA6F00979016 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */; }; + 55E037792577FA6F00979016 /* popup in Resources */ = {isa = PBXBuildFile; fileRef = 55E037702577FA6F00979016 /* popup */; }; + 55E0377A2577FA6F00979016 /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = 55E037712577FA6F00979016 /* background.js */; }; + 55E0377B2577FA6F00979016 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 55E037722577FA6F00979016 /* images */; }; + 55E0377C2577FA6F00979016 /* notification in Resources */ = {isa = PBXBuildFile; fileRef = 55E037732577FA6F00979016 /* notification */; }; + 55E0377D2577FA6F00979016 /* content in Resources */ = {isa = PBXBuildFile; fileRef = 55E037742577FA6F00979016 /* content */; }; + 55E0377E2577FA6F00979016 /* vendor.js in Resources */ = {isa = PBXBuildFile; fileRef = 55E037752577FA6F00979016 /* vendor.js */; }; + 55E0377F2577FA6F00979016 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 55E037762577FA6F00979016 /* manifest.json */; }; + 55E037802577FA6F00979016 /* background.html in Resources */ = {isa = PBXBuildFile; fileRef = 55E037772577FA6F00979016 /* background.html */; }; + 55E037812577FA6F00979016 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 55E037782577FA6F00979016 /* _locales */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 27E5E9B222F3D5FE005EA1D9 /* PBXContainerItemProxy */ = { + 55E0375C2577FA6F00979016 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 27E5E98122F3D5B2005EA1D9 /* Project object */; + containerPortal = 55E037402577FA6B00979016 /* Project object */; proxyType = 1; - remoteGlobalIDString = 27E5E99F22F3D5FD005EA1D9; - remoteInfo = safari; + remoteGlobalIDString = 55E037592577FA6F00979016; + remoteInfo = "safari"; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 27E5E9B822F3D5FE005EA1D9 /* Embed App Extensions */ = { + 55E0376B2577FA6F00979016 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - 27E5E9B422F3D5FE005EA1D9 /* safari.appex in Embed App Extensions */, + 55E0375B2577FA6F00979016 /* safari.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -45,160 +50,173 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 27E5E98922F3D5B2005EA1D9 /* desktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktop.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 27E5E98C22F3D5B2005EA1D9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 27E5E98E22F3D5B2005EA1D9 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 27E5E99022F3D5B4005EA1D9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 27E5E99322F3D5B4005EA1D9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 27E5E99522F3D5B4005EA1D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 27E5E99622F3D5B4005EA1D9 /* desktop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = desktop.entitlements; sourceTree = ""; }; - 27E5E9A022F3D5FE005EA1D9 /* safari.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = safari.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 27E5E9A222F3D5FE005EA1D9 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - 27E5E9A522F3D5FE005EA1D9 /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = ""; }; - 27E5E9A722F3D5FE005EA1D9 /* SafariExtensionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionViewController.swift; sourceTree = ""; }; - 27E5E9AA22F3D5FE005EA1D9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SafariExtensionViewController.xib; sourceTree = ""; }; - 27E5E9AC22F3D5FE005EA1D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 27E5E9AF22F3D5FE005EA1D9 /* ToolbarItemIcon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ToolbarItemIcon.pdf; sourceTree = ""; }; - 27E5E9B122F3D5FE005EA1D9 /* safari.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = safari.entitlements; sourceTree = ""; }; - 27E5E9BB22F4B9D5005EA1D9 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = ""; }; + 55E037482577FA6B00979016 /* desktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktop.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 55E0374B2577FA6B00979016 /* desktop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = desktop.entitlements; sourceTree = ""; }; + 55E0374C2577FA6B00979016 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 55E0374F2577FA6B00979016 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 55E037512577FA6B00979016 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 55E037532577FA6E00979016 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 55E037552577FA6E00979016 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 55E0375A2577FA6F00979016 /* safari.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = safari.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 55E0375F2577FA6F00979016 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; + 55E037642577FA6F00979016 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 55E037652577FA6F00979016 /* safari.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = safari.entitlements; sourceTree = ""; }; + 55E037702577FA6F00979016 /* popup */ = {isa = PBXFileReference; lastKnownFileType = folder; name = popup; path = ../../../build/popup; sourceTree = ""; }; + 55E037712577FA6F00979016 /* background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = background.js; path = ../../../build/background.js; sourceTree = ""; }; + 55E037722577FA6F00979016 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../../build/images; sourceTree = ""; }; + 55E037732577FA6F00979016 /* notification */ = {isa = PBXFileReference; lastKnownFileType = folder; name = notification; path = ../../../build/notification; sourceTree = ""; }; + 55E037742577FA6F00979016 /* content */ = {isa = PBXFileReference; lastKnownFileType = folder; name = content; path = ../../../build/content; sourceTree = ""; }; + 55E037752577FA6F00979016 /* vendor.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = vendor.js; path = ../../../build/vendor.js; sourceTree = ""; }; + 55E037762577FA6F00979016 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = ../../../build/manifest.json; sourceTree = ""; }; + 55E037772577FA6F00979016 /* background.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = background.html; path = ../../../build/background.html; sourceTree = ""; }; + 55E037782577FA6F00979016 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; name = _locales; path = ../../../build/_locales; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 27E5E98622F3D5B2005EA1D9 /* Frameworks */ = { + 55E037452577FA6B00979016 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 27E5E99D22F3D5FD005EA1D9 /* Frameworks */ = { + 55E037572577FA6F00979016 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 27E5E9A322F3D5FE005EA1D9 /* Cocoa.framework in Frameworks */, + 55E037602577FA6F00979016 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 27E5E98022F3D5B2005EA1D9 = { + 55E0373F2577FA6B00979016 = { isa = PBXGroup; children = ( - 27E5E98B22F3D5B2005EA1D9 /* desktop */, - 27E5E9A422F3D5FE005EA1D9 /* safari */, - 27E5E9A122F3D5FE005EA1D9 /* Frameworks */, - 27E5E98A22F3D5B2005EA1D9 /* Products */, + 55E0374A2577FA6B00979016 /* desktop */, + 55E037612577FA6F00979016 /* safari */, + 55E0375E2577FA6F00979016 /* Frameworks */, + 55E037492577FA6B00979016 /* Products */, ); sourceTree = ""; }; - 27E5E98A22F3D5B2005EA1D9 /* Products */ = { + 55E037492577FA6B00979016 /* Products */ = { isa = PBXGroup; children = ( - 27E5E98922F3D5B2005EA1D9 /* desktop.app */, - 27E5E9A022F3D5FE005EA1D9 /* safari.appex */, + 55E037482577FA6B00979016 /* desktop.app */, + 55E0375A2577FA6F00979016 /* safari.appex */, ); name = Products; sourceTree = ""; }; - 27E5E98B22F3D5B2005EA1D9 /* desktop */ = { + 55E0374A2577FA6B00979016 /* desktop */ = { isa = PBXGroup; children = ( - 27E5E98C22F3D5B2005EA1D9 /* AppDelegate.swift */, - 27E5E98E22F3D5B2005EA1D9 /* ViewController.swift */, - 27E5E99022F3D5B4005EA1D9 /* Assets.xcassets */, - 27E5E99222F3D5B4005EA1D9 /* Main.storyboard */, - 27E5E99522F3D5B4005EA1D9 /* Info.plist */, - 27E5E99622F3D5B4005EA1D9 /* desktop.entitlements */, + 55E0374B2577FA6B00979016 /* desktop.entitlements */, + 55E0374C2577FA6B00979016 /* AppDelegate.swift */, + 55E0374E2577FA6B00979016 /* Main.storyboard */, + 55E037512577FA6B00979016 /* ViewController.swift */, + 55E037532577FA6E00979016 /* Assets.xcassets */, + 55E037552577FA6E00979016 /* Info.plist */, ); path = desktop; sourceTree = ""; }; - 27E5E9A122F3D5FE005EA1D9 /* Frameworks */ = { + 55E0375E2577FA6F00979016 /* Frameworks */ = { isa = PBXGroup; children = ( - 27E5E9A222F3D5FE005EA1D9 /* Cocoa.framework */, + 55E0375F2577FA6F00979016 /* Cocoa.framework */, ); name = Frameworks; sourceTree = ""; }; - 27E5E9A422F3D5FE005EA1D9 /* safari */ = { + 55E037612577FA6F00979016 /* safari */ = { isa = PBXGroup; children = ( - 27E5E9BB22F4B9D5005EA1D9 /* app */, - 27E5E9A522F3D5FE005EA1D9 /* SafariExtensionHandler.swift */, - 27E5E9A722F3D5FE005EA1D9 /* SafariExtensionViewController.swift */, - 27E5E9A922F3D5FE005EA1D9 /* SafariExtensionViewController.xib */, - 27E5E9AC22F3D5FE005EA1D9 /* Info.plist */, - 27E5E9AF22F3D5FE005EA1D9 /* ToolbarItemIcon.pdf */, - 27E5E9B122F3D5FE005EA1D9 /* safari.entitlements */, + 55E0376F2577FA6F00979016 /* Resources */, + 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */, + 55E037642577FA6F00979016 /* Info.plist */, + 55E037652577FA6F00979016 /* safari.entitlements */, ); path = safari; sourceTree = ""; }; + 55E0376F2577FA6F00979016 /* Resources */ = { + isa = PBXGroup; + children = ( + 55E037702577FA6F00979016 /* popup */, + 55E037712577FA6F00979016 /* background.js */, + 55E037722577FA6F00979016 /* images */, + 55E037732577FA6F00979016 /* notification */, + 55E037742577FA6F00979016 /* content */, + 55E037752577FA6F00979016 /* vendor.js */, + 55E037762577FA6F00979016 /* manifest.json */, + 55E037772577FA6F00979016 /* background.html */, + 55E037782577FA6F00979016 /* _locales */, + ); + name = Resources; + path = "safari"; + sourceTree = SOURCE_ROOT; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 27E5E98822F3D5B2005EA1D9 /* desktop */ = { + 55E037472577FA6B00979016 /* desktop */ = { isa = PBXNativeTarget; - buildConfigurationList = 27E5E99922F3D5B4005EA1D9 /* Build configuration list for PBXNativeTarget "desktop" */; + buildConfigurationList = 55E0376C2577FA6F00979016 /* Build configuration list for PBXNativeTarget "desktop" */; buildPhases = ( - 27E5E98522F3D5B2005EA1D9 /* Sources */, - 27E5E98622F3D5B2005EA1D9 /* Frameworks */, - 27E5E98722F3D5B2005EA1D9 /* Resources */, - 27E5E9B822F3D5FE005EA1D9 /* Embed App Extensions */, + 55E037442577FA6B00979016 /* Sources */, + 55E037452577FA6B00979016 /* Frameworks */, + 55E037462577FA6B00979016 /* Resources */, + 55E0376B2577FA6F00979016 /* Embed App Extensions */, ); buildRules = ( ); dependencies = ( - 27E5E9B322F3D5FE005EA1D9 /* PBXTargetDependency */, + 55E0375D2577FA6F00979016 /* PBXTargetDependency */, ); name = desktop; productName = desktop; - productReference = 27E5E98922F3D5B2005EA1D9 /* desktop.app */; + productReference = 55E037482577FA6B00979016 /* desktop.app */; productType = "com.apple.product-type.application"; }; - 27E5E99F22F3D5FD005EA1D9 /* safari */ = { + 55E037592577FA6F00979016 /* safari */ = { isa = PBXNativeTarget; - buildConfigurationList = 27E5E9B522F3D5FE005EA1D9 /* Build configuration list for PBXNativeTarget "safari" */; + buildConfigurationList = 55E037682577FA6F00979016 /* Build configuration list for PBXNativeTarget "safari" */; buildPhases = ( - 27E5E99C22F3D5FD005EA1D9 /* Sources */, - 27E5E99D22F3D5FD005EA1D9 /* Frameworks */, - 27E5E99E22F3D5FD005EA1D9 /* Resources */, + 55E037562577FA6F00979016 /* Sources */, + 55E037572577FA6F00979016 /* Frameworks */, + 55E037582577FA6F00979016 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = safari; - productName = safari; - productReference = 27E5E9A022F3D5FE005EA1D9 /* safari.appex */; + productName = "safari"; + productReference = 55E0375A2577FA6F00979016 /* safari.appex */; productType = "com.apple.product-type.app-extension"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 27E5E98122F3D5B2005EA1D9 /* Project object */ = { + 55E037402577FA6B00979016 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1030; - LastUpgradeCheck = 1030; - ORGANIZATIONNAME = "8bit Solutions LLC"; + LastSwiftUpdateCheck = 1220; + LastUpgradeCheck = 1220; TargetAttributes = { - 27E5E98822F3D5B2005EA1D9 = { - CreatedOnToolsVersion = 10.3; + 55E037472577FA6B00979016 = { + CreatedOnToolsVersion = 12.2; }; - 27E5E99F22F3D5FD005EA1D9 = { - CreatedOnToolsVersion = 10.3; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; + 55E037592577FA6F00979016 = { + CreatedOnToolsVersion = 12.2; }; }; }; - buildConfigurationList = 27E5E98422F3D5B2005EA1D9 /* Build configuration list for PBXProject "desktop" */; + buildConfigurationList = 55E037432577FA6B00979016 /* Build configuration list for PBXProject "desktop" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; @@ -206,92 +224,88 @@ en, Base, ); - mainGroup = 27E5E98022F3D5B2005EA1D9; - productRefGroup = 27E5E98A22F3D5B2005EA1D9 /* Products */; + mainGroup = 55E0373F2577FA6B00979016; + productRefGroup = 55E037492577FA6B00979016 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 27E5E98822F3D5B2005EA1D9 /* desktop */, - 27E5E99F22F3D5FD005EA1D9 /* safari */, + 55E037472577FA6B00979016 /* desktop */, + 55E037592577FA6F00979016 /* safari */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 27E5E98722F3D5B2005EA1D9 /* Resources */ = { + 55E037462577FA6B00979016 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27E5E99122F3D5B4005EA1D9 /* Assets.xcassets in Resources */, - 27E5E99422F3D5B4005EA1D9 /* Main.storyboard in Resources */, + 55E037542577FA6E00979016 /* Assets.xcassets in Resources */, + 55E037502577FA6B00979016 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 27E5E99E22F3D5FD005EA1D9 /* Resources */ = { + 55E037582577FA6F00979016 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27E5E9BC22F4B9D5005EA1D9 /* app in Resources */, - 27E5E9B022F3D5FE005EA1D9 /* ToolbarItemIcon.pdf in Resources */, - 27E5E9AB22F3D5FE005EA1D9 /* SafariExtensionViewController.xib in Resources */, + 55E037812577FA6F00979016 /* _locales in Resources */, + 55E0377B2577FA6F00979016 /* images in Resources */, + 55E0377F2577FA6F00979016 /* manifest.json in Resources */, + 55E037802577FA6F00979016 /* background.html in Resources */, + 55E0377A2577FA6F00979016 /* background.js in Resources */, + 55E037792577FA6F00979016 /* popup in Resources */, + 55E0377C2577FA6F00979016 /* notification in Resources */, + 55E0377E2577FA6F00979016 /* vendor.js in Resources */, + 55E0377D2577FA6F00979016 /* content in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 27E5E98522F3D5B2005EA1D9 /* Sources */ = { + 55E037442577FA6B00979016 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27E5E98F22F3D5B2005EA1D9 /* ViewController.swift in Sources */, - 27E5E98D22F3D5B2005EA1D9 /* AppDelegate.swift in Sources */, + 55E037522577FA6B00979016 /* ViewController.swift in Sources */, + 55E0374D2577FA6B00979016 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 27E5E99C22F3D5FD005EA1D9 /* Sources */ = { + 55E037562577FA6F00979016 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 27E5E9A822F3D5FE005EA1D9 /* SafariExtensionViewController.swift in Sources */, - 27E5E9A622F3D5FE005EA1D9 /* SafariExtensionHandler.swift in Sources */, + 55E037632577FA6F00979016 /* SafariWebExtensionHandler.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 27E5E9B322F3D5FE005EA1D9 /* PBXTargetDependency */ = { + 55E0375D2577FA6F00979016 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 27E5E99F22F3D5FD005EA1D9 /* safari */; - targetProxy = 27E5E9B222F3D5FE005EA1D9 /* PBXContainerItemProxy */; + target = 55E037592577FA6F00979016 /* safari */; + targetProxy = 55E0375C2577FA6F00979016 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 27E5E99222F3D5B4005EA1D9 /* Main.storyboard */ = { + 55E0374E2577FA6B00979016 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( - 27E5E99322F3D5B4005EA1D9 /* Base */, + 55E0374F2577FA6B00979016 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; - 27E5E9A922F3D5FE005EA1D9 /* SafariExtensionViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - 27E5E9AA22F3D5FE005EA1D9 /* Base */, - ); - name = SafariExtensionViewController.xib; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 27E5E99722F3D5B4005EA1D9 /* Debug */ = { + 55E037662577FA6F00979016 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -315,13 +329,13 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -340,7 +354,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -350,10 +364,9 @@ }; name = Debug; }; - 27E5E99822F3D5B4005EA1D9 /* Release */ = { + 55E037672577FA6F00979016 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -377,13 +390,13 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -396,7 +409,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -405,90 +418,82 @@ }; name = Release; }; - 27E5E99A22F3D5B4005EA1D9 /* Debug */ = { + 55E037692577FA6F00979016 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; + CODE_SIGN_ENTITLEMENTS = "safari/safari.entitlements"; CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = LTZ2PFU5D6; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = desktop/Info.plist; + INFOPLIST_FILE = "safari/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; - 27E5E99B22F3D5B4005EA1D9 /* Release */ = { + 55E0376A2577FA6F00979016 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; + CODE_SIGN_ENTITLEMENTS = "safari/safari.entitlements"; CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = LTZ2PFU5D6; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = desktop/Info.plist; + INFOPLIST_FILE = "safari/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Release; }; - 27E5E9B622F3D5FE005EA1D9 /* Debug */ = { + 55E0376D2577FA6F00979016 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_ENTITLEMENTS = safari/safari.entitlements; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = LTZ2PFU5D6; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = safari/Info.plist; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = desktop/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; - 27E5E9B722F3D5FE005EA1D9 /* Release */ = { + 55E0376E2577FA6F00979016 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_ENTITLEMENTS = safari/safari.entitlements; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = LTZ2PFU5D6; - ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = safari/Info.plist; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = desktop/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Release; @@ -496,34 +501,34 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 27E5E98422F3D5B2005EA1D9 /* Build configuration list for PBXProject "desktop" */ = { + 55E037432577FA6B00979016 /* Build configuration list for PBXProject "desktop" */ = { isa = XCConfigurationList; buildConfigurations = ( - 27E5E99722F3D5B4005EA1D9 /* Debug */, - 27E5E99822F3D5B4005EA1D9 /* Release */, + 55E037662577FA6F00979016 /* Debug */, + 55E037672577FA6F00979016 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 27E5E99922F3D5B4005EA1D9 /* Build configuration list for PBXNativeTarget "desktop" */ = { + 55E037682577FA6F00979016 /* Build configuration list for PBXNativeTarget "safari" */ = { isa = XCConfigurationList; buildConfigurations = ( - 27E5E99A22F3D5B4005EA1D9 /* Debug */, - 27E5E99B22F3D5B4005EA1D9 /* Release */, + 55E037692577FA6F00979016 /* Debug */, + 55E0376A2577FA6F00979016 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 27E5E9B522F3D5FE005EA1D9 /* Build configuration list for PBXNativeTarget "safari" */ = { + 55E0376C2577FA6F00979016 /* Build configuration list for PBXNativeTarget "desktop" */ = { isa = XCConfigurationList; buildConfigurations = ( - 27E5E9B622F3D5FE005EA1D9 /* Debug */, - 27E5E9B722F3D5FE005EA1D9 /* Release */, + 55E0376D2577FA6F00979016 /* Debug */, + 55E0376E2577FA6F00979016 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 27E5E98122F3D5B2005EA1D9 /* Project object */; + rootObject = 55E037402577FA6B00979016 /* Project object */; } diff --git a/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 699699887b..919434a625 100644 --- a/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme b/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme new file mode 100644 index 0000000000..7dd13c8dc8 --- /dev/null +++ b/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/safari/desktop/AppDelegate.swift b/src/safari/desktop/AppDelegate.swift index 9ef5111723..6222982a6e 100644 --- a/src/safari/desktop/AppDelegate.swift +++ b/src/safari/desktop/AppDelegate.swift @@ -1,12 +1,18 @@ import Cocoa -@NSApplicationMain +@main class AppDelegate: NSObject, NSApplicationDelegate { - func applicationDidFinishLaunching(_: Notification) { + + func applicationDidFinishLaunching(_ notification: Notification) { // Insert code here to initialize your application } - func applicationWillTerminate(_: Notification) { + func applicationWillTerminate(_ notification: Notification) { // Insert code here to tear down your application } + + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + } diff --git a/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json b/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json index 2db2b1c7c6..6bf9a9b330 100644 --- a/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,54 +1,58 @@ { "images" : [ { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "icon16.png", "scale" : "1x" }, { - "idiom" : "mac", "size" : "16x16", + "idiom" : "mac", + "filename" : "icon32.png", "scale" : "2x" }, { - "idiom" : "mac", "size" : "32x32", + "idiom" : "mac", + "filename" : "icon32.png", "scale" : "1x" }, { "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" + "scale" : "2x", + "size" : "32x32" }, { - "idiom" : "mac", "size" : "128x128", + "idiom" : "mac", + "filename" : "icon128.png", "scale" : "1x" }, { "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" + "scale" : "2x", + "size" : "128x128" }, { "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" + "scale" : "1x", + "size" : "256x256" }, { "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" + "scale" : "2x", + "size" : "256x256" }, { "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" + "scale" : "1x", + "size" : "512x512" }, { "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" + "scale" : "2x", + "size" : "512x512" } ], "info" : { diff --git a/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png new file mode 100644 index 0000000000..914b3e3899 Binary files /dev/null and b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png differ diff --git a/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png new file mode 100644 index 0000000000..3acbfd1435 Binary files /dev/null and b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png differ diff --git a/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png new file mode 100644 index 0000000000..35008195d9 Binary files /dev/null and b/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png differ diff --git a/src/safari/desktop/Assets.xcassets/Contents.json b/src/safari/desktop/Assets.xcassets/Contents.json index da4a164c91..73c00596a7 100644 --- a/src/safari/desktop/Assets.xcassets/Contents.json +++ b/src/safari/desktop/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/src/safari/desktop/Base.lproj/Main.storyboard b/src/safari/desktop/Base.lproj/Main.storyboard index 10c32c44e0..5a53dedcec 100644 --- a/src/safari/desktop/Base.lproj/Main.storyboard +++ b/src/safari/desktop/Base.lproj/Main.storyboard @@ -1,7 +1,8 @@ - - + + - + + @@ -21,13 +22,6 @@ - - - - - - - @@ -54,607 +48,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -677,15 +70,15 @@ - + - - - - + + + + @@ -705,13 +98,70 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/safari/desktop/Info.plist b/src/safari/desktop/Info.plist index 3c9b847a73..201669d037 100644 --- a/src/safari/desktop/Info.plist +++ b/src/safari/desktop/Info.plist @@ -11,13 +11,13 @@ CFBundleIconFile CFBundleIdentifier - com.bitwarden.desktop + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - Bitwarden + $(PRODUCT_NAME) CFBundlePackageType - APPL + $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion diff --git a/src/safari/desktop/ViewController.swift b/src/safari/desktop/ViewController.swift index 5af73ffee0..fbda5decf8 100644 --- a/src/safari/desktop/ViewController.swift +++ b/src/safari/desktop/ViewController.swift @@ -1,14 +1,44 @@ import Cocoa +import SafariServices.SFSafariApplication +import SafariServices.SFSafariExtensionManager + +let appName = "desktop" +let extensionBundleIdentifier = "com.bitwarden.desktop.Extension" class ViewController: NSViewController { + + @IBOutlet var appNameLabel: NSTextField! + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view. - } + self.appNameLabel.stringValue = appName + SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in + guard let state = state, error == nil else { + // Insert code to inform the user that something went wrong. + return + } - override var representedObject: Any? { - didSet { - // Update the view, if already loaded. + DispatchQueue.main.async { + if (state.isEnabled) { + self.appNameLabel.stringValue = "\(appName)'s extension is currently on." + } else { + self.appNameLabel.stringValue = "\(appName)'s extension is currently off. You can turn it on in Safari Extensions preferences." + } + } } } + + @IBAction func openSafariExtensionPreferences(_ sender: AnyObject?) { + SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in + guard error == nil else { + // Insert code to inform the user that something went wrong. + return + } + + DispatchQueue.main.async { + NSApplication.shared.terminate(nil) + } + } + } + } diff --git a/src/safari/safari/Base.lproj/SafariExtensionViewController.xib b/src/safari/safari/Base.lproj/SafariExtensionViewController.xib deleted file mode 100644 index 3716df7567..0000000000 --- a/src/safari/safari/Base.lproj/SafariExtensionViewController.xib +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/safari/safari/Info.plist b/src/safari/safari/Info.plist index 82f785e9c6..eaec1ff8e0 100644 --- a/src/safari/safari/Info.plist +++ b/src/safari/safari/Info.plist @@ -9,75 +9,25 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.bitwarden.desktop.safari + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - Bitwarden + $(PRODUCT_NAME) CFBundlePackageType - XPC! + $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.0.1 + 1.0 CFBundleVersion - 0.0.2 + 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSExtension NSExtensionPointIdentifier - com.apple.Safari.extension + com.apple.Safari.web-extension NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).SafariExtensionHandler - SFSafariStyleSheet - - - Style Sheet - app/content/autofill.css - - - SFSafariContentScript - - - Script - app/content/autofill.js - - - Script - app/content/autofiller.js - - - Script - app/content/notificationBar.js - - - Script - app/content/shortcuts.js - - - Script - app/content/sso.js - - - SFSafariToolbarItem - - Action - Popover - Identifier - Button - Image - ToolbarItemIcon.pdf - Label - Bitwarden - - SFSafariWebsiteAccess - - Level - All - - SFSafariExtensionBundleIdentifiersToUninstall - - com.bitwarden.safari - + $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler NSHumanReadableCopyright Copyright © 2020 Bitwarden Inc. All rights reserved. diff --git a/src/safari/safari/SafariExtensionHandler.swift b/src/safari/safari/SafariExtensionHandler.swift deleted file mode 100644 index 3d8711f401..0000000000 --- a/src/safari/safari/SafariExtensionHandler.swift +++ /dev/null @@ -1,101 +0,0 @@ -import SafariServices - -class SafariExtensionHandler: SFSafariExtensionHandler { - override init() { - super.init() - SafariExtensionViewController.shared.initWebView() - } - - override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String: Any]?) { - // This method will be called when a content script provided by your extension - // calls safari.extension.dispatchMessage("message"). - if messageName == "bitwarden" { - page.getPropertiesWithCompletionHandler { properties in - DispatchQueue.main.async { - makeSenderTabObject(page: page, props: properties, complete: { senderTab in - DispatchQueue.main.async { - self.sendMessage(msg: userInfo, sender: senderTab) - } - }) - } - } - } - } - - override func toolbarItemClicked(in _: SFSafariWindow) { - // This method will be called when your toolbar item is clicked. - } - - override func validateToolbarItem(in _: SFSafariWindow, validationHandler: @escaping ((Bool, String) -> Void)) { - // This is called when Safari's state changed in some way that would require the extension's - // toolbar item to be validated again. - validationHandler(true, "") - } - - override func popoverViewController() -> SFSafariExtensionViewController { - return SafariExtensionViewController.shared - } - - override func popoverWillShow(in _: SFSafariWindow) { - SafariExtensionViewController.shared.popoverOpenCount += 1 - DispatchQueue.main.async { - self.sendMessage(msg: ["command": "reloadPopup"], sender: nil) - } - } - - override func popoverDidClose(in _: SFSafariWindow) { - SafariExtensionViewController.shared.popoverOpenCount -= 1 - } - - func sendMessage(msg: [String: Any]?, sender: Tab? = nil) { - if SafariExtensionViewController.shared.webView == nil { - return - } - let newMsg = AppMessage() - newMsg.command = "app_message" - newMsg.senderTab = sender - do { - let jsonData = try JSONSerialization.data(withJSONObject: msg as Any, options: []) - newMsg.data = String(data: jsonData, encoding: .utf8) - } catch let error { - print("error converting to json: \(error)") - } - SafariExtensionViewController.shared.replyMessage(message: newMsg) - } -} - -func makeSenderTabObject(page: SFSafariPage, props: SFSafariPageProperties?, complete: @escaping (Tab) -> Void) { - let t = Tab() - t.title = props?.title - t.url = props?.url?.absoluteString - page.getContainingTab { tab in - tab.getContainingWindow(completionHandler: { win in - guard let window = win else { - t.active = false; - t.windowId = -100 - SFSafariApplication.getAllWindows(completionHandler: { allWins in - if (allWins.count == 0) { - return - } - allWins[0].getAllTabs { allWinTabs in - t.index = allWinTabs.firstIndex(of: tab) ?? -1 - t.id = "\(t.windowId)_\(t.index)" - complete(t) - } - }) - return - } - window.getActiveTab(completionHandler: { activeTab in - t.active = activeTab != nil && tab == activeTab - SFSafariApplication.getAllWindows(completionHandler: { allWins in - t.windowId = allWins.firstIndex(of: window) ?? -100 - window.getAllTabs { allWinTabs in - t.index = allWinTabs.firstIndex(of: tab) ?? -1 - t.id = "\(t.windowId)_\(t.index)" - complete(t) - } - }) - }) - }) - } -} diff --git a/src/safari/safari/SafariExtensionViewController.swift b/src/safari/safari/SafariExtensionViewController.swift deleted file mode 100644 index 0f2ac13eaa..0000000000 --- a/src/safari/safari/SafariExtensionViewController.swift +++ /dev/null @@ -1,422 +0,0 @@ -import SafariServices -import WebKit - -class SafariExtensionViewController: SFSafariExtensionViewController, WKScriptMessageHandler, WKNavigationDelegate { - var webView: WKWebView! - var initedWebView: Bool = false - var popoverOpenCount: Int = 0 - - static let shared: SafariExtensionViewController = { - let shared = SafariExtensionViewController() - shared.preferredContentSize = NSSize(width: 375, height: 600) - return shared - }() - - func initWebView() { - if initedWebView { - return - } - let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String - initedWebView = true - let parentHeight = SafariExtensionViewController.shared.preferredContentSize.height - let parentWidth = SafariExtensionViewController.shared.preferredContentSize.width - let webViewConfig = WKWebViewConfiguration() - let bundleURL = Bundle.main.resourceURL!.absoluteURL - let html = bundleURL.appendingPathComponent("app/popup/index.html") - let url = URL(string: "\(html.absoluteString)?appVersion=\(version!)") - webViewConfig.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") - webViewConfig.preferences.setValue(true, forKey: "developerExtrasEnabled") - webViewConfig.userContentController.add(self, name: "bitwardenApp") - webView = WKWebView(frame: CGRect(x: 0, y: 0, width: parentWidth, height: parentHeight), - configuration: webViewConfig) - webView.navigationDelegate = self - webView.allowsLinkPreview = false - webView.loadFileURL(url!, allowingReadAccessTo: bundleURL) - webView.alphaValue = 0.0 - webView.uiDelegate = self - view.addSubview(webView) - } - - func webView(_ webView: WKWebView, didFinish _: WKNavigation!) { - if #available(OSXApplicationExtension 10.12, *) { - NSAnimationContext.runAnimationGroup({ _ in - NSAnimationContext.current.duration = 0.35 - webView.animator().alphaValue = 1.0 - }) - } else { - // Fallback on earlier versions - } - } - - override func viewDidLoad() { - super.viewDidLoad() - let backgroundColor = NSColor(red: (39 / 255.0), green: (42 / 255.0), blue: (46 / 255.0), alpha: 1.0) - view.setValue(backgroundColor, forKey: "backgroundColor") - initWebView() - } - - func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) { - if message.name != "bitwardenApp" { - return - } - guard let messageBody = message.body as? String else { - return - } - guard let m: AppMessage = jsonDeserialize(json: messageBody) else { - return - } - let command = m.command - NSLog("Command: \(command)") - if command == "storage_get" { - if let data = m.data { - let obj = UserDefaults.standard.string(forKey: data) - m.responseData = obj - replyMessage(message: m) - } - } else if command == "storage_save" { - guard let data: StorageData = jsonDeserialize(json: m.data) else { - return - } - if let obj = data.obj { - UserDefaults.standard.set(obj, forKey: data.key) - } else { - UserDefaults.standard.removeObject(forKey: data.key) - } - replyMessage(message: m) - } else if command == "storage_remove" { - if let data = m.data { - UserDefaults.standard.removeObject(forKey: data) - replyMessage(message: m) - } - } else if command == "getLocaleStrings" { - let language = m.data ?? "en" - guard let bundleUrl = Bundle.main.resourceURL?.absoluteURL else { - return - } - let messagesUrl = bundleUrl.appendingPathComponent("app/_locales/\(language)/messages.json") - do { - let json = try String(contentsOf: messagesUrl, encoding: .utf8) - webView.evaluateJavaScript("window.bitwardenLocaleStrings = \(json);", completionHandler: {(result, error) in - guard let err = error else { - return; - } - NSLog("evaluateJavaScript error : %@", err.localizedDescription); - }) - } catch { - NSLog("ERROR on getLocaleStrings, \(error)") - } - replyMessage(message: m) - } else if command == "tabs_query" { - guard let options: TabQueryOptions = jsonDeserialize(json: m.data) else { - return - } - if options.currentWindow ?? false { - SFSafariApplication.getActiveWindow { win in - if win != nil { - processWindowsForTabs(wins: [win!], options: options, complete: { tabs in - m.responseData = jsonSerialize(obj: tabs) - self.replyMessage(message: m) - }) - } else { - SFSafariApplication.getAllWindows { wins in - processWindowsForTabs(wins: wins, options: options, complete: { tabs in - m.responseData = jsonSerialize(obj: tabs) - self.replyMessage(message: m) - }) - } - } - } - } else { - SFSafariApplication.getAllWindows { wins in - processWindowsForTabs(wins: wins, options: options, complete: { tabs in - m.responseData = jsonSerialize(obj: tabs) - self.replyMessage(message: m) - }) - } - } - } else if command == "tabs_message" { - guard let tabMsg: TabMessage = jsonDeserialize(json: m.data) else { - return - } - SFSafariApplication.getAllWindows { wins in - var theWin: SFSafariWindow? - var winIndex = 0 - for win in wins { - if tabMsg.tab.windowId == winIndex { - theWin = win - break - } - winIndex = winIndex + 1 - } - var theTab: SFSafariTab? - theWin?.getAllTabs { tabs in - var tabIndex = 0 - for tab in tabs { - if tabMsg.tab.index == tabIndex { - theTab = tab - break - } - tabIndex = tabIndex + 1 - } - theTab?.getActivePage { activePage in - activePage?.dispatchMessageToScript(withName: "bitwarden", userInfo: ["msg": tabMsg.obj]) - } - } - } - } else if command == "hidePopover" { - dismissPopover() - replyMessage(message: m) - } else if command == "showPopover" { - if popoverOpenCount <= 0 { - SFSafariApplication.getActiveWindow { win in - win?.getToolbarItem(completionHandler: { item in - item?.showPopover() - }) - } - } - } else if command == "isPopoverOpen" { - m.responseData = popoverOpenCount > 0 ? "true" : "false" - replyMessage(message: m) - } else if command == "createNewTab" { - if let data = m.data, let url = URL(string: data) { - SFSafariApplication.getActiveWindow { win in - win?.openTab(with: url, makeActiveIfPossible: true, completionHandler: { _ in - // Tab opened - }) - } - } - } else if command == "reloadExtension" { - webView?.reload() - replyMessage(message: m) - } else if command == "copyToClipboard" { - let pasteboard = NSPasteboard.general - pasteboard.declareTypes([NSPasteboard.PasteboardType.string], owner: nil) - pasteboard.setString(m.data ?? "", forType: NSPasteboard.PasteboardType.string) - replyMessage(message: m) - } else if command == "readFromClipboard" { - let pasteboard = NSPasteboard.general - m.responseData = pasteboard.pasteboardItems?.first?.string(forType: .string) - replyMessage(message: m) - } else if command == "downloadFile" { - guard let jsonData = m.data else { - return - } - guard let dlMsg: DownloadFileMessage = jsonDeserialize(json: jsonData) else { - return - } - var blobData: Data? - if dlMsg.blobOptions?.type == "text/plain" { - blobData = dlMsg.blobData?.data(using: .utf8) - } else if let blob = dlMsg.blobData { - blobData = Data(base64Encoded: blob) - } - guard let data = blobData else { - return - } - let panel = NSSavePanel() - panel.canCreateDirectories = true - panel.nameFieldStringValue = dlMsg.fileName - panel.begin { response in - if response == NSApplication.ModalResponse.OK { - if let url = panel.url { - do { - let fileManager = FileManager.default - if !fileManager.fileExists(atPath: url.absoluteString) { - fileManager.createFile(atPath: url.absoluteString, contents: Data(), - attributes: nil) - } - try data.write(to: url) - } catch { - print(error) - NSLog("ERROR in downloadFile, \(error)") - } - } - } - } - } - } - - func replyMessage(message: AppMessage) { - if webView == nil { - return - } - let json = (jsonSerialize(obj: message) ?? "null") - webView.evaluateJavaScript("window.bitwardenSafariAppMessageReceiver(\(json));", completionHandler: {(result, error) in - guard let err = error else { - return; - } - NSLog("evaluateJavaScript error : %@", err.localizedDescription); - }) - } -} - -extension SafariExtensionViewController: WKUIDelegate { - @available(OSXApplicationExtension 10.12, *) - func webView(_: WKWebView, runOpenPanelWith _: WKOpenPanelParameters, initiatedByFrame _: WKFrameInfo, - completionHandler: @escaping ([URL]?) -> Void) { - let openPanel = NSOpenPanel() - openPanel.canChooseFiles = true - openPanel.begin { result in - if result == NSApplication.ModalResponse.OK && openPanel.url != nil { - completionHandler([openPanel.url!]) - } else { - completionHandler(nil) - } - } - } -} - -func processWindowsForTabs(wins: [SFSafariWindow], options: TabQueryOptions?, complete: @escaping ([Tab]) -> Void) { - if wins.count == 0 { - complete([]) - return - } - var newTabs: [Tab] = [] - let winGroup = DispatchGroup() - for win in wins { - winGroup.enter() - win.getActiveTab { activeTab in - win.getAllTabs { allTabs in - let tabGroup = DispatchGroup() - for tab in allTabs { - tabGroup.enter() - if options?.active ?? false { - if activeTab != nil && activeTab == tab { - let windowIndex = wins.firstIndex(of: win) ?? -100 - let tabIndex = allTabs.firstIndex(of: tab) ?? -1 - makeTabObject(tab: tab, activeTab: activeTab, windowIndex: windowIndex, - tabIndex: tabIndex, complete: { t in - newTabs.append(t) - tabGroup.leave() - }) - } else { - tabGroup.leave() - } - } else { - let windowIndex = wins.firstIndex(of: win) ?? -100 - let tabIndex = allTabs.firstIndex(of: tab) ?? -1 - makeTabObject(tab: tab, activeTab: activeTab, windowIndex: windowIndex, - tabIndex: tabIndex, complete: { t in - newTabs.append(t) - tabGroup.leave() - }) - } - } - tabGroup.notify(queue: .main) { - winGroup.leave() - } - } - } - } - winGroup.notify(queue: .main) { - complete(newTabs) - } -} - -func makeTabObject(tab: SFSafariTab, activeTab: SFSafariTab?, windowIndex: Int, tabIndex: Int, - complete: @escaping (Tab) -> Void) { - let t = Tab() - t.active = activeTab != nil && tab == activeTab - t.windowId = windowIndex - t.index = tabIndex - t.id = "\(windowIndex)_\(tabIndex)" - tab.getActivePage { page in - guard let activePage = page else { - complete(t) - return - } - activePage.getPropertiesWithCompletionHandler({ props in - t.title = props?.title - t.url = props?.url?.absoluteString - complete(t) - }) - } -} - -func jsonSerialize(obj: T?) -> String? { - let encoder = JSONEncoder() - do { - let data = try encoder.encode(obj) - return String(data: data, encoding: .utf8) ?? "null" - } catch _ { - return "null" - } -} - -func jsonDeserialize(json: String?) -> T? { - if json == nil { - return nil - } - let decoder = JSONDecoder() - do { - let obj = try decoder.decode(T.self, from: json!.data(using: .utf8)!) - return obj - } catch _ { - return nil - } -} - -class AppMessage: Decodable, Encodable { - init() { - id = "" - command = "" - data = nil - responseData = nil - responseError = nil - } - - var id: String - var command: String - var data: String? - var responseData: String? - var responseError: Bool? - var senderTab: Tab? -} - -class StorageData: Decodable, Encodable { - var key: String - var obj: String? -} - -class TabQueryOptions: Decodable, Encodable { - var currentWindow: Bool? - var active: Bool? -} - -class Tab: Decodable, Encodable { - init() { - id = "" - index = -1 - windowId = -100 - title = "" - active = false - url = "" - } - - var id: String - var index: Int - var windowId: Int - var title: String? - var active: Bool - var url: String? -} - -class TabMessage: Decodable, Encodable { - var tab: Tab - var obj: String - var options: TabMessageOptions? -} - -class TabMessageOptions: Decodable, Encodable { - var frameId: Int? -} - -class DownloadFileMessage: Decodable, Encodable { - var fileName: String - var blobData: String? - var blobOptions: DownloadFileMessageBlobOptions? -} - -class DownloadFileMessageBlobOptions: Decodable, Encodable { - var type: String? -} diff --git a/src/safari/safari/SafariWebExtensionHandler.swift b/src/safari/safari/SafariWebExtensionHandler.swift new file mode 100644 index 0000000000..001d388e6e --- /dev/null +++ b/src/safari/safari/SafariWebExtensionHandler.swift @@ -0,0 +1,109 @@ +import SafariServices +import os.log + +let SFExtensionMessageKey = "message" + +class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { + + func beginRequest(with context: NSExtensionContext) { + let item = context.inputItems[0] as! NSExtensionItem + let message = item.userInfo?[SFExtensionMessageKey] as AnyObject? + os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg) + + let response = NSExtensionItem() + + guard let command = message?["command"] as? String else { + return + } + + switch (command) { + case "readFromClipboard": + let pasteboard = NSPasteboard.general + response.userInfo = [ SFExtensionMessageKey: pasteboard.pasteboardItems?.first?.string(forType: .string) as Any ] + break + case "showPopover": + SFSafariApplication.getActiveWindow { win in + win?.getToolbarItem(completionHandler: { item in + item?.showPopover() + }) + } + break + case "downloadFile": + guard let jsonData = message?["data"] as? String else { + return + } + guard let dlMsg: DownloadFileMessage = jsonDeserialize(json: jsonData) else { + return + } + var blobData: Data? + if dlMsg.blobOptions?.type == "text/plain" { + blobData = dlMsg.blobData?.data(using: .utf8) + } else if let blob = dlMsg.blobData { + blobData = Data(base64Encoded: blob) + } + guard let data = blobData else { + return + } + let panel = NSSavePanel() + panel.canCreateDirectories = true + panel.nameFieldStringValue = dlMsg.fileName + panel.begin { response in + if response == NSApplication.ModalResponse.OK { + if let url = panel.url { + do { + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: url.absoluteString) { + fileManager.createFile(atPath: url.absoluteString, contents: Data(), + attributes: nil) + } + try data.write(to: url) + } catch { + print(error) + NSLog("ERROR in downloadFile, \(error)") + } + } + } + } + break + + default: + return + } + + context.completeRequest(returningItems: [response], completionHandler: nil) + } + +} + +func jsonSerialize(obj: T?) -> String? { + let encoder = JSONEncoder() + do { + let data = try encoder.encode(obj) + return String(data: data, encoding: .utf8) ?? "null" + } catch _ { + return "null" + } +} + +func jsonDeserialize(json: String?) -> T? { + if json == nil { + return nil + } + let decoder = JSONDecoder() + do { + let obj = try decoder.decode(T.self, from: json!.data(using: .utf8)!) + return obj + } catch _ { + return nil + } +} + +class DownloadFileMessage: Decodable, Encodable { + var fileName: String + var blobData: String? + var blobOptions: DownloadFileMessageBlobOptions? +} + +class DownloadFileMessageBlobOptions: Decodable, Encodable { + var type: String? +} diff --git a/src/safari/safari/ToolbarItemIcon.pdf b/src/safari/safari/ToolbarItemIcon.pdf deleted file mode 100644 index dbf98ce90e..0000000000 Binary files a/src/safari/safari/ToolbarItemIcon.pdf and /dev/null differ diff --git a/src/safari/safari/app/popup/index.html b/src/safari/safari/app/popup/index.html deleted file mode 100644 index a6282445c3..0000000000 --- a/src/safari/safari/app/popup/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - Bitwarden - - - - - - -
-
- - - - - - - - - diff --git a/src/services/browserMessaging.service.ts b/src/services/browserMessaging.service.ts index 01f94269fb..e5bd9b1e98 100644 --- a/src/services/browserMessaging.service.ts +++ b/src/services/browserMessaging.service.ts @@ -1,16 +1,8 @@ -import { BrowserApi } from '../browser/browserApi'; -import { SafariApp } from '../browser/safariApp'; - import { MessagingService } from 'jslib/abstractions/messaging.service'; export default class BrowserMessagingService implements MessagingService { send(subscriber: string, arg: any = {}) { const message = Object.assign({}, { command: subscriber }, arg); - if (BrowserApi.isSafariApi) { - SafariApp.sendMessageToApp(subscriber, arg); - SafariApp.sendMessageToListeners(message, 'BrowserMessagingService', null); - } else { - chrome.runtime.sendMessage(message); - } + chrome.runtime.sendMessage(message); } } diff --git a/src/services/browserPlatformUtils.service.ts b/src/services/browserPlatformUtils.service.ts index b9946937f4..02d2f5698d 100644 --- a/src/services/browserPlatformUtils.service.ts +++ b/src/services/browserPlatformUtils.service.ts @@ -189,13 +189,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService } const clearing = options ? !!options.clearing : false; const clearMs: number = options && options.clearMs ? options.clearMs : null; - if (this.isSafariExtension()) { - SafariApp.sendMessageToApp('copyToClipboard', text).then(() => { - if (!clearing && this.clipboardWriteCallback != null) { - this.clipboardWriteCallback(text, clearMs); - } - }); - } else if (this.isFirefox() && (win as any).navigator.clipboard && (win as any).navigator.clipboard.writeText) { + if (this.isFirefox() && (win as any).navigator.clipboard && (win as any).navigator.clipboard.writeText) { (win as any).navigator.clipboard.writeText(text).then(() => { if (!clearing && this.clipboardWriteCallback != null) { this.clipboardWriteCallback(text, clearMs); @@ -311,6 +305,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService } private isSafariExtension(): boolean { - return (window as any).safariAppExtension === true; + return navigator.userAgent.indexOf(' Safari/') !== -1; } } diff --git a/src/services/browserStorage.service.ts b/src/services/browserStorage.service.ts index 7510327d7d..8f8cf60792 100644 --- a/src/services/browserStorage.service.ts +++ b/src/services/browserStorage.service.ts @@ -3,61 +3,39 @@ import { StorageService, } from 'jslib/abstractions'; -import { SafariApp } from '../browser/safariApp'; - export default class BrowserStorageService implements StorageService { private chromeStorageApi: any; - private isSafari: boolean; - constructor(platformUtilsService: PlatformUtilsService) { - this.isSafari = platformUtilsService.isSafari(); - if (!this.isSafari) { - this.chromeStorageApi = chrome.storage.local; - } + constructor() { + this.chromeStorageApi = chrome.storage.local; } async get(key: string): Promise { - if (this.isSafari) { - const obj = await SafariApp.sendMessageToApp('storage_get', key); - return obj == null ? null : JSON.parse(obj) as T; - } else { - return new Promise((resolve) => { - this.chromeStorageApi.get(key, (obj: any) => { - if (obj != null && obj[key] != null) { - resolve(obj[key] as T); - return; - } - resolve(null); - }); + return new Promise((resolve) => { + this.chromeStorageApi.get(key, (obj: any) => { + if (obj != null && obj[key] != null) { + resolve(obj[key] as T); + return; + } + resolve(null); }); - } + }); } async save(key: string, obj: any): Promise { const keyedObj = { [key]: obj }; - if (this.isSafari) { - await SafariApp.sendMessageToApp('storage_save', JSON.stringify({ - key: key, - obj: JSON.stringify(obj), - })); - } else { - return new Promise((resolve) => { - this.chromeStorageApi.set(keyedObj, () => { - resolve(); - }); + return new Promise((resolve) => { + this.chromeStorageApi.set(keyedObj, () => { + resolve(); }); - } + }); } async remove(key: string): Promise { - if (this.isSafari) { - await SafariApp.sendMessageToApp('storage_remove', key); - } else { - return new Promise((resolve) => { - this.chromeStorageApi.remove(key, () => { - resolve(); - }); + return new Promise((resolve) => { + this.chromeStorageApi.remove(key, () => { + resolve(); }); - } + }); } } diff --git a/src/services/i18n.service.ts b/src/services/i18n.service.ts index 4eb880424d..542dbb6f35 100644 --- a/src/services/i18n.service.ts +++ b/src/services/i18n.service.ts @@ -1,19 +1,11 @@ import { I18nService as BaseI18nService } from 'jslib/services/i18n.service'; -import { BrowserApi } from '../browser/browserApi'; -import { SafariApp } from '../browser/safariApp'; - export default class I18nService extends BaseI18nService { constructor(systemLanguage: string) { - super(systemLanguage, BrowserApi.isSafariApi ? 'safari' : null, async (formattedLocale: string) => { - if (BrowserApi.isSafariApi) { - await SafariApp.sendMessageToApp('getLocaleStrings', formattedLocale); - return (window as any).bitwardenLocaleStrings; - } else { - // Deprecated - const file = await fetch(this.localesDirectory + formattedLocale + '/messages.json'); - return await file.json(); - } + super(systemLanguage, null, async (formattedLocale: string) => { + // Deprecated + const file = await fetch(this.localesDirectory + formattedLocale + '/messages.json'); + return await file.json(); }); this.supportedTranslationLocales = [