1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/components/searchengine/SearchEngineWriter.kt

85 lines
3.5 KiB
Kotlin
Raw Normal View History

Adds custom search engines (#6551) * For #5577 - Adds button to add a new search engine * For #5577 - Adds custom engine store * For #5577 - Creates a custom SearchEngineProvider * For #5577 - Gives the ability to delete search engines * For #5577 - Adds the UI to add a custom search engine * For #5577 - Adds form to create a custom search engine * For #5577 - Adds the ability to add a custom search engine * For #5577 - Adds the ability to delete custom search engines * For #5577 - Selects the first element on the add custom search engine screen * For #5577 - Prevents adding a search engine that already exists * For #5577 - Styles the add search engine preference * For #5577 - Makes the name check case-insensitive * For #5577 - Fix bug where home screen doesnt see new search engines * For #5577 - Moves Search URL validation to its own type * For #5577 - Fixes linting errors * For #5577 - Adds the ability to edit a custom search engine * For #5577 - Allows the user to edit a serach engine even when it is the last item in the list * For #5577 - Adds an undo snackbar when deleting a search engine * For #5577 - Moves all of the strings to be translated * For #5577 - Fixes bug when deleting your default search engine * For #5577 - Puts adding search engines behind a feature flag * For #5577 - Navigate to custom search engine SUMO article when tapping learn more * For #5577 - Fixes nits * For #5577 - Uses concept-fetch to validate search string * For #5577 - Adds string resources for the cannot reach error state
2019-11-20 01:30:56 +01:00
/* 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/. */
package org.mozilla.fenix.components.searchengine
import android.graphics.Bitmap
import android.util.Log
import org.w3c.dom.Document
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.parsers.ParserConfigurationException
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerConfigurationException
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import android.util.Base64
import java.io.ByteArrayOutputStream
private const val BITMAP_COMPRESS_QUALITY = 100
private fun Bitmap.toBase64(): String {
val stream = ByteArrayOutputStream()
compress(Bitmap.CompressFormat.PNG, BITMAP_COMPRESS_QUALITY, stream)
val encodedImage = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT)
return "data:image/png;base64,$encodedImage"
}
class SearchEngineWriter {
companion object {
private const val LOG_TAG = "SearchEngineWriter"
fun buildSearchEngineXML(engineName: String, searchQuery: String, iconBitmap: Bitmap): String? {
try {
val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()
val rootElement = document!!.createElement("OpenSearchDescription")
rootElement.setAttribute("xmlns", "http://a9.com/-/spec/opensearch/1.1/")
document.appendChild(rootElement)
val shortNameElement = document.createElement("ShortName")
shortNameElement.textContent = engineName
rootElement.appendChild(shortNameElement)
val imageElement = document.createElement("Image")
imageElement.setAttribute("width", "16")
imageElement.setAttribute("height", "16")
imageElement.textContent = iconBitmap.toBase64()
rootElement.appendChild(imageElement)
val descriptionElement = document.createElement("Description")
descriptionElement.textContent = engineName
rootElement.appendChild(descriptionElement)
val urlElement = document.createElement("Url")
urlElement.setAttribute("type", "text/html")
val templateSearchString = searchQuery.replace("%s", "{searchTerms}")
urlElement.setAttribute("template", templateSearchString)
rootElement.appendChild(urlElement)
return xmlToString(document)
} catch (e: ParserConfigurationException) {
Log.e(LOG_TAG, "Couldn't create new Document for building search engine XML", e)
return null
}
}
private fun xmlToString(doc: Document): String? {
val writer = StringWriter()
try {
val tf = TransformerFactory.newInstance().newTransformer()
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8")
tf.transform(DOMSource(doc), StreamResult(writer))
} catch (e: TransformerConfigurationException) {
return null
} catch (e: TransformerException) {
return null
}
return writer.toString()
}
}
}