Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove PushKit #3268

Merged
merged 27 commits into from
May 29, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
53bb87d
Create notification service extension
ismailgulek May 22, 2020
a3890c6
update fastlane commands for new target
ismailgulek May 25, 2020
7335682
Configure log files correctly
ismailgulek May 25, 2020
9475cd7
Fix Manu's comments
ismailgulek May 25, 2020
f85aee0
Implement a workaround to delete some notifications afterwards
ismailgulek May 25, 2020
87e702a
Swiftify some ifs
ismailgulek May 25, 2020
23203af
Swiftify some ifs
ismailgulek May 25, 2020
db01577
Swiftify some ifs
ismailgulek May 25, 2020
4e25323
Swiftify code, ignore session state
ismailgulek May 25, 2020
09353f4
Swiftify content function, use switch for ifs when possible
ismailgulek May 25, 2020
f25e3b6
Swiftify code, style changes
ismailgulek May 25, 2020
7f39581
Swiftify extension methods
ismailgulek May 25, 2020
63d4a16
Update Riot/Utils/Constants.swift
ismailgulek May 26, 2020
db8b5a4
Update RiotNSE/NotificationService.swift
ismailgulek May 26, 2020
ba50f47
Remove some commented code
ismailgulek May 26, 2020
b1a654d
Change logs for fallback cases
ismailgulek May 26, 2020
69d9b5b
Add fallback method calls on some points
ismailgulek May 26, 2020
c4bdf33
Remove some redundant semicolons
ismailgulek May 26, 2020
fa44dae
Update RiotNSE/NotificationService.swift
ismailgulek May 26, 2020
a0e9540
Update RiotNSE/NotificationService.swift
ismailgulek May 26, 2020
f5324ae
Update RiotNSE/NotificationService.swift
ismailgulek May 26, 2020
3bd9e6b
Change some guarding to if check
ismailgulek May 26, 2020
bcd9683
Implement a memory store specific to NSE
ismailgulek May 27, 2020
d859ce8
Drop MXKAccount and MXFileStore usages
ismailgulek May 27, 2020
845363b
Fix Manu's comments
ismailgulek May 29, 2020
4ef5e17
Add some comments
ismailgulek May 29, 2020
0b639e8
Adapt to new method, change timeout to seconds
ismailgulek May 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Riot.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@
EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */; };
EC85D754247C0F5B002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
EC85D755247C0F84002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */; };
ECB101302477CFDB00CF8C11 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012C2477CFDB00CF8C11 /* UITableView.swift */; };
ECB101312477CFDB00CF8C11 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012D2477CFDB00CF8C11 /* UILabel.swift */; };
ECB101322477CFDB00CF8C11 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */; };
Expand Down Expand Up @@ -1725,6 +1726,7 @@
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RiotNSE.entitlements; sourceTree = "<group>"; };
EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNUserNotificationCenter.swift; sourceTree = "<group>"; };
EC85D753247C0F5B002C44C9 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEMemoryStore.swift; sourceTree = "<group>"; };
ECB1012C2477CFDB00CF8C11 /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = "<group>"; };
ECB1012D2477CFDB00CF8C11 /* UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = "<group>"; };
ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4288,6 +4290,7 @@
children = (
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */,
EC85D7452477E5F7002C44C9 /* NotificationService.swift */,
EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */,
EC85D7472477E5F7002C44C9 /* Info.plist */,
);
path = RiotNSE;
Expand Down Expand Up @@ -5106,6 +5109,7 @@
buildActionMask = 2147483647;
files = (
EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */,
EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */,
EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */,
EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */,
EC85D755247C0F84002C44C9 /* Constants.swift in Sources */,
Expand Down
83 changes: 83 additions & 0 deletions RiotNSE/NSEMemoryStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2020 New Vector Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Foundation
import MatrixSDK

class NSEMemoryStore: MXMemoryStore {

private var credentials: MXCredentials
private var fileStore: MXFileStore

init(withCredentials credentials: MXCredentials) {
self.credentials = credentials
fileStore = MXFileStore(credentials: credentials)
fileStore.loadMetaData()
}

// Return real eventStreamToken, to be able to launch a meaningful background sync
override var eventStreamToken: String? {
get {
return fileStore.eventStreamToken
} set {
// no-op
}
}

// Return real userAccountData, to be able to use push rules
override var userAccountData: [AnyHashable : Any]? {
get {
return fileStore.userAccountData
} set {
// no-op
}
}

// This store should act like as a permanent one
override var isPermanent: Bool {
return true
}

// Some mandatory methods to implement to be permanent
override func storeState(forRoom roomId: String, stateEvents: [MXEvent]) {

}

override func state(ofRoom roomId: String, success: @escaping ([MXEvent]) -> Void, failure: ((Error) -> Void)? = nil) {

}

override func summary(ofRoom roomId: String) -> MXRoomSummary? {
return fileStore.summary(ofRoom: roomId)
}

override func accountData(ofRoom roomId: String) -> MXRoomAccountData? {
return fileStore.accountData(ofRoom: roomId)
}

// Override and return a user to be stored on session.myUser
override func user(withUserId userId: String) -> MXUser? {
if userId == credentials.userId {
return MXMyUser(userId: userId)
}
return MXUser(userId: userId)
}

override func close() {
fileStore.close()
}

}
123 changes: 69 additions & 54 deletions RiotNSE/NotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var originalContent: UNMutableNotificationContent?

var userAccount: MXKAccount?
var store: MXFileStore?
var mxSession: MXSession?
var store: NSEMemoryStore!
var showDecryptedContentInNotifications: Bool {
return RiotSettings.shared.showDecryptedContentInNotifications
}
Expand All @@ -42,21 +42,19 @@ class NotificationService: UNNotificationServiceExtension {

let userInfo = content.userInfo
NSLog("[NotificationService] Payload came: \(userInfo)")
let roomId = userInfo["room_id"] as? String
let eventId = userInfo["event_id"] as? String

guard roomId != nil, eventId != nil else {
guard let roomId = userInfo["room_id"] as? String, let _ = userInfo["event_id"] as? String else {
// it's not a Matrix notification, do not change the content
NSLog("[NotificationService] didReceiveRequest: This is not a Matrix notification.")
contentHandler(content)
return
}

// setup user account
setup()

// fetch the event first
fetchEvent()
setup(withRoomId: roomId) {
// fetch the event first
self.fetchEvent()
}
}

override func serviceExtensionTimeWillExpire() {
Expand All @@ -66,7 +64,7 @@ class NotificationService: UNNotificationServiceExtension {
fallbackToOriginalContent()
}

func setup() {
func setup(withRoomId roomId: String, completion: @escaping () -> Void) {
let sdkOptions = MXSDKOptions.sharedInstance()
sdkOptions.applicationGroupIdentifier = "group.im.vector"
sdkOptions.disableIdenticonUseForUserAvatar = true
Expand All @@ -79,21 +77,30 @@ class NotificationService: UNNotificationServiceExtension {
MXLogger.redirectNSLog(toFiles: true)
}

userAccount = MXKAccountManager.shared()?.activeAccounts.first

if let userAccount = userAccount {
store = MXFileStore(credentials: userAccount.mxCredentials)
if let userAccount = MXKAccountManager.shared()?.activeAccounts.first {
store = NSEMemoryStore(withCredentials: userAccount.mxCredentials)
store.open(with: userAccount.mxCredentials, onComplete: nil, failure: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be removed. It is called by MXSession.setStore()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right. Removing.

store.getOrCreateRoomStore(roomId)
manuroe marked this conversation as resolved.
Show resolved Hide resolved

if userAccount.mxSession == nil {
userAccount.openSession(with: store!)
}
mxSession = MXSession(matrixRestClient: MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil))
mxSession?.setStore(store, completion: { (response) in
switch response {
case .success:
completion()
break
case .failure(let error):
NSLog("[NotificationService] setup: MXSession.setStore method returned error: \(String(describing: error))")
self.fallbackToOriginalContent()
break
}
})
}
}

func fetchEvent() {
guard let content = originalContent, let userAccount = self.userAccount else {
guard let content = originalContent, let mxSession = mxSession else {
// there is something wrong, do not change the content
NSLog("[NotificationService] fetchEvent: Either originalContent or userAccount is missing.")
NSLog("[NotificationService] fetchEvent: Either originalContent or mxSession is missing.")
fallbackToOriginalContent()
return
}
Expand All @@ -106,7 +113,7 @@ class NotificationService: UNNotificationServiceExtension {
return
}

userAccount.mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in
mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in
guard let self = self else {
NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late successfully.")
return
Expand Down Expand Up @@ -138,7 +145,7 @@ class NotificationService: UNNotificationServiceExtension {
}

// should decrypt it first
if userAccount.mxSession.decryptEvent(event, inTimeline: nil) {
if mxSession.decryptEvent(event, inTimeline: nil) {
// decryption succeeded
self.processEvent(event)
} else {
Expand All @@ -157,44 +164,43 @@ class NotificationService: UNNotificationServiceExtension {
}

func launchBackgroundSync() {
guard let userAccount = userAccount else {
self.fallbackToOriginalContent()
return
}
guard let store = store else {
guard let mxSession = mxSession else {
NSLog("[NotificationService] launchBackgroundSync: mxSession is missing.")
self.fallbackToOriginalContent()
return
}
if userAccount.mxSession == nil {
userAccount.openSession(with: store)
}

// launch an initial background sync
userAccount.initialBackgroundSync(20000, success: { [weak self] in
guard let self = self else {
NSLog("[NotificationService] launchBackgroundSync: MXKAccount.initialBackgroundSync returned too late successfully")
return
}
self.fetchEvent()
}) { [weak self] (error) in
guard let self = self else {
NSLog("[NotificationService] launchBackgroundSync: MXKAccount.initialBackgroundSync returned too late with error: \(String(describing: error))")
return
mxSession.initialBackgroundSync(withTimeout: 20000) { [weak self] (response) in
switch response {
case .success:
guard let self = self else {
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully")
return
}
self.fetchEvent()
break
case .failure(let error):
guard let self = self else {
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late with error: \(String(describing: error))")
return
}
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned with error: \(String(describing: error))")
self.fallbackToOriginalContent()
break
}
NSLog("[NotificationService] launchBackgroundSync: MXKAccount.initialBackgroundSync returned with error: \(String(describing: error))")
self.fallbackToOriginalContent()
}
}

func processEvent(_ event: MXEvent) {
guard let content = originalContent, let userAccount = userAccount else {
guard let content = originalContent, let mxSession = mxSession else {
self.fallbackToOriginalContent()
return
manuroe marked this conversation as resolved.
Show resolved Hide resolved
}

self.notificationContent(forEvent: event, inAccount: userAccount) { (notificationContent) in
self.notificationContent(forEvent: event, inSession: mxSession) { (notificationContent) in
// close store
self.store?.close()
self.store.close()

// Modify the notification content here...
if let newContent = notificationContent {
Expand All @@ -215,7 +221,7 @@ class NotificationService: UNNotificationServiceExtension {
}

func fallbackToOriginalContent() {
store?.close()
store.close()
guard let content = originalContent else {
NSLog("[NotificationService] fallbackToOriginalContent: Original content is missing.")
return
Expand All @@ -225,28 +231,37 @@ class NotificationService: UNNotificationServiceExtension {
contentHandler?(content)
}

func notificationContent(forEvent event: MXEvent, inAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) {
func notificationContent(forEvent event: MXEvent, inSession session: MXSession, onComplete: @escaping (UNNotificationContent?) -> Void) {
guard let content = event.content, content.count > 0 else {
NSLog("[NotificationService][Push] notificationContentForEvent: empty event content")
onComplete(nil)
return
}

guard let room = account.mxSession.room(withRoomId: event.roomId) else {
guard let room = MXRoom(roomId: event.roomId, matrixSession: session, andStore: store) else {
NSLog("[NotificationService][Push] notificationBodyForEvent: Unknown room")
onComplete(nil)
return
}

let pushRule = room.getRoomPushRule()

room.state({ (roomState: MXRoomState!) in

// initialize a temporary file store, just to load the room state
let fileStore = MXFileStore(credentials: session.credentials)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using the existing NSEMemoryStore and implement stateOfRoom there?

Copy link
Contributor Author

@ismailgulek ismailgulek May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, totally makes sense. Updating.


MXRoomState.load(from: fileStore, withRoomId: event.roomId, matrixSession: session) { (roomState) in
guard let roomState = roomState else {
NSLog("[NotificationService] notificationContentForEvent: Could not load the room state")
onComplete(nil)
return
}

var notificationTitle: String?
var notificationBody: String?

var threadIdentifier = room.roomId
let eventSenderName = roomState.members.memberName(event.sender)
let currentUserId = account.mxCredentials.userId
let currentUserId = session.credentials.userId

switch event.eventType {
case .roomMessage, .roomEncrypted:
Expand Down Expand Up @@ -284,7 +299,7 @@ class NotificationService: UNNotificationServiceExtension {
}

let roomDisplayName = room.summary.displayname
let myUserId = account.mxSession.myUser.userId
let myUserId = session.myUser.userId
let isIncomingEvent = event.sender != myUserId

// Display the room name only if it is different than the sender name
Expand All @@ -298,8 +313,8 @@ class NotificationService: UNNotificationServiceExtension {
} else if msgType == kMXMessageTypeImage {
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
} else if room.isDirect && isIncomingEvent && msgType == kMXMessageTypeKeyVerificationRequest {
account.mxSession.crypto.keyVerificationManager.keyVerification(fromKeyVerificationEvent: event,
success:{ (keyVerification) in
session.crypto.keyVerificationManager.keyVerification(fromKeyVerificationEvent: event,
success:{ (keyVerification) in
guard let request = keyVerification.request, request.state == MXKeyVerificationRequestStatePending else {
onComplete(nil)
return
Expand Down Expand Up @@ -391,7 +406,7 @@ class NotificationService: UNNotificationServiceExtension {
pushRule: pushRule)

onComplete(notificationContent)
})
}
}

func notificationContent(withTitle title: String?,
Expand Down