rhodes 7.4.1 → 7.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (305) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +319 -0
  3. data/CREDITS +3 -1
  4. data/LICENSE +1 -1
  5. data/README.md +6 -16
  6. data/Rakefile +55 -43
  7. data/SECURITY.md +19 -0
  8. data/appveyor.yml +66 -8
  9. data/azure-pipelines.yml +67 -0
  10. data/bin/rhodes-setup +22 -8
  11. data/extensions/emdk3-manager/ext/platform/android/src/com/rho/emdk3/EMDK3Extension.java +14 -5
  12. data/extensions/instrumentation/ext/platform/android/src/com/rho/instrumentation/Instrumentation.java +29 -15
  13. data/extensions/rhoconnect-push/ext/rhoconnect-push/platform/android/src/com/rhomobile/rhoelements/ans/ANSManager.java +3 -3
  14. data/extensions/rhoelementsext/ext/rhoelementsext/platform/android/rhoelements_temp/src/com/rho/rhoelements/ElementsCore.java +12 -9
  15. data/extensions/rhoelementsext/ext/rhoelementsext/platform/android/rhoelements_temp/src/com/rho/rhoelements/graphics/BatteryIndicator.java +2 -2
  16. data/lib/commonAPI/barcode/ext/platform/android/AndroidManifest.xml +3 -1
  17. data/lib/commonAPI/barcode/ext/platform/android/src/com/google/barcodereader/BarcodeCaptureActivity.java +11 -13
  18. data/lib/commonAPI/barcode/ext/platform/android/src/com/google/barcodereader/BarcodeGraphicTracker.java +1 -1
  19. data/lib/commonAPI/barcode/ext/platform/android/src/com/google/barcodereader/ui/camera/CameraSource.java +3 -3
  20. data/lib/commonAPI/barcode/ext/platform/android/src/com/google/barcodereader/ui/camera/CameraSourcePreview.java +1 -1
  21. data/lib/commonAPI/barcode/ext/platform/qt/Barcode.pro +1 -1
  22. data/lib/commonAPI/barcode/ext/platform/qt/Barcode.pro.erb +2 -2
  23. data/lib/commonAPI/barcode/ext/platform/qt/src/qzxing/QZXing.pri +9 -21
  24. data/lib/commonAPI/barcode/ext.yml +5 -8
  25. data/lib/commonAPI/bluetooth/ext/platform/qt/Bluetooth.pro +1 -1
  26. data/lib/commonAPI/bluetooth/ext/platform/qt/Bluetooth.pro.erb +1 -1
  27. data/lib/commonAPI/bluetooth/ext/platform/qt/src/bluetooth/bluetoothhelper.h +1 -1
  28. data/lib/commonAPI/coreapi/RhoSystemApi.rb +6 -0
  29. data/lib/commonAPI/coreapi/ext/Intent.xml +4 -0
  30. data/lib/commonAPI/coreapi/ext/platform/android/Rakefile +0 -12
  31. data/lib/commonAPI/coreapi/ext/platform/android/src/com/rho/intent/IntentSingleton.java +6 -0
  32. data/lib/commonAPI/coreapi/ext/platform/android/src/com/rho/notification/Notification.java +5 -2
  33. data/lib/commonAPI/coreapi/ext/platform/android/src/com/rho/notification/NotificationScheduler.java +4 -4
  34. data/lib/commonAPI/coreapi/ext/platform/android/src/com/rho/notification/NotificationSingleton.java +1 -1
  35. data/lib/commonAPI/coreapi/ext/platform/android/src/com/rho/webview/WebViewSingleton.java +40 -27
  36. data/lib/commonAPI/coreapi/ext/platform/iphone/cpp_based_impl/SystemImpl.mm +5 -6
  37. data/lib/commonAPI/coreapi/ext/platform/iphone/impl/Intent.h +1 -1
  38. data/lib/commonAPI/coreapi/ext/platform/iphone/impl/Intent.m +3 -1
  39. data/lib/commonAPI/coreapi/ext/platform/iphone/impl/NotificationSingleton.h +2 -1
  40. data/lib/commonAPI/coreapi/ext/platform/iphone/impl/NotificationSingleton.m +10 -0
  41. data/lib/commonAPI/coreapi/ext/platform/wm/src/IntentImpl.cpp +3 -0
  42. data/lib/commonAPI/coreapi/ext/push.xml +5 -2
  43. data/lib/commonAPI/coreapi/ext/shared/SystemImplBase.cpp +13 -0
  44. data/lib/commonAPI/coreapi/ext/shared/SystemImplBase.h +2 -0
  45. data/lib/commonAPI/coreapi/ext/system.xml +3 -0
  46. data/lib/commonAPI/mediacapture/ext/camera.xml +4 -9
  47. data/lib/commonAPI/mediacapture/ext/platform/android/ApplicationCameraActivity.erb +2 -2
  48. data/lib/commonAPI/mediacapture/ext/platform/android/ApplicationFileProvider.erb +1 -1
  49. data/lib/commonAPI/mediacapture/ext/platform/android/ext_java.files +2 -9
  50. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraExtension.java +0 -2
  51. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraFactory.java +19 -24
  52. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraObject.java +322 -730
  53. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraRhoListener.java +247 -433
  54. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/{CameraSingletonObject.java → CameraSingleton.java} +68 -74
  55. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/mediacapture/RhoCameraFileProvider.java +6 -0
  56. data/lib/commonAPI/mediacapture/ext/platform/qt/MediaCapture.pro.erb +1 -1
  57. data/lib/commonAPI/mediacapture/ext/platform/qt/Mediacapture.pro +1 -1
  58. data/lib/commonAPI/printing_zebra/ext/platform/android/src/com/rhomobile/printing/zebra/impl/ZebraPrintingProviderImpl.java +2 -1
  59. data/lib/commonAPI/signature/ext/platform/iphone/impl/readme.txt +7 -0
  60. data/lib/commonAPI/signature/ext/platform/qt/Signature.pro +3 -10
  61. data/lib/commonAPI/signature/ext/platform/qt/Signature.pro.erb +2 -2
  62. data/lib/extensions/fcm-push/ext/android/ApplicationManifestAdds.erb +15 -17
  63. data/lib/extensions/fcm-push/ext/android/Rakefile +59 -34
  64. data/lib/extensions/fcm-push/ext/android/ext_java.files +0 -1
  65. data/lib/extensions/fcm-push/ext/android/src/com/rhomobile/rhodes/fcm/FCMFacade.java +13 -17
  66. data/lib/extensions/fcm-push/ext/android/src/com/rhomobile/rhodes/fcm/FCMIntentService.java +81 -80
  67. data/lib/extensions/fcm-push/ext/android/src/com/rhomobile/rhodes/fcm/FCMListener.java +0 -16
  68. data/lib/extensions/fcm-push/ext/iphone/Podfile +15 -2
  69. data/lib/extensions/fcm-push/ext/iphone/fcm-push.xcodeproj/project.pbxproj +6 -7
  70. data/lib/extensions/fcm-push/ext.yml +1 -1
  71. data/lib/extensions/gmaps/ext/platform/android/ApplicationManifestAdds.erb +1 -0
  72. data/lib/extensions/gmaps/ext/platform/android/src/com/rhomobile/rhodes/gmaps/GMapActivity.java +12 -4
  73. data/lib/extensions/gmaps/ext.yml +3 -1
  74. data/lib/extensions/nfc/ext/platform/android/src/com/rhomobile/nfc/Nfc.java +2 -1
  75. data/lib/extensions/serialport/ext/serialport.pro +1 -1
  76. data/platform/android/Rhodes/jni/include/rhodes/JNIRhodes.h +1 -0
  77. data/platform/android/Rhodes/jni/src/MethodResultJni.cpp +4 -0
  78. data/platform/android/Rhodes/jni/src/fileapi.cpp +4 -0
  79. data/platform/android/Rhodes/res/drawable/baseline_check_24.xml +5 -0
  80. data/platform/android/Rhodes/res/drawable/baseline_check_240.xml +5 -0
  81. data/platform/android/Rhodes/res/drawable/baseline_close_24.xml +5 -0
  82. data/platform/android/Rhodes/res/drawable/baseline_close_240.xml +5 -0
  83. data/platform/android/Rhodes/res/layout/overlay_layout.xml +39 -0
  84. data/platform/android/Rhodes/res/layout/perrmission_alert_dialog.xml +267 -0
  85. data/platform/android/Rhodes/src/com/rhomobile/rhodes/BaseActivity.java +183 -66
  86. data/platform/android/Rhodes/src/com/rhomobile/rhodes/LocalFileProvider.java +38 -6
  87. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhoFileProvider.java +32 -0
  88. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesActivity.java +532 -92
  89. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesApplication.java +26 -4
  90. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesService.java +259 -163
  91. data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/StatusNotification.java +1 -1
  92. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/AbstractRhoExtension.java +14 -3
  93. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/IRhoExtManager.java +4 -0
  94. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/IRhoExtension.java +5 -4
  95. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/RhoExtManagerImpl.java +79 -38
  96. data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocation.java +20 -15
  97. data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocationImpl.java +18 -9
  98. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/CallReceiver.java +22 -0
  99. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/IKioskMode.java +11 -0
  100. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/KioskManager.java +18 -0
  101. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/MyAccessibilityService.java +230 -0
  102. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/MyNotificationListenerService.java +16 -0
  103. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/MyOverlayService.java +197 -0
  104. data/platform/android/Rhodes/src/com/rhomobile/rhodes/kioskservices/PermissionManager.java +232 -0
  105. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +34 -8
  106. data/platform/android/Rhodes/src/com/rhomobile/rhodes/osfunctionality/AndroidFunctionality26.java +1 -1
  107. data/platform/android/Rhodes/src/com/rhomobile/rhodes/permissioncheck/CheckDrawable.java +53 -0
  108. data/platform/android/Rhodes/src/com/rhomobile/rhodes/permissioncheck/PermissionListGenerate.java +366 -0
  109. data/platform/android/Rhodes/src/com/rhomobile/rhodes/rhodes.iml +11 -0
  110. data/platform/android/Rhodes/src/com/rhomobile/rhodes/socket/SSLImpl.java +1 -0
  111. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/GoogleWebView.java +782 -41
  112. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoInputConnectionWrapper.java +146 -0
  113. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoInputListener.java +21 -0
  114. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoWebViewClient.java +92 -32
  115. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/TauWebViewOptions.java +118 -0
  116. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/WebSettingsProviderBase.java +18 -17
  117. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/WebSettingsProviderEclairMR1.java +4 -4
  118. data/platform/android/build/RhodesSRC_build.files +13 -0
  119. data/platform/android/build/{aab_builder.rb → aapt2_helper.rb} +94 -37
  120. data/platform/android/build/android-repack.rake +8 -1
  121. data/platform/android/build/android.rake +238 -238
  122. data/platform/android/build/android_tools.rb +10 -10
  123. data/platform/android/build/androidcommon.rb +31 -14
  124. data/platform/android/build/build_tools_finder.rb +46 -0
  125. data/platform/android/build/config.yml +8 -0
  126. data/platform/android/build/dex_builder.rb +88 -0
  127. data/platform/android/build/hostplatform.rb +9 -0
  128. data/platform/android/build/manifest_generator.rb +15 -10
  129. data/platform/android/build/maven_deps_extractor.rb +29 -22
  130. data/platform/android/build/ndkwrapper.rb +92 -51
  131. data/platform/android/proguard/proguard-base-rules.pro +5 -0
  132. data/platform/android/proguard/proguard.jar +0 -0
  133. data/platform/iphone/Classes/AppManager/AppManager.m +3 -1
  134. data/platform/iphone/Classes/Camera/PickImageDelegate.h +2 -0
  135. data/platform/iphone/Classes/Camera/PickImageDelegate.m +45 -23
  136. data/platform/iphone/Classes/CocoaServer/CCocoaServer.h +27 -0
  137. data/platform/iphone/Classes/CocoaServer/CCocoaServer.m +107 -0
  138. data/platform/iphone/Classes/CocoaServer/RhoHTTPConnection.h +16 -0
  139. data/platform/iphone/Classes/CocoaServer/RhoHTTPConnection.m +226 -0
  140. data/platform/iphone/Classes/RhoAppBaseLib-Bridging-Header.h +4 -0
  141. data/platform/iphone/Classes/RhoAppBaseStandaloneLib-Bridging-Header.h +4 -0
  142. data/platform/iphone/Classes/RhoCryptAESGCM.swift +105 -0
  143. data/platform/iphone/Classes/RhoUIWebView.h +1 -1
  144. data/platform/iphone/Classes/RhoUIWebView.m +1 -1
  145. data/platform/iphone/Classes/RhoWKWebView.h +1 -1
  146. data/platform/iphone/Classes/RhoWKWebView.mm +110 -15
  147. data/platform/iphone/Classes/RhoWebView.h +1 -1
  148. data/platform/iphone/Classes/RhoWebViewFabrique.m +13 -2
  149. data/platform/iphone/Classes/Rhodes.m +3 -0
  150. data/platform/iphone/Classes/SimpleMainView.m +5 -5
  151. data/platform/iphone/Classes/URLProtocol/CRhoURLProtocol.m +21 -10
  152. data/platform/iphone/Classes/rho/net/IPhoneNetRequest.mm +4 -0
  153. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDData.h +14 -0
  154. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDData.m +158 -0
  155. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDNumber.h +12 -0
  156. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDNumber.m +88 -0
  157. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDRange.h +56 -0
  158. data/platform/iphone/CocoaHTTPServer/Core/Categories/DDRange.m +104 -0
  159. data/platform/iphone/CocoaHTTPServer/Core/HTTPAuthenticationRequest.h +45 -0
  160. data/platform/iphone/CocoaHTTPServer/Core/HTTPAuthenticationRequest.m +195 -0
  161. data/platform/iphone/CocoaHTTPServer/Core/HTTPConnection.h +120 -0
  162. data/platform/iphone/CocoaHTTPServer/Core/HTTPConnection.m +2708 -0
  163. data/platform/iphone/CocoaHTTPServer/Core/HTTPLogging.h +136 -0
  164. data/platform/iphone/CocoaHTTPServer/Core/HTTPMessage.h +48 -0
  165. data/platform/iphone/CocoaHTTPServer/Core/HTTPMessage.m +113 -0
  166. data/platform/iphone/CocoaHTTPServer/Core/HTTPResponse.h +149 -0
  167. data/platform/iphone/CocoaHTTPServer/Core/HTTPServer.h +205 -0
  168. data/platform/iphone/CocoaHTTPServer/Core/HTTPServer.m +772 -0
  169. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.h +65 -0
  170. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.m +529 -0
  171. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.h +33 -0
  172. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.m +86 -0
  173. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.h +23 -0
  174. data/platform/iphone/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.m +211 -0
  175. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.h +75 -0
  176. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.m +405 -0
  177. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPDataResponse.h +13 -0
  178. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPDataResponse.m +79 -0
  179. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.h +52 -0
  180. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.m +292 -0
  181. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.h +9 -0
  182. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.m +38 -0
  183. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPFileResponse.h +25 -0
  184. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +237 -0
  185. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.h +12 -0
  186. data/platform/iphone/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.m +73 -0
  187. data/platform/iphone/CocoaHTTPServer/Core/WebSocket.h +105 -0
  188. data/platform/iphone/CocoaHTTPServer/Core/WebSocket.m +791 -0
  189. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.h +7 -0
  190. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.m +160 -0
  191. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.h +11 -0
  192. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.m +372 -0
  193. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.h +7 -0
  194. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.m +49 -0
  195. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.h +8 -0
  196. data/platform/iphone/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.m +69 -0
  197. data/platform/iphone/CocoaHTTPServer/LICENSE.txt +18 -0
  198. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaAsyncSocket/About.txt +4 -0
  199. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +1226 -0
  200. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +8528 -0
  201. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/About.txt +33 -0
  202. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDASLLogger.h +41 -0
  203. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDASLLogger.m +99 -0
  204. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
  205. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m +727 -0
  206. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDFileLogger.h +334 -0
  207. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDFileLogger.m +1353 -0
  208. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDLog.h +601 -0
  209. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDLog.m +1083 -0
  210. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDTTYLogger.h +167 -0
  211. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/DDTTYLogger.m +1479 -0
  212. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
  213. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
  214. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
  215. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
  216. data/platform/iphone/CocoaHTTPServer/Vendor/CocoaLumberjack/Extensions/README.txt +7 -0
  217. data/platform/iphone/Framework/RhoApplication/RhoApplication.xcodeproj/project.pbxproj +1 -1
  218. data/platform/iphone/Framework/Rhodes/Rhodes.xcodeproj/project.pbxproj +2 -2
  219. data/platform/iphone/RhoAppBaseLib/RhoAppBaseLib.xcodeproj/project.pbxproj +410 -1
  220. data/platform/iphone/RhoLib/RhoLib.xcodeproj/project.pbxproj +1 -1
  221. data/platform/iphone/curl/curl.xcodeproj/project.pbxproj +4 -1
  222. data/platform/iphone/rbuild/iphone.rake +13 -8
  223. data/platform/iphone/rhoextlib/rhoextlib.xcodeproj/project.pbxproj +4 -1
  224. data/platform/iphone/rhorubylib/rhorubylib.xcodeproj/project.pbxproj +1 -1
  225. data/platform/iphone/rhosynclib/rhosynclib.xcodeproj/project.pbxproj +1 -1
  226. data/platform/osx/bin/RhoSimulator/RhoSimulator.app.zip +0 -0
  227. data/platform/sailfish/build/{harbour-SailfishRhodes.pro.erb → SailfishRhodes.pro.erb} +10 -17
  228. data/platform/sailfish/build/rhodes.pro.erb +7 -17
  229. data/platform/sailfish/build/rpm/SailfishRhodes.desktop.erb +12 -0
  230. data/platform/sailfish/build/rpm/SailfishRhodes.erb +2 -0
  231. data/platform/sailfish/build/rpm/SailfishRhodes.spec.erb +43 -0
  232. data/platform/sailfish/build/rubylib.pro.erb +29 -29
  233. data/platform/sailfish/build/sailfish.rake +188 -180
  234. data/platform/sailfish/keys/regular_cert.pem +14 -0
  235. data/platform/sailfish/keys/regular_key.pem +4 -0
  236. data/platform/shared/common/RhodesApp.cpp +59 -10
  237. data/platform/shared/common/iphone/RhoCryptImpl.mm +130 -54
  238. data/platform/shared/net/HttpServer.cpp +20 -0
  239. data/platform/shared/qt/RhoSimulator.pro +1 -1
  240. data/platform/shared/qt/rhodes/rhodes.pro +4 -11
  241. data/platform/shared/qt/sailfish/SailfishRhodes.desktop +3 -4
  242. data/platform/shared/qt/sailfish/SailfishRhodes.pro +9 -10
  243. data/platform/shared/qt/sailfish/icons/108x108/108x108.png +0 -0
  244. data/platform/shared/qt/sailfish/privileges/sailfishrhodes +2 -0
  245. data/platform/shared/qt/sailfish/qml/pages/FirstPageWK.qml +7 -11
  246. data/platform/shared/qt/sailfish/qml/{harbour-sailfishrhodes.qml → sailfishrhodes.qml} +1 -1
  247. data/platform/shared/qt/sailfish/rpm/sailfishrhodes.spec +80 -0
  248. data/platform/shared/qt/sailfish/rpm/{harbour-sailfishrhodes.yaml → sailfishrhodes.yaml} +2 -2
  249. data/platform/shared/qt/sailfish/src/QtMainWindow.cpp +1 -1
  250. data/platform/shared/qt/sailfish/src/QtMainWindow.h +1 -1
  251. data/platform/shared/qt/sailfish/src/main.cpp +6 -38
  252. data/platform/shared/qt/sailfish/src/rootdelegate.h +2 -14
  253. data/platform/shared/ruby/aurora/ruby/config.h +386 -0
  254. data/platform/shared/ruby/aurora/ruby/constdefs.c +5866 -0
  255. data/platform/shared/ruby/aurora/ruby/constdefs.h +1788 -0
  256. data/platform/shared/ruby/osx/ruby/config.h +2 -0
  257. data/platform/shared/ruby/win32/win32.c +10 -3
  258. data/platform/shared/sqlite/crypto.c +14 -0
  259. data/platform/win32/RhoSimulator/RhoSimulator.exe +0 -0
  260. data/platform/win32/build/rhodes.nsi +3 -3
  261. data/platform/win32/build/win32.rake +1 -1
  262. data/rakefile.rb +55 -43
  263. data/res/build-tools/RhoRuby.exe +0 -0
  264. data/res/build-tools/aapt2/linux/aapt2 +0 -0
  265. data/res/build-tools/aapt2/osx/aapt2 +0 -0
  266. data/res/build-tools/iphonesim/build/Release/iphonesim_8 +4 -4
  267. data/res/generators/templates/application/AndroidManifest.erb +28 -6
  268. data/res/generators/templates/application/build.yml +18 -11
  269. data/res/generators/templates/application/resources/android/res/xml/provider_paths.xml +4 -0
  270. data/res/generators/templates/application/rhoconfig.txt +15 -1
  271. data/res/generators/templates/iphone_project/Bremen8.xcodeproj/project.pbxproj +24 -1
  272. data/res/generators/templates/iphone_project/Classes/SimpleSwiftClass.swift +20 -0
  273. data/res/generators/templates/iphone_project/Classes/rhorunner-Bridging-Header.h +4 -0
  274. data/rhobuild.yml.example +4 -4
  275. data/rhodes.gemspec +4 -3
  276. data/version +1 -1
  277. metadata +157 -57
  278. data/lib/commonAPI/mediacapture/ext/platform/android/adds/res/drawable/camera_btn.xml +0 -14
  279. data/lib/commonAPI/mediacapture/ext/platform/android/adds/res/layout/camera_land.xml +0 -23
  280. data/lib/commonAPI/mediacapture/ext/platform/android/adds/res/layout/camera_port.xml +0 -23
  281. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraActivity.java +0 -156
  282. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraEclair.java +0 -227
  283. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraGingerbread.java +0 -152
  284. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraPreview.java +0 -183
  285. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraSingletonEclair.java +0 -14
  286. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/CameraSingletonGingerbread.java +0 -60
  287. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/ICameraObject.java +0 -20
  288. data/lib/commonAPI/mediacapture/ext/platform/android/src/com/rho/camera/ICameraSingletonObject.java +0 -8
  289. data/lib/extensions/fcm-push/ext/android/src/com/rhomobile/rhodes/fcm/FCMTokenRefresherService.java +0 -27
  290. data/platform/android/Rhodes/AndroidManifest.xml.erb +0 -89
  291. data/platform/sailfish/build/rho_build.cmd.erb +0 -14
  292. data/platform/sailfish/build/rho_clean.cmd.erb +0 -14
  293. data/platform/sailfish/build/rho_deploy.cmd.erb +0 -15
  294. data/platform/sailfish/build/rho_rpm.cmd.erb +0 -14
  295. data/platform/sailfish/build/rho_rpmvalidation.cmd.erb +0 -14
  296. data/platform/sailfish/build/rpm/harbour-SailfishRhodes.desktop.erb +0 -7
  297. data/platform/sailfish/build/rpm/harbour-SailfishRhodes.erb +0 -2
  298. data/platform/sailfish/build/rpm/harbour-SailfishRhodes.yaml.erb +0 -37
  299. data/platform/shared/qt/sailfish/harbour-sailfishrhodes.desktop +0 -6
  300. data/platform/shared/qt/sailfish/icons/108x108/harbour-sailfishrhodes.png +0 -0
  301. data/platform/shared/qt/sailfish/privileges/harbour-sailfishrhodes +0 -2
  302. data/platform/shared/qt/sailfish/qml/pages/FirstPageWE.qml +0 -236
  303. /data/platform/shared/qt/sailfish/icons/128x128/{harbour-sailfishrhodes.png → sailfishrhodes.png} +0 -0
  304. /data/platform/shared/qt/sailfish/icons/172x172/{harbour-sailfishrhodes.png → sailfishrhodes.png} +0 -0
  305. /data/platform/shared/qt/sailfish/icons/86x86/{harbour-sailfishrhodes.png → sailfishrhodes.png} +0 -0
@@ -0,0 +1,1083 @@
1
+ #import "DDLog.h"
2
+
3
+ #import <pthread.h>
4
+ #import <objc/runtime.h>
5
+ #import <mach/mach_host.h>
6
+ #import <mach/host_info.h>
7
+ #import <libkern/OSAtomic.h>
8
+
9
+
10
+ /**
11
+ * Welcome to Cocoa Lumberjack!
12
+ *
13
+ * The project page has a wealth of documentation if you have any questions.
14
+ * https://github.com/robbiehanson/CocoaLumberjack
15
+ *
16
+ * If you're new to the project you may wish to read the "Getting Started" wiki.
17
+ * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted
18
+ *
19
+ **/
20
+
21
+ #if ! __has_feature(objc_arc)
22
+ #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
23
+ #endif
24
+
25
+ // We probably shouldn't be using DDLog() statements within the DDLog implementation.
26
+ // But we still want to leave our log statements for any future debugging,
27
+ // and to allow other developers to trace the implementation (which is a great learning tool).
28
+ //
29
+ // So we use a primitive logging macro around NSLog.
30
+ // We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
31
+
32
+ #define DD_DEBUG NO
33
+
34
+ #define NSLogDebug(frmt, ...) do{ if(DD_DEBUG) NSLog((frmt), ##__VA_ARGS__); } while(0)
35
+
36
+ // Specifies the maximum queue size of the logging thread.
37
+ //
38
+ // Since most logging is asynchronous, its possible for rogue threads to flood the logging queue.
39
+ // That is, to issue an abundance of log statements faster than the logging thread can keepup.
40
+ // Typically such a scenario occurs when log statements are added haphazardly within large loops,
41
+ // but may also be possible if relatively slow loggers are being used.
42
+ //
43
+ // This property caps the queue size at a given number of outstanding log statements.
44
+ // If a thread attempts to issue a log statement when the queue is already maxed out,
45
+ // the issuing thread will block until the queue size drops below the max again.
46
+
47
+ #define LOG_MAX_QUEUE_SIZE 1000 // Should not exceed INT32_MAX
48
+
49
+ // The "global logging queue" refers to [DDLog loggingQueue].
50
+ // It is the queue that all log statements go through.
51
+ //
52
+ // The logging queue sets a flag via dispatch_queue_set_specific using this key.
53
+ // We can check for this key via dispatch_get_specific() to see if we're on the "global logging queue".
54
+
55
+ static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueIdentityKey;
56
+
57
+
58
+ @interface DDLoggerNode : NSObject {
59
+ @public
60
+ id <DDLogger> logger;
61
+ dispatch_queue_t loggerQueue;
62
+ }
63
+
64
+ + (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue;
65
+
66
+ @end
67
+
68
+
69
+ @interface DDLog (PrivateAPI)
70
+
71
+ + (void)lt_addLogger:(id <DDLogger>)logger;
72
+ + (void)lt_removeLogger:(id <DDLogger>)logger;
73
+ + (void)lt_removeAllLoggers;
74
+ + (void)lt_log:(DDLogMessage *)logMessage;
75
+ + (void)lt_flush;
76
+
77
+ @end
78
+
79
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80
+ #pragma mark -
81
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82
+
83
+ @implementation DDLog
84
+
85
+ // An array used to manage all the individual loggers.
86
+ // The array is only modified on the loggingQueue/loggingThread.
87
+ static NSMutableArray *loggers;
88
+
89
+ // All logging statements are added to the same queue to ensure FIFO operation.
90
+ static dispatch_queue_t loggingQueue;
91
+
92
+ // Individual loggers are executed concurrently per log statement.
93
+ // Each logger has it's own associated queue, and a dispatch group is used for synchrnoization.
94
+ static dispatch_group_t loggingGroup;
95
+
96
+ // In order to prevent to queue from growing infinitely large,
97
+ // a maximum size is enforced (LOG_MAX_QUEUE_SIZE).
98
+ static dispatch_semaphore_t queueSemaphore;
99
+
100
+ // Minor optimization for uniprocessor machines
101
+ static unsigned int numProcessors;
102
+
103
+ /**
104
+ * The runtime sends initialize to each class in a program exactly one time just before the class,
105
+ * or any class that inherits from it, is sent its first message from within the program. (Thus the
106
+ * method may never be invoked if the class is not used.) The runtime sends the initialize message to
107
+ * classes in a thread-safe manner. Superclasses receive this message before their subclasses.
108
+ *
109
+ * This method may also be called directly (assumably by accident), hence the safety mechanism.
110
+ **/
111
+ + (void)initialize
112
+ {
113
+ static BOOL initialized = NO;
114
+ if (!initialized)
115
+ {
116
+ initialized = YES;
117
+
118
+ loggers = [[NSMutableArray alloc] initWithCapacity:4];
119
+
120
+ NSLogDebug(@"DDLog: Using grand central dispatch");
121
+
122
+ loggingQueue = dispatch_queue_create("cocoa.lumberjack", NULL);
123
+ loggingGroup = dispatch_group_create();
124
+
125
+ void *nonNullValue = GlobalLoggingQueueIdentityKey; // Whatever, just not null
126
+ dispatch_queue_set_specific(loggingQueue, GlobalLoggingQueueIdentityKey, nonNullValue, NULL);
127
+
128
+ queueSemaphore = dispatch_semaphore_create(LOG_MAX_QUEUE_SIZE);
129
+
130
+ // Figure out how many processors are available.
131
+ // This may be used later for an optimization on uniprocessor machines.
132
+
133
+ host_basic_info_data_t hostInfo;
134
+ mach_msg_type_number_t infoCount;
135
+
136
+ infoCount = HOST_BASIC_INFO_COUNT;
137
+ host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
138
+
139
+ unsigned int result = (unsigned int)(hostInfo.max_cpus);
140
+ unsigned int one = (unsigned int)(1);
141
+
142
+ numProcessors = MAX(result, one);
143
+
144
+ NSLogDebug(@"DDLog: numProcessors = %u", numProcessors);
145
+
146
+
147
+ #if TARGET_OS_IPHONE
148
+ NSString *notificationName = @"UIApplicationWillTerminateNotification";
149
+ #else
150
+ NSString *notificationName = @"NSApplicationWillTerminateNotification";
151
+ #endif
152
+
153
+ [[NSNotificationCenter defaultCenter] addObserver:self
154
+ selector:@selector(applicationWillTerminate:)
155
+ name:notificationName
156
+ object:nil];
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Provides access to the logging queue.
162
+ **/
163
+ + (dispatch_queue_t)loggingQueue
164
+ {
165
+ return loggingQueue;
166
+ }
167
+
168
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169
+ #pragma mark Notifications
170
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
171
+
172
+ + (void)applicationWillTerminate:(NSNotification *)notification
173
+ {
174
+ [self flushLog];
175
+ }
176
+
177
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
178
+ #pragma mark Logger Management
179
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
180
+
181
+ + (void)addLogger:(id <DDLogger>)logger
182
+ {
183
+ if (logger == nil) return;
184
+
185
+ dispatch_async(loggingQueue, ^{ @autoreleasepool {
186
+
187
+ [self lt_addLogger:logger];
188
+ }});
189
+ }
190
+
191
+ + (void)removeLogger:(id <DDLogger>)logger
192
+ {
193
+ if (logger == nil) return;
194
+
195
+ dispatch_async(loggingQueue, ^{ @autoreleasepool {
196
+
197
+ [self lt_removeLogger:logger];
198
+ }});
199
+ }
200
+
201
+ + (void)removeAllLoggers
202
+ {
203
+ dispatch_async(loggingQueue, ^{ @autoreleasepool {
204
+
205
+ [self lt_removeAllLoggers];
206
+ }});
207
+ }
208
+
209
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210
+ #pragma mark Master Logging
211
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
212
+
213
+ + (void)queueLogMessage:(DDLogMessage *)logMessage asynchronously:(BOOL)asyncFlag
214
+ {
215
+ // We have a tricky situation here...
216
+ //
217
+ // In the common case, when the queueSize is below the maximumQueueSize,
218
+ // we want to simply enqueue the logMessage. And we want to do this as fast as possible,
219
+ // which means we don't want to block and we don't want to use any locks.
220
+ //
221
+ // However, if the queueSize gets too big, we want to block.
222
+ // But we have very strict requirements as to when we block, and how long we block.
223
+ //
224
+ // The following example should help illustrate our requirements:
225
+ //
226
+ // Imagine that the maximum queue size is configured to be 5,
227
+ // and that there are already 5 log messages queued.
228
+ // Let us call these 5 queued log messages A, B, C, D, and E. (A is next to be executed)
229
+ //
230
+ // Now if our thread issues a log statement (let us call the log message F),
231
+ // it should block before the message is added to the queue.
232
+ // Furthermore, it should be unblocked immediately after A has been unqueued.
233
+ //
234
+ // The requirements are strict in this manner so that we block only as long as necessary,
235
+ // and so that blocked threads are unblocked in the order in which they were blocked.
236
+ //
237
+ // Returning to our previous example, let us assume that log messages A through E are still queued.
238
+ // Our aforementioned thread is blocked attempting to queue log message F.
239
+ // Now assume we have another separate thread that attempts to issue log message G.
240
+ // It should block until log messages A and B have been unqueued.
241
+
242
+
243
+ // We are using a counting semaphore provided by GCD.
244
+ // The semaphore is initialized with our LOG_MAX_QUEUE_SIZE value.
245
+ // Everytime we want to queue a log message we decrement this value.
246
+ // If the resulting value is less than zero,
247
+ // the semaphore function waits in FIFO order for a signal to occur before returning.
248
+ //
249
+ // A dispatch semaphore is an efficient implementation of a traditional counting semaphore.
250
+ // Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked.
251
+ // If the calling semaphore does not need to block, no kernel call is made.
252
+
253
+ dispatch_semaphore_wait(queueSemaphore, DISPATCH_TIME_FOREVER);
254
+
255
+ // We've now sure we won't overflow the queue.
256
+ // It is time to queue our log message.
257
+
258
+ dispatch_block_t logBlock = ^{ @autoreleasepool {
259
+
260
+ [self lt_log:logMessage];
261
+ }};
262
+
263
+ if (asyncFlag)
264
+ dispatch_async(loggingQueue, logBlock);
265
+ else
266
+ dispatch_sync(loggingQueue, logBlock);
267
+ }
268
+
269
+ + (void)log:(BOOL)asynchronous
270
+ level:(int)level
271
+ flag:(int)flag
272
+ context:(int)context
273
+ file:(const char *)file
274
+ function:(const char *)function
275
+ line:(int)line
276
+ tag:(id)tag
277
+ format:(NSString *)format, ...
278
+ {
279
+ va_list args;
280
+ if (format)
281
+ {
282
+ va_start(args, format);
283
+
284
+ NSString *logMsg = [[NSString alloc] initWithFormat:format arguments:args];
285
+ DDLogMessage *logMessage = [[DDLogMessage alloc] initWithLogMsg:logMsg
286
+ level:level
287
+ flag:flag
288
+ context:context
289
+ file:file
290
+ function:function
291
+ line:line
292
+ tag:tag
293
+ options:0];
294
+
295
+ [self queueLogMessage:logMessage asynchronously:asynchronous];
296
+
297
+ va_end(args);
298
+ }
299
+ }
300
+
301
+ + (void)log:(BOOL)asynchronous
302
+ level:(int)level
303
+ flag:(int)flag
304
+ context:(int)context
305
+ file:(const char *)file
306
+ function:(const char *)function
307
+ line:(int)line
308
+ tag:(id)tag
309
+ format:(NSString *)format
310
+ args:(va_list)args
311
+ {
312
+ if (format)
313
+ {
314
+ NSString *logMsg = [[NSString alloc] initWithFormat:format arguments:args];
315
+ DDLogMessage *logMessage = [[DDLogMessage alloc] initWithLogMsg:logMsg
316
+ level:level
317
+ flag:flag
318
+ context:context
319
+ file:file
320
+ function:function
321
+ line:line
322
+ tag:tag
323
+ options:0];
324
+
325
+ [self queueLogMessage:logMessage asynchronously:asynchronous];
326
+ }
327
+ }
328
+
329
+ + (void)flushLog
330
+ {
331
+ dispatch_sync(loggingQueue, ^{ @autoreleasepool {
332
+
333
+ [self lt_flush];
334
+ }});
335
+ }
336
+
337
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338
+ #pragma mark Registered Dynamic Logging
339
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340
+
341
+ + (BOOL)isRegisteredClass:(Class)class
342
+ {
343
+ SEL getterSel = @selector(ddLogLevel);
344
+ SEL setterSel = @selector(ddSetLogLevel:);
345
+
346
+ #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
347
+
348
+ // Issue #6 (GoogleCode) - Crashes on iOS 4.2.1 and iPhone 4
349
+ //
350
+ // Crash caused by class_getClassMethod(2).
351
+ //
352
+ // "It's a bug with UIAccessibilitySafeCategory__NSObject so it didn't pop up until
353
+ // users had VoiceOver enabled [...]. I was able to work around it by searching the
354
+ // result of class_copyMethodList() instead of calling class_getClassMethod()"
355
+
356
+ BOOL result = NO;
357
+
358
+ unsigned int methodCount, i;
359
+ Method *methodList = class_copyMethodList(object_getClass(class), &methodCount);
360
+
361
+ if (methodList != NULL)
362
+ {
363
+ BOOL getterFound = NO;
364
+ BOOL setterFound = NO;
365
+
366
+ for (i = 0; i < methodCount; ++i)
367
+ {
368
+ SEL currentSel = method_getName(methodList[i]);
369
+
370
+ if (currentSel == getterSel)
371
+ {
372
+ getterFound = YES;
373
+ }
374
+ else if (currentSel == setterSel)
375
+ {
376
+ setterFound = YES;
377
+ }
378
+
379
+ if (getterFound && setterFound)
380
+ {
381
+ result = YES;
382
+ break;
383
+ }
384
+ }
385
+
386
+ free(methodList);
387
+ }
388
+
389
+ return result;
390
+
391
+ #else
392
+
393
+ // Issue #24 (GitHub) - Crashing in in ARC+Simulator
394
+ //
395
+ // The method +[DDLog isRegisteredClass] will crash a project when using it with ARC + Simulator.
396
+ // For running in the Simulator, it needs to execute the non-iOS code.
397
+
398
+ Method getter = class_getClassMethod(class, getterSel);
399
+ Method setter = class_getClassMethod(class, setterSel);
400
+
401
+ if ((getter != NULL) && (setter != NULL))
402
+ {
403
+ return YES;
404
+ }
405
+
406
+ return NO;
407
+
408
+ #endif
409
+ }
410
+
411
+ + (NSArray *)registeredClasses
412
+ {
413
+ int numClasses, i;
414
+
415
+ // We're going to get the list of all registered classes.
416
+ // The Objective-C runtime library automatically registers all the classes defined in your source code.
417
+ //
418
+ // To do this we use the following method (documented in the Objective-C Runtime Reference):
419
+ //
420
+ // int objc_getClassList(Class *buffer, int bufferLen)
421
+ //
422
+ // We can pass (NULL, 0) to obtain the total number of
423
+ // registered class definitions without actually retrieving any class definitions.
424
+ // This allows us to allocate the minimum amount of memory needed for the application.
425
+
426
+ numClasses = objc_getClassList(NULL, 0);
427
+
428
+ // The numClasses method now tells us how many classes we have.
429
+ // So we can allocate our buffer, and get pointers to all the class definitions.
430
+
431
+ Class *classes = (Class *)malloc(sizeof(Class) * numClasses);
432
+
433
+ numClasses = objc_getClassList(classes, numClasses);
434
+
435
+ // We can now loop through the classes, and test each one to see if it is a DDLogging class.
436
+
437
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:numClasses];
438
+
439
+ for (i = 0; i < numClasses; i++)
440
+ {
441
+ Class class = classes[i];
442
+
443
+ if ([self isRegisteredClass:class])
444
+ {
445
+ [result addObject:class];
446
+ }
447
+ }
448
+
449
+ free(classes);
450
+
451
+ return result;
452
+ }
453
+
454
+ + (NSArray *)registeredClassNames
455
+ {
456
+ NSArray *registeredClasses = [self registeredClasses];
457
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:[registeredClasses count]];
458
+
459
+ for (Class class in registeredClasses)
460
+ {
461
+ [result addObject:NSStringFromClass(class)];
462
+ }
463
+
464
+ return result;
465
+ }
466
+
467
+ + (int)logLevelForClass:(Class)aClass
468
+ {
469
+ if ([self isRegisteredClass:aClass])
470
+ {
471
+ return [aClass ddLogLevel];
472
+ }
473
+
474
+ return -1;
475
+ }
476
+
477
+ + (int)logLevelForClassWithName:(NSString *)aClassName
478
+ {
479
+ Class aClass = NSClassFromString(aClassName);
480
+
481
+ return [self logLevelForClass:aClass];
482
+ }
483
+
484
+ + (void)setLogLevel:(int)logLevel forClass:(Class)aClass
485
+ {
486
+ if ([self isRegisteredClass:aClass])
487
+ {
488
+ [aClass ddSetLogLevel:logLevel];
489
+ }
490
+ }
491
+
492
+ + (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName
493
+ {
494
+ Class aClass = NSClassFromString(aClassName);
495
+
496
+ [self setLogLevel:logLevel forClass:aClass];
497
+ }
498
+
499
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
500
+ #pragma mark Logging Thread
501
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
502
+
503
+ /**
504
+ * This method should only be run on the logging thread/queue.
505
+ **/
506
+ + (void)lt_addLogger:(id <DDLogger>)logger
507
+ {
508
+ // Add to loggers array.
509
+ // Need to create loggerQueue if loggerNode doesn't provide one.
510
+
511
+ dispatch_queue_t loggerQueue = NULL;
512
+
513
+ if ([logger respondsToSelector:@selector(loggerQueue)])
514
+ {
515
+ // Logger may be providing its own queue
516
+
517
+ loggerQueue = [logger loggerQueue];
518
+ }
519
+
520
+ if (loggerQueue == nil)
521
+ {
522
+ // Automatically create queue for the logger.
523
+ // Use the logger name as the queue name if possible.
524
+
525
+ const char *loggerQueueName = NULL;
526
+ if ([logger respondsToSelector:@selector(loggerName)])
527
+ {
528
+ loggerQueueName = [[logger loggerName] UTF8String];
529
+ }
530
+
531
+ loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
532
+ }
533
+
534
+ DDLoggerNode *loggerNode = [DDLoggerNode nodeWithLogger:logger loggerQueue:loggerQueue];
535
+ [loggers addObject:loggerNode];
536
+
537
+ if ([logger respondsToSelector:@selector(didAddLogger)])
538
+ {
539
+ dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
540
+
541
+ [logger didAddLogger];
542
+ }});
543
+ }
544
+ }
545
+
546
+ /**
547
+ * This method should only be run on the logging thread/queue.
548
+ **/
549
+ + (void)lt_removeLogger:(id <DDLogger>)logger
550
+ {
551
+ // Find associated loggerNode in list of added loggers
552
+
553
+ DDLoggerNode *loggerNode = nil;
554
+
555
+ for (DDLoggerNode *node in loggers)
556
+ {
557
+ if (node->logger == logger)
558
+ {
559
+ loggerNode = node;
560
+ break;
561
+ }
562
+ }
563
+
564
+ if (loggerNode == nil)
565
+ {
566
+ NSLogDebug(@"DDLog: Request to remove logger which wasn't added");
567
+ return;
568
+ }
569
+
570
+ // Notify logger
571
+
572
+ if ([logger respondsToSelector:@selector(willRemoveLogger)])
573
+ {
574
+ dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
575
+
576
+ [logger willRemoveLogger];
577
+ }});
578
+ }
579
+
580
+ // Remove from loggers array
581
+
582
+ [loggers removeObject:loggerNode];
583
+ }
584
+
585
+ /**
586
+ * This method should only be run on the logging thread/queue.
587
+ **/
588
+ + (void)lt_removeAllLoggers
589
+ {
590
+ // Notify all loggers
591
+
592
+ for (DDLoggerNode *loggerNode in loggers)
593
+ {
594
+ if ([loggerNode->logger respondsToSelector:@selector(willRemoveLogger)])
595
+ {
596
+ dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
597
+
598
+ [loggerNode->logger willRemoveLogger];
599
+ }});
600
+ }
601
+ }
602
+
603
+ // Remove all loggers from array
604
+
605
+ [loggers removeAllObjects];
606
+ }
607
+
608
+ /**
609
+ * This method should only be run on the logging thread/queue.
610
+ **/
611
+ + (void)lt_log:(DDLogMessage *)logMessage
612
+ {
613
+ // Execute the given log message on each of our loggers.
614
+
615
+ if (numProcessors > 1)
616
+ {
617
+ // Execute each logger concurrently, each within its own queue.
618
+ // All blocks are added to same group.
619
+ // After each block has been queued, wait on group.
620
+ //
621
+ // The waiting ensures that a slow logger doesn't end up with a large queue of pending log messages.
622
+ // This would defeat the purpose of the efforts we made earlier to restrict the max queue size.
623
+
624
+ for (DDLoggerNode *loggerNode in loggers)
625
+ {
626
+ dispatch_group_async(loggingGroup, loggerNode->loggerQueue, ^{ @autoreleasepool {
627
+
628
+ [loggerNode->logger logMessage:logMessage];
629
+
630
+ }});
631
+ }
632
+
633
+ dispatch_group_wait(loggingGroup, DISPATCH_TIME_FOREVER);
634
+ }
635
+ else
636
+ {
637
+ // Execute each logger serialy, each within its own queue.
638
+
639
+ for (DDLoggerNode *loggerNode in loggers)
640
+ {
641
+ dispatch_sync(loggerNode->loggerQueue, ^{ @autoreleasepool {
642
+
643
+ [loggerNode->logger logMessage:logMessage];
644
+
645
+ }});
646
+ }
647
+ }
648
+
649
+ // If our queue got too big, there may be blocked threads waiting to add log messages to the queue.
650
+ // Since we've now dequeued an item from the log, we may need to unblock the next thread.
651
+
652
+ // We are using a counting semaphore provided by GCD.
653
+ // The semaphore is initialized with our LOG_MAX_QUEUE_SIZE value.
654
+ // When a log message is queued this value is decremented.
655
+ // When a log message is dequeued this value is incremented.
656
+ // If the value ever drops below zero,
657
+ // the queueing thread blocks and waits in FIFO order for us to signal it.
658
+ //
659
+ // A dispatch semaphore is an efficient implementation of a traditional counting semaphore.
660
+ // Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked.
661
+ // If the calling semaphore does not need to block, no kernel call is made.
662
+
663
+ dispatch_semaphore_signal(queueSemaphore);
664
+ }
665
+
666
+ /**
667
+ * This method should only be run on the background logging thread.
668
+ **/
669
+ + (void)lt_flush
670
+ {
671
+ // All log statements issued before the flush method was invoked have now been executed.
672
+ //
673
+ // Now we need to propogate the flush request to any loggers that implement the flush method.
674
+ // This is designed for loggers that buffer IO.
675
+
676
+ for (DDLoggerNode *loggerNode in loggers)
677
+ {
678
+ if ([loggerNode->logger respondsToSelector:@selector(flush)])
679
+ {
680
+ dispatch_group_async(loggingGroup, loggerNode->loggerQueue, ^{ @autoreleasepool {
681
+
682
+ [loggerNode->logger flush];
683
+
684
+ }});
685
+ }
686
+ }
687
+
688
+ dispatch_group_wait(loggingGroup, DISPATCH_TIME_FOREVER);
689
+ }
690
+
691
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
692
+ #pragma mark Utilities
693
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
694
+
695
+ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
696
+ {
697
+ if (filePath == NULL) return nil;
698
+
699
+ char *lastSlash = NULL;
700
+ char *lastDot = NULL;
701
+
702
+ char *p = (char *)filePath;
703
+
704
+ while (*p != '\0')
705
+ {
706
+ if (*p == '/')
707
+ lastSlash = p;
708
+ else if (*p == '.')
709
+ lastDot = p;
710
+
711
+ p++;
712
+ }
713
+
714
+ char *subStr;
715
+ NSUInteger subLen;
716
+
717
+ if (lastSlash)
718
+ {
719
+ if (lastDot)
720
+ {
721
+ // lastSlash -> lastDot
722
+ subStr = lastSlash + 1;
723
+ subLen = lastDot - subStr;
724
+ }
725
+ else
726
+ {
727
+ // lastSlash -> endOfString
728
+ subStr = lastSlash + 1;
729
+ subLen = p - subStr;
730
+ }
731
+ }
732
+ else
733
+ {
734
+ if (lastDot)
735
+ {
736
+ // startOfString -> lastDot
737
+ subStr = (char *)filePath;
738
+ subLen = lastDot - subStr;
739
+ }
740
+ else
741
+ {
742
+ // startOfString -> endOfString
743
+ subStr = (char *)filePath;
744
+ subLen = p - subStr;
745
+ }
746
+ }
747
+
748
+ if (copy)
749
+ {
750
+ return [[NSString alloc] initWithBytes:subStr
751
+ length:subLen
752
+ encoding:NSUTF8StringEncoding];
753
+ }
754
+ else
755
+ {
756
+ // We can take advantage of the fact that __FILE__ is a string literal.
757
+ // Specifically, we don't need to waste time copying the string.
758
+ // We can just tell NSString to point to a range within the string literal.
759
+
760
+ return [[NSString alloc] initWithBytesNoCopy:subStr
761
+ length:subLen
762
+ encoding:NSUTF8StringEncoding
763
+ freeWhenDone:NO];
764
+ }
765
+ }
766
+
767
+ @end
768
+
769
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
770
+ #pragma mark -
771
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
772
+
773
+ @implementation DDLoggerNode
774
+
775
+ - (id)initWithLogger:(id <DDLogger>)aLogger loggerQueue:(dispatch_queue_t)aLoggerQueue
776
+ {
777
+ if ((self = [super init]))
778
+ {
779
+ logger = aLogger;
780
+
781
+ if (aLoggerQueue) {
782
+ loggerQueue = aLoggerQueue;
783
+ #if !OS_OBJECT_USE_OBJC
784
+ dispatch_retain(loggerQueue);
785
+ #endif
786
+ }
787
+ }
788
+ return self;
789
+ }
790
+
791
+ + (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue
792
+ {
793
+ return [[DDLoggerNode alloc] initWithLogger:logger loggerQueue:loggerQueue];
794
+ }
795
+
796
+ - (void)dealloc
797
+ {
798
+ #if !OS_OBJECT_USE_OBJC
799
+ if (loggerQueue) dispatch_release(loggerQueue);
800
+ #endif
801
+ }
802
+
803
+ @end
804
+
805
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
806
+ #pragma mark -
807
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
808
+
809
+ @implementation DDLogMessage
810
+
811
+ static char *dd_str_copy(const char *str)
812
+ {
813
+ if (str == NULL) return NULL;
814
+
815
+ size_t length = strlen(str);
816
+ char * result = malloc(length + 1);
817
+ strncpy(result, str, length);
818
+ result[length] = 0;
819
+
820
+ return result;
821
+ }
822
+
823
+ - (id)initWithLogMsg:(NSString *)msg
824
+ level:(int)level
825
+ flag:(int)flag
826
+ context:(int)context
827
+ file:(const char *)aFile
828
+ function:(const char *)aFunction
829
+ line:(int)line
830
+ tag:(id)aTag
831
+ options:(DDLogMessageOptions)optionsMask
832
+ {
833
+ if ((self = [super init]))
834
+ {
835
+ logMsg = msg;
836
+ logLevel = level;
837
+ logFlag = flag;
838
+ logContext = context;
839
+ lineNumber = line;
840
+ tag = aTag;
841
+ options = optionsMask;
842
+
843
+ if (options & DDLogMessageCopyFile)
844
+ file = dd_str_copy(aFile);
845
+ else
846
+ file = (char *)aFile;
847
+
848
+ if (options & DDLogMessageCopyFunction)
849
+ function = dd_str_copy(aFunction);
850
+ else
851
+ function = (char *)aFunction;
852
+
853
+ timestamp = [[NSDate alloc] init];
854
+
855
+ machThreadID = pthread_mach_thread_np(pthread_self());
856
+
857
+ #pragma clang diagnostic push
858
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
859
+ // The documentation for dispatch_get_current_queue() states:
860
+ //
861
+ // > [This method is] "recommended for debugging and logging purposes only"...
862
+ //
863
+ // Well that's exactly how we're using it here. Literally for logging purposes only.
864
+ // However, Apple has decided to deprecate this method anyway.
865
+ // However they have not given us an alternate version of dispatch_queue_get_label() that
866
+ // automatically uses the current queue, thus dispatch_get_current_queue() is still required.
867
+ //
868
+ // If dispatch_get_current_queue() disappears, without a dispatch_queue_get_label() alternative,
869
+ // Apple will have effectively taken away our ability to properly log the name of executing dispatch queue.
870
+
871
+ dispatch_queue_t currentQueue = dispatch_get_current_queue();
872
+ #pragma clang diagnostic pop
873
+
874
+ queueLabel = dd_str_copy(dispatch_queue_get_label(currentQueue));
875
+
876
+ threadName = [[NSThread currentThread] name];
877
+ }
878
+ return self;
879
+ }
880
+
881
+ - (NSString *)threadID
882
+ {
883
+ return [[NSString alloc] initWithFormat:@"%x", machThreadID];
884
+ }
885
+
886
+ - (NSString *)fileName
887
+ {
888
+ return DDExtractFileNameWithoutExtension(file, NO);
889
+ }
890
+
891
+ - (NSString *)methodName
892
+ {
893
+ if (function == NULL)
894
+ return nil;
895
+ else
896
+ return [[NSString alloc] initWithUTF8String:function];
897
+ }
898
+
899
+ - (void)dealloc
900
+ {
901
+ if (file && (options & DDLogMessageCopyFile))
902
+ free(file);
903
+
904
+ if (function && (options & DDLogMessageCopyFunction))
905
+ free(function);
906
+
907
+ if (queueLabel)
908
+ free(queueLabel);
909
+ }
910
+
911
+ @end
912
+
913
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
914
+ #pragma mark -
915
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
916
+
917
+ @implementation DDAbstractLogger
918
+
919
+ - (id)init
920
+ {
921
+ if ((self = [super init]))
922
+ {
923
+ const char *loggerQueueName = NULL;
924
+ if ([self respondsToSelector:@selector(loggerName)])
925
+ {
926
+ loggerQueueName = [[self loggerName] UTF8String];
927
+ }
928
+
929
+ loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
930
+
931
+ // We're going to use dispatch_queue_set_specific() to "mark" our loggerQueue.
932
+ // Later we can use dispatch_get_specific() to determine if we're executing on our loggerQueue.
933
+ // The documentation states:
934
+ //
935
+ // > Keys are only compared as pointers and are never dereferenced.
936
+ // > Thus, you can use a pointer to a static variable for a specific subsystem or
937
+ // > any other value that allows you to identify the value uniquely.
938
+ // > Specifying a pointer to a string constant is not recommended.
939
+ //
940
+ // So we're going to use the very convenient key of "self",
941
+ // which also works when multiple logger classes extend this class, as each will have a different "self" key.
942
+ //
943
+ // This is used primarily for thread-safety assertions (via the isOnInternalLoggerQueue method below).
944
+
945
+ void *key = (__bridge void *)self;
946
+ void *nonNullValue = (__bridge void *)self;
947
+
948
+ dispatch_queue_set_specific(loggerQueue, key, nonNullValue, NULL);
949
+ }
950
+ return self;
951
+ }
952
+
953
+ - (void)dealloc
954
+ {
955
+ #if !OS_OBJECT_USE_OBJC
956
+ if (loggerQueue) dispatch_release(loggerQueue);
957
+ #endif
958
+ }
959
+
960
+ - (void)logMessage:(DDLogMessage *)logMessage
961
+ {
962
+ // Override me
963
+ }
964
+
965
+ - (id <DDLogFormatter>)logFormatter
966
+ {
967
+ // This method must be thread safe and intuitive.
968
+ // Therefore if somebody executes the following code:
969
+ //
970
+ // [logger setLogFormatter:myFormatter];
971
+ // formatter = [logger logFormatter];
972
+ //
973
+ // They would expect formatter to equal myFormatter.
974
+ // This functionality must be ensured by the getter and setter method.
975
+ //
976
+ // The thread safety must not come at a cost to the performance of the logMessage method.
977
+ // This method is likely called sporadically, while the logMessage method is called repeatedly.
978
+ // This means, the implementation of this method:
979
+ // - Must NOT require the logMessage method to acquire a lock.
980
+ // - Must NOT require the logMessage method to access an atomic property (also a lock of sorts).
981
+ //
982
+ // Thread safety is ensured by executing access to the formatter variable on the loggerQueue.
983
+ // This is the same queue that the logMessage method operates on.
984
+ //
985
+ // Note: The last time I benchmarked the performance of direct access vs atomic property access,
986
+ // direct access was over twice as fast on the desktop and over 6 times as fast on the iPhone.
987
+ //
988
+ // Furthermore, consider the following code:
989
+ //
990
+ // DDLogVerbose(@"log msg 1");
991
+ // DDLogVerbose(@"log msg 2");
992
+ // [logger setFormatter:myFormatter];
993
+ // DDLogVerbose(@"log msg 3");
994
+ //
995
+ // Our intuitive requirement means that the new formatter will only apply to the 3rd log message.
996
+ // This must remain true even when using asynchronous logging.
997
+ // We must keep in mind the various queue's that are in play here:
998
+ //
999
+ // loggerQueue : Our own private internal queue that the logMessage method runs on.
1000
+ // Operations are added to this queue from the global loggingQueue.
1001
+ //
1002
+ // globalLoggingQueue : The queue that all log messages go through before they arrive in our loggerQueue.
1003
+ //
1004
+ // All log statements go through the serial gloabalLoggingQueue before they arrive at our loggerQueue.
1005
+ // Thus this method also goes through the serial globalLoggingQueue to ensure intuitive operation.
1006
+
1007
+ // IMPORTANT NOTE:
1008
+ //
1009
+ // Methods within the DDLogger implementation MUST access the formatter ivar directly.
1010
+ // This method is designed explicitly for external access.
1011
+ //
1012
+ // Using "self." syntax to go through this method will cause immediate deadlock.
1013
+ // This is the intended result. Fix it by accessing the ivar directly.
1014
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
1015
+
1016
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
1017
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
1018
+
1019
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
1020
+
1021
+ __block id <DDLogFormatter> result;
1022
+
1023
+ dispatch_sync(globalLoggingQueue, ^{
1024
+ dispatch_sync(loggerQueue, ^{
1025
+ result = formatter;
1026
+ });
1027
+ });
1028
+
1029
+ return result;
1030
+ }
1031
+
1032
+ - (void)setLogFormatter:(id <DDLogFormatter>)logFormatter
1033
+ {
1034
+ // The design of this method is documented extensively in the logFormatter message (above in code).
1035
+
1036
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
1037
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
1038
+
1039
+ dispatch_block_t block = ^{ @autoreleasepool {
1040
+
1041
+ if (formatter != logFormatter)
1042
+ {
1043
+ if ([formatter respondsToSelector:@selector(willRemoveFromLogger:)]) {
1044
+ [formatter willRemoveFromLogger:self];
1045
+ }
1046
+
1047
+ formatter = logFormatter;
1048
+
1049
+ if ([formatter respondsToSelector:@selector(didAddToLogger:)]) {
1050
+ [formatter didAddToLogger:self];
1051
+ }
1052
+ }
1053
+ }};
1054
+
1055
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
1056
+
1057
+ dispatch_async(globalLoggingQueue, ^{
1058
+ dispatch_async(loggerQueue, block);
1059
+ });
1060
+ }
1061
+
1062
+ - (dispatch_queue_t)loggerQueue
1063
+ {
1064
+ return loggerQueue;
1065
+ }
1066
+
1067
+ - (NSString *)loggerName
1068
+ {
1069
+ return NSStringFromClass([self class]);
1070
+ }
1071
+
1072
+ - (BOOL)isOnGlobalLoggingQueue
1073
+ {
1074
+ return (dispatch_get_specific(GlobalLoggingQueueIdentityKey) != NULL);
1075
+ }
1076
+
1077
+ - (BOOL)isOnInternalLoggerQueue
1078
+ {
1079
+ void *key = (__bridge void *)self;
1080
+ return (dispatch_get_specific(key) != NULL);
1081
+ }
1082
+
1083
+ @end