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") {