mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 15:22:39 +00:00
Merge branch 'release/1.11.10/master'
This commit is contained in:
commit
e999a8a519
13 changed files with 699 additions and 53 deletions
11
CHANGES.md
11
CHANGES.md
|
@ -1,3 +1,14 @@
|
|||
## Changes in 1.11.10 (2024-05-01)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Upgrade MatrixSDK version ([v0.27.7](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.27.7)).
|
||||
|
||||
Others
|
||||
|
||||
- Improvements to reporting of decryption failures.
|
||||
|
||||
|
||||
## Changes in 1.11.9 (2024-04-02)
|
||||
|
||||
Others
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
//
|
||||
|
||||
// Version
|
||||
MARKETING_VERSION = 1.11.9
|
||||
CURRENT_PROJECT_VERSION = 1.11.9
|
||||
MARKETING_VERSION = 1.11.10
|
||||
CURRENT_PROJECT_VERSION = 1.11.10
|
||||
|
|
2
Podfile
2
Podfile
|
@ -16,7 +16,7 @@ use_frameworks!
|
|||
# - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI
|
||||
#
|
||||
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
|
||||
$matrixSDKVersion = '= 0.27.6'
|
||||
$matrixSDKVersion = '= 0.27.7'
|
||||
# $matrixSDKVersion = :local
|
||||
# $matrixSDKVersion = { :branch => 'develop'}
|
||||
# $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } }
|
||||
|
|
16
Podfile.lock
16
Podfile.lock
|
@ -39,9 +39,9 @@ PODS:
|
|||
- LoggerAPI (1.9.200):
|
||||
- Logging (~> 1.1)
|
||||
- Logging (1.4.0)
|
||||
- MatrixSDK (0.27.6):
|
||||
- MatrixSDK/Core (= 0.27.6)
|
||||
- MatrixSDK/Core (0.27.6):
|
||||
- MatrixSDK (0.27.7):
|
||||
- MatrixSDK/Core (= 0.27.7)
|
||||
- MatrixSDK/Core (0.27.7):
|
||||
- AFNetworking (~> 4.0.0)
|
||||
- GZIP (~> 1.3.0)
|
||||
- libbase58 (~> 0.1.4)
|
||||
|
@ -49,7 +49,7 @@ PODS:
|
|||
- OLMKit (~> 3.2.5)
|
||||
- Realm (= 10.27.0)
|
||||
- SwiftyBeaver (= 1.9.5)
|
||||
- MatrixSDK/JingleCallStack (0.27.6):
|
||||
- MatrixSDK/JingleCallStack (0.27.7):
|
||||
- JitsiMeetSDKLite (= 8.1.2-lite)
|
||||
- MatrixSDK/Core
|
||||
- MatrixSDKCrypto (0.3.13)
|
||||
|
@ -102,8 +102,8 @@ DEPENDENCIES:
|
|||
- KeychainAccess (~> 4.2.2)
|
||||
- KTCenterFlowLayout (~> 1.3.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.27.6)
|
||||
- MatrixSDK/JingleCallStack (= 0.27.6)
|
||||
- MatrixSDK (= 0.27.7)
|
||||
- MatrixSDK/JingleCallStack (= 0.27.7)
|
||||
- OLMKit
|
||||
- PostHog (~> 2.0.0)
|
||||
- ReadMoreTextView (~> 3.0.1)
|
||||
|
@ -187,7 +187,7 @@ SPEC CHECKSUMS:
|
|||
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
||||
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
|
||||
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
||||
MatrixSDK: 4129ab9c0acda1d0aad50b1c9765bd795b8d70b9
|
||||
MatrixSDK: e07b2309f3c6498c1df987441da7006d099c47a4
|
||||
MatrixSDKCrypto: bf08b72f2cd015d8749420a2b8b92fc0536bedf4
|
||||
OLMKit: da115f16582e47626616874e20f7bb92222c7a51
|
||||
PostHog: 660ec6c9d80cec17b685e148f17f6785a88b597d
|
||||
|
@ -208,6 +208,6 @@ SPEC CHECKSUMS:
|
|||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
||||
|
||||
PODFILE CHECKSUM: c87b532985dd755b373732f841e3bcfe616f4e4f
|
||||
PODFILE CHECKSUM: 1197abec9c5affbef652747dd5cd6aaf00ef3a47
|
||||
|
||||
COCOAPODS: 1.14.3
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
"contacts_address_book_matrix_users_toggle" = "فقط کاربران ماتریس";
|
||||
"directory_search_results_more_than" = ">%tu نتیجه برای %@ یافت شد";
|
||||
"directory_search_results" = "%tu نتیجه برای %@ یافت شد";
|
||||
"search_in_progress" = "در حال جست وجو";
|
||||
"search_in_progress" = "جوییدن…";
|
||||
"search_no_result" = "نتیچه ای یافت نشد";
|
||||
"search_people_placeholder" = "جستجو بر اساس شناسه کاربری، نام یا آدرس ایمیل";
|
||||
"search_default_placeholder" = "جست و جو";
|
||||
|
@ -246,7 +246,7 @@
|
|||
"room_accessibility_search" = "جستجو";
|
||||
"room_message_edits_history_title" = "ویرایش های پیام";
|
||||
"room_resource_usage_limit_reached_message_2" = "برخی از کاربران نمی توانند وارد سیستم شوند.";
|
||||
"room_resource_limit_exceeded_message_contact_3" = " برای ادامه استفاده از این سرویس";
|
||||
"room_resource_limit_exceeded_message_contact_3" = " برای ادامه استفاده از این خدمت.";
|
||||
"room_resource_limit_exceeded_message_contact_2_link" = "با سرپرست سرویس خود تماس بگیرید";
|
||||
"room_resource_limit_exceeded_message_contact_1" = " لطفا ";
|
||||
"room_predecessor_link" = "برای دیدن پیامهای قدیمیتر به اینجاضربه بزنید.";
|
||||
|
@ -416,7 +416,7 @@
|
|||
"event_formatter_call_retry" = "تلاش مجدد";
|
||||
"event_formatter_call_answer" = "پاسخ";
|
||||
"event_formatter_call_decline" = "رد تماس";
|
||||
"event_formatter_call_back" = "تماس";
|
||||
"event_formatter_call_back" = "پاسخ تماس";
|
||||
"event_formatter_call_connection_failed" = "ارتباط ناموفق بود";
|
||||
"event_formatter_call_missed_video" = "تماس ویدیویی از دست رفته";
|
||||
"event_formatter_call_missed_voice" = "تماس صوتی از دست رفته";
|
||||
|
@ -464,7 +464,7 @@
|
|||
"group_participants_invited_section" = "دعوت شده";
|
||||
"group_participants_invite_malformed_id_title" = "خطای دعوت";
|
||||
"group_participants_invite_another_user" = "جستجو / دعوت با شناسه کاربری یا نام";
|
||||
"group_participants_filter_members" = "اعضای انجمن را فیلتر کنید";
|
||||
"group_participants_filter_members" = "پالایش اعضای اجتماع";
|
||||
"group_participants_invite_prompt_msg" = "آیا مطمئنید که می خواهید %@ را به این گروه دعوت کنید؟";
|
||||
"group_participants_invite_prompt_title" = "تایید";
|
||||
"group_participants_remove_prompt_msg" = "آیا مطمئنید که می خواهید %@ را از این گروه حذف کنید؟";
|
||||
|
@ -570,7 +570,7 @@
|
|||
"room_details_files" = "بارگذاری شده ها";
|
||||
"room_details_people" = "اعضا";
|
||||
"room_details_title_for_dm" = "جزییات";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "به هر حال قطع کن";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "قطع شدن به هر روی";
|
||||
"identity_server_settings_alert_disconnect_button" = "قطع کردن";
|
||||
"identity_server_settings_disconnect" = "قطع کردن";
|
||||
"identity_server_settings_change" = "تغییر دادن";
|
||||
|
@ -652,7 +652,7 @@
|
|||
"settings_confirm_password" = "تایید رمز";
|
||||
"settings_new_password" = "رمز جدید";
|
||||
"settings_old_password" = "رمز قدیمی";
|
||||
"settings_third_party_notices" = "اعلامیه های شخص ثالث";
|
||||
"settings_third_party_notices" = "یادآوریهای سومشخص";
|
||||
"settings_privacy_policy" = "سیاست حفظ حریم خصوصی";
|
||||
"settings_term_conditions" = "شرایط و ضوابط";
|
||||
"settings_copyright" = "کپی رایت";
|
||||
|
@ -684,7 +684,7 @@
|
|||
"settings_room_upgrades" = "ارتقاء اتاق";
|
||||
"settings_messages_by_a_bot" = "پیام های ربات";
|
||||
"settings_call_invitations" = "دعوت نامه های تماس";
|
||||
"settings_room_invitations" = "دعوت نامه های اتاق";
|
||||
"settings_room_invitations" = "دعوتهای اتاق";
|
||||
"settings_messages_containing_keywords" = "کلمات کلیدی";
|
||||
"settings_messages_containing_at_room" = "@ اتاق";
|
||||
"settings_messages_containing_user_name" = "نام کاربری من";
|
||||
|
@ -694,13 +694,13 @@
|
|||
"settings_encrypted_direct_messages" = "پیام های مستقیم رمزگذاری شده";
|
||||
"settings_direct_messages" = "پیام مستقیم";
|
||||
"settings_notify_me_for" = "به من اطلاع بده برای";
|
||||
"settings_mentions_and_keywords" = "ذکر و کلمات کلیدی";
|
||||
"settings_mentions_and_keywords" = "نامبری و کلیدواژگان";
|
||||
"settings_default" = "اعلان های پیش فرض";
|
||||
"settings_notifications_disabled_alert_message" = "برای فعال کردن اعلانها، به تنظیمات دستگاه خود بروید.";
|
||||
"settings_notifications_disabled_alert_title" = "غیر فعال کردن اعلان ها";
|
||||
"settings_pin_rooms_with_missed_notif" = "پین کردن اتاق هایی با اعلان های از دست رفته";
|
||||
"settings_pin_rooms_with_unread" = "پین کردن اتاق هایی با پیام های خوانده نشده";
|
||||
"settings_global_settings_info" = "تنظیمات اعلان جهانی در سرویس گیرنده وب %@ شما موجود است";
|
||||
"settings_global_settings_info" = "تنظیمات آگاهی عمومی در کارخواه وب %@تان موجود است";
|
||||
"settings_show_decrypted_content" = "نمایش محتوای رمزگشایی شده";
|
||||
"settings_device_notifications" = "اعلان های دستگاه";
|
||||
"settings_enable_push_notif" = "اعلان ها در این دستگاه";
|
||||
|
@ -1346,3 +1346,4 @@
|
|||
"onboarding_splash_page_2_title" = "تحت کنترل شماست.";
|
||||
"onboarding_splash_page_1_message" = "یک ارتباط امن و مستقل که سطح حریم شخصی آن دقیقا مشابه ارتباط رو در رو در منزل شماست.";
|
||||
"accessibility_selected" = "انتخاب شده";
|
||||
"room_title_members" = "%@ عضو";
|
||||
|
|
|
@ -2740,3 +2740,18 @@
|
|||
|
||||
"key_verification_self_verify_security_upgrade_alert_title" = "Alkalmazás frissítve";
|
||||
"settings_acceptable_use" = "Elfogadható felhasználói feltételek";
|
||||
"room_creation_user_not_found_prompt_title" = "Megerősítés";
|
||||
"room_creation_user_not_found_prompt_message" = "Nem található profil ehhez a Matrix-azonosítóhoz. Mindenképp elindítja a privát csevegést?";
|
||||
"room_creation_user_not_found_prompt_invite_action" = "Privát csevegés mindenképp";
|
||||
"room_participants_invite_unknown_participant_prompt_to_msg" = "Nem található profil ehhez a Matrix-azonosítóhoz. Mindenképp meghívja %@ felhasználót a(z) %@ szobába?";
|
||||
"room_participants_invite_anyway" = "Meghívás mindenképp";
|
||||
|
||||
// Room commands descriptions
|
||||
"room_command_change_display_name_description" = "Megváltoztatja a megjelenítendő becenevét";
|
||||
"room_command_emote_description" = "Megjeleníti a műveletet";
|
||||
"room_command_join_room_description" = "Csatlakozik a megadott című szobához";
|
||||
"room_command_part_room_description" = "Elhagyja a szobát";
|
||||
"room_command_invite_user_description" = "Meghívja az adott azonosítójú felhasználót a jelenlegi szobába";
|
||||
"room_command_kick_user_description" = "Eltávolítja az adott azonosítójú felhasználót ebből a szobából";
|
||||
"room_command_ban_user_description" = "Kitiltja az adott azonosítójú felhasználót";
|
||||
"room_command_unban_user_description" = "Feloldja az adott azonosítójú felhasználó kitiltását";
|
||||
|
|
|
@ -1 +1,77 @@
|
|||
|
||||
|
||||
// String for App Store
|
||||
"store_short_description" = "უსაფრთხო დეცენტრალიზებული ჩატი/ვოიპი";
|
||||
|
||||
// Titles
|
||||
"title_home" = "მთავარი";
|
||||
"title_favourites" = "ფავორიტები";
|
||||
"title_people" = "ხალხი";
|
||||
"title_rooms" = "ოთახები";
|
||||
"title_groups" = "თემები";
|
||||
"warning" = "გაფრთხილება";
|
||||
|
||||
// Actions
|
||||
"view" = "ხედი";
|
||||
"next" = "შემდეგი";
|
||||
"back" = "უკან";
|
||||
"continue" = "გაგრძელება";
|
||||
"create" = "შექმნა";
|
||||
"start" = "აწყება";
|
||||
"leave" = "დატოვება";
|
||||
"remove" = "წაშლა";
|
||||
"retry" = "გამეორება";
|
||||
"on" = "ჩართული";
|
||||
"off" = "გამორთული";
|
||||
"enable" = "ჩართვა";
|
||||
"save" = "შენახვა";
|
||||
"join" = "შეუერთდება";
|
||||
"decline" = "უარყოფა";
|
||||
"accept" = "მიღება";
|
||||
"camera" = "კამერა";
|
||||
"voice" = "ხმა";
|
||||
"video" = "ვიდეო";
|
||||
"active_call" = "აქტიური ზარი";
|
||||
"later" = "შემდეგ";
|
||||
"rename" = "გადარქმევა";
|
||||
"collapse" = "ჩაკეცვა";
|
||||
"send_to" = "გაგზავნა %@-ს";
|
||||
"close" = "დახურვა";
|
||||
"skip" = "გამოტოვება";
|
||||
"joined" = "შეუერთდა";
|
||||
"switch" = "გადართვა";
|
||||
"more" = "მეტი";
|
||||
"less" = "ნაკლები";
|
||||
"open" = "გახსნა";
|
||||
"private" = "ირადი";
|
||||
"public" = "საჯარო";
|
||||
"stop" = "შეჩერება";
|
||||
"new_word" = "ახალი";
|
||||
"existing" = "არსებული";
|
||||
"add" = "დამატება";
|
||||
"ok" = "კარგი";
|
||||
"error" = "შეცდომა";
|
||||
"suggest" = "შესთავაზება";
|
||||
"confirm" = "დადასტურება";
|
||||
"invite_to" = "მიწვევა %@-ში";
|
||||
|
||||
// Activities
|
||||
"loading" = "ჩატვირთვა";
|
||||
"sending" = "გაგზავნა";
|
||||
"callbar_active_and_single_paused" = "1 აქტიური ზარი (%@) · 1 შეჩერებული ზარი";
|
||||
"callbar_active_and_multiple_paused" = "1 აქტიური ზარი (%@) · %@ შეჩერებული ზარები";
|
||||
"callbar_only_single_paused" = "შეჩერებული ზარი";
|
||||
"callbar_return" = "დაბრუნება";
|
||||
"store_promotional_text" = "კონფიდენციალობის დაცვით ჩატისა და თანამშრომლობის აპლიკაცია, ღია ქსელზე. დეცენტრალიზებული, რათა მართვა გადაგიცემათ. არაა დათამაინინგი, არაა უკანა კარები და არაა მესამე მხარის წვდომა.";
|
||||
"invite" = "მიწვევა";
|
||||
"cancel" = "გაუქმება";
|
||||
"preview" = "წინასწარი ხილვა";
|
||||
"active_call_details" = "აქტიური ზარი (%@)";
|
||||
"joining" = "შეერთება";
|
||||
"done" = "დასრულებული";
|
||||
"edit" = "რედაქტირება";
|
||||
"saving" = "შენახვა";
|
||||
|
||||
// Call Bar
|
||||
"callbar_only_single_active" = "შეეხეთ, რომ დაბრუნდეთ ზარში (%@)";
|
||||
"callbar_only_multiple_paused" = "%@ შეჩერებული ზარები";
|
||||
|
|
|
@ -21,24 +21,34 @@ extension DecryptionFailure {
|
|||
|
||||
public func toAnalyticsEvent() -> AnalyticsEvent.Error {
|
||||
|
||||
let timeToDecryptMillis: Int = if self.timeToDecrypt != nil {
|
||||
Int(self.timeToDecrypt! * 1000)
|
||||
let timeToDecryptMillis: Int = if let ttd = self.timeToDecrypt {
|
||||
Int(ttd * 1000)
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
|
||||
let isHistoricalEvent = if let localAge = self.eventLocalAgeMillis {
|
||||
localAge < 0
|
||||
} else { false }
|
||||
|
||||
let errorName = if isHistoricalEvent && self.trustOwnIdentityAtTimeOfFailure == false {
|
||||
AnalyticsEvent.Error.Name.HistoricalMessage
|
||||
} else {
|
||||
self.reason.errorName
|
||||
}
|
||||
|
||||
return AnalyticsEvent.Error(
|
||||
context: self.context,
|
||||
cryptoModule: .Rust,
|
||||
cryptoSDK: .Rust,
|
||||
domain: .E2EE,
|
||||
|
||||
eventLocalAgeMillis: nil,
|
||||
isFederated: nil,
|
||||
isMatrixDotOrg: nil,
|
||||
name: self.reason.errorName,
|
||||
eventLocalAgeMillis: self.eventLocalAgeMillis,
|
||||
isFederated: self.isFederated,
|
||||
isMatrixDotOrg: self.isMatrixOrg,
|
||||
name: errorName,
|
||||
timeToDecryptMillis: timeToDecryptMillis,
|
||||
userTrustsOwnIdentity: nil,
|
||||
wasVisibleToUser: nil
|
||||
userTrustsOwnIdentity: self.trustOwnIdentityAtTimeOfFailure,
|
||||
wasVisibleToUser: self.wasVisibleToUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,19 @@ import AnalyticsEvents
|
|||
/// UTDs can be permanent or temporary. If temporary, this field will contain the time it took to decrypt the message in milliseconds. If permanent should be nil
|
||||
var timeToDecrypt: TimeInterval?
|
||||
|
||||
/// Was the current cross-signing identity trusted at the time of decryption
|
||||
var trustOwnIdentityAtTimeOfFailure: Bool?
|
||||
|
||||
var eventLocalAgeMillis: Int?
|
||||
|
||||
/// Is the current user on matrix org
|
||||
var isMatrixOrg: Bool?
|
||||
/// Are the sender and recipient on the same homeserver
|
||||
var isFederated: Bool?
|
||||
|
||||
/// As for now the ios App only reports UTDs visible to user (error are reported from EventFormatter
|
||||
var wasVisibleToUser: Bool = true
|
||||
|
||||
init(failedEventId: String, reason: DecryptionFailureReason, context: String, ts: TimeInterval) {
|
||||
self.failedEventId = failedEventId
|
||||
self.reason = reason
|
||||
|
|
|
@ -62,14 +62,14 @@ class DecryptionFailureTracker: NSObject {
|
|||
selector: #selector(eventDidDecrypt(_:)),
|
||||
name: .mxEventDidDecrypt,
|
||||
object: nil)
|
||||
|
||||
}
|
||||
|
||||
@objc
|
||||
func reportUnableToDecryptError(forEvent event: MXEvent, withRoomState roomState: MXRoomState, myUser userId: String) {
|
||||
func reportUnableToDecryptError(forEvent event: MXEvent, withRoomState roomState: MXRoomState, mySession: MXSession) {
|
||||
if reportedFailures[event.eventId] != nil || trackedEvents.contains(event.eventId) {
|
||||
return
|
||||
}
|
||||
guard let userId = mySession.myUserId else { return }
|
||||
|
||||
// Filter out "expected" UTDs
|
||||
// We cannot decrypt messages sent before the user joined the room
|
||||
|
@ -82,6 +82,12 @@ class DecryptionFailureTracker: NSObject {
|
|||
|
||||
guard let error = event.decryptionError as? NSError else { return }
|
||||
|
||||
let eventOrigin = event.originServerTs
|
||||
let deviceTimestamp = mySession.crypto.deviceCreationTs
|
||||
// If negative it's an historical event relative to the current session
|
||||
let eventRelativeAgeMillis = Int(eventOrigin) - Int(deviceTimestamp)
|
||||
let isSessionVerified = mySession.crypto.crossSigning.canTrustCrossSigning
|
||||
|
||||
var reason = DecryptionFailureReason.unspecified
|
||||
|
||||
if error.code == MXDecryptingErrorUnknownInboundSessionIdCode.rawValue {
|
||||
|
@ -92,7 +98,24 @@ class DecryptionFailureTracker: NSObject {
|
|||
|
||||
let context = String(format: "code: %ld, description: %@", error.code, event.decryptionError.localizedDescription)
|
||||
|
||||
reportedFailures[failedEventId] = DecryptionFailure(failedEventId: failedEventId, reason: reason, context: context, ts: self.timeProvider.nowTs())
|
||||
let failure = DecryptionFailure(failedEventId: failedEventId, reason: reason, context: context, ts: self.timeProvider.nowTs())
|
||||
|
||||
failure.eventLocalAgeMillis = Int(exactly: eventRelativeAgeMillis)
|
||||
failure.trustOwnIdentityAtTimeOfFailure = isSessionVerified
|
||||
|
||||
let myDomain = userId.components(separatedBy: ":").last
|
||||
failure.isMatrixOrg = myDomain == "matrix.org"
|
||||
|
||||
if MXTools.isMatrixUserIdentifier(event.sender) {
|
||||
let senderDomain = event.sender.components(separatedBy: ":").last
|
||||
failure.isFederated = senderDomain != nil && senderDomain != myDomain
|
||||
}
|
||||
|
||||
/// XXX for future work, as for now only the event formatter reports UTDs. That means that it's only UTD ~visible to users
|
||||
failure.wasVisibleToUser = true
|
||||
|
||||
reportedFailures[failedEventId] = failure
|
||||
|
||||
|
||||
// Start the ticker if needed. There is no need to have a ticker if no failures are tracked
|
||||
if checkFailuresTimer == nil {
|
||||
|
|
|
@ -334,7 +334,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
|||
{
|
||||
// Track e2e failures
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[DecryptionFailureTracker sharedInstance] reportUnableToDecryptErrorForEvent:event withRoomState:roomState myUser:self->mxSession.myUser.userId];
|
||||
[[DecryptionFailureTracker sharedInstance] reportUnableToDecryptErrorForEvent:event withRoomState:roomState mySession:self->mxSession];
|
||||
});
|
||||
|
||||
if (event.decryptionError.code == MXDecryptingErrorUnknownInboundSessionIdCode)
|
||||
|
|
|
@ -41,10 +41,23 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
}
|
||||
|
||||
let timeShifter = TimeShifter()
|
||||
var fakeCrypto: FakeCrypto!
|
||||
var fakeSession: FakeSession!
|
||||
var fakeCrossSigning: FakeCrossSigning!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
self.fakeCrypto = FakeCrypto()
|
||||
self.fakeCrossSigning = FakeCrossSigning()
|
||||
self.fakeCrypto.crossSigning = self.fakeCrossSigning
|
||||
self.fakeSession = FakeSession(mockCrypto: self.fakeCrypto)
|
||||
}
|
||||
|
||||
|
||||
func test_grace_period() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -61,7 +74,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
timeShifter.timestamp = TimeInterval(2)
|
||||
|
||||
|
@ -82,7 +95,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_report_ratcheted_key_utd() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -99,7 +113,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Pass the max period
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
@ -111,7 +125,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_report_unspecified_error() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -128,7 +143,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Pass the max period
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
@ -142,7 +157,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_do_not_double_report() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -160,7 +176,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Pass the max period
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
@ -171,7 +187,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
// Try to report again the same event
|
||||
testDelegate.reportedFailure = nil
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
// Pass the grace period
|
||||
timeShifter.timestamp = TimeInterval(10)
|
||||
|
||||
|
@ -183,7 +199,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_ignore_not_member() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -203,7 +220,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
fakeMembers.mockMembers[myUser] = MXMembership.ban
|
||||
fakeRoomState.mockMembers = fakeMembers
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Pass the grace period
|
||||
timeShifter.timestamp = TimeInterval(5)
|
||||
|
@ -217,7 +234,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_notification_center() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -235,7 +253,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Shift time below GRACE_PERIOD
|
||||
timeShifter.timestamp = TimeInterval(2)
|
||||
|
@ -257,7 +275,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_should_report_late_decrypt() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -275,7 +294,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Simulate succesful decryption after grace period but before max wait
|
||||
timeShifter.timestamp = TimeInterval(20)
|
||||
|
@ -301,7 +320,8 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
|
||||
func test_should_report_permanent_decryption_error() {
|
||||
|
||||
let myUser = "test@example.com";
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
@ -319,7 +339,7 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, myUser: myUser);
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Simulate succesful decryption after max wait
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
@ -337,5 +357,246 @@ class DecryptionFailureTrackerTests: XCTestCase {
|
|||
XCTAssertEqual(analyticsError.timeToDecryptMillis, -1)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func test_should_report_trust_status_at_decryption_time() {
|
||||
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
||||
let testDelegate = AnalyticsDelegate();
|
||||
|
||||
decryptionFailureTracker.delegate = testDelegate;
|
||||
|
||||
timeShifter.timestamp = TimeInterval(0)
|
||||
|
||||
let fakeEvent = FakeEvent(id: "$0000");
|
||||
fakeEvent.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
// set session as not yet verified
|
||||
fakeCrossSigning.canTrustCrossSigning = false
|
||||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// set verified now
|
||||
fakeCrossSigning.canTrustCrossSigning = true
|
||||
|
||||
// Simulate succesful decryption after max wait
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
// Event should have been reported as a late decrypt
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.trustOwnIdentityAtTimeOfFailure, false);
|
||||
|
||||
// Assert that it's converted to -1 for reporting
|
||||
let analyticsError = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError.userTrustsOwnIdentity, false)
|
||||
|
||||
// Report a new error now that session is verified
|
||||
|
||||
let fakeEvent2 = FakeEvent(id: "$0001");
|
||||
fakeEvent2.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent2, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Simulate permanent UTD
|
||||
timeShifter.timestamp = TimeInterval(140)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.failedEventId, "$0001");
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.trustOwnIdentityAtTimeOfFailure, true);
|
||||
|
||||
let analyticsError2 = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError2.userTrustsOwnIdentity, true)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func test_should_report_event_age() {
|
||||
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let format = DateFormatter()
|
||||
format.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
|
||||
|
||||
let sessionCreationTimeMillis = format.date(from: "2024-03-09T10:00:00Z")!.timeIntervalSince1970 * 1000
|
||||
|
||||
let now = format.date(from: "2024-03-09T10:02:00Z")!.timeIntervalSince1970
|
||||
|
||||
// 5mn after session was created
|
||||
let postCreationMessageTs = UInt64(format.date(from: "2024-03-09T10:05:00Z")!.timeIntervalSince1970 * 1000)
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
||||
let testDelegate = AnalyticsDelegate();
|
||||
|
||||
decryptionFailureTracker.delegate = testDelegate;
|
||||
|
||||
timeShifter.timestamp = now
|
||||
|
||||
let fakeEvent = FakeEvent(id: "$0000");
|
||||
fakeEvent.mockOrigineServerTs = postCreationMessageTs;
|
||||
fakeEvent.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
fakeCrypto.deviceCreationTs = UInt64(sessionCreationTimeMillis)
|
||||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// set verified now
|
||||
fakeCrossSigning.canTrustCrossSigning = true
|
||||
|
||||
// Simulate permanent UTD
|
||||
timeShifter.timestamp = now + TimeInterval(70)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.eventLocalAgeMillis, 5 * 60 * 1000);
|
||||
|
||||
let analyticsError = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError.eventLocalAgeMillis, 5 * 60 * 1000)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func test_should_report_expected_utds() {
|
||||
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let format = DateFormatter()
|
||||
format.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
|
||||
|
||||
let sessionCreationTimeMillis = format.date(from: "2024-03-09T10:00:00Z")!.timeIntervalSince1970 * 1000
|
||||
|
||||
let now = format.date(from: "2024-03-09T10:02:00Z")!.timeIntervalSince1970
|
||||
|
||||
// 1 day before session was created
|
||||
let historicalMessageTs = UInt64(format.date(from: "2024-03-08T10:00:00Z")!.timeIntervalSince1970 * 1000)
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
||||
let testDelegate = AnalyticsDelegate();
|
||||
|
||||
decryptionFailureTracker.delegate = testDelegate;
|
||||
|
||||
timeShifter.timestamp = now
|
||||
|
||||
let fakeEvent = FakeEvent(id: "$0000");
|
||||
fakeEvent.mockOrigineServerTs = historicalMessageTs;
|
||||
fakeEvent.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
fakeCrypto.deviceCreationTs = UInt64(sessionCreationTimeMillis)
|
||||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
fakeCrossSigning.canTrustCrossSigning = false
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// set verified now
|
||||
fakeCrossSigning.canTrustCrossSigning = true
|
||||
|
||||
// Simulate permanent UTD
|
||||
timeShifter.timestamp = now + TimeInterval(70)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
// Event should have been reported as a late decrypt
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.eventLocalAgeMillis, -24 * 60 * 60 * 1000);
|
||||
|
||||
let analyticsError = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError.name, .HistoricalMessage)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func test_should_report_is_matrix_org_and_is_federated() {
|
||||
|
||||
let myUser = "@test:example.com";
|
||||
fakeSession.mockUserId = myUser;
|
||||
|
||||
let decryptionFailureTracker = DecryptionFailureTracker();
|
||||
decryptionFailureTracker.timeProvider = timeShifter;
|
||||
|
||||
let testDelegate = AnalyticsDelegate();
|
||||
|
||||
decryptionFailureTracker.delegate = testDelegate;
|
||||
|
||||
timeShifter.timestamp = TimeInterval(0)
|
||||
|
||||
let fakeEvent = FakeEvent(id: "$0000");
|
||||
fakeEvent.sender = "@bob:example.com"
|
||||
fakeEvent.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
// set session as not yet verified
|
||||
fakeCrossSigning.canTrustCrossSigning = false
|
||||
|
||||
let fakeRoomState = FakeRoomState();
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [myUser])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Simulate succesful decryption after max wait
|
||||
timeShifter.timestamp = TimeInterval(70)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.isMatrixOrg, false);
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.isFederated, false);
|
||||
|
||||
|
||||
let analyticsError = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError.isMatrixDotOrg, false)
|
||||
XCTAssertEqual(analyticsError.isFederated, false)
|
||||
|
||||
// Report a new error now that session is verified
|
||||
|
||||
let fakeEvent2 = FakeEvent(id: "$0001");
|
||||
fakeEvent2.sender = "@bob:example.com"
|
||||
fakeEvent2.decryptionError = NSError(domain: MXDecryptingErrorDomain, code: Int(MXDecryptingErrorUnknownInboundSessionIdCode.rawValue))
|
||||
|
||||
fakeSession.mockUserId = "@test:matrix.org";
|
||||
fakeRoomState.mockMembers = FakeRoomMembers(joined: [fakeSession.mockUserId])
|
||||
|
||||
decryptionFailureTracker.reportUnableToDecryptError(forEvent: fakeEvent2, withRoomState: fakeRoomState, mySession: fakeSession);
|
||||
|
||||
// Simulate permanent UTD
|
||||
timeShifter.timestamp = TimeInterval(140)
|
||||
|
||||
decryptionFailureTracker.checkFailures();
|
||||
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.failedEventId, "$0001");
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.isMatrixOrg, true);
|
||||
XCTAssertEqual(testDelegate.reportedFailure?.isFederated, true);
|
||||
|
||||
let analyticsError2 = testDelegate.reportedFailure!.toAnalyticsEvent()
|
||||
|
||||
XCTAssertEqual(analyticsError2.isMatrixDotOrg, true)
|
||||
XCTAssertEqual(analyticsError2.isFederated, true)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// Copyright 2024 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -22,6 +22,7 @@ class FakeEvent: MXEvent {
|
|||
var mockEventId: String;
|
||||
var mockSender: String!;
|
||||
var mockDecryptionError: Error?
|
||||
var mockOrigineServerTs: UInt64 = 0
|
||||
|
||||
init(id: String) {
|
||||
mockEventId = id
|
||||
|
@ -31,7 +32,7 @@ class FakeEvent: MXEvent {
|
|||
required init?(coder: NSCoder) {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
|
||||
override var sender: String! {
|
||||
get { return mockSender }
|
||||
set { mockSender = newValue }
|
||||
|
@ -47,6 +48,12 @@ class FakeEvent: MXEvent {
|
|||
set { mockDecryptionError = newValue }
|
||||
}
|
||||
|
||||
override var originServerTs: UInt64 {
|
||||
get { return mockOrigineServerTs }
|
||||
set { mockOrigineServerTs = newValue }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,7 +87,7 @@ class FakeRoomMember: MXRoomMember {
|
|||
get { return mockUserId }
|
||||
set { mockUserId = newValue }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,3 +114,232 @@ class FakeRoomMembers: MXRoomMembers {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class FakeSession: MXSession {
|
||||
|
||||
var mockCrypto: MXCrypto? = FakeCrypto()
|
||||
|
||||
var mockUserId: String = "@alice:localhost"
|
||||
|
||||
init(mockCrypto: MXCrypto? = nil) {
|
||||
self.mockCrypto = mockCrypto
|
||||
super.init()
|
||||
}
|
||||
|
||||
override var crypto: MXCrypto? {
|
||||
get {
|
||||
return mockCrypto
|
||||
}
|
||||
set {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
override var myUserId: String! {
|
||||
get {
|
||||
return mockUserId
|
||||
}
|
||||
set {
|
||||
mockUserId = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FakeCrypto: NSObject, MXCrypto {
|
||||
|
||||
|
||||
var version: String = ""
|
||||
|
||||
var deviceCurve25519Key: String?
|
||||
|
||||
var deviceEd25519Key: String?
|
||||
|
||||
var deviceCreationTs: UInt64 = 0
|
||||
|
||||
var backup: MXKeyBackup?
|
||||
|
||||
var keyVerificationManager: MXKeyVerificationManager = FakeKeyVerificationManager()
|
||||
|
||||
var crossSigning: MXCrossSigning = FakeCrossSigning()
|
||||
|
||||
var recoveryService: MXRecoveryService! = nil
|
||||
|
||||
var dehydrationService: MatrixSDK.DehydrationService! = nil
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func start(_ onComplete: (() -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func close(_ deleteStore: Bool) {
|
||||
|
||||
}
|
||||
|
||||
func isRoomEncrypted(_ roomId: String) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func encryptEventContent(_ eventContent: [AnyHashable : Any], withType eventType: String, in room: MXRoom, success: (([AnyHashable : Any], String) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) -> MXHTTPOperation? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decryptEvents(_ events: [MXEvent], inTimeline timeline: String?, onComplete: (([MXEventDecryptionResult]) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func ensureEncryption(inRoom roomId: String, success: (() -> Void)?, failure: ((Swift.Error) -> Void)? = nil) -> MXHTTPOperation? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func eventDeviceInfo(_ event: MXEvent) -> MXDeviceInfo? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func discardOutboundGroupSessionForRoom(withRoomId roomId: String, onComplete: (() -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func handle(_ syncResponse: MXSyncResponse, onComplete: @escaping () -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func setDeviceVerification(_ verificationStatus: MXDeviceVerification, forDevice deviceId: String, ofUser userId: String, success: (() -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func setUserVerification(_ verificationStatus: Bool, forUser userId: String, success: (() -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func trustLevel(forUser userId: String) -> MXUserTrustLevel {
|
||||
return MXUserTrustLevel.init(crossSigningVerified: true, locallyVerified: true)
|
||||
}
|
||||
|
||||
func deviceTrustLevel(forDevice deviceId: String, ofUser userId: String) -> MXDeviceTrustLevel? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func trustLevelSummary(forUserIds userIds: [String], forceDownload: Bool, success: ((MXUsersTrustLevelSummary?) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func downloadKeys(_ userIds: [String], forceDownload: Bool, success: ((MXUsersDevicesMap<MXDeviceInfo>?, [String : MXCrossSigningInfo]?) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) -> MXHTTPOperation? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func devices(forUser userId: String) -> [String : MXDeviceInfo] {
|
||||
return [:];
|
||||
}
|
||||
|
||||
func device(withDeviceId deviceId: String, ofUser userId: String) -> MXDeviceInfo? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportRoomKeys(withPassword password: String, success: ((Data) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func importRoomKeys(_ keyFile: Data, withPassword password: String, success: ((UInt, UInt) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func reRequestRoomKey(for event: MXEvent) {
|
||||
|
||||
}
|
||||
|
||||
var globalBlacklistUnverifiedDevices: Bool = false
|
||||
|
||||
func isBlacklistUnverifiedDevices(inRoom roomId: String) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func setBlacklistUnverifiedDevicesInRoom(_ roomId: String, blacklist: Bool) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FakeCrossSigning: NSObject, MXCrossSigning {
|
||||
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
var state: MXCrossSigningState = MXCrossSigningState.trustCrossSigning
|
||||
|
||||
var myUserCrossSigningKeys: MXCrossSigningInfo? = nil
|
||||
|
||||
var canTrustCrossSigning: Bool = true
|
||||
|
||||
var canCrossSign: Bool = true
|
||||
|
||||
var hasAllPrivateKeys: Bool = true
|
||||
|
||||
func refreshState(success: ((Bool) -> Void)?, failure: ((Swift.Error) -> Void)? = nil) {
|
||||
|
||||
}
|
||||
|
||||
func setup(withPassword password: String, success: @escaping () -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func setup(withAuthParams authParams: [AnyHashable : Any], success: @escaping () -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func crossSignDevice(withDeviceId deviceId: String, userId: String, success: @escaping () -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func signUser(withUserId userId: String, success: @escaping () -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func crossSigningKeys(forUser userId: String) -> MXCrossSigningInfo? {
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FakeKeyVerificationManager: NSObject, MXKeyVerificationManager {
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func requestVerificationByToDevice(withUserId userId: String, deviceIds: [String]?, methods: [String], success: @escaping (MXKeyVerificationRequest) -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func requestVerificationByDM(withUserId userId: String, roomId: String?, fallbackText: String, methods: [String], success: @escaping (MXKeyVerificationRequest) -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
var pendingRequests: [MXKeyVerificationRequest] = []
|
||||
|
||||
func beginKeyVerification(from request: MXKeyVerificationRequest, method: String, success: @escaping (MXKeyVerificationTransaction) -> Void, failure: @escaping (Swift.Error) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func transactions(_ complete: @escaping ([MXKeyVerificationTransaction]) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
func keyVerification(fromKeyVerificationEvent event: MXEvent, roomId: String, success: @escaping (MXKeyVerification) -> Void, failure: @escaping (Swift.Error) -> Void) -> MXHTTPOperation? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func qrCodeTransaction(withTransactionId transactionId: String) -> MXQRCodeTransaction? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeQRCodeTransaction(withTransactionId transactionId: String) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue