mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-20 07:17:42 +00:00
feat(linux): keyman:// protocol handler
This change implements the custom keyman:// protocol handler which will cause the browser to launch km-config when it encounters a URL using the keyman protocol. Related to #3271.
This commit is contained in:
parent
d83cfffe51
commit
8fbdebc9df
6 changed files with 179 additions and 10 deletions
|
|
@ -2,3 +2,6 @@
|
|||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.sharedmimeinfo]
|
||||
indent_style = tab
|
||||
|
|
@ -6,4 +6,7 @@
|
|||
<glob pattern="*.kmp"/>
|
||||
<icon name="application-x-kmp"/>
|
||||
</mime-type>
|
||||
<mime-type type="application/keyman">
|
||||
<comment>Keyman keyboard installation link</comment>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Name=Keyman Keyboards
|
|||
Name[en_GB]=Keyman Keyboards
|
||||
Comment=Configure Keyman keyboards
|
||||
Comment[en_GB]=Configure Keyman keyboards
|
||||
Exec=km-config -i %f
|
||||
Exec=km-config -i %u
|
||||
Icon=km-config
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
@ -11,4 +11,4 @@ StartupNotify=true
|
|||
Categories=Settings;
|
||||
Keywords=keyman;keyboard;input;
|
||||
X-Desktop-File-Install-Version=0.21
|
||||
MimeType=application/x-kmp;x-scheme-handler/x-kmp
|
||||
MimeType=application/x-kmp;x-scheme-handler/x-kmp;application/keyman;x-scheme-handler/keyman
|
||||
|
|
|
|||
63
linux/keyman-config/keyman_config/handle_install.py
Normal file
63
linux/keyman-config/keyman_config/handle_install.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
from keyman_config import KeymanComUrl, __tier__
|
||||
from keyman_config.install_window import InstallKmpWindow
|
||||
from keyman_config.get_kmp import get_download_folder, download_kmp_file
|
||||
|
||||
|
||||
def download_and_install_package(url):
|
||||
"""
|
||||
Handle the download and installation of the given package. This can either be a .kmp
|
||||
file that got downloaded previously, or a keyman:// URL which will be downloaded and
|
||||
installed.
|
||||
|
||||
Args:
|
||||
url: a .kmp file, a keyman:// URL, or a file:// URL pointing to a .kmp file,
|
||||
possibly with a bcp47=<language> specified
|
||||
"""
|
||||
parsedUrl = urlparse(url)
|
||||
bcp47 = _extract_bcp47(parsedUrl.query)
|
||||
|
||||
if parsedUrl.scheme == 'keyman':
|
||||
logging.info("downloading " + url)
|
||||
if not url.startswith('keyman://download/keyboard/'):
|
||||
logging.error("Don't know what to do with URL " + url)
|
||||
return
|
||||
|
||||
packageId = parsedUrl.path[len('/keyboard/'):]
|
||||
if not packageId:
|
||||
logging.error("Missing package id")
|
||||
return
|
||||
|
||||
downloadFile = os.path.join(get_download_folder(), packageId)
|
||||
downloadUrl = KeymanComUrl + '/go/package/download/' + packageId + '?platform=linux&tier=' + __tier__
|
||||
packageFile = download_kmp_file(downloadUrl, downloadFile)
|
||||
elif parsedUrl.scheme == '' or parsedUrl.scheme == 'file':
|
||||
packageFile = parsedUrl.path
|
||||
else:
|
||||
logging.error("Invalid URL: " + url)
|
||||
return
|
||||
|
||||
if not _install_package(packageFile, bcp47):
|
||||
logging.error("Can't find file " + url)
|
||||
|
||||
|
||||
def _extract_bcp47(query):
|
||||
if query:
|
||||
queryStrings = parse_qs(query)
|
||||
values = queryStrings['bcp47']
|
||||
if len(values) > 0:
|
||||
return values[0]
|
||||
return ''
|
||||
|
||||
|
||||
def _install_package(packageFile, bcp47):
|
||||
if not os.path.isfile(packageFile):
|
||||
return False
|
||||
|
||||
w = InstallKmpWindow(packageFile, language=bcp47)
|
||||
w.run()
|
||||
w.destroy()
|
||||
return True
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from keyman_config import __version__
|
||||
from keyman_config.handle_install import download_and_install_package
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
@ -23,13 +23,7 @@ if __name__ == '__main__':
|
|||
logging.basicConfig(format='%(levelname)s:%(message)s')
|
||||
|
||||
if args.install:
|
||||
if os.path.isfile(args.install):
|
||||
from keyman_config.install_window import InstallKmpWindow
|
||||
w = InstallKmpWindow(args.install)
|
||||
w.run()
|
||||
w.destroy()
|
||||
else:
|
||||
logging.error("Can't find file " + args.install)
|
||||
download_and_install_package(args.install)
|
||||
else:
|
||||
from keyman_config.view_installed import ViewInstalledWindow
|
||||
w = ViewInstalledWindow()
|
||||
|
|
|
|||
106
linux/keyman-config/tests/test_handle_install.py
Normal file
106
linux/keyman-config/tests/test_handle_install.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/python3
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from keyman_config import KeymanComUrl
|
||||
from keyman_config.handle_install import download_and_install_package
|
||||
|
||||
|
||||
class HandleInstallTests(unittest.TestCase):
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
def test_downloadAndInstallPackage_file(self, installPackageMethod):
|
||||
# Execute
|
||||
download_and_install_package('/tmp/keyboard/sil_euro_latin.kmp')
|
||||
|
||||
# Verify
|
||||
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '')
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
def test_downloadAndInstallPackage_fileUrl(self, installPackageMethod):
|
||||
# Execute
|
||||
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp')
|
||||
|
||||
# Verify
|
||||
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '')
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
def test_downloadAndInstallPackage_fileUrlWithBcp47(self, installPackageMethod):
|
||||
# Execute
|
||||
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo')
|
||||
|
||||
# Verify
|
||||
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo')
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
def test_downloadAndInstallPackage_fileUrlWithBcp47AndVersion(self, installPackageMethod):
|
||||
# Execute
|
||||
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo&version=1')
|
||||
|
||||
# Verify
|
||||
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo')
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
def test_downloadAndInstallPackage_InvalidUrl(self, installPackageMethod):
|
||||
# Execute
|
||||
download_and_install_package('http://localhost/keyboard/sil_euro_latin.kmp')
|
||||
|
||||
# Verify
|
||||
installPackageMethod.assert_not_called()
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
@patch('keyman_config.get_kmp.download_kmp_file')
|
||||
def test_downloadAndInstallPackage_invalidUrl(self, downloadKmpFileMethod,
|
||||
installPackageMethod):
|
||||
for url in ['foo://download/keyboard/sil_euro_latin', 'keyman://keyboard/sil_euro_latin',
|
||||
'keyman://download/sil_euro_latin', 'keyman://download/keyboard/']:
|
||||
with self.subTest(url=url):
|
||||
# Execute
|
||||
download_and_install_package(url)
|
||||
|
||||
# Verify
|
||||
downloadKmpFileMethod.assert_not_called()
|
||||
installPackageMethod.assert_not_called()
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
@patch('keyman_config.get_kmp.keyman_cache_dir')
|
||||
@patch('keyman_config.handle_install.download_kmp_file')
|
||||
def test_downloadAndInstallPackage_keymanUrl(self, downloadKmpFileMethod,
|
||||
keymanCacheDirMethod, installPackageMethod):
|
||||
# Setup
|
||||
mockPackagePath = '/tmp/sil_euro_latin'
|
||||
keymanCacheDirMethod.return_value = '/tmp'
|
||||
downloadKmpFileMethod.return_value = mockPackagePath
|
||||
|
||||
# Execute
|
||||
download_and_install_package('keyman://download/keyboard/sil_euro_latin')
|
||||
|
||||
# Verify
|
||||
downloadKmpFileMethod.assert_called_with(
|
||||
KeymanComUrl + '/go/package/download/sil_euro_latin?platform=linux&tier=alpha',
|
||||
mockPackagePath)
|
||||
installPackageMethod.assert_called_with(mockPackagePath, '')
|
||||
|
||||
@patch('keyman_config.handle_install._install_package')
|
||||
@patch('keyman_config.get_kmp.keyman_cache_dir')
|
||||
@patch('keyman_config.handle_install.download_kmp_file')
|
||||
def test_downloadAndInstallPackage_keymanUrlWithBcp47(self, downloadKmpFileMethod,
|
||||
keymanCacheDirMethod,
|
||||
installPackageMethod):
|
||||
# Setup
|
||||
mockPackagePath = '/tmp/sil_euro_latin'
|
||||
keymanCacheDirMethod.return_value = '/tmp'
|
||||
downloadKmpFileMethod.return_value = mockPackagePath
|
||||
|
||||
# Execute
|
||||
download_and_install_package('keyman://download/keyboard/sil_euro_latin?bcp47=de')
|
||||
|
||||
# Verify
|
||||
downloadKmpFileMethod.assert_called_with(
|
||||
KeymanComUrl + '/go/package/download/sil_euro_latin?platform=linux&tier=alpha',
|
||||
mockPackagePath)
|
||||
installPackageMethod.assert_called_with(mockPackagePath, 'de')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
Add table
Reference in a new issue