mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
187
mobile/ios/Push/PushClient.swift
Normal file
187
mobile/ios/Push/PushClient.swift
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/* 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/. */
|
||||
|
||||
import Foundation
|
||||
import Alamofire
|
||||
import Deferred
|
||||
import Shared
|
||||
import SwiftyJSON
|
||||
|
||||
//public struct PushRemoteError {
|
||||
// static let MissingNecessaryCryptoKeys: Int32 = 101
|
||||
// static let InvalidURLEndpoint: Int32 = 102
|
||||
// static let ExpiredURLEndpoint: Int32 = 103
|
||||
// static let DataPayloadTooLarge: Int32 = 104
|
||||
// static let EndpointBecameUnavailable: Int32 = 105
|
||||
// static let InvalidSubscription: Int32 = 106
|
||||
// static let RouterTypeIsInvalid: Int32 = 108
|
||||
// static let InvalidAuthentication: Int32 = 109
|
||||
// static let InvalidCryptoKeysSpecified: Int32 = 110
|
||||
// static let MissingRequiredHeader: Int32 = 111
|
||||
// static let InvalidTTLHeaderValue: Int32 = 112
|
||||
// static let UnknownError: Int32 = 999
|
||||
//}
|
||||
|
||||
public let PushClientErrorDomain = "org.mozilla.push.error"
|
||||
private let PushClientUnknownError = NSError(domain: PushClientErrorDomain, code: 999,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Invalid server response"])
|
||||
private let log = Logger.browserLogger
|
||||
|
||||
/// Bug 1364403 – This is to be put into the push registration
|
||||
private let apsEnvironment: [String: Any] = [
|
||||
"mutable-content": 1,
|
||||
"alert": [
|
||||
"title": " ",
|
||||
"body": " "
|
||||
],
|
||||
]
|
||||
|
||||
public struct PushRemoteError {
|
||||
let code: Int
|
||||
let errno: Int
|
||||
let error: String
|
||||
let message: String?
|
||||
|
||||
public static func from(json: JSON) -> PushRemoteError? {
|
||||
guard let code = json["code"].int,
|
||||
let errno = json["errno"].int,
|
||||
let error = json["error"].string else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let message = json["message"].string
|
||||
return PushRemoteError(code: code, errno: errno, error: error, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
public enum PushClientError: MaybeErrorType {
|
||||
case Remote(PushRemoteError)
|
||||
case Local(Error)
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .Remote(error):
|
||||
let errorString = error.error
|
||||
let messageString = error.message ?? ""
|
||||
return "<FxAClientError.Remote \(error.code)/\(error.errno): \(errorString) (\(messageString))>"
|
||||
case let .Local(error):
|
||||
return "<FxAClientError.Local Error \"\(error.localizedDescription)\">"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PushClient {
|
||||
let endpointURL: NSURL
|
||||
let experimentalMode: Bool
|
||||
|
||||
lazy fileprivate var alamofire: SessionManager = {
|
||||
let ua = UserAgent.fxaUserAgent
|
||||
let configuration = URLSessionConfiguration.ephemeral
|
||||
var defaultHeaders = SessionManager.default.session.configuration.httpAdditionalHeaders ?? [:]
|
||||
defaultHeaders["User-Agent"] = ua
|
||||
configuration.httpAdditionalHeaders = defaultHeaders
|
||||
return SessionManager(configuration: configuration)
|
||||
}()
|
||||
|
||||
public init(endpointURL: NSURL, experimentalMode: Bool = false) {
|
||||
self.endpointURL = endpointURL
|
||||
self.experimentalMode = experimentalMode
|
||||
}
|
||||
}
|
||||
|
||||
public extension PushClient {
|
||||
public func register(_ apnsToken: String) -> Deferred<Maybe<PushRegistration>> {
|
||||
// POST /v1/{type}/{app_id}/registration
|
||||
let registerURL = endpointURL.appendingPathComponent("registration")!
|
||||
|
||||
var mutableURLRequest = URLRequest(url: registerURL)
|
||||
mutableURLRequest.httpMethod = HTTPMethod.post.rawValue
|
||||
|
||||
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
let parameters: [String: Any]
|
||||
if experimentalMode {
|
||||
parameters = [
|
||||
"token": apnsToken,
|
||||
"aps": apsEnvironment,
|
||||
]
|
||||
} else {
|
||||
parameters = ["token": apnsToken]
|
||||
}
|
||||
|
||||
mutableURLRequest.httpBody = JSON(parameters).stringValue()?.utf8EncodedData
|
||||
|
||||
if experimentalMode {
|
||||
log.info("curl -X POST \(registerURL.absoluteString) --data '\(JSON(parameters).stringValue()!)'")
|
||||
}
|
||||
|
||||
return send(request: mutableURLRequest) >>== { json in
|
||||
guard let response = PushRegistration.from(json: json) else {
|
||||
return deferMaybe(PushClientError.Local(PushClientUnknownError))
|
||||
}
|
||||
|
||||
return deferMaybe(response)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateUAID(_ apnsToken: String, withRegistration creds: PushRegistration) -> Deferred<Maybe<PushRegistration>> {
|
||||
// PUT /v1/{type}/{app_id}/registration/{uaid}
|
||||
let registerURL = endpointURL.appendingPathComponent("registration/\(creds.uaid)")!
|
||||
var mutableURLRequest = URLRequest(url: registerURL)
|
||||
|
||||
mutableURLRequest.httpMethod = HTTPMethod.put.rawValue
|
||||
mutableURLRequest.addValue("Bearer \(creds.secret)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
let parameters = ["token": apnsToken]
|
||||
mutableURLRequest.httpBody = JSON(parameters).stringValue()?.utf8EncodedData
|
||||
|
||||
return send(request: mutableURLRequest) >>== { json in
|
||||
return deferMaybe(creds)
|
||||
}
|
||||
}
|
||||
|
||||
public func unregister(_ creds: PushRegistration) -> Success {
|
||||
// DELETE /v1/{type}/{app_id}/registration/{uaid}
|
||||
let unregisterURL = endpointURL.appendingPathComponent("registration/\(creds.uaid)")
|
||||
|
||||
var mutableURLRequest = URLRequest(url: unregisterURL!)
|
||||
mutableURLRequest.httpMethod = HTTPMethod.delete.rawValue
|
||||
mutableURLRequest.addValue("Bearer \(creds.secret)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
return send(request: mutableURLRequest) >>> succeed
|
||||
}
|
||||
}
|
||||
|
||||
/// Utilities
|
||||
extension PushClient {
|
||||
fileprivate func send(request: URLRequest) -> Deferred<Maybe<JSON>> {
|
||||
log.info("\(request.httpMethod!) \(request.url?.absoluteString ?? "nil")")
|
||||
let deferred = Deferred<Maybe<JSON>>()
|
||||
alamofire.request(request)
|
||||
.validate(contentType: ["application/json"])
|
||||
.responseJSON { response in
|
||||
// Don't cancel requests just because our client is deallocated.
|
||||
withExtendedLifetime(self.alamofire) {
|
||||
let result = response.result
|
||||
if let error = result.error {
|
||||
return deferred.fill(Maybe(failure: PushClientError.Local(error)))
|
||||
}
|
||||
|
||||
guard let data = response.data else {
|
||||
return deferred.fill(Maybe(failure: PushClientError.Local(PushClientUnknownError)))
|
||||
}
|
||||
|
||||
let json = JSON(data: data)
|
||||
|
||||
if let remoteError = PushRemoteError.from(json: json) {
|
||||
return deferred.fill(Maybe(failure: PushClientError.Remote(remoteError)))
|
||||
}
|
||||
|
||||
deferred.fill(Maybe(success: json))
|
||||
}
|
||||
}
|
||||
|
||||
return deferred
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue