diff --git a/Cartfile b/Cartfile index 8070c9681..28f99c632 100644 --- a/Cartfile +++ b/Cartfile @@ -1,12 +1,12 @@ github "Quick/Quick" github "Quick/Nimble" -github "ReactiveX/RxSwift" +github "ReactiveX/RxSwift" ~> 4.4.0 github "RxSwiftCommunity/RxDataSources" "81b709c28b8ceb5cddc8c2262d009ea8735f0893" github "RxSwiftCommunity/RxOptional" ~> 3.1.3 github "mozilla-mobile/telemetry-ios" github "jrendel/SwiftKeychainWrapper" ~> 3.0 github "mozilla-mobile/MappaMundi" "master" -github "mozilla/application-services" "0.2.5-xcode10gm" +github "mozilla/application-services" "0.9.0" github "mozilla-lockbox/lockbox-ios-fxa-sync" "880f310086bac8ad16c81775b3235550d9ffc7f3" github "adjust/ios_sdk" ~> 4.14.1 github "getsentry/sentry-cocoa" "4.1.0" diff --git a/Cartfile.resolved b/Cartfile.resolved index 03b862762..05d0fcf0f 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -2,7 +2,7 @@ github "Alamofire/Alamofire" "4.7.3" github "DaveWoodCom/XCGLogger" "Version_4.0.0" github "Quick/Nimble" "v7.3.1" github "Quick/Quick" "v1.3.2" -github "ReactiveX/RxSwift" "4.3.1" +github "ReactiveX/RxSwift" "4.4.0" github "RxSwiftCommunity/RxDataSources" "81b709c28b8ceb5cddc8c2262d009ea8735f0893" github "RxSwiftCommunity/RxOptional" "3.5.0" github "SwiftyJSON/SwiftyJSON" "3.1.4" @@ -12,5 +12,5 @@ github "jrendel/SwiftKeychainWrapper" "3.0.1" github "mozilla-lockbox/lockbox-ios-fxa-sync" "880f310086bac8ad16c81775b3235550d9ffc7f3" github "mozilla-mobile/MappaMundi" "981095dff1c014a458624820ac8f2cda39c92144" github "mozilla-mobile/telemetry-ios" "v1.1.0" -github "mozilla/application-services" "0.2.5-xcode10gm" +github "mozilla/application-services" "v0.9.0" github "sleroux/Deferred" "35b8927c1b94ce074e10793c57e1f80d0e2227fa" diff --git a/CredentialProvider/Info.plist b/CredentialProvider/Info.plist index 173ec99dd..76502cf98 100644 --- a/CredentialProvider/Info.plist +++ b/CredentialProvider/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 1.3.2 + 1.3.3 CFBundleVersion 1 MozDevelopmentTeam diff --git a/CredentialProvider/Resources/FileLists/Frameworks.xcfilelist b/CredentialProvider/Resources/FileLists/Frameworks.xcfilelist index f223a4c2e..afda05b0d 100644 --- a/CredentialProvider/Resources/FileLists/Frameworks.xcfilelist +++ b/CredentialProvider/Resources/FileLists/Frameworks.xcfilelist @@ -1,6 +1,6 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. $(SRCROOT)/Carthage/Build/iOS/RxCocoa.framework $(SRCROOT)/Carthage/Build/iOS/RxDataSources.framework diff --git a/Lockbox.xcodeproj/project.pbxproj b/Lockbox.xcodeproj/project.pbxproj index e7dbd490b..2c9cf6cdc 100644 --- a/Lockbox.xcodeproj/project.pbxproj +++ b/Lockbox.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 48; objects = { /* Begin PBXBuildFile section */ @@ -138,8 +138,6 @@ 7D078EF32124E24100D10D1B /* BaseConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D078EF22124E24100D10D1B /* BaseConstants.swift */; }; 7D078EF42124E24100D10D1B /* BaseConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D078EF22124E24100D10D1B /* BaseConstants.swift */; }; 7D078EF62124E48300D10D1B /* Observable+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA54FE4F9D6DAEF984F63E6 /* Observable+.swift */; }; - 7D078EF72124E52B00D10D1B /* RxOptional.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D92DAF220586FBA00195A1B /* RxOptional.framework */; }; - 7D078EF82124E58000D10D1B /* Differentiator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7DEA1C4120362E09008AD7C4 /* Differentiator.framework */; }; 7D07A31B21385C4300772283 /* Login+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DFF2EEE21384FB800F001ED /* Login+.swift */; }; 7D07A31C21385C6F00772283 /* CredentialStatusAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D9722DF21349B9F0071D82B /* CredentialStatusAction.swift */; }; 7D07A31D213885C900772283 /* BaseAutoLockStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D895605B20967C5300CC7E47 /* BaseAutoLockStore.swift */; }; @@ -192,7 +190,6 @@ 7D8057EC2135E51300D41BDD /* CredentialProviderStoreSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8057EB2135E51300D41BDD /* CredentialProviderStoreSpec.swift */; }; 7D8057EE2135ED8F00D41BDD /* ASCredentialIdentityStore+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8057ED2135ED8F00D41BDD /* ASCredentialIdentityStore+.swift */; }; 7D8057EF2135ED8F00D41BDD /* ASCredentialIdentityStore+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8057ED2135ED8F00D41BDD /* ASCredentialIdentityStore+.swift */; }; - 7D80F3082118DCC700DA191B /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D80F3072118DCC700DA191B /* AuthenticationServices.framework */; }; 7D80F30B2118DCC700DA191B /* CredentialProviderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D80F30A2118DCC700DA191B /* CredentialProviderView.swift */; }; 7D80F30E2118DCC700DA191B /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D80F30C2118DCC700DA191B /* MainInterface.storyboard */; }; 7D80F3132118DCC700DA191B /* CredentialProvider.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7D80F3062118DCC700DA191B /* CredentialProvider.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -236,13 +233,6 @@ 7DC75D79206AD01C007CDDBB /* AccountSetting.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7DC75D7B206AD01C007CDDBB /* AccountSetting.storyboard */; }; 7DDEAA612124B0B000A7D521 /* Frameworks.xcfilelist in Resources */ = {isa = PBXBuildFile; fileRef = 7DDEAA602124B0B000A7D521 /* Frameworks.xcfilelist */; }; 7DDEAA622124B24E00A7D521 /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA54CDEA56C47263160AD0E /* Dispatcher.swift */; }; - 7DDEAA632124B26F00A7D521 /* FxAClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D73BD6F20D3135E0075D1CE /* FxAClient.framework */; }; - 7DDEAA642124B27200A7D521 /* FxAUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39B1508620878E42007497E5 /* FxAUtils.framework */; }; - 7DDEAA652124B27600A7D521 /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D9D64921F9F8EE300279C39 /* RxCocoa.framework */; }; - 7DDEAA662124B27900A7D521 /* RxDataSources.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D320B3420360F9000891F73 /* RxDataSources.framework */; }; - 7DDEAA672124B27F00A7D521 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7DF469C31F9F8F8000375C74 /* RxSwift.framework */; }; - 7DDEAA682124B28500A7D521 /* Shared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 391233772090E5A200CB0233 /* Shared.framework */; }; - 7DDEAA692124B28500A7D521 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3912337A2090E5E200CB0233 /* Storage.framework */; }; 7DDEAA6A2124B60F00A7D521 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA5445B47B7A548F0F0E294 /* Action.swift */; }; 7DDEAA6B2124B61800A7D521 /* ErrorAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA54D4E439D76B910034E2A /* ErrorAction.swift */; }; 7DDEAA6C2124B7A700A7D521 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D80F3072118DCC700DA191B /* AuthenticationServices.framework */; }; @@ -669,16 +659,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7DDEAA652124B27600A7D521 /* RxCocoa.framework in Frameworks */, - 7D80F3082118DCC700DA191B /* AuthenticationServices.framework in Frameworks */, - 7DDEAA632124B26F00A7D521 /* FxAClient.framework in Frameworks */, - 7D078EF72124E52B00D10D1B /* RxOptional.framework in Frameworks */, - 7DDEAA682124B28500A7D521 /* Shared.framework in Frameworks */, - 7DDEAA692124B28500A7D521 /* Storage.framework in Frameworks */, - 7D078EF82124E58000D10D1B /* Differentiator.framework in Frameworks */, - 7DDEAA662124B27900A7D521 /* RxDataSources.framework in Frameworks */, - 7DDEAA672124B27F00A7D521 /* RxSwift.framework in Frameworks */, - 7DDEAA642124B27200A7D521 /* FxAUtils.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1305,7 +1285,6 @@ isa = PBXNativeTarget; buildConfigurationList = 7D80F3172118DCC700DA191B /* Build configuration list for PBXNativeTarget "CredentialProvider" */; buildPhases = ( - 7DDEAA5F2124A61900A7D521 /* ShellScript */, 7D80F3022118DCC700DA191B /* Sources */, 7D80F3032118DCC700DA191B /* Frameworks */, 7D80F3042118DCC700DA191B /* Resources */, @@ -1525,24 +1504,6 @@ shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; - 7DDEAA5F2124A61900A7D521 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "$(SRCROOT)/CredentialProvider/Resources/FileLists/Frameworks.xcfilelist", - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks\n"; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1912,11 +1873,7 @@ ); INFOPLIST_FILE = LockboxXCUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.LockboxXCUITests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1938,11 +1895,7 @@ ); INFOPLIST_FILE = LockboxXCUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.LockboxXCUITests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1964,11 +1917,7 @@ ); INFOPLIST_FILE = LockboxXCUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.LockboxXCUITests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1992,11 +1941,7 @@ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; INFOPLIST_FILE = "lockbox-iosTests/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "mozilla.lockbox-iosTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2022,11 +1967,7 @@ ); INFOPLIST_FILE = "lockbox-iosTests/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "mozilla.lockbox-iosTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2151,9 +2092,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OBJC_BRIDGING_HEADER = "lockbox-ios/Common/Resources/lockbox-ios-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 4.2; VALIDATE_PRODUCT = YES; @@ -2180,10 +2120,7 @@ HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "lockbox-ios/Common/Resources/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -2221,10 +2158,7 @@ HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "lockbox-ios/Common/Resources/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -2255,11 +2189,7 @@ ); INFOPLIST_FILE = CredentialProvider/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.Lockbox.CredentialProvider; @@ -2284,11 +2214,7 @@ ); INFOPLIST_FILE = CredentialProvider/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.Lockbox.adhoc.CredentialProvider; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2312,11 +2238,7 @@ ); INFOPLIST_FILE = CredentialProvider/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.Lockbox.CredentialProvider; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2410,10 +2332,7 @@ HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "lockbox-ios/Common/Resources/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -2448,11 +2367,7 @@ ); INFOPLIST_FILE = "lockbox-iosTests/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "mozilla.lockbox-iosTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/LockboxXCUITests/LockboxXCUITests.swift b/LockboxXCUITests/LockboxXCUITests.swift index d0aeb9112..30d9431d9 100644 --- a/LockboxXCUITests/LockboxXCUITests.swift +++ b/LockboxXCUITests/LockboxXCUITests.swift @@ -306,7 +306,8 @@ class LockboxXCUITests: BaseTestCase { XCTAssertTrue(safari.buttons.otherElements["iosmztest@gmail.com, for this website — Lockbox"].exists) } else if (safari.otherElements["Password Auto-fill"].exists) { safari.otherElements["Password Auto-fill"].tap() - XCTAssertTrue(safari.buttons["iosmztest@gmail.com, for this website — Lockbox"].exists) + waitforExistence(safari.buttons["Lockbox…"], timeout: 3) + XCTAssertTrue(safari.buttons["Lockbox…"].exists) } else { XCTAssertTrue(safari.buttons["Use “iosmztest@gmail.com”"].exists) } diff --git a/Shared/Action/TelemetryAction.swift b/Shared/Action/TelemetryAction.swift index 73daea788..c0f068b6e 100644 --- a/Shared/Action/TelemetryAction.swift +++ b/Shared/Action/TelemetryAction.swift @@ -50,6 +50,7 @@ enum TelemetryEventObject: String { case autofillSettingsInstructions = "autofill_instructions" case autofillOnboardingInstructions = "autofill_onboarding_instructions" case forceLock = "force_lock" + case openInBrowser = "open_in_browser" } enum ExtraKey: String { diff --git a/Shared/Common/Resources/Assets.xcassets/copy.imageset/Contents.json b/Shared/Common/Resources/Assets.xcassets/copy.imageset/Contents.json new file mode 100644 index 000000000..c0196db7a --- /dev/null +++ b/Shared/Common/Resources/Assets.xcassets/copy.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "iconCopy.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "iconCopy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "iconCopy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy.png b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy.png new file mode 100644 index 000000000..82b608c7b Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@2x.png b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@2x.png new file mode 100644 index 000000000..32656028a Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@2x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@3x.png b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@3x.png new file mode 100644 index 000000000..3972fef08 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/copy.imageset/iconCopy@3x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/Contents.json b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/Contents.json index d57a0dc45..56f38fd46 100644 --- a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/Contents.json +++ b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/Contents.json @@ -2,17 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "iconHide.png", + "filename" : "iconShow.png", "scale" : "1x" }, { "idiom" : "universal", - "filename" : "iconHide@2x.png", + "filename" : "iconShow@2x.png", "scale" : "2x" }, { "idiom" : "universal", - "filename" : "iconHide@3x.png", + "filename" : "iconShow@3x.png", "scale" : "3x" } ], diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide.png deleted file mode 100644 index c1c74d55f..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@2x.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@2x.png deleted file mode 100644 index b9f4c693d..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@2x.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@3x.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@3x.png deleted file mode 100644 index 6cf7d6664..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconHide@3x.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow.png new file mode 100644 index 000000000..db12d3940 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@2x.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@2x.png new file mode 100644 index 000000000..7a9e1907d Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@2x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@3x.png b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@3x.png new file mode 100644 index 000000000..f04ab3302 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/hide-eye.imageset/iconShow@3x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/open.imageset/Contents.json b/Shared/Common/Resources/Assets.xcassets/open.imageset/Contents.json new file mode 100644 index 000000000..c44b642bb --- /dev/null +++ b/Shared/Common/Resources/Assets.xcassets/open.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "iconOpen.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "iconOpen@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "iconOpen@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen.png b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen.png new file mode 100644 index 000000000..203bc348b Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@2x.png b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@2x.png new file mode 100644 index 000000000..018a814e4 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@2x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@3x.png b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@3x.png new file mode 100644 index 000000000..f25f42dc2 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/open.imageset/iconOpen@3x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/Contents.json b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/Contents.json index f032544b0..56f38fd46 100644 --- a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/Contents.json +++ b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/Contents.json @@ -2,17 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "iconReveal.png", + "filename" : "iconShow.png", "scale" : "1x" }, { "idiom" : "universal", - "filename" : "iconReveal@2x.png", + "filename" : "iconShow@2x.png", "scale" : "2x" }, { "idiom" : "universal", - "filename" : "iconReveal@3x.png", + "filename" : "iconShow@3x.png", "scale" : "3x" } ], diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal.png deleted file mode 100644 index 99419f2a5..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@2x.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@2x.png deleted file mode 100644 index 891489721..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@2x.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@3x.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@3x.png deleted file mode 100644 index a708330a3..000000000 Binary files a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconReveal@3x.png and /dev/null differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow.png new file mode 100644 index 000000000..c17e8346d Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@2x.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@2x.png new file mode 100644 index 000000000..6ea8e5f8c Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@2x.png differ diff --git a/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@3x.png b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@3x.png new file mode 100644 index 000000000..de5447265 Binary files /dev/null and b/Shared/Common/Resources/Assets.xcassets/reveal-eye.imageset/iconShow@3x.png differ diff --git a/Shared/Store/BaseDataStore.swift b/Shared/Store/BaseDataStore.swift index db539094f..3bebd00c4 100644 --- a/Shared/Store/BaseDataStore.swift +++ b/Shared/Store/BaseDataStore.swift @@ -95,6 +95,7 @@ class BaseDataStore { internal let userDefaults: UserDefaults internal var profile: FxAUtils.Profile internal let dispatcher: Dispatcher + private let application: UIApplication public var list: Observable<[Login]> { return self.listSubject.asObservable() @@ -116,11 +117,13 @@ class BaseDataStore { profileFactory: @escaping ProfileFactory = defaultProfileFactory, fxaLoginHelper: FxALoginHelper = FxALoginHelper.sharedInstance, keychainWrapper: KeychainWrapper = KeychainWrapper.standard, - userDefaults: UserDefaults = UserDefaults(suiteName: Constant.app.group)!) { + userDefaults: UserDefaults = UserDefaults(suiteName: Constant.app.group)!, + application: UIApplication = UIApplication.shared) { self.profileFactory = profileFactory self.fxaLoginHelper = fxaLoginHelper self.keychainWrapper = keychainWrapper self.userDefaults = userDefaults + self.application = application self.dispatcher = dispatcher self.profile = profileFactory(false) @@ -157,6 +160,11 @@ class BaseDataStore { switch action { case .background: self.profile.syncManager?.applicationDidEnterBackground() + var taskId = UIBackgroundTaskIdentifier.invalid + taskId = application.beginBackgroundTask (expirationHandler: { + self.profile.shutdown() + application.endBackgroundTask(taskId) + }) case .foreground: self.profile.syncManager?.applicationDidBecomeActive() self.handleLock() diff --git a/Shared/Store/CredentialProviderStore.swift b/Shared/Store/CredentialProviderStore.swift index e0f777090..7c318c983 100644 --- a/Shared/Store/CredentialProviderStore.swift +++ b/Shared/Store/CredentialProviderStore.swift @@ -19,6 +19,7 @@ class CredentialProviderStore { private let dispatcher: Dispatcher private let dataStore: DataStore private let credentialStore: CredentialIdentityStoreProtocol + private let accountStore: BaseAccountStore private let disposeBag = DisposeBag() private let _stateSubject = ReplaySubject.create(bufferSize: 1) @@ -35,10 +36,12 @@ class CredentialProviderStore { init(dispatcher: Dispatcher = .shared, dataStore: DataStore = .shared, - credentialStore: CredentialIdentityStoreProtocol = ASCredentialIdentityStore.shared) { + credentialStore: CredentialIdentityStoreProtocol = ASCredentialIdentityStore.shared, + accountStore: BaseAccountStore = AccountStore.shared) { self.dispatcher = dispatcher self.dataStore = dataStore self.credentialStore = credentialStore + self.accountStore = accountStore self.dispatcher.register .filterByType(class: CredentialProviderAction.self) @@ -81,11 +84,22 @@ extension CredentialProviderStore { } private func refresh() { + Observable.combineLatest(self.dataStore.list, self.accountStore.oauthInfo, self.accountStore.profile) + .filter { $0.1 != nil && $0.2 != nil } + .map { $0.0 } + .filter { $0.isEmpty } + .bind { _ in + self._stateSubject.onNext(.Populated) + } + .disposed(by: self.disposeBag) + self._stateSubject.onNext(.Populating) let loginObservable = self.dataStore.list.filterEmpty() loginObservable.flatMap { logins -> Observable<(Void, [Login])> in + self._stateSubject.onNext(.Populating) + let clearObservable = self.clearCredentialStore() .asObservable() let justLoginObservable = Observable.just(logins) diff --git a/Shared/View/TableViewCell/ItemDetailCell.swift b/Shared/View/TableViewCell/ItemDetailCell.swift index 16f4b1eb8..1be5b19e4 100644 --- a/Shared/View/TableViewCell/ItemDetailCell.swift +++ b/Shared/View/TableViewCell/ItemDetailCell.swift @@ -9,6 +9,8 @@ class ItemDetailCell: UITableViewCell { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var valueLabel: UILabel! @IBOutlet weak var revealButton: UIButton! + @IBOutlet weak var copyButton: UIButton! + @IBOutlet weak var openButton: UIButton! var disposeBag = DisposeBag() diff --git a/docs/release-notes.md b/docs/release-notes.md index 858014d91..821189f89 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,30 @@ # Release Notes +## 1.3.3 (Build 2731) + +_Date: 2018-12-19_ + +We fixed more bugs and added some (hopefully) helpful icons to the item detail view. You should see some slight improvements but nothing major. Here's the full list of changes: + +- We added icons to show that you can open the webpage and/or copy the username and password with one tap +- We fully close the database so it can't crash in the background, this means you should see AutoFill work more reliably +- If you don't have any saved logins in your Firefox Account and try to enable AutoFill, we gracefully stop trying to set that up for you (since there's nothing to set up yet!) +- We also updated some underlying libraries to keep up with other fixes and improvements + +A big "thanks" to all the contributors that helped along the way! + +## 1.3.3 (Build 2717) + +_Date: 2018-12-17_ + +We fixed more bugs! You should see some slight improvements but nothing major. + +Here's the full list of changes: + +- Upgrade to RxSwift, application services dependencies +- Add Copy and Open icons to item detail screen +- Properly close DB when app is backgrounded + ## 1.3.2 (Build 2635) _Date: 2018-11-03_ diff --git a/lockbox-ios/Action/ExternalLinkAction.swift b/lockbox-ios/Action/ExternalLinkAction.swift index 90a935b5f..5330916e9 100644 --- a/lockbox-ios/Action/ExternalLinkAction.swift +++ b/lockbox-ios/Action/ExternalLinkAction.swift @@ -22,3 +22,21 @@ extension ExternalLinkAction: Equatable { return lhs.baseURLString == rhs.baseURLString } } + +extension ExternalLinkAction: TelemetryAction { + var eventMethod: TelemetryEventMethod { + return .tap + } + + var eventObject: TelemetryEventObject { + return .openInBrowser + } + + var value: String? { + return nil + } + + var extras: [String: Any?]? { + return nil + } +} diff --git a/lockbox-ios/Common/Resources/Info.plist b/lockbox-ios/Common/Resources/Info.plist index 202f4fdaf..481c07023 100644 --- a/lockbox-ios/Common/Resources/Info.plist +++ b/lockbox-ios/Common/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.2 + 1.3.3 CFBundleVersion 1 LSApplicationQueriesSchemes diff --git a/lockbox-ios/Presenter/ItemDetailPresenter.swift b/lockbox-ios/Presenter/ItemDetailPresenter.swift index fec7703cf..19177413e 100644 --- a/lockbox-ios/Presenter/ItemDetailPresenter.swift +++ b/lockbox-ios/Presenter/ItemDetailPresenter.swift @@ -167,21 +167,26 @@ extension ItemDetailPresenter { accessibilityLabel: String(format: Constant.string.websiteCellAccessibilityLabel, hostname), password: false, valueFontColor: Constant.color.lockBoxBlue, - accessibilityId: "webAddressItemDetail") + accessibilityId: "webAddressItemDetail", + showOpenButton: true) ]), ItemDetailSectionModel(model: 1, items: [ ItemDetailCellConfiguration( title: Constant.string.username, value: username, accessibilityLabel: String(format: Constant.string.usernameCellAccessibilityLabel, username), - password: false, accessibilityId: "userNameItemDetail"), + password: false, + accessibilityId: "userNameItemDetail", + showCopyButton: true), ItemDetailCellConfiguration( title: Constant.string.password, value: passwordText, accessibilityLabel: String( format: Constant.string.passwordCellAccessibilityLabel, passwordText), - password: true, accessibilityId: "passwordItemDetail") + password: true, + accessibilityId: "passwordItemDetail", + showCopyButton: true) ]) ] diff --git a/lockbox-ios/Storyboard/Base.lproj/ItemDetail.storyboard b/lockbox-ios/Storyboard/Base.lproj/ItemDetail.storyboard index 17d02b21a..137412e69 100644 --- a/lockbox-ios/Storyboard/Base.lproj/ItemDetail.storyboard +++ b/lockbox-ios/Storyboard/Base.lproj/ItemDetail.storyboard @@ -1,11 +1,11 @@ - + - + @@ -50,7 +50,7 @@ + + + + + - + + + + @@ -128,8 +156,10 @@ - + + + diff --git a/lockbox-ios/View/ItemDetailView.swift b/lockbox-ios/View/ItemDetailView.swift index 64ec7080f..4c87d824c 100644 --- a/lockbox-ios/View/ItemDetailView.swift +++ b/lockbox-ios/View/ItemDetailView.swift @@ -16,19 +16,25 @@ struct ItemDetailCellConfiguration { let password: Bool let valueFontColor: UIColor let accessibilityId: String + let showCopyButton: Bool + let showOpenButton: Bool init(title: String, value: String, accessibilityLabel: String, password: Bool, valueFontColor: UIColor = UIColor.black, - accessibilityId: String) { + accessibilityId: String, + showCopyButton: Bool = false, + showOpenButton: Bool = false) { self.title = title self.value = value self.accessibilityLabel = accessibilityLabel self.password = password self.valueFontColor = valueFontColor self.accessibilityId = accessibilityId + self.showCopyButton = showCopyButton + self.showOpenButton = showOpenButton } } @@ -142,6 +148,8 @@ extension ItemDetailView: UIGestureRecognizerDelegate { cell.accessibilityIdentifier = cellConfiguration.accessibilityId cell.revealButton.isHidden = !cellConfiguration.password + cell.openButton.isHidden = !cellConfiguration.showOpenButton + cell.copyButton.isHidden = !cellConfiguration.showCopyButton if cellConfiguration.password { cell.valueLabel.font = UIFont(name: "Menlo-Regular", size: 16) diff --git a/lockbox-iosTests/ItemDetailPresenterSpec.swift b/lockbox-iosTests/ItemDetailPresenterSpec.swift index 224d7e510..71e65e5c4 100644 --- a/lockbox-iosTests/ItemDetailPresenterSpec.swift +++ b/lockbox-iosTests/ItemDetailPresenterSpec.swift @@ -376,6 +376,30 @@ class ItemDetailPresenterSpec: QuickSpec { expect(passwordSection.value).to(equal("•••••••••")) expect(passwordSection.password).to(beTrue()) } + + it("open button is displayed for web address") { + let viewConfig = self.view.itemDetailObserver.events.last!.value.element! + + let webAddressSection = viewConfig[0].items[0] + let usernameSection = viewConfig[1].items[0] + let passwordSection = viewConfig[1].items[1] + + expect(webAddressSection.showOpenButton).to(beTrue()) + expect(usernameSection.showOpenButton).to(beFalse()) + expect(passwordSection.showOpenButton).to(beFalse()) + } + + it("copy button is displayed for username and password") { + let viewConfig = self.view.itemDetailObserver.events.last!.value.element! + + let webAddressSection = viewConfig[0].items[0] + let usernameSection = viewConfig[1].items[0] + let passwordSection = viewConfig[1].items[1] + + expect(webAddressSection.showCopyButton).to(beFalse()) + expect(usernameSection.showCopyButton).to(beTrue()) + expect(passwordSection.showCopyButton).to(beTrue()) + } } describe("when there is no title, origin, username, or notes") {