Dactyloidae/mobile/ios/Client/Frontend/Browser/SearchSuggestClient.swift
2026-06-26 21:04:09 -07:00

78 lines
3.1 KiB
Swift

/* 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 Alamofire
import Foundation
import Shared
let SearchSuggestClientErrorDomain = "org.mozilla.firefox.SearchSuggestClient"
let SearchSuggestClientErrorInvalidEngine = 0
let SearchSuggestClientErrorInvalidResponse = 1
/*
* Clients of SearchSuggestionClient should retain the object during the
* lifetime of the search suggestion query, as requests are canceled during destruction.
*
* Query callbacks that must run even if they are cancelled should wrap their contents in `withExtendendLifetime`.
*/
class SearchSuggestClient {
fileprivate let searchEngine: OpenSearchEngine
fileprivate weak var request: Request?
fileprivate let userAgent: String
lazy fileprivate var alamofire: SessionManager = {
let configuration = URLSessionConfiguration.ephemeral
var defaultHeaders = SessionManager.default.session.configuration.httpAdditionalHeaders ?? [:]
defaultHeaders["User-Agent"] = self.userAgent
configuration.httpAdditionalHeaders = defaultHeaders
return SessionManager(configuration: configuration)
}()
init(searchEngine: OpenSearchEngine, userAgent: String) {
self.searchEngine = searchEngine
self.userAgent = userAgent
}
func query(_ query: String, callback: @escaping (_ response: [String]?, _ error: NSError?) -> Void) {
let url = searchEngine.suggestURLForQuery(query)
if url == nil {
let error = NSError(domain: SearchSuggestClientErrorDomain, code: SearchSuggestClientErrorInvalidEngine, userInfo: nil)
callback(nil, error)
return
}
request = alamofire.request(url!)
.validate(statusCode: 200..<300)
.responseJSON { response in
if let error = response.result.error {
callback(nil, error as NSError?)
return
}
// The response will be of the following format:
// ["foobar",["foobar","foobar2000 mac","foobar skins",...]]
// That is, an array of at least two elements: the search term and an array of suggestions.
let array = response.result.value as? NSArray
if array?.count ?? 0 < 2 {
let error = NSError(domain: SearchSuggestClientErrorDomain, code: SearchSuggestClientErrorInvalidResponse, userInfo: nil)
callback(nil, error)
return
}
let suggestions = array?[1] as? [String]
if suggestions == nil {
let error = NSError(domain: SearchSuggestClientErrorDomain, code: SearchSuggestClientErrorInvalidResponse, userInfo: nil)
callback(nil, error)
return
}
callback(suggestions!, nil)
}
}
func cancelPendingRequest() {
request?.cancel()
}
}