Skip to content

Commit f0f76cc

Browse files
huhuanmingclaudehappy-otter
authored
feat: migrate legacy native modules to Nitro Modules (#22)
* feat: add react-native-native-logger module Unified native logging module with static OneKeyLog API that self-initializes on first call, replacing react-native-file-logger's JS-configured approach. - iOS: CocoaLumberjack backend with custom log file naming (app- prefix) and message-only formatter - Android: SLF4J + logback-android backend - Nitro HybridObject bridge for JS layer (write, getLogFilePaths, deleteLogFiles) - Consistent log file naming across platforms (app- prefix + date) - Same log config as existing: 20MB max, 3 files, daily rolling, {CachesDir}/logs Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: code review fixes for native-logger module - Remove unnecessary CocoaLumberjack import from iOS NativeLogger.swift - Add else branch in Android NativeLogger.kt write() for unknown levels - Use detachAndStopAllAppenders() in Android OneKeyLog to prevent duplicate logcat - Unify iOS logsDirectory path to use computed property (remove duplication) - Add sortedBy to Android getLogFilePaths() for consistent ordering with iOS Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: integrate OneKeyLog into native modules Add file-based logging via OneKeyLog to 5 native modules: - device-utils: UI style changes, foldable detection, spanning state - keychain-module: keychain operations success/failure with OSStatus - cloud-kit-module: CloudKit CRUD operations and query results - check-biometric-auth-changed: biometric state change detection - get-random-values: error-only logging for SecRandomCopyBytes/SecureRandom Each module declares a dependency on ReactNativeNativeLogger (iOS podspec) and compileOnly project dependency (Android build.gradle where applicable). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add NativeLogger test page to example app Add test page with log directory viewer, write operations (custom message, all levels, batch), and file management (refresh, delete). Registers the native-logger module in the example app route and package.json. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * chore: bump version to 1.1.20 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * chore: add native-logger as default dependency in module template New modules created via create-nitro-module.js will now include OneKeyLog dependency out of the box (podspec, build.gradle, imports). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: address code review issues for native-logger module - Replace force unwrap with safe unwrap in iOS logsDirectory - Use detachAppender instead of detachAndStopAllAppenders on Android - Handle applicationContext null gracefully in Android OneKeyLog - Log failures in getLogFilePaths and deleteLogFiles (iOS + Android) - Redact keychain key names in log output for security - Replace setTimeout with await in test page Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: remove key names from keychain logs and improve comments - Remove all key name references from Keychain log messages for security - Add detailed comment explaining maximumNumberOfLogFiles off-by-one Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: security hardening for native-logger module HIGH: - H-2: Replace unsafe /tmp/logs fallback with no-op when context is null - H-3: Apply iOS file protection (completeUntilFirstUserAuthentication) - H-1: Add 4KB message truncation to prevent disk abuse MEDIUM: - M-1: Attach file appender to named "OneKey" logger instead of ROOT to prevent capturing third-party SLF4J output - M-2: Change compileOnly to implementation to prevent NoClassDefFoundError - M-3: Truncation also mitigates log injection via oversized messages - M-5: Fix TOCTOU race in iOS log archive with retry loop Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: final review fixes for native-logger - P1: deleteLogFiles skips active app-latest.log to avoid breaking logger's open file handle (iOS + Android) - P2: Android logger uses retry-able cached getter instead of by-lazy, so if applicationContext is null at first access, logging can recover once context becomes available - P3: Log warning if iOS archive TOCTOU retry loop exhausts 1000 attempts - P4: Remove unused OneKeyLog imports from module template - P5: Use NSString.appendingPathComponent for iOS path construction Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix. missing log dir * fix: audit fixes across integrated native modules - P1: Replace force unwrap with guard let in ReactNativeGetRandomValues (iOS) - P2: Remove duplicate error logging in KeychainModule wrapper (Core already logs) - P2: Change biometric auth change log level from warn to info - P2: Add @volatile to windowLayoutInfo for thread-safe reads from Promise.async - P2: Use error.localizedDescription in CloudKit logs for consistency - P3: Remove unnecessary UserDefaults.synchronize() call Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add timestamp format for native log writes and copy button for log dir - Native-side log writes now use `HH:mm:ss | LEVEL : [tag] message` format - JS-side log writes remain unformatted (raw message preserved) - Add copy-to-clipboard button for log directory path in test page - Integrate native-logger into example app and update pod dependencies Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add startup log in native layer for iOS and Android - iOS: call OneKeyLog via ObjC bridge (OneKeyLogBridge) to avoid Clang module build failure with NitroModules C++ headers - Android: call OneKeyLog.info directly in MainApplication.onCreate - Both log "Application started" with native timestamp format Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use correct autolinked Gradle project name for native-logger React Native autolinking generates project names from scoped npm package names by replacing `@`/`/` with `_`, so `@onekeyfe/react-native-native-logger` becomes `:onekeyfe_react-native-native-logger`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: auto-init OneKeyLog via ContentProvider before Application.onCreate ContentProvider.onCreate() runs between attachBaseContext() and Application.onCreate(), so the logger is ready for the earliest app-level startup logs. Consuming apps no longer need to call OneKeyLog.init() manually. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add native modules migrated from legacy bridge architecture Add 5 new Nitro modules and extend device-utils for migrating all legacy RCTBridgeModule/ReactContextBaseJavaModule code to New Architecture: - react-native-bundle-update: JS bundle OTA update with SHA256 verification, ZIP extraction, PGP signature validation, and download progress events - react-native-app-update: Android APK download/install with notification progress (iOS stub) - react-native-perf-memory: Memory usage reporting (RSS) for iOS and Android - react-native-splash-screen: Legacy splash screen for Android < 12 (iOS stub) - react-native-webview-checker: Android WebView package info and Google Play Services availability check (iOS stub) - react-native-device-utils: Extended with LaunchOptions, ExitApp, and startup time tracking All modules use OneKeyLog for logging and follow the Nitro callback listener pattern for events (replacing NativeEventEmitter). * feat: add example test pages for new native modules Add test pages for BundleUpdate, AppUpdate, PerfMemory, SplashScreen, and WebViewChecker modules. Also add LaunchOptions and ExitApp tests to the existing DeviceUtils test page. * fix: critical security and reliability fixes for bundle-update and app-update - Use custom urlSession instead of URLSession.shared to prevent HTTPS bypass via HTTP redirects (iOS bundle-update) - Add HTTPS redirect detection after download completes (iOS bundle-update) - Enforce TLS 1.2 minimum on URLSession configuration (iOS bundle-update) - Use defer to guarantee isDownloading reset on all error paths (iOS bundle-update) - Wrap downloadAPK in try/finally to guarantee isDownloading reset (Android app-update) - Make verifyASC throw instead of silently succeeding without GPG verification (Android app-update) - Fix response.body!! force-unwrap crash in downloadASC (Android app-update) - Add readTimeout to OkHttpClient to prevent indefinite hangs (Android app-update) - Make testVerification return false instead of true when GPG is unimplemented (both platforms) - Remove dead downloadThread field and unused MessageDigest import (Android app-update) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: implement GPG signature verification for bundle-update and app-update Port GPG verification from app-monorepo desktop implementation to native modules: - iOS bundle-update: Gopenpgp framework integration via dynamic ObjC calls with graceful fallback - Android bundle-update: BouncyCastle bcpg for PGP cleartext signature verification - Android app-update: Full verifyASC implementation with SHA256 hash comparison - Embed OneKey developer GPG public key for signature validation - Add real test signatures from app-monorepo for testVerification() Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: high severity issues across native modules - native-logger: replace thread-unsafe SimpleDateFormat with DateTimeFormatter (Android), add NSLock around DateFormatter calls (iOS) - native-logger: add android.util.Log fallback when file logger is unavailable (Android) - bundle-update: add DispatchQueue for thread-safe access to listeners/isDownloading (iOS) - app-update: validate file paths against app directories to prevent path traversal (Android) - webview-checker: use WebView.getCurrentWebViewPackage() API 26+ with fallback candidates (Android) - device-utils: replace exit(0) with UIApplication suspend to avoid App Store rejection (iOS) - bundle-update: add symlink detection after zip extraction (Android) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: medium severity issues across native modules - Fix Base64 encoding inconsistency between iOS/Android in get-random-values - Fix UTF-8 truncation at buffer boundaries in bundle-update readFileContent - Fix dead downloadTask property in iOS bundle-update, use session invalidation - Fix non-atomic write in bundle-update writeFallbackUpdateBundleDataFile - Fix clearCache not actually clearing cached files in app-update - Downgrade CloudKit recordID logging from info to debug level - Add ProGuard consumer rules for logback-android in native-logger - Flush log buffers before getLogFilePaths on both platforms Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: vendor Gopenpgp xcframework into bundle-update module Integrate Gopenpgp v3.3.0 xcframework directly into app-modules so app-monorepo no longer needs to separately import the GPG framework. Replace dynamic ObjC runtime calls (NSClassFromString/NSSelectorFromString) with direct typed Gopenpgp API imports for type safety and clarity. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: migrate lite-card logging to NativeLogger and remove sensitive data from logs Replace all android.util.Log and NSLog calls in react-native-lite-card with OneKeyLog (NativeLogger) for unified file-based logging. Remove plaintext PIN logging, cardInfo dumps, certificate serial numbers, and APDU response data from log output. Add native-logger as dependency on both Android (build.gradle) and iOS (podspec). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: migrate background-thread logging to NativeLogger Replace NSLog with OneKeyLog in BackgroundRunnerReactNativeDelegate. This was the last remaining module using direct system logging. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: replace @import with dynamic dispatch for NativeLogger in background-thread .mm files @import ReactNativeNativeLogger fails in Objective-C++ (.mm) files because C++ modules (-fcxx-modules) are not enabled. Introduce BTLogger as an internal wrapper that dynamically dispatches to OneKeyLog via ObjC runtime, and add a startup log in BackgroundThreadManager to verify the logging path works. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: pod install to sync new headers and dependencies Re-ran pod install to pick up LaunchOptions.hpp for ReactNativeDeviceUtils and sync ReactNativePerfMemory + ReactNativeNativeLogger dependency changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace @import with dynamic dispatch for NativeLogger in lite-card module Same issue as BackgroundThread — @import ReactNativeNativeLogger fails because the module's umbrella header includes C++ headers, making the entire module unbuildable without -fcxx-modules. Introduce LCLogger as a dynamic dispatch wrapper and replace all direct OneKeyLog calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add missing deepLink parameter to LaunchOptions initializer The nitrogen-generated LaunchOptions struct now requires a deepLink field. Update all call sites to pass deepLink (nil for non-URL launches, extracted from LaunchOptionsKey.url otherwise). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: yarn install to link new workspace packages Re-ran yarn install to generate node_modules symlinks for react-native-bundle-update and react-native-app-update. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add initialization log in parent TurboModule entry points Log via BTLogger/LCLogger in getTurboModule: of BackgroundThread and ReactNativeLiteCard to verify dynamic dispatch to OneKeyLog works as soon as the module is loaded by JS. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use module-qualified class name and typed IMP for OneKeyLog dispatch NSClassFromString(@"OneKeyLog") returns nil because Swift classes need the module-qualified name (ReactNativeNativeLogger.OneKeyLog). Also switch from performSelector to methodForSelector with typed function pointer, matching the working pattern in OneKeyLogBridge. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: pod install to add app-update, bundle-update and related pods Re-ran pod install to register ReactNativeAppUpdate, ReactNativeBundleUpdate and their dependencies (Gopenpgp, ReactNativeSplashScreen, ReactNativeWebViewChecker) in the Xcode project. Pods count 91 → 96. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add override keyword to ReactNativeBundleUpdate init HybridReactNativeBundleUpdateSpec (Nitro base class) already defines init(), so the subclass must use override init() + super.init(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fix compilation errors in ReactNativeBundleUpdate - Add missing `import SSZipArchive` - Convert Gopenpgp ObjC error-pointer APIs to Swift throwing syntax: builderWithKey.new() and verifyCleartext/signatureError now use try - Add override/super.init() was already fixed in previous commit Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fix remaining BundleUpdate compilation errors - Use `any CryptoPGPVerifyProtocol` for verify handle type (Swift existential protocol) - SSZipArchive.unzipFile is a throwing method, use do/try/catch instead of guard Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: security hardening across native modules - Restrict skipGPGVerification to debug builds only (bundle-update) - Remove plain JSON fallback in GPG signature verification - Require bundle verification before activation via setCurrentUpdateBundleData - Restrict getSha256FromFilePath to bundle directories only - Enforce HTTPS for all download URLs (app-update) - Verify APK signing certificate matches installed app - Require verifyAPK before installAPK - Fix buildFile path validation when context is null (app-update) - Add decompression bomb protection (512MB limit) for zip extraction - Sanitize version strings before use in file paths - Add constant-time hash comparison (secureCompare) - Fix isDownloading flag reset with try/finally (Android bundle-update) - Add HTTPS redirect validator for all redirect hops (iOS bundle-update) - Gate NFC/APDU debug logging behind FLAG_DEBUGGABLE (lite-card) - Add sensitive data redaction for JS log writes (native-logger) - Return filenames instead of absolute paths from getLogFilePaths - Add log injection protection (newline stripping) in OneKeyLog - Change keychain iCloud sync default to false - Add upper bound validation for getRandomBase64 (64KB) - Remove sensitive data from error messages (app-update) - Fix file:/// prefix stripping to use removePrefix - Fix clearBundle data race on isDownloading (iOS) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: comprehensive security hardening across all native modules (round 2) - bundle-update: disable insecure verifyBundle path, add decompression bomb protection, unconditional downgrade protection - app-update: TOCTOU protection with hash verification, modern APK signature API, disable redirects, ASC size limit - native-logger: expanded sensitive data patterns (WIF, xprv, Bearer), rate limiting, tag sanitization - lite-card: redact APDU data from logs, clear PINs after use, semaphore timeouts, PIN validation, memory cleanup - background-thread: deny cross-sandbox routing by default, add error logging in catch blocks - keychain: atomic add-or-update instead of delete-then-add race condition - cloud-kit: input validation for record IDs/types, query results limit - biometric: migrate domain state from UserDefaults to Keychain Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: security hardening round 3 - metadata validation, downgrade protection, hash validation - bundle-update(Android): parseMetadataJson now throws on parse failure instead of returning empty map that could bypass file validation - bundle-update(Android+iOS): version downgrade check rejects non-numeric version when current is numeric, preventing bypass via malformed version strings - app-update(Android): SHA256 hash from ASC file validated as 64-char lowercase hex, not just length check - lite-card(Android): mCardConnection marked @volatile for cross-thread visibility Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * Update KeychainModuleCore.swift * feat: replace debug-mode GPG skip with MMKV DevSettings toggle Replace the previous `isDebuggable()` / `#if DEBUG` guard with a runtime check of two MMKV keys read from the host app's "onekey-app-setting" store: - onekey_developer_mode_enabled (DevSettings master switch) - onekey_bundle_skip_gpg_verification (skip-GPG sub-toggle) GPG / SHA-256 verification is now skipped only when **both** keys are true, making it possible to test the skip path on release builds in a controlled way without shipping a permanently open backdoor. Changes: - BundleUpdate iOS/Android: add isDevSettingsEnabled / isSkipGPGEnabled helpers; apply to verifyBundleASC, verifyExtractedBundle, setCurrentUpdateBundleData, and startup SHA256 check - AppUpdate Android: add isDevSettingsEnabled; apply to verifyASC - Remove skipGPGVerification field from BundleVerifyASCParams / BundleInstallParams (callers no longer need to pass it) - Add MMKV compileOnly dependency to Android build.gradle files - Add MMKV pod dependency to ReactNativeBundleUpdate.podspec - Example app: add DevSettings Skip-GPG test panel with live toggles and "Verify All Local Bundles" button; add react-native-mmkv dep Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add saveDeviceToken to DeviceUtils and make exitApp a no-op on iOS - Add saveDeviceToken(token) API (iOS + Android) that persists the push-notification device token to UserDefaults / SharedPreferences under key "1k_device_token" - Update getDeviceTokenString (iOS) to prefer the JS-saved token over the raw APNs Data token set by AppDelegate, with graceful fallback - Make exitApp() a no-op on iOS: Apple prohibits programmatic termination (App Store guideline 2.4.5); removes the suspend selector Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: add logging for invalid byteLength in GetRandomValues Log a warning via OneKeyLog before throwing the error when an out-of-range byteLength is passed to getRandomBase64 on both iOS and Android, making it easier to diagnose bad callers. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: implement Android legacy splash screen with SplashScreenBridge Port SplashScreenView, SplashViewController, SplashImageResizeMode, and SplashScreenBridge from app-monorepo Java to Kotlin for Android API < 31 compatibility. iOS implementation is intentionally a no-op since expo-splash-screen handles it via the launch storyboard. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: merge react-native-webview-checker into react-native-device-utils Add WebViewPackageInfo and GooglePlayServicesStatus types plus getCurrentWebViewPackageInfo() and isGooglePlayServicesAvailable() methods to DeviceUtils. Delete the standalone webview-checker module. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add WebView & Play Services examples to DeviceUtils test page Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * update podfile * chore: update Podfile.lock to v1.1.21, remove ReactNativeWebviewChecker Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix iOS build errors in BundleUpdate (MMKV and SSZipArchive API) - Rename initializeMMKV(nil) to initialize(rootDir: nil) for latest MMKV - Fix SSZipArchive.payloadSize call to include error parameter Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: remove SSZipArchive payloadSize call that fails to compile The payloadSizeForArchiveAtPath:error: method is not visible to Swift in SSZipArchive 2.4.3. The zip file size check on disk already provides decompression bomb protection. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: pass archived path to super.didArchiveLogFile to prevent crash After moving the log file to its archived name, the super call must receive the new path. Passing the original (now nonexistent) path caused an unhandled ObjC exception in DDLogFileManagerDefault. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add download bundle test with platform-specific default URLs iOS default: uni-test.onekey-asset.com 5016000 bundle Android default: uni.onekey-asset.com 5019002 bundle Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: redesign BundleUpdateTestPage with step-by-step pipeline UI Replace flat button layout with a modern dark-themed pipeline: - 3 sequential steps: Download → Verify → Install - Animated progress bar (percentage on Android, indeterminate on iOS) - Step indicators with status colors (pending/active/completed/error) - Dev settings and utilities in collapsible sections Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix missing funcs * fix: move PGP signature to verifyBundleASC step in BundleUpdateTestPage Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add comprehensive logging to AppUpdate and BundleUpdate native modules Add detailed input params and execution status logging to all functions in both modules for easier debugging. Fix verifyBundle to perform SHA256 verification instead of throwing unsupported error. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add logging to all remaining BundleUpdate functions (iOS + Android) Add OneKeyLog calls to every function that was missing logging: addDownloadListener, removeDownloadListener, clearAllJSBundleData, getWebEmbedPath, getJsBundlePath, getNativeAppVersion, isBundleExists, verifyExtractedBundle, listLocalBundles, getSha256FromFilePath, and all test* functions. Every function now logs input params and results. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix Android build errors across native modules - Change Promise<Void> to Promise<Unit> in AppUpdate and BundleUpdate to match updated Nitro codegen specs - Fix smart cast issue with signatures in verifyAPK by extracting to local vals - Add missing deepLink parameter to LaunchOptions in DeviceUtils - Replace NitroModules.applicationContext with BuildConfig.DEBUG in lite-card LogUtil (module doesn't depend on nitro-modules) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: add BuildConfig import to lite-card LogUtil Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: use host app FLAG_DEBUGGABLE instead of library BuildConfig.DEBUG Library module's BuildConfig.DEBUG won't reflect the host app's build type. Use Utils.getApp().applicationInfo.flags to check FLAG_DEBUGGABLE at runtime, which correctly detects the host app's debug state. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: redesign AppUpdateTestPage with pipeline UI matching BundleUpdateTestPage Dark theme, card layout, step-by-step pipeline (Download → Verify → Install) with animated progress bar, collapsible utilities section, and platform info. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * Update BundleUpdateTestPage.tsx * feat: improve app-update download with sandbox path fix, error logging, and APK cache verification - Fix relative path resolution: resolve to cacheDir/apks/ instead of root / - Add detailed error logging in buildFile and downloadAPK catch block - Verify existing APK via ASC SHA256 before re-downloading - Extract shared computeSha256 helper to reduce duplication - Update clearCache to clean cacheDir/apks/ directory (APK + ASC files) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: remove filePath from AppUpdate API, derive from downloadUrl filePath is now inferred internally from the download URL's last path segment instead of being passed as a parameter. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix remaining params.filePath reference in installAPK Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: fix download progress events and prevent duplicate downloads in native layer - Fix event type mismatch: JS now listens for 'downloading' instead of 'update/downloading' - Native downloadAPK throws error instead of silently returning when already downloading Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * Update AppUpdateTestPage.tsx * fix: skip packageName and certificate checks in debug builds, still log results In verifyAPK and installAPK, debug builds (FLAG_DEBUGGABLE) now run all comparisons and log match/mismatch results but skip throwing exceptions, allowing testing with different-signed APKs. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add Download ASC and Verify ASC steps to AppUpdate pipeline Pipeline now has 5 steps: Download APK → Download ASC → Verify ASC → Verify APK → Install APK. Removed redundant ASC buttons from utilities. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * refactor: unify AppUpdate event types with update/ prefix Align with BundleUpdate convention: update/start, update/downloading, update/downloaded, update/error. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: add BouncyCastle provider dependency and registration for GPG verification - Add bcprov-jdk15to18 dependency (was missing, only bcpg was included) - Register BouncyCastleProvider at class init to fix "cannot create signature: no provider" - Add try/catch logging in verifyASC to capture exceptions before they propagate - Applied to both app-update and bundle-update modules Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use BouncyCastle provider instance instead of string name to avoid Android built-in BC conflict Android ships a stripped-down "BC" provider that doesn't support SHA256withRSA. Passing our own BouncyCastleProvider() instance directly bypasses the name lookup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add FileProvider config for APK install intent - Declare FileProvider in library manifest (auto-merged into host app) - Add file_paths.xml exposing cacheDir/apks/ for FileProvider access - Add REQUEST_INSTALL_PACKAGES permission Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: move bcProvider to BundleUpdateStoreAndroid where it's used bcProvider was in ReactNativeBundleUpdate companion but used in BundleUpdateStoreAndroid.verifyGPGAndExtractSha256, causing unresolved reference error. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * feat: add download progress logging and error catch in bundle-update downloadBundle - Log progress percentage at each 1% increment during download - Add catch block to log exceptions before propagating - Deduplicate sendEvent calls by only emitting on progress change Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update BundleUpdateTestPage.tsx * feat: add download progress logging in iOS bundle-update - Log progress percentage at each 1% increment during URLSession download - Deduplicate progress callbacks by tracking previous progress value - Reset progress state on delegate reset Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add diagnostic logging for bundle download file creation - Ensure parent directory exists before FileOutputStream - Log totalBytesRead, fileExists, and fileSize after download completes - Helps diagnose ENOENT issue after download Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update BundleUpdateTestPage.tsx * Update BundleUpdateTestPage.tsx * Update BundleUpdateTestPage.tsx * fix: add detailed diagnostic logging to getJsBundlePath on Android and iOS Each validation step that can silently return null/empty now logs the specific failure reason, making it easy to diagnose why getJsBundlePath returns empty after bundle install. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update BundleUpdateTestPage.tsx * feat: migrate signature storage from SharedPreferences/UserDefaults to file Store signatures as files at <bundleDir>/asc/<version>-signature.asc instead of SharedPreferences (Android) / UserDefaults (iOS) to avoid storage size issues with multiple versions. Also adds listAscFiles API and fixes installBundle passing empty signature in example. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add logging to writeSignatureFile and readSignatureFile on both platforms Log file existence, size, and path on write; log existence and content size on read to help diagnose signature storage issues. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add filePath field to AscFileInfo in listAscFiles API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: expose BundleUpdateStore to ObjC runtime and bump to 1.1.22 Add @objcMembers and NSObject inheritance to BundleUpdateStore so AppDelegate can access it via NSClassFromString + KVC, avoiding direct Nitro module imports that cause Clang dependency scanner failures. * Update package.json * Update Podfile.lock * fix: address PR review security and robustness issues - AppUpdate: verify GPG signature before trusting ASC hash in tryVerifyExistingApk - AppUpdate: use constant-time secureCompare for SHA256 hash comparison - SplashScreen: set isAlreadyHidden only after successful hide - SplashScreen: add cancellation to searchForRootView polling loop - BiometricAuth: handle nil evaluatedPolicyDomainState explicitly - GetRandomValues: reject non-integer byteLength (iOS + Android) - AppUpdate iOS: use monotonically increasing listener IDs - Keychain: fix misleading enableSync comment to match actual default - Remove all README.md files from native-modules Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * fix: use onekey-app-dev-setting MMKV instance and require dual check for GPG skip - Change MMKV instance ID from onekey-app-setting to onekey-app-dev-setting across bundle update (Android/iOS) and app update (Android) - Add isSkipGPGEnabled() to app update module requiring both dev mode and skip-GPG toggle to bypass ASC verification (matching bundle update behavior) - Update test page MMKV instance ID * chore: bump native modules and views version to 1.1.23 * fix: address Copilot review - stack traces, import Security, FileProvider authority - Add exception stack traces to error logs in MiUtil.kt and ReactNativeGetRandomValues.kt - Add explicit `import Security` in ReactNativeGetRandomValues.swift - Use module-specific FileProvider authority `appupdate.fileprovider` to avoid conflicts Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> * chore: bump native modules and views version to 1.1.24 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Happy <yesreply@happy.engineering>
1 parent 54fd2df commit f0f76cc

211 files changed

Lines changed: 17432 additions & 452 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

example/react-native/android/app/src/main/java/com/example/MainApplication.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.facebook.react.ReactApplication
66
import com.facebook.react.ReactHost
77
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
88
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
9+
import com.margelo.nitro.nativelogger.OneKeyLog
910

1011
class MainApplication : Application(), ReactApplication {
1112

@@ -22,6 +23,7 @@ class MainApplication : Application(), ReactApplication {
2223

2324
override fun onCreate() {
2425
super.onCreate()
26+
OneKeyLog.info("App", "Application started")
2527
loadReactNative(this)
2628
}
2729
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
#import "BackgroundRunnerModule.h"
2+
#import "OneKeyLogBridge.h"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface OneKeyLogBridge : NSObject
4+
+ (void)info:(NSString *)tag message:(NSString *)message;
5+
@end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#import "OneKeyLogBridge.h"
2+
3+
// OneKeyLog is an @objc public Swift class in ReactNativeNativeLogger pod.
4+
// We use forward declaration + performSelector to avoid importing the
5+
// ReactNativeNativeLogger module (which fails due to C++ headers in NitroModules).
6+
@implementation OneKeyLogBridge
7+
8+
+ (void)info:(NSString *)tag message:(NSString *)message {
9+
Class cls = NSClassFromString(@"ReactNativeNativeLogger.OneKeyLog");
10+
if (!cls) {
11+
cls = NSClassFromString(@"OneKeyLog");
12+
}
13+
if (cls) {
14+
SEL sel = NSSelectorFromString(@"info::");
15+
if ([cls respondsToSelector:sel]) {
16+
typedef void (*InfoFunc)(id, SEL, NSString *, NSString *);
17+
InfoFunc func = (InfoFunc)[cls methodForSelector:sel];
18+
func(cls, sel, tag, message);
19+
}
20+
}
21+
}
22+
23+
@end

0 commit comments

Comments
 (0)