From db89286ec3fa19156b7a85628e93469ef1616546 Mon Sep 17 00:00:00 2001 From: Calin Culianu Date: Thu, 29 Nov 2018 00:09:06 +0200 Subject: [PATCH] [macOS] Added QR scanner facility using platform-native helper app. --- .gitmodules | 3 +++ contrib/CalinsQRReader | 1 + contrib/build-osx/base.sh | 2 +- contrib/build-osx/make_osx | 9 +++++++++ contrib/build-osx/osx.spec | 3 +++ electrum/qrscanner.py | 25 ++++++++++++++++++++++++- 6 files changed, 41 insertions(+), 2 deletions(-) create mode 160000 contrib/CalinsQRReader diff --git a/.gitmodules b/.gitmodules index 5a0f914f1..34cfeafbd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "contrib/deterministic-build/electrum-locale"] path = contrib/deterministic-build/electrum-locale url = https://github.com/spesmilo/electrum-locale +[submodule "contrib/CalinsQRReader"] + path = contrib/CalinsQRReader + url = https://github.com/spesmilo/CalinsQRReader diff --git a/contrib/CalinsQRReader b/contrib/CalinsQRReader new file mode 160000 index 000000000..20189155a --- /dev/null +++ b/contrib/CalinsQRReader @@ -0,0 +1 @@ +Subproject commit 20189155a461cf7fbad14357e58fbc8e7c964608 diff --git a/contrib/build-osx/base.sh b/contrib/build-osx/base.sh index e7454f7a8..2c22ca9cf 100644 --- a/contrib/build-osx/base.sh +++ b/contrib/build-osx/base.sh @@ -21,7 +21,7 @@ function DoCodeSignMaybe { # ARGS: infoName fileOrDirName codesignIdentity identity="$3" deep="" if [ -z "$identity" ]; then - # we are ok with them not passing anything -- master script calls us always even if no identity is specified + # we are ok with them not passing anything; master script calls us unconditionally even if no identity is specified return fi if [ -d "$file" ]; then diff --git a/contrib/build-osx/make_osx b/contrib/build-osx/make_osx index ecccbef38..ff836fd62 100755 --- a/contrib/build-osx/make_osx +++ b/contrib/build-osx/make_osx @@ -16,6 +16,7 @@ export PYTHONHASHSEED=22 VERSION=`git describe --tags --dirty --always` which brew > /dev/null 2>&1 || fail "Please install brew from https://brew.sh/ to continue" +which xcodebuild > /dev/null 2>&1 || fail "Please install Xcode and xcode command line tools to continue" # Code Signing: See https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html APP_SIGN="" @@ -87,6 +88,14 @@ popd cp $BUILDDIR/secp256k1/.libs/libsecp256k1.0.dylib contrib/build-osx DoCodeSignMaybe "libsecp256k1" "contrib/build-osx/libsecp256k1.0.dylib" "$APP_SIGN" # If APP_SIGN is empty will be a noop +info "Building CalinsQRReader..." +d=contrib/CalinsQRReader +pushd $d +rm -fr build +xcodebuild || fail "Could not build CalinsQRReader" +popd +DoCodeSignMaybe "CalinsQRReader.app" "${d}/build/Release/CalinsQRReader.app" "$APP_SIGN" # If APP_SIGN is empty will be a noop + info "Installing requirements..." python3 -m pip install -Ir ./contrib/deterministic-build/requirements.txt --user && \ diff --git a/contrib/build-osx/osx.spec b/contrib/build-osx/osx.spec index 501df88ec..e48ba97cf 100644 --- a/contrib/build-osx/osx.spec +++ b/contrib/build-osx/osx.spec @@ -41,6 +41,9 @@ datas += collect_data_files('btchip') datas += collect_data_files('keepkeylib') datas += collect_data_files('ckcc') +# Add the QR Scanner helper app +datas += [(electrum + "contrib/CalinsQRReader/build/Release/CalinsQRReader.app", "./contrib/CalinsQRReader/build/Release/CalinsQRReader.app")] + # Add libusb so Trezor and Safe-T mini will work binaries = [(electrum + "contrib/build-osx/libusb-1.0.dylib", ".")] binaries += [(electrum + "contrib/build-osx/libsecp256k1.0.dylib", ".")] diff --git a/electrum/qrscanner.py b/electrum/qrscanner.py index 463d5ec6f..5d15aad9a 100644 --- a/electrum/qrscanner.py +++ b/electrum/qrscanner.py @@ -40,7 +40,7 @@ except BaseException: libzbar = None -def scan_barcode(device='', timeout=-1, display=True, threaded=False, try_again=True): +def scan_barcode_ctypes(device='', timeout=-1, display=True, threaded=False, try_again=True): if libzbar is None: raise RuntimeError("Cannot start QR scanner; zbar not available.") libzbar.zbar_symbol_get_data.restype = ctypes.c_char_p @@ -69,6 +69,29 @@ def scan_barcode(device='', timeout=-1, display=True, threaded=False, try_again= data = libzbar.zbar_symbol_get_data(symbol) return data.decode('utf8') +def scan_barcode_osx(*args_ignored, **kwargs_ignored): + import subprocess + # NOTE: This code needs to be modified if the positions of this file changes with respect to the helper app! + # This assumes the built macOS .app bundle which ends up putting the helper app in + # .app/contrib/CalinsQRReader/build/Release/CalinsQRReader.app. + root_ec_dir = os.path.abspath(os.path.dirname(__file__) + "/../") + prog = root_ec_dir + "/" + "contrib/CalinsQRReader/build/Release/CalinsQRReader.app/Contents/MacOS/CalinsQRReader" + if not os.path.exists(prog): + raise RuntimeError("Cannot start QR scanner; helper app not found.") + data = '' + try: + # This will run the "CalinsQRReader" helper app (which also gets bundled with the built .app) + # Just like the zbar implementation -- the main app will hang until the QR window returns a QR code + # (or is closed). Communication with the subprocess is done via stdout. + # See contrib/CalinsQRReader for the helper app source code. + with subprocess.Popen([prog], stdout=subprocess.PIPE) as p: + data = p.stdout.read().decode('utf-8').strip() + return data + except OSError as e: + raise RuntimeError("Cannot start camera helper app; {}".format(e.strerror)) + +scan_barcode = scan_barcode_osx if sys.platform == 'darwin' else scan_barcode_ctypes + def _find_system_cameras(): device_root = "/sys/class/video4linux" devices = {} # Name -> device