From 4ac9bef80d507305d9d203645e8adf07bb3f411a Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Sat, 30 May 2020 09:39:20 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 936092, initial DnD support for e10s, r=enndeakin,karlt (3cde556cf) - Bug 1152066 - Remove ugly dynamic loading code now that we can assume this symbol exists. r=roc (04813dd18) - Bug 966395 - Correctly propagate the input language's direction on OSX. r=masayuki/mrbkap (14a21fa0c) - Bug 1158791 - Try harder to avoid Gtk-Critical errors in xpcshell tests. r=karlt (f6cec3b99) - Bug 1153922 - Add a SandboxOptions option for creating the sandbox in a fresh JS::Zone. r=mrbkap (f99b17726) - Bug 968520 - Always use fallible allocator with nsTArray_base::ShrinkCapacity. r=froydnj (b7cf63063) - Bug 1160027 - Move ResourceQueue implementation from header file - r=cpearce (5fabd8c8f) - Bug 1119277 - Remove the process CPU priority parameter and simplify all the associated code. r=khuey, r=dhylands (32d2b0df2) - Goanna -> Gecko (2b16bec4c) - Bug 892371 - Adjust oom_score_adj values for foreground processes according to an LRU policy. r=dhylands, r=khuey (61cdfc3db) - Bug 892371 - Add mochitests covering LRU priority adjustments for both foreground and background processes. r=khuey (46676e34f) - Bug 1164297 - tweaks to logging modules of MediaDecoderStateMachine to remove accessing to env vars. r=cpearce. (e9dc910da) - Bug 1150539: log getUserMedia constraints used in MediaManager:5. r=jesup (161853b66) - Bug 1139027 - Permit running of camera mochitests on B2G desktop. r=mikeh (8bb265db2) - Bug 1145403 - Don't open MediaManager on shutdown. r=jesup (9338eef82) - Bug 1046245 - enumerateDevices w/non-blocking e10s, nsICryptoHMAC, clear cookies, lambdas. r=keeler, florian, billm, jesup (ce9d684a0) - remove StopWebRtcLoc() to be readded in Bug 1219339 - Part2 (7a0c901fc) - Bug 1046245 - IO on STS thread + cleanup BackgroundChild on shutdown r=jesup (e85dd7716) - Bug 579517 follow-up: Remove NSPR types that crept in (35aee15a6) - Bug 1152443 - Fix broken validation which prevented reading of enumerate_devices.txt. r=jesup (4e135355b) - Bug 1143562 - use /data/b2g/mozilla/gmp as the gmp storage folder on B2G. r=cpearce. (ddc07f09a) - Bug 1143562. Part2 - only init |mStorageBaseDir| in the chrome process. r=cpearce (3039a4f44) - remove specific hack, this code is going away anyway (34aed4d6b) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 0 - Make mozIGeckoMediaPluginService::GetPluginVersionForAPI return whether we even have the plugin. r=cpearce. (e6ac61630) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 1 - split GeckoMediaPluginService into a part for chrome and a part for both content and chrome. r=jwwang. (09f8c4a83) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 2 - support asynchronous GMP API getters. r=jwwang,rjesup. (e33266976) - Bug 1143532 - Include pid in the log messages of GMPParent. r=edwin (8486ebc50) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 3 - split the GMP IPDL actors in 2 parts (and use opens to open the second in non-e10s). r=billm. (d17fa36ff) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 4 - make GetNodeId asynchronous. r=jwwang. (db7a21e4a) - Bug 1150049 - tidy up nsImageBoxFrame::Init a little bit; r=dholbert (41c258a71) - Bug 1150266 - fix IPDL thinko for never-inline method declarations; r=bent (445d3420b) - Bug 1150207 - Convert a focus() call to use SpecialPowers to avoid out-of-order focusing behaviour. r=mwargers (4d134848c) - Bug 1148641 - Guard against null parameters to SendSetTargetAPZCNotification. r=botond (8c5f4bb6d) - Bug 1096172 - Fix position reporting of bad charrefs in RCDATA. r=hsivonen. (77100d26d) - Bug 1149971 Part 2: Cet rid of kCurrentProcessId as it makes lots of static initializers. r=dvander (3efaefdba) - remove android widgets (0c2565418) - Bug 1129991 - Remove QuotaManager::SetCurrentWindow(); r=bent (7ccabf88c) - Bug 1133748 - Fix ipdl code for bridged protocols that are also opened. r=billm. (402751d09) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 5 - use bridging for GMP in e10s. r=billm. (e45a87c5f) - Bug 1057908 followup: Add missing 'override' annotation on GMPServiceParent::ActorDestroy method decl. rs=ehsan (48f53b28a) - Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Add nsServiceManagerUtils.h include to WMFDecoderModule.cpp. (67cddb4da) - kill android widgets better (bec243c8d) --- b2g/app/b2g.js | 9 +- browser/base/content/sanitize.js | 5 + dom/base/Navigator.cpp | 4 +- dom/base/nsContentAreaDragDrop.cpp | 17 +- dom/base/nsContentUtils.cpp | 94 + dom/base/nsContentUtils.h | 8 + .../bluedroid/BluetoothDaemonHelpers.cpp | 4 +- .../bluedroid/BluetoothDaemonHelpers.cpp | 4 +- .../mochitest/browserElementTestHelpers.js | 69 +- .../mochitest/priority/CAUTION | 15 - .../mochitest/priority/mochitest.ini | 3 +- .../priority/test_BackgroundLRU.html | 17 +- .../priority/test_ForegroundLRU.html | 80 + .../priority/test_HighPriorityDowngrade.html | 81 - .../priority/test_HighPriorityDowngrade2.html | 76 - .../mochitest/priority/test_Preallocated.html | 2 +- dom/camera/CameraPreferences.cpp | 7 + dom/camera/CameraPreferences.h | 2 + dom/camera/DOMCameraManager.cpp | 7 +- dom/camera/FallbackCameraPlatform.cpp | 91 + dom/camera/FallbackCameraPlatform.h | 300 ++ dom/camera/GonkCameraControl.cpp | 29 +- dom/camera/GonkCameraControl.h | 16 +- dom/camera/GonkCameraHwMgr.cpp | 45 +- dom/camera/GonkCameraHwMgr.h | 40 +- dom/camera/GonkCameraManager.cpp | 9 +- dom/camera/GonkCameraParameters.cpp | 207 +- dom/camera/GonkCameraParameters.h | 204 +- dom/camera/GonkRecorderProfiles.cpp | 10 +- dom/camera/GonkRecorderProfiles.h | 9 + dom/camera/TestGonkCameraHardware.cpp | 6 + dom/camera/TestGonkCameraHardware.h | 6 + dom/camera/moz.build | 14 +- dom/camera/test/camera_common.js | 53 +- dom/camera/test/mochitest.ini | 4 + dom/camera/test/test_bug1037322.html | 100 +- dom/camera/test/test_bug1099390.html | 109 +- dom/camera/test/test_bug975472.html | 385 +-- .../test/test_camera_bad_initial_config.html | 50 +- dom/events/DataTransfer.cpp | 55 +- dom/events/DataTransfer.h | 4 + dom/events/EventStateManager.cpp | 62 +- dom/events/EventStateManager.h | 13 +- dom/filehandle/FileStreamWrappers.cpp | 14 - dom/filehandle/FileStreamWrappers.h | 3 - dom/filehandle/MutableFile.h | 12 +- dom/indexedDB/IDBMutableFile.cpp | 17 - dom/indexedDB/IDBMutableFile.h | 6 - dom/ipc/ContentChild.cpp | 89 +- dom/ipc/ContentChild.h | 11 + dom/ipc/ContentParent.cpp | 98 +- dom/ipc/ContentParent.h | 13 + dom/ipc/DOMTypes.ipdlh | 17 + dom/ipc/PBrowser.ipdl | 5 + dom/ipc/PContent.ipdl | 25 +- dom/ipc/ProcessPriorityManager.cpp | 588 ++-- dom/ipc/ProcessPriorityManager.h | 12 - dom/ipc/TabChild.cpp | 38 + dom/ipc/TabChild.h | 3 + dom/ipc/TabParent.cpp | 121 + dom/ipc/TabParent.h | 40 + dom/ipc/moz.build | 1 + dom/ipc/tests/test_NuwaProcessCreation.html | 2 +- dom/ipc/tests/test_NuwaProcessDeadlock.html | 2 +- dom/media/AudioSink.cpp | 8 +- dom/media/MediaDecoder.cpp | 5 +- dom/media/MediaDecoderStateMachine.cpp | 23 +- dom/media/MediaManager.cpp | 333 ++- dom/media/MediaManager.h | 24 +- dom/media/VideoUtils.cpp | 23 +- dom/media/VideoUtils.h | 6 +- dom/media/gmp/GMPAudioDecoderChild.cpp | 4 +- dom/media/gmp/GMPAudioDecoderChild.h | 6 +- dom/media/gmp/GMPAudioDecoderParent.cpp | 11 +- dom/media/gmp/GMPAudioDecoderParent.h | 7 +- dom/media/gmp/GMPChild.cpp | 174 +- dom/media/gmp/GMPChild.h | 31 +- dom/media/gmp/GMPContentChild.cpp | 215 ++ dom/media/gmp/GMPContentChild.h | 58 + dom/media/gmp/GMPContentParent.cpp | 302 ++ dom/media/gmp/GMPContentParent.h | 105 + dom/media/gmp/GMPDecryptorChild.cpp | 2 +- dom/media/gmp/GMPDecryptorChild.h | 6 +- dom/media/gmp/GMPDecryptorParent.cpp | 11 +- dom/media/gmp/GMPDecryptorParent.h | 8 +- dom/media/gmp/GMPParent.cpp | 482 ++-- dom/media/gmp/GMPParent.h | 84 +- dom/media/gmp/GMPService.cpp | 1501 +--------- dom/media/gmp/GMPService.h | 166 +- dom/media/gmp/GMPServiceChild.cpp | 382 +++ dom/media/gmp/GMPServiceChild.h | 90 + dom/media/gmp/GMPServiceParent.cpp | 1485 ++++++++++ dom/media/gmp/GMPServiceParent.h | 214 ++ dom/media/gmp/GMPStorageParent.cpp | 6 +- dom/media/gmp/GMPVideoDecoderChild.cpp | 4 +- dom/media/gmp/GMPVideoDecoderChild.h | 6 +- dom/media/gmp/GMPVideoDecoderParent.cpp | 11 +- dom/media/gmp/GMPVideoDecoderParent.h | 7 +- dom/media/gmp/GMPVideoEncoderChild.cpp | 4 +- dom/media/gmp/GMPVideoEncoderChild.h | 6 +- dom/media/gmp/GMPVideoEncoderParent.cpp | 11 +- dom/media/gmp/GMPVideoEncoderParent.h | 7 +- dom/media/gmp/PGMP.ipdl | 23 +- dom/media/gmp/PGMPAudioDecoder.ipdl | 5 +- dom/media/gmp/PGMPContent.ipdl | 33 + dom/media/gmp/PGMPDecryptor.ipdl | 6 +- dom/media/gmp/PGMPService.ipdl | 27 + dom/media/gmp/PGMPVideoDecoder.ipdl | 5 +- dom/media/gmp/PGMPVideoEncoder.ipdl | 5 +- dom/media/gmp/moz.build | 11 + .../gmp/mozIGeckoMediaPluginChromeService.idl | 47 + dom/media/gmp/mozIGeckoMediaPluginService.idl | 148 +- dom/media/gtest/TestGMPCrossOrigin.cpp | 673 +++-- dom/media/mediasource/ResourceQueue.cpp | 215 ++ dom/media/mediasource/ResourceQueue.h | 179 +- dom/media/mediasource/moz.build | 1 + dom/media/nsIMediaManager.idl | 6 +- .../agnostic/gmp/GMPAudioDecoder.cpp | 61 +- .../platforms/agnostic/gmp/GMPAudioDecoder.h | 57 + .../agnostic/gmp/GMPVideoDecoder.cpp | 76 +- .../platforms/agnostic/gmp/GMPVideoDecoder.h | 57 + dom/media/platforms/wmf/WMFDecoderModule.cpp | 1 + dom/media/systemservices/MediaChild.cpp | 174 ++ dom/media/systemservices/MediaChild.h | 74 + dom/media/systemservices/MediaParent.cpp | 457 +++ dom/media/systemservices/MediaParent.h | 46 + dom/media/systemservices/MediaUtils.cpp | 13 + dom/media/systemservices/MediaUtils.h | 197 ++ dom/media/systemservices/PMedia.ipdl | 35 + dom/media/systemservices/moz.build | 16 + dom/media/webm/WebMReader.cpp | 2 +- .../webrtc/MediaEngineCameraVideoSource.cpp | 36 +- .../webrtc/MediaEngineCameraVideoSource.h | 2 + dom/media/webrtc/MediaEngineWebRTC.cpp | 6 +- dom/media/webrtc/MediaEngineWebRTC.h | 2 +- dom/media/webrtc/moz.build | 2 +- dom/plugins/base/moz.build | 10 - dom/plugins/ipc/PluginAsyncSurrogate.cpp | 2 +- dom/plugins/test/mochitest/cocoa_focus.html | 2 +- dom/quota/QuotaManager.cpp | 32 +- dom/quota/QuotaManager.h | 31 - editor/libeditor/tests/test_bug417418.html | 1 + embedding/browser/nsDocShellTreeOwner.cpp | 2 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 3 + gfx/layers/ipc/ImageBridgeChild.cpp | 4 +- gfx/layers/ipc/ImageBridgeParent.cpp | 2 +- gfx/layers/ipc/LayerTransactionParent.cpp | 2 +- gfx/layers/ipc/ShadowLayers.cpp | 2 +- hal/Hal.cpp | 92 +- hal/Hal.h | 9 +- hal/HalTypes.h | 15 +- hal/fallback/FallbackProcessPriority.cpp | 8 +- hal/gonk/GonkHal.cpp | 17 +- hal/sandbox/SandboxHal.cpp | 5 +- ipc/glue/BackgroundChildImpl.cpp | 13 + ipc/glue/BackgroundChildImpl.h | 6 + ipc/glue/BackgroundImpl.cpp | 2 +- ipc/glue/BackgroundParentImpl.cpp | 13 + ipc/glue/BackgroundParentImpl.h | 6 + ipc/glue/PBackground.ipdl | 3 + ipc/glue/ProtocolUtils.cpp | 4 +- ipc/glue/ProtocolUtils.h | 1 - ipc/ipdl/ipdl/cxx/cgen.py | 2 +- ipc/ipdl/ipdl/lower.py | 5 +- ipc/ipdl/test/cxx/PTestBridgeMain.ipdl | 1 + ipc/ipdl/test/cxx/TestBridgeMain.h | 10 + ipc/ipdl/test/cxx/TestDataStructures.cpp | 2 +- ipc/ipdl/test/cxx/TestFailedCtor.cpp | 2 +- js/xpconnect/src/Sandbox.cpp | 36 +- js/xpconnect/src/xpcprivate.h | 2 + layout/xul/nsImageBoxFrame.cpp | 6 +- .../src/peerconnection/PeerConnectionCtx.h | 6 +- parser/html/javasrc/Tokenizer.java | 2 +- parser/html/nsHtml5Tokenizer.cpp | 2 +- security/manager/ssl/src/nsNSSModule.cpp | 8 +- toolkit/content/tests/browser/browser.ini | 2 +- toolkit/content/widgets/browser.xml | 4 +- toolkit/forgetaboutsite/ForgetAboutSite.jsm | 2 +- toolkit/library/moz.build | 2 +- .../extensions/internal/GMPProvider.jsm | 2 +- widget/MouseEvents.h | 7 + widget/PuppetBidiKeyboard.cpp | 46 + widget/PuppetBidiKeyboard.h | 35 + widget/android/APZCCallbackHandler.cpp | 180 -- widget/android/APZCCallbackHandler.h | 68 - widget/android/AndroidBridge.cpp | 2089 -------------- widget/android/AndroidBridge.h | 610 ---- widget/android/AndroidBridgeUtilities.h | 13 - widget/android/AndroidDirectTexture.cpp | 126 - widget/android/AndroidDirectTexture.h | 59 - widget/android/AndroidGraphicBuffer.cpp | 501 ---- widget/android/AndroidGraphicBuffer.h | 73 - widget/android/AndroidJNI.cpp | 1037 ------- widget/android/AndroidJNIWrapper.cpp | 124 - widget/android/AndroidJNIWrapper.h | 34 - widget/android/AndroidJavaWrappers.cpp | 1073 ------- widget/android/AndroidJavaWrappers.h | 799 ------ widget/android/GeneratedJNIWrappers.cpp | 1312 --------- widget/android/GeneratedJNIWrappers.h | 2545 ----------------- widget/android/GfxInfo.cpp | 638 ----- widget/android/GfxInfo.h | 102 - widget/android/NativeJSContainer.cpp | 1011 ------- widget/android/NativeJSContainer.h | 21 - widget/android/android/StrongPointer.h | 239 -- widget/android/bindings/Makefile.in | 32 - .../android/bindings/MediaCodec-classes.txt | 3 - .../bindings/SurfaceTexture-classes.txt | 2 - widget/android/bindings/moz.build | 35 - widget/android/jni/Accessors.h | 287 -- widget/android/jni/Refs.h | 644 ----- widget/android/jni/Types.h | 120 - widget/android/jni/Utils.cpp | 43 - widget/android/jni/Utils.h | 27 - widget/android/jni/moz.build | 24 - widget/android/moz.build | 65 - widget/android/nsAndroidProtocolHandler.cpp | 182 -- widget/android/nsAndroidProtocolHandler.h | 37 - widget/android/nsAppShell.cpp | 848 ------ widget/android/nsAppShell.h | 79 - widget/android/nsClipboard.cpp | 116 - widget/android/nsClipboard.h | 23 - widget/android/nsDeviceContextAndroid.cpp | 86 - widget/android/nsDeviceContextAndroid.h | 32 - widget/android/nsIAndroidBridge.idl | 75 - widget/android/nsIMEPicker.cpp | 27 - widget/android/nsIMEPicker.h | 22 - widget/android/nsIdleServiceAndroid.cpp | 23 - widget/android/nsIdleServiceAndroid.h | 36 - widget/android/nsLookAndFeel.cpp | 495 ---- widget/android/nsLookAndFeel.h | 36 - widget/android/nsPrintOptionsAndroid.cpp | 36 - widget/android/nsPrintOptionsAndroid.h | 23 - widget/android/nsScreenManagerAndroid.cpp | 125 - widget/android/nsScreenManagerAndroid.h | 46 - widget/android/nsWidgetFactory.cpp | 130 - widget/android/nsWindow.cpp | 2499 ---------------- widget/android/nsWindow.h | 255 -- widget/cocoa/TextInputHandler.h | 2 + widget/cocoa/TextInputHandler.mm | 17 + widget/cocoa/moz.build | 1 + widget/cocoa/nsWidgetFactory.mm | 6 +- widget/gtk/mozgtk/mozgtk.c | 1 + widget/gtk/nsBidiKeyboard.cpp | 34 +- widget/gtk/nsDragService.cpp | 33 +- widget/gtk/nsDragService.h | 7 +- widget/moz.build | 15 +- widget/nsBaseDragService.cpp | 70 + widget/nsBaseDragService.h | 15 + widget/nsBaseWidget.cpp | 2 +- widget/nsContentProcessWidgetFactory.cpp | 12 + widget/nsDragServiceProxy.cpp | 87 + widget/nsDragServiceProxy.h | 27 + widget/nsGUIEventIPC.h | 23 + widget/nsIDragService.idl | 14 +- widget/nsIDragSession.idl | 12 +- widget/nsPrintSettingsImpl.cpp | 1 + widget/nsWidgetsCID.h | 3 + xpcom/glue/nsTArray-inl.h | 11 +- xpcom/glue/nsTArray.h | 7 +- 259 files changed, 8481 insertions(+), 23525 deletions(-) delete mode 100644 dom/browser-element/mochitest/priority/CAUTION create mode 100644 dom/browser-element/mochitest/priority/test_ForegroundLRU.html delete mode 100644 dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html delete mode 100644 dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html create mode 100644 dom/camera/FallbackCameraPlatform.cpp create mode 100644 dom/camera/FallbackCameraPlatform.h create mode 100644 dom/media/gmp/GMPContentChild.cpp create mode 100644 dom/media/gmp/GMPContentChild.h create mode 100644 dom/media/gmp/GMPContentParent.cpp create mode 100644 dom/media/gmp/GMPContentParent.h create mode 100644 dom/media/gmp/GMPServiceChild.cpp create mode 100644 dom/media/gmp/GMPServiceChild.h create mode 100644 dom/media/gmp/GMPServiceParent.cpp create mode 100644 dom/media/gmp/GMPServiceParent.h create mode 100644 dom/media/gmp/PGMPContent.ipdl create mode 100644 dom/media/gmp/PGMPService.ipdl create mode 100644 dom/media/gmp/mozIGeckoMediaPluginChromeService.idl create mode 100644 dom/media/mediasource/ResourceQueue.cpp create mode 100644 dom/media/systemservices/MediaChild.cpp create mode 100644 dom/media/systemservices/MediaChild.h create mode 100644 dom/media/systemservices/MediaParent.cpp create mode 100644 dom/media/systemservices/MediaParent.h create mode 100644 dom/media/systemservices/MediaUtils.cpp create mode 100644 dom/media/systemservices/MediaUtils.h create mode 100644 dom/media/systemservices/PMedia.ipdl create mode 100644 widget/PuppetBidiKeyboard.cpp create mode 100644 widget/PuppetBidiKeyboard.h delete mode 100644 widget/android/APZCCallbackHandler.cpp delete mode 100644 widget/android/APZCCallbackHandler.h delete mode 100644 widget/android/AndroidBridge.cpp delete mode 100644 widget/android/AndroidBridge.h delete mode 100644 widget/android/AndroidBridgeUtilities.h delete mode 100644 widget/android/AndroidDirectTexture.cpp delete mode 100644 widget/android/AndroidDirectTexture.h delete mode 100644 widget/android/AndroidGraphicBuffer.cpp delete mode 100644 widget/android/AndroidGraphicBuffer.h delete mode 100644 widget/android/AndroidJNI.cpp delete mode 100644 widget/android/AndroidJNIWrapper.cpp delete mode 100644 widget/android/AndroidJNIWrapper.h delete mode 100644 widget/android/AndroidJavaWrappers.cpp delete mode 100644 widget/android/AndroidJavaWrappers.h delete mode 100644 widget/android/GeneratedJNIWrappers.cpp delete mode 100644 widget/android/GeneratedJNIWrappers.h delete mode 100644 widget/android/GfxInfo.cpp delete mode 100644 widget/android/GfxInfo.h delete mode 100644 widget/android/NativeJSContainer.cpp delete mode 100644 widget/android/NativeJSContainer.h delete mode 100644 widget/android/android/StrongPointer.h delete mode 100644 widget/android/bindings/Makefile.in delete mode 100644 widget/android/bindings/MediaCodec-classes.txt delete mode 100644 widget/android/bindings/SurfaceTexture-classes.txt delete mode 100644 widget/android/bindings/moz.build delete mode 100644 widget/android/jni/Accessors.h delete mode 100644 widget/android/jni/Refs.h delete mode 100644 widget/android/jni/Types.h delete mode 100644 widget/android/jni/Utils.cpp delete mode 100644 widget/android/jni/Utils.h delete mode 100644 widget/android/jni/moz.build delete mode 100644 widget/android/moz.build delete mode 100644 widget/android/nsAndroidProtocolHandler.cpp delete mode 100644 widget/android/nsAndroidProtocolHandler.h delete mode 100644 widget/android/nsAppShell.cpp delete mode 100644 widget/android/nsAppShell.h delete mode 100644 widget/android/nsClipboard.cpp delete mode 100644 widget/android/nsClipboard.h delete mode 100644 widget/android/nsDeviceContextAndroid.cpp delete mode 100644 widget/android/nsDeviceContextAndroid.h delete mode 100644 widget/android/nsIAndroidBridge.idl delete mode 100644 widget/android/nsIMEPicker.cpp delete mode 100644 widget/android/nsIMEPicker.h delete mode 100644 widget/android/nsIdleServiceAndroid.cpp delete mode 100644 widget/android/nsIdleServiceAndroid.h delete mode 100644 widget/android/nsLookAndFeel.cpp delete mode 100644 widget/android/nsLookAndFeel.h delete mode 100644 widget/android/nsPrintOptionsAndroid.cpp delete mode 100644 widget/android/nsPrintOptionsAndroid.h delete mode 100644 widget/android/nsScreenManagerAndroid.cpp delete mode 100644 widget/android/nsScreenManagerAndroid.h delete mode 100644 widget/android/nsWidgetFactory.cpp delete mode 100644 widget/android/nsWindow.cpp delete mode 100644 widget/android/nsWindow.h create mode 100644 widget/nsDragServiceProxy.cpp create mode 100644 widget/nsDragServiceProxy.h diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 08c60efdbe..44462914c9 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -640,10 +640,11 @@ pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000); pref("dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", 5000); pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000); -// Number of different background levels for background processes. We use -// these different levels to force the low-memory killer to kill processes in -// a LRU order. -pref("dom.ipc.processPriorityManager.backgroundLRUPoolLevels", 5); +// Number of different background/foreground levels for background/foreground +// processes. We use these different levels to force the low-memory killer to +// kill processes in a LRU order. +pref("dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels", 5); +pref("dom.ipc.processPriorityManager.FOREGROUND.LRUPoolLevels", 3); // Kernel parameters for process priorities. These affect how processes are // killed on low-memory and their relative CPU priorities. diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js index 0692e84433..ed86110037 100644 --- a/browser/base/content/sanitize.js +++ b/browser/base/content/sanitize.js @@ -156,6 +156,11 @@ Sanitizer.prototype = { cookieMgr.removeAll(); } + // Clear deviceIds. Done asynchronously (returns before complete). + let mediaMgr = Components.classes["@mozilla.org/mediaManagerService;1"] + .getService(Ci.nsIMediaManagerService); + mediaMgr.sanitizeDeviceIds(this.range && this.range[0]); + // Clear plugin data. const phInterface = Ci.nsIPluginHost; const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL; diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 203ec5ba30..bbc3a3e140 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1983,8 +1983,8 @@ Navigator::OnNavigation() } #ifdef MOZ_MEDIA_NAVIGATOR - // Inform MediaManager in case there are live streams or pending callbacks. - MediaManager *manager = MediaManager::Get(); + // If MediaManager is open let it inform any live streams or pending callbacks + MediaManager *manager = MediaManager::GetIfExists(); if (manager) { manager->OnNavigation(mWindow->WindowID()); } diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp index 23a1e2cd75..174fb060fd 100644 --- a/dom/base/nsContentAreaDragDrop.cpp +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -32,6 +32,7 @@ #include "nsServiceManagerUtils.h" #include "nsNetUtil.h" #include "nsIFile.h" +#include "nsFrameLoader.h" #include "nsIWebNavigation.h" #include "nsIDocShell.h" #include "nsIContent.h" @@ -52,6 +53,7 @@ #include "mozilla/dom/DataTransfer.h" #include "nsIMIMEInfo.h" #include "nsRange.h" +#include "TabParent.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/HTMLAreaElement.h" @@ -414,8 +416,21 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, dsti && dsti->ItemType() == nsIDocShellTreeItem::typeChrome; // In chrome shells, only allow dragging inside editable areas. - if (isChromeShell && !editingElement) + if (isChromeShell && !editingElement) { + nsCOMPtr flo = do_QueryInterface(mTarget); + if (flo) { + nsRefPtr fl = flo->GetFrameLoader(); + if (fl) { + TabParent* tp = static_cast(fl->GetRemoteBrowser()); + if (tp) { + // We have a TabParent, so it may have data for dnd in case the child + // process started a dnd session. + tp->AddInitialDnDDataTo(aDataTransfer); + } + } + } return NS_OK; + } if (isChromeShell && textControl) { // Only use the selection if the target node is in the selection. diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index bb2d7761ea..bb26fb3390 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -35,11 +35,14 @@ #include "mozilla/DebugOnly.h" #include "mozilla/LoadInfo.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/dom/HTMLTemplateElement.h" #include "mozilla/dom/HTMLContentElement.h" #include "mozilla/dom/HTMLShadowElement.h" +#include "mozilla/dom/ipc/BlobChild.h" +#include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TabParent.h" @@ -7365,3 +7368,94 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrCSPInternal(nsContentPolicy } +void +nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables, + nsTArray& aIPC, + mozilla::dom::nsIContentChild* aChild, + mozilla::dom::nsIContentParent* aParent) +{ + aIPC.Clear(); + MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent)); + if (aTransferables) { + uint32_t transferableCount = 0; + aTransferables->Count(&transferableCount); + for (uint32_t i = 0; i < transferableCount; ++i) { + IPCDataTransfer* dt = aIPC.AppendElement(); + nsCOMPtr genericItem; + aTransferables->GetElementAt(i, getter_AddRefs(genericItem)); + nsCOMPtr item(do_QueryInterface(genericItem)); + if (item) { + nsCOMPtr flavorList; + item->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); + if (flavorList) { + uint32_t flavorCount = 0; + flavorList->Count(&flavorCount); + for (uint32_t j = 0; j < flavorCount; ++j) { + nsCOMPtr flavor = do_QueryElementAt(flavorList, j); + if (!flavor) { + continue; + } + + nsAutoCString flavorStr; + flavor->GetData(flavorStr); + if (!flavorStr.Length()) { + continue; + } + + nsCOMPtr data; + uint32_t dataLen = 0; + item->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen); + + nsCOMPtr text = do_QueryInterface(data); + if (text) { + nsAutoString dataAsString; + text->GetData(dataAsString); + IPCDataTransferItem* item = dt->items().AppendElement(); + item->flavor() = nsCString(flavorStr); + item->data() = nsString(dataAsString); + } else { + nsCOMPtr sip = + do_QueryInterface(data); + if (sip) { + sip->GetData(getter_AddRefs(data)); + } + nsCOMPtr fileImpl; + nsCOMPtr file = do_QueryInterface(data); + if (file) { + fileImpl = new FileImplFile(file, false); + ErrorResult rv; + fileImpl->GetSize(rv); + fileImpl->GetLastModified(rv); + } else { + fileImpl = do_QueryInterface(data); + } + if (fileImpl) { + IPCDataTransferItem* item = dt->items().AppendElement(); + item->flavor() = nsCString(flavorStr); + if (aChild) { + item->data() = + mozilla::dom::BlobChild::GetOrCreate(aChild, + static_cast(fileImpl.get())); + } else if (aParent) { + item->data() = + mozilla::dom::BlobParent::GetOrCreate(aParent, + static_cast(fileImpl.get())); + } + } else { + // This is a hack to support kFilePromiseMime. + // On Windows there just needs to be an entry for it, + // and for OSX we need to create + // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider. + if (flavorStr.EqualsLiteral(kFilePromiseMime)) { + IPCDataTransferItem* item = dt->items().AppendElement(); + item->flavor() = nsCString(flavorStr); + item->data() = NS_ConvertUTF8toUTF16(flavorStr); + } + } + } + } + } + } + } + } +} diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index b5f5a9e4c0..cdf395fa35 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -87,6 +87,7 @@ class nsIScriptGlobalObject; class nsIScriptSecurityManager; class nsIStringBundle; class nsIStringBundleService; +class nsISupportsArray; class nsISupportsHashKey; class nsIURI; class nsIWidget; @@ -120,7 +121,10 @@ namespace dom { class DocumentFragment; class Element; class EventTarget; +class IPCDataTransfer; class NodeInfo; +class nsIContentChild; +class nsIContentParent; class Selection; class TabParent; } // namespace dom @@ -2373,6 +2377,10 @@ public: CallOnRemoteChildFunction aCallback, void* aArg); + static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables, + nsTArray& aIPC, + mozilla::dom::nsIContentChild* aChild, + mozilla::dom::nsIContentParent* aParent); private: static bool InitializeEventTable(); diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp index 3dacea5be1..50fce64cd6 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp @@ -1117,9 +1117,9 @@ PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU) return NS_ERROR_ILLEGAL_VALUE; /* integer overflow detected */ } - PRUint32 clen = cstr.Length() + 1; /* include \0 character */ + uint32_t clen = cstr.Length() + 1; /* include \0 character */ - rv = PackPDU(PackConversion(clen), aPDU); + rv = PackPDU(PackConversion(clen), aPDU); if (NS_FAILED(rv)) { return rv; } diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp index daef6083fa..540985f05f 100644 --- a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp @@ -1070,9 +1070,9 @@ PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU) return NS_ERROR_ILLEGAL_VALUE; /* integer overflow detected */ } - PRUint32 clen = cstr.Length() + 1; /* include \0 character */ + uint32_t clen = cstr.Length() + 1; /* include \0 character */ - rv = PackPDU(PackConversion(clen), aPDU); + rv = PackPDU(PackConversion(clen), aPDU); if (NS_FAILED(rv)) { return rv; } diff --git a/dom/browser-element/mochitest/browserElementTestHelpers.js b/dom/browser-element/mochitest/browserElementTestHelpers.js index f6d9a86719..007b0300cc 100644 --- a/dom/browser-element/mochitest/browserElementTestHelpers.js +++ b/dom/browser-element/mochitest/browserElementTestHelpers.js @@ -50,9 +50,10 @@ const browserElementTestHelpers = { enableProcessPriorityManager: function() { this._setPrefs( + ['dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2], + ['dom.ipc.processPriorityManager.FOREGROUND.LRUPoolLevels', 2], ['dom.ipc.processPriorityManager.testMode', true], - ['dom.ipc.processPriorityManager.enabled', true], - ['dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2] + ['dom.ipc.processPriorityManager.enabled', true] ); }, @@ -111,8 +112,7 @@ const browserElementTestHelpers = { // Returns a promise which is resolved when a subprocess is created. The // argument to resolve() is the childID of the subprocess. -function expectProcessCreated(/* optional */ initialPriority, - /* optional */ initialCPUPriority) { +function expectProcessCreated(/* optional */ initialPriority) { return new Promise(function(resolve, reject) { var observed = false; browserElementTestHelpers.addProcessPriorityObserver( @@ -128,7 +128,7 @@ function expectProcessCreated(/* optional */ initialPriority, var childID = parseInt(data); ok(true, 'Got new process, id=' + childID); if (initialPriority) { - expectPriorityChange(childID, initialPriority, initialCPUPriority).then(function() { + expectPriorityChange(childID, initialPriority).then(function() { resolve(childID); }); } else { @@ -141,9 +141,8 @@ function expectProcessCreated(/* optional */ initialPriority, // Just like expectProcessCreated(), except we'll call ok(false) if a second // process is created. -function expectOnlyOneProcessCreated(/* optional */ initialPriority, - /* optional */ initialCPUPriority) { - var p = expectProcessCreated(initialPriority, initialCPUPriority); +function expectOnlyOneProcessCreated(/* optional */ initialPriority) { + var p = expectProcessCreated(initialPriority); p.then(function() { expectProcessCreated().then(function(childID) { ok(false, 'Got unexpected process creation, childID=' + childID); @@ -153,15 +152,10 @@ function expectOnlyOneProcessCreated(/* optional */ initialPriority, } // Returns a promise which is resolved or rejected the next time the process -// childID changes its priority. We resolve if the (priority, CPU priority) -// tuple matches (expectedPriority, expectedCPUPriority) and we reject -// otherwise. -// -// expectedCPUPriority is an optional argument; if it's not specified, we -// resolve if priority matches expectedPriority. +// childID changes its priority. We resolve if the priority matches +// expectedPriority, and we reject otherwise. -function expectPriorityChange(childID, expectedPriority, - /* optional */ expectedCPUPriority) { +function expectPriorityChange(childID, expectedPriority) { return new Promise(function(resolve, reject) { var observed = false; browserElementTestHelpers.addProcessPriorityObserver( @@ -171,7 +165,7 @@ function expectPriorityChange(childID, expectedPriority, return; } - var [id, priority, cpuPriority] = data.split(":"); + var [id, priority] = data.split(":"); if (id != childID) { return; } @@ -184,14 +178,7 @@ function expectPriorityChange(childID, expectedPriority, 'Expected priority of childID ' + childID + ' to change to ' + expectedPriority); - if (expectedCPUPriority) { - is(cpuPriority, expectedCPUPriority, - 'Expected CPU priority of childID ' + childID + - ' to change to ' + expectedCPUPriority); - } - - if (priority == expectedPriority && - (!expectedCPUPriority || expectedCPUPriority == cpuPriority)) { + if (priority == expectedPriority) { resolve(); } else { reject(); @@ -201,27 +188,37 @@ function expectPriorityChange(childID, expectedPriority, }); } -// Returns a promise which is resolved or rejected the next time the background -// process childID changes its priority. We resolve if the backgroundLRU -// matches expectedBackgroundLRU and we reject otherwise. +// Returns a promise which is resolved or rejected the next time the +// process childID changes its priority. We resolve if the expectedPriority +// matches the priority and the LRU parameter matches expectedLRU and we +// reject otherwise. -function expectPriorityWithBackgroundLRUSet(childID, expectedBackgroundLRU) { +function expectPriorityWithLRUSet(childID, expectedPriority, expectedLRU) { return new Promise(function(resolve, reject) { - + var observed = false; browserElementTestHelpers.addProcessPriorityObserver( - 'process-priority-with-background-LRU-set', + 'process-priority-with-LRU-set', function(subject, topic, data) { + if (observed) { + return; + } - var [id, priority, cpuPriority, backgroundLRU] = data.split(":"); + var [id, priority, lru] = data.split(":"); if (id != childID) { return; } - is(backgroundLRU, expectedBackgroundLRU, - 'Expected backgroundLRU ' + backgroundLRU + ' of childID ' + childID + - ' to change to ' + expectedBackgroundLRU); + // Make sure we run the is() calls in this observer only once, + // otherwise we'll expect /every/ priority/LRU change to match + // expectedPriority/expectedLRU. + observed = true; - if (backgroundLRU == expectedBackgroundLRU) { + is(lru, expectedLRU, + 'Expected LRU ' + lru + + ' of childID ' + childID + + ' to change to ' + expectedLRU); + + if ((priority == expectedPriority) && (lru == expectedLRU)) { resolve(); } else { reject(); diff --git a/dom/browser-element/mochitest/priority/CAUTION b/dom/browser-element/mochitest/priority/CAUTION deleted file mode 100644 index 5b878888ed..0000000000 --- a/dom/browser-element/mochitest/priority/CAUTION +++ /dev/null @@ -1,15 +0,0 @@ -A word to the wise: - -You must ensure that if your test finishes successfully, no processes have -priority FOREGROUND_HIGH. - -If you don't do this, expect to see tests randomly fail with mysterious -FOREGROUND --> FOREGROUND priority transitions. - -What's happening in this case is that your FOREGROUND_HIGH process lives until -the beginning of the next test. This causes the process started by the next -test to have low CPU priority. Then the FOREGROUND_HIGH process dies, because -its iframe gets GC'ed, and we transition the new test's process from low CPU -priority to regular CPU priority. - -Ouch. diff --git a/dom/browser-element/mochitest/priority/mochitest.ini b/dom/browser-element/mochitest/priority/mochitest.ini index a0804148e5..2f6ae1ee92 100644 --- a/dom/browser-element/mochitest/priority/mochitest.ini +++ b/dom/browser-element/mochitest/priority/mochitest.ini @@ -10,12 +10,11 @@ skip-if = toolkit != "gtk2" || ((buildapp =='mulet' || buildapp == 'b2g') && (to [test_Visibility.html] [test_HighPriority.html] support-files = file_HighPriority.html -[test_HighPriorityDowngrade.html] -[test_HighPriorityDowngrade2.html] [test_Background.html] [test_BackgroundLRU.html] [test_Audio.html] support-files = file_Audio.html silence.ogg +[test_ForegroundLRU.html] [test_Keyboard.html] [test_MultipleFrames.html] support-files = file_MultipleFrames.html diff --git a/dom/browser-element/mochitest/priority/test_BackgroundLRU.html b/dom/browser-element/mochitest/priority/test_BackgroundLRU.html index 183c2671ef..692c362674 100644 --- a/dom/browser-element/mochitest/priority/test_BackgroundLRU.html +++ b/dom/browser-element/mochitest/priority/test_BackgroundLRU.html @@ -46,19 +46,22 @@ function runTest() { document.body.appendChild(iframe2); // At this point, we should have iframe1 in background already. - // We wait until another one is set to background, too. - // Once there are two in background, the first one (LRU order) - // should have 'backgroundLRU' equals 1 - var p = expectPriorityWithBackgroundLRUSet(childID, '1'); + // We wait until another process goes into the background, too. + // Once there are two in background, the first one should have its LRU + // adjustment value increased to 1. + var p = expectPriorityWithLRUSet(childID, 'BACKGROUND', '1'); iframe2.setVisible(false); return p; }).then(function() { - // Don't call removeChild immediately after calling setVisible. - // setVisible on remote browser is async method, so we should wait - // until it sends to the child process. + // When iframe2 is removed iframe1's LRU value should be decreased again. + var p = expectPriorityWithLRUSet(childID, 'BACKGROUND', '0'); + document.body.removeChild(iframe2); + + return p; + }).then(function() { SimpleTest.finish(); }); diff --git a/dom/browser-element/mochitest/priority/test_ForegroundLRU.html b/dom/browser-element/mochitest/priority/test_ForegroundLRU.html new file mode 100644 index 0000000000..64f2895e2e --- /dev/null +++ b/dom/browser-element/mochitest/priority/test_ForegroundLRU.html @@ -0,0 +1,80 @@ + + + + + + + + + + + + + diff --git a/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html b/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html deleted file mode 100644 index 3f2d71b0ff..0000000000 --- a/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - diff --git a/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html b/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html deleted file mode 100644 index 4947334108..0000000000 --- a/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - diff --git a/dom/browser-element/mochitest/priority/test_Preallocated.html b/dom/browser-element/mochitest/priority/test_Preallocated.html index f96eee878c..b2cb0335ee 100644 --- a/dom/browser-element/mochitest/priority/test_Preallocated.html +++ b/dom/browser-element/mochitest/priority/test_Preallocated.html @@ -53,7 +53,7 @@ function runTest() // Ensure that the preallocated process initially gets BACKGROUND priority. // That's it. - expectProcessCreated('PREALLOC', 'CPU_LOW').then(function() { + expectProcessCreated('PREALLOC').then(function() { // We need to set the pref asynchoronously or the preallocated process won't // be shut down. SimpleTest.executeSoon(function(){ diff --git a/dom/camera/CameraPreferences.cpp b/dom/camera/CameraPreferences.cpp index 8b49478710..0b3cd55038 100644 --- a/dom/camera/CameraPreferences.cpp +++ b/dom/camera/CameraPreferences.cpp @@ -31,6 +31,8 @@ uint32_t CameraPreferences::sPrefCameraControlLowMemoryThresholdMB = 0; bool CameraPreferences::sPrefCameraParametersIsLowMemory = false; +bool CameraPreferences::sPrefCameraParametersPermission = false; + #ifdef MOZ_WIDGET_GONK StaticRefPtr CameraPreferences::sObserver; @@ -113,6 +115,11 @@ CameraPreferences::Pref CameraPreferences::sPrefs[] = { kPrefValueIsCString, { &sPrefHardwareTest } }, + { + "camera.control.test.permission", + kPrefValueIsBoolean, + { &sPrefCameraParametersPermission } + }, #ifdef MOZ_B2G { "camera.control.test.hardware.gonk.parameters", diff --git a/dom/camera/CameraPreferences.h b/dom/camera/CameraPreferences.h index 7fd09aeb40..274c2b1d12 100644 --- a/dom/camera/CameraPreferences.h +++ b/dom/camera/CameraPreferences.h @@ -80,6 +80,8 @@ protected: static bool sPrefCameraParametersIsLowMemory; + static bool sPrefCameraParametersPermission; + #ifdef MOZ_WIDGET_GONK static StaticRefPtr sObserver; diff --git a/dom/camera/DOMCameraManager.cpp b/dom/camera/DOMCameraManager.cpp index 88286d576e..9a30e2aabd 100644 --- a/dom/camera/DOMCameraManager.cpp +++ b/dom/camera/DOMCameraManager.cpp @@ -16,6 +16,7 @@ #include "DOMCameraControl.h" #include "nsDOMClassInfo.h" #include "CameraCommon.h" +#include "CameraPreferences.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/PermissionMessageUtils.h" @@ -298,7 +299,11 @@ nsDOMCameraManager::GetCamera(const nsAString& aCamera, // which gets us a performance win. uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED; principal->GetAppStatus(&status); - if (status == nsIPrincipal::APP_STATUS_CERTIFIED && CheckPermission(mWindow)) { + // Unprivileged mochitests always fail the dispatched permission check, + // even if permission to the camera has been granted. + bool immediateCheck = false; + CameraPreferences::GetPref("camera.control.test.permission", immediateCheck); + if ((status == nsIPrincipal::APP_STATUS_CERTIFIED || immediateCheck) && CheckPermission(mWindow)) { PermissionAllowed(cameraId, aInitialConfig, promise); return promise.forget(); } diff --git a/dom/camera/FallbackCameraPlatform.cpp b/dom/camera/FallbackCameraPlatform.cpp new file mode 100644 index 0000000000..5da2755517 --- /dev/null +++ b/dom/camera/FallbackCameraPlatform.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2015 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FallbackCameraPlatform.h" + +using namespace android; + +MediaProfiles* MediaProfiles::sMediaProfiles = nullptr; + +const char CameraParameters::KEY_PREVIEW_SIZE[] = "preview-size"; +const char CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES[] = "preview-size-values"; +const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format"; +const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values"; +const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate"; +const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values"; +const char CameraParameters::KEY_PREVIEW_FPS_RANGE[] = "preview-fps-range"; +const char CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE[] = "preview-fps-range-values"; +const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size"; +const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values"; +const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format"; +const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values"; +const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width"; +const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height"; +const char CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values"; +const char CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY[] = "jpeg-thumbnail-quality"; +const char CameraParameters::KEY_JPEG_QUALITY[] = "jpeg-quality"; +const char CameraParameters::KEY_ROTATION[] = "rotation"; +const char CameraParameters::KEY_GPS_LATITUDE[] = "gps-latitude"; +const char CameraParameters::KEY_GPS_LONGITUDE[] = "gps-longitude"; +const char CameraParameters::KEY_GPS_ALTITUDE[] = "gps-altitude"; +const char CameraParameters::KEY_GPS_TIMESTAMP[] = "gps-timestamp"; +const char CameraParameters::KEY_GPS_PROCESSING_METHOD[] = "gps-processing-method"; +const char CameraParameters::KEY_WHITE_BALANCE[] = "whitebalance"; +const char CameraParameters::KEY_SUPPORTED_WHITE_BALANCE[] = "whitebalance-values"; +const char CameraParameters::KEY_EFFECT[] = "effect"; +const char CameraParameters::KEY_SUPPORTED_EFFECTS[] = "effect-values"; +const char CameraParameters::KEY_ANTIBANDING[] = "antibanding"; +const char CameraParameters::KEY_SUPPORTED_ANTIBANDING[] = "antibanding-values"; +const char CameraParameters::KEY_SCENE_MODE[] = "scene-mode"; +const char CameraParameters::KEY_SUPPORTED_SCENE_MODES[] = "scene-mode-values"; +const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode"; +const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values"; +const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode"; +const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values"; +const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas"; +const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas"; +const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length"; +const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle"; +const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle"; +const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensation"; +const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation"; +const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation"; +const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step"; +const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = "auto-exposure-lock"; +const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[] = "auto-exposure-lock-supported"; +const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK[] = "auto-whitebalance-lock"; +const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[] = "auto-whitebalance-lock-supported"; +const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas"; +const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas"; +const char CameraParameters::KEY_ZOOM[] = "zoom"; +const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom"; +const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios"; +const char CameraParameters::KEY_ZOOM_SUPPORTED[] = "zoom-supported"; +const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported"; +const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances"; +const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format"; +const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size"; +const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values"; +const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video"; +const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw"; +const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw"; +const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint"; +const char CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED[] = "video-snapshot-supported"; +const char CameraParameters::KEY_VIDEO_STABILIZATION[] = "video-stabilization"; +const char CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED[] = "video-stabilization-supported"; +const char CameraParameters::KEY_LIGHTFX[] = "light-fx"; + diff --git a/dom/camera/FallbackCameraPlatform.h b/dom/camera/FallbackCameraPlatform.h new file mode 100644 index 0000000000..53c4da752f --- /dev/null +++ b/dom/camera/FallbackCameraPlatform.h @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2015 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOM_CAMERA_FALLBACKCAMERAPLATFORM_H +#define DOM_CAMERA_FALLBACKCAMERAPLATFORM_H + +#include +#include + +typedef struct { + int32_t id; + int32_t score; + int32_t rect[4]; + int32_t left_eye[2]; + int32_t right_eye[2]; + int32_t mouth[2]; +} camera_face_t; + +typedef struct { + uint32_t number_of_faces; + camera_face_t* faces; +} camera_frame_metadata_t; + +namespace android { + enum camcorder_quality { + CAMCORDER_QUALITY_LOW, + CAMCORDER_QUALITY_HIGH, + CAMCORDER_QUALITY_QCIF, + CAMCORDER_QUALITY_CIF, + CAMCORDER_QUALITY_480P, + CAMCORDER_QUALITY_720P, + CAMCORDER_QUALITY_1080P, + CAMCORDER_QUALITY_QVGA, + CAMCORDER_QUALITY_VGA, + CAMCORDER_QUALITY_LIST_START = CAMCORDER_QUALITY_LOW, + CAMCORDER_QUALITY_LIST_END = CAMCORDER_QUALITY_VGA + }; + + enum output_format { + OUTPUT_FORMAT_THREE_GPP, + OUTPUT_FORMAT_MPEG_4 + }; + + enum video_encoder { + VIDEO_ENCODER_H263, + VIDEO_ENCODER_H264, + VIDEO_ENCODER_MPEG_4_SP + }; + + enum audio_encoder { + AUDIO_ENCODER_AMR_WB, + AUDIO_ENCODER_AMR_NB, + AUDIO_ENCODER_AAC + }; + + template + class sp final + { + public: + sp() + : mPtr(nullptr) + { } + + sp(T *aPtr) + : mPtr(aPtr) + { } + + virtual ~sp() { } + T* get() const { return mPtr; } + void clear() { mPtr = nullptr; } + T* operator->() const { return get(); } + + private: + nsRefPtr mPtr; + }; + + typedef uint64_t nsecs_t; + + enum error_t { + OK = 0, + UNKNOWN_ERROR, + INVALID_OPERATION + }; + + enum camera_msg_t { + CAMERA_MSG_SHUTTER, + CAMERA_MSG_COMPRESSED_IMAGE + }; + + class String8 final + { + public: + String8() { } + String8(const char* aData) { mData.AssignASCII(aData); } + virtual ~String8() { } + const char* string() const { return mData.Data(); } + + private: + nsCString mData; + }; + + enum camera_facing_t { + CAMERA_FACING_BACK, + CAMERA_FACING_FRONT + }; + + struct CameraInfo { + camera_facing_t facing; + }; + + class Camera final : public nsISupports + { + public: + NS_DECL_ISUPPORTS; + + void disconnect() { } + String8 getParameters() { return String8(); } + int setParameters(const String8& aParams) { return UNKNOWN_ERROR; } + int storeMetaDataInBuffers(bool aEnabled) { return UNKNOWN_ERROR; } + int autoFocus() { return UNKNOWN_ERROR; } + int cancelAutoFocus() { return UNKNOWN_ERROR; } + int takePicture(uint32_t flags) { return UNKNOWN_ERROR; } + int startPreview() { return UNKNOWN_ERROR; } + int stopPreview() { return UNKNOWN_ERROR; } + int startRecording() { return UNKNOWN_ERROR; } + int stopRecording() { return UNKNOWN_ERROR; } + int startFaceDetection() { return UNKNOWN_ERROR; } + int stopFaceDetection() { return UNKNOWN_ERROR; } + static int32_t getNumberOfCameras() { return 2; } + + static int getCameraInfo(int32_t aDevice, CameraInfo* aInfo) + { + switch (aDevice) { + case 0: + aInfo->facing = CAMERA_FACING_BACK; + break; + case 1: + aInfo->facing = CAMERA_FACING_FRONT; + break; + default: + return UNKNOWN_ERROR; + } + return OK; + } + + protected: + Camera() { } + virtual ~Camera() { } + + private: + Camera(const Camera&) = delete; + Camera& operator=(const Camera&) = delete; + }; + + class CameraParameters final + { + public: + static const char KEY_PREVIEW_SIZE[]; + static const char KEY_SUPPORTED_PREVIEW_SIZES[]; + static const char KEY_PREVIEW_FPS_RANGE[]; + static const char KEY_SUPPORTED_PREVIEW_FPS_RANGE[]; + static const char KEY_PREVIEW_FORMAT[]; + static const char KEY_SUPPORTED_PREVIEW_FORMATS[]; + static const char KEY_PREVIEW_FRAME_RATE[]; + static const char KEY_SUPPORTED_PREVIEW_FRAME_RATES[]; + static const char KEY_PICTURE_SIZE[]; + static const char KEY_SUPPORTED_PICTURE_SIZES[]; + static const char KEY_PICTURE_FORMAT[]; + static const char KEY_SUPPORTED_PICTURE_FORMATS[]; + static const char KEY_JPEG_THUMBNAIL_WIDTH[]; + static const char KEY_JPEG_THUMBNAIL_HEIGHT[]; + static const char KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[]; + static const char KEY_JPEG_THUMBNAIL_QUALITY[]; + static const char KEY_JPEG_QUALITY[]; + static const char KEY_ROTATION[]; + static const char KEY_GPS_LATITUDE[]; + static const char KEY_GPS_LONGITUDE[]; + static const char KEY_GPS_ALTITUDE[]; + static const char KEY_GPS_TIMESTAMP[]; + static const char KEY_GPS_PROCESSING_METHOD[]; + static const char KEY_WHITE_BALANCE[]; + static const char KEY_SUPPORTED_WHITE_BALANCE[]; + static const char KEY_EFFECT[]; + static const char KEY_SUPPORTED_EFFECTS[]; + static const char KEY_ANTIBANDING[]; + static const char KEY_SUPPORTED_ANTIBANDING[]; + static const char KEY_SCENE_MODE[]; + static const char KEY_SUPPORTED_SCENE_MODES[]; + static const char KEY_FLASH_MODE[]; + static const char KEY_SUPPORTED_FLASH_MODES[]; + static const char KEY_FOCUS_MODE[]; + static const char KEY_SUPPORTED_FOCUS_MODES[]; + static const char KEY_MAX_NUM_FOCUS_AREAS[]; + static const char KEY_FOCUS_AREAS[]; + static const char KEY_FOCAL_LENGTH[]; + static const char KEY_HORIZONTAL_VIEW_ANGLE[]; + static const char KEY_VERTICAL_VIEW_ANGLE[]; + static const char KEY_EXPOSURE_COMPENSATION[]; + static const char KEY_MAX_EXPOSURE_COMPENSATION[]; + static const char KEY_MIN_EXPOSURE_COMPENSATION[]; + static const char KEY_EXPOSURE_COMPENSATION_STEP[]; + static const char KEY_AUTO_EXPOSURE_LOCK[]; + static const char KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[]; + static const char KEY_AUTO_WHITEBALANCE_LOCK[]; + static const char KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[]; + static const char KEY_MAX_NUM_METERING_AREAS[]; + static const char KEY_METERING_AREAS[]; + static const char KEY_ZOOM[]; + static const char KEY_MAX_ZOOM[]; + static const char KEY_ZOOM_RATIOS[]; + static const char KEY_ZOOM_SUPPORTED[]; + static const char KEY_SMOOTH_ZOOM_SUPPORTED[]; + static const char KEY_FOCUS_DISTANCES[]; + static const char KEY_VIDEO_SIZE[]; + static const char KEY_SUPPORTED_VIDEO_SIZES[]; + static const char KEY_MAX_NUM_DETECTED_FACES_HW[]; + static const char KEY_MAX_NUM_DETECTED_FACES_SW[]; + static const char KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[]; + static const char KEY_VIDEO_FRAME_FORMAT[]; + static const char KEY_RECORDING_HINT[]; + static const char KEY_VIDEO_SNAPSHOT_SUPPORTED[]; + static const char KEY_VIDEO_STABILIZATION[]; + static const char KEY_VIDEO_STABILIZATION_SUPPORTED[]; + static const char KEY_LIGHTFX[]; + }; + + class MediaProfiles final + { + public: + static MediaProfiles* getInstance() { + if (!sMediaProfiles) { + sMediaProfiles = new MediaProfiles(); + } + return sMediaProfiles; + } + + bool hasCamcorderProfile(int aCameraId, camcorder_quality aQuality) const { + switch (aQuality) { + case CAMCORDER_QUALITY_LOW: + case CAMCORDER_QUALITY_HIGH: + case CAMCORDER_QUALITY_QVGA: + case CAMCORDER_QUALITY_VGA: + return true; + default: + break; + } + return false; + } + + int getCamcorderProfileParamByName(const char* aParameter, int aCameraId, camcorder_quality aQuality) const { + switch (aQuality) { + case CAMCORDER_QUALITY_LOW: + case CAMCORDER_QUALITY_QVGA: + if (strcmp(aParameter, "vid.width") == 0) { + return 320; + } else if (strcmp(aParameter, "vid.height") == 0) { + return 240; + } + return 0; + case CAMCORDER_QUALITY_HIGH: + case CAMCORDER_QUALITY_VGA: + if (strcmp(aParameter, "vid.width") == 0) { + return 640; + } else if (strcmp(aParameter, "vid.height") == 0) { + return 480; + } + return 0; + default: + break; + } + return -1; + } + + protected: + MediaProfiles() { } + virtual ~MediaProfiles() { } + + private: + MediaProfiles(const MediaProfiles&) = delete; + MediaProfiles& operator=(const MediaProfiles&) = delete; + + static MediaProfiles* sMediaProfiles; + }; +} + +#endif diff --git a/dom/camera/GonkCameraControl.cpp b/dom/camera/GonkCameraControl.cpp index 153d4f2628..77584176a7 100644 --- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -22,25 +22,24 @@ #include #include #include "base/basictypes.h" -#include "camera/CameraParameters.h" +#include "Layers.h" +#ifdef MOZ_WIDGET_GONK +#include +#include +#include "GrallocImages.h" +#endif #include "nsCOMPtr.h" #include "nsMemory.h" #include "nsThread.h" -#include #include "mozilla/FileUtils.h" #include "mozilla/Services.h" #include "mozilla/unused.h" #include "mozilla/ipc/FileDescriptorUtils.h" #include "nsAlgorithm.h" -#include #include "nsPrintfCString.h" -#include "nsIObserverService.h" -#include "nsIVolume.h" -#include "nsIVolumeService.h" #include "AutoRwLock.h" #include "GonkCameraHwMgr.h" #include "GonkRecorderProfiles.h" -#include "GrallocImages.h" #include "CameraCommon.h" #include "GonkCameraParameters.h" #include "DeviceStorageFileDescriptor.h" @@ -71,7 +70,9 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId) , mAutoFlashModeOverridden(false) , mSeparateVideoAndPreviewSizesSupported(false) , mDeferConfigUpdate(0) +#ifdef MOZ_WIDGET_GONK , mRecorder(nullptr) +#endif , mRecorderMonitor("GonkCameraControl::mRecorder.Monitor") , mVideoFile(nullptr) , mReentrantMonitor("GonkCameraControl::OnTakePicture.Monitor") @@ -1165,7 +1166,9 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri ReentrantMonitorAutoEnter mon(mRecorderMonitor); NS_ENSURE_TRUE(!mCurrentConfiguration.mRecorderProfile.IsEmpty(), NS_ERROR_NOT_INITIALIZED); +#ifdef MOZ_WIDGET_GONK NS_ENSURE_FALSE(mRecorder, NS_ERROR_FAILURE); +#endif /** * Get the base path from device storage and append the app-specified @@ -1212,6 +1215,7 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri return rv; } +#ifdef MOZ_WIDGET_GONK if (mRecorder->start() != OK) { DOM_CAMERA_LOGE("mRecorder->start() failed\n"); // important: we MUST destroy the recorder if start() fails! @@ -1222,6 +1226,7 @@ nsGonkCameraControl::StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescri } return NS_ERROR_FAILURE; } +#endif OnRecorderStateChange(CameraControlListener::kRecorderStarted); return NS_OK; @@ -1255,6 +1260,7 @@ nsGonkCameraControl::StopRecordingImpl() ReentrantMonitorAutoEnter mon(mRecorderMonitor); +#ifdef MOZ_WIDGET_GONK // nothing to do if we have no mRecorder if (!mRecorder) { return NS_OK; @@ -1277,6 +1283,9 @@ nsGonkCameraControl::StopRecordingImpl() // notify DeviceStorage that the new video file is closed and ready return NS_DispatchToMainThread(new RecordingComplete(mVideoFile)); +#else + return NS_OK; +#endif } nsresult @@ -1697,6 +1706,7 @@ nsGonkCameraControl::SetVideoConfiguration(const Configuration& aConfig) return NS_OK; } +#ifdef MOZ_WIDGET_GONK class GonkRecorderListener : public IMediaRecorderClient { public: @@ -1843,6 +1853,7 @@ nsGonkCameraControl::OnRecorderEvent(int msg, int ext1, int ext2) // All unhandled cases wind up here DOM_CAMERA_LOGW("recorder-event : unhandled: msg=%d, ext1=%d, ext2=%d\n", msg, ext1, ext2); } +#endif nsresult nsGonkCameraControl::SetupRecording(int aFd, int aRotation, @@ -1851,6 +1862,7 @@ nsGonkCameraControl::SetupRecording(int aFd, int aRotation, { RETURN_IF_NO_CAMERA_HW(); +#ifdef MOZ_WIDGET_GONK // choosing a size big enough to hold the params const size_t SIZE = 256; char buffer[SIZE]; @@ -1911,6 +1923,7 @@ nsGonkCameraControl::SetupRecording(int aFd, int aRotation, // recording API needs file descriptor of output file CHECK_SETARG_RETURN(mRecorder->setOutputFile(aFd, 0, 0), NS_ERROR_FAILURE); CHECK_SETARG_RETURN(mRecorder->prepare(), NS_ERROR_FAILURE); +#endif return NS_OK; } @@ -2046,6 +2059,7 @@ nsGonkCameraControl::OnRateLimitPreview(bool aLimit) void nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer) { +#ifdef MOZ_WIDGET_GONK nsRefPtr frame = mImageContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR); GrallocImage* videoImage = static_cast(frame.get()); @@ -2058,6 +2072,7 @@ nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer) OnNewPreviewFrame(frame, mCurrentConfiguration.mPreviewSize.width, mCurrentConfiguration.mPreviewSize.height); +#endif } void diff --git a/dom/camera/GonkCameraControl.h b/dom/camera/GonkCameraControl.h index 8cce3a46db..e2d6539fd2 100644 --- a/dom/camera/GonkCameraControl.h +++ b/dom/camera/GonkCameraControl.h @@ -19,18 +19,24 @@ #include "base/basictypes.h" #include "nsRefPtrHashtable.h" -#include #include "mozilla/ReentrantMonitor.h" #include "DeviceStorage.h" #include "CameraControlImpl.h" #include "CameraCommon.h" -#include "GonkRecorder.h" #include "GonkCameraHwMgr.h" #include "GonkCameraParameters.h" +#ifdef MOZ_WIDGET_GONK +#include +#include +#include "GonkRecorder.h" +#else +#include "FallbackCameraPlatform.h" +#endif + + namespace android { class GonkCameraHardware; - class MediaProfiles; class GonkRecorder; class GonkCameraSource; } @@ -56,7 +62,9 @@ public: void OnTakePictureError(); void OnRateLimitPreview(bool aLimit); void OnNewPreviewFrame(layers::TextureClient* aBuffer); +#ifdef MOZ_WIDGET_GONK void OnRecorderEvent(int msg, int ext1, int ext2); +#endif void OnSystemError(CameraControlListener::SystemContext aWhere, nsresult aError); // See ICameraControl.h for getter/setter return values. @@ -177,7 +185,9 @@ protected: nsRefPtr mImageContainer; +#ifdef MOZ_WIDGET_GONK nsRefPtr mRecorder; +#endif // Touching mRecorder happens inside this monitor because the destructor // can run on any thread, and we need to be able to clean up properly if // GonkCameraControl goes away. diff --git a/dom/camera/GonkCameraHwMgr.cpp b/dom/camera/GonkCameraHwMgr.cpp index 94df66a1aa..8c634f62dc 100644 --- a/dom/camera/GonkCameraHwMgr.cpp +++ b/dom/camera/GonkCameraHwMgr.cpp @@ -17,8 +17,11 @@ #include "GonkCameraHwMgr.h" #include "TestGonkCameraHardware.h" +#ifdef MOZ_WIDGET_GONK #include #include +#include "GonkNativeWindow.h" +#endif #include "base/basictypes.h" #include "nsDebug.h" @@ -26,19 +29,26 @@ #include "CameraPreferences.h" #include "mozilla/RefPtr.h" #include "GonkCameraControl.h" -#include "GonkNativeWindow.h" #include "CameraCommon.h" using namespace mozilla; using namespace mozilla::layers; using namespace android; +#ifndef MOZ_WIDGET_GONK +NS_IMPL_ISUPPORTS0(GonkCameraHardware); +NS_IMPL_ISUPPORTS0(android::Camera); +#endif + GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp& aCamera) : mCameraId(aCameraId) , mClosing(false) , mNumFrames(0) +#ifdef MOZ_WIDGET_GONK , mCamera(aCamera) +#endif , mTarget(aTarget) + , mRawSensorOrientation(0) , mSensorOrientation(0) { DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget); @@ -50,6 +60,7 @@ GonkCameraHardware::OnRateLimitPreview(bool aLimit) ::OnRateLimitPreview(mTarget, aLimit); } +#ifdef MOZ_WIDGET_GONK void GonkCameraHardware::OnNewFrame() { @@ -147,12 +158,14 @@ GonkCameraHardware::postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, cons mCamera->releaseRecordingFrame(aDataPtr); } } +#endif nsresult GonkCameraHardware::Init() { DOM_CAMERA_LOGT("%s: this=%p\n", __func__, (void* )this); +#ifdef MOZ_WIDGET_GONK CameraInfo info; int rv = Camera::getCameraInfo(mCameraId, &info); if (rv != 0) { @@ -181,8 +194,6 @@ GonkCameraHardware::Init() // Disable shutter sound in android CameraService because gaia camera app will play it mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0); -#if defined(MOZ_WIDGET_GONK) - #if ANDROID_VERSION >= 21 sp producer; sp consumer; @@ -227,10 +238,12 @@ GonkCameraHardware::Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCam CameraPreferences::GetPref("camera.control.test.enabled", test); if (!test.EqualsASCII("hardware")) { -#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18 +#ifdef MOZ_WIDGET_GONK +#if ANDROID_VERSION >= 18 camera = Camera::connect(aCameraId, /* clientPackageName */String16("gonk.camera"), Camera::USE_CALLING_UID); #else camera = Camera::connect(aCameraId); +#endif #endif if (camera.get() == nullptr) { @@ -266,21 +279,25 @@ GonkCameraHardware::Close() mCamera->stopPreview(); mCamera->disconnect(); } + mCamera.clear(); +#ifdef MOZ_WIDGET_GONK if (mNativeWindow.get()) { mNativeWindow->abandon(); } - mCamera.clear(); mNativeWindow.clear(); // Ensure that ICamera's destructor is actually executed IPCThreadState::self()->flushCommands(); +#endif } GonkCameraHardware::~GonkCameraHardware() { DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this); mCamera.clear(); +#ifdef MOZ_WIDGET_GONK mNativeWindow.clear(); +#endif } int @@ -366,13 +383,6 @@ GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams) return mCamera->setParameters(s); } -int -GonkCameraHardware::PushParameters(const CameraParameters& aParams) -{ - String8 s = aParams.flatten(); - return mCamera->setParameters(s); -} - nsresult GonkCameraHardware::PullParameters(GonkCameraParameters& aParams) { @@ -380,12 +390,21 @@ GonkCameraHardware::PullParameters(GonkCameraParameters& aParams) return aParams.Unflatten(s); } +#ifdef MOZ_WIDGET_GONK +int +GonkCameraHardware::PushParameters(const CameraParameters& aParams) +{ + String8 s = aParams.flatten(); + return mCamera->setParameters(s); +} + void GonkCameraHardware::PullParameters(CameraParameters& aParams) { const String8 s = mCamera->getParameters(); aParams.unflatten(s); } +#endif int GonkCameraHardware::StartPreview() @@ -422,6 +441,7 @@ GonkCameraHardware::StopRecording() return OK; } +#ifdef MOZ_WIDGET_GONK int GonkCameraHardware::SetListener(const sp& aListener) { @@ -434,6 +454,7 @@ GonkCameraHardware::ReleaseRecordingFrame(const sp& aFrame) { mCamera->releaseRecordingFrame(aFrame); } +#endif int GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled) diff --git a/dom/camera/GonkCameraHwMgr.h b/dom/camera/GonkCameraHwMgr.h index cd228547e0..1dc3a0b8d6 100644 --- a/dom/camera/GonkCameraHwMgr.h +++ b/dom/camera/GonkCameraHwMgr.h @@ -17,18 +17,21 @@ #ifndef DOM_CAMERA_GONKCAMERAHWMGR_H #define DOM_CAMERA_GONKCAMERAHWMGR_H +#include "GonkCameraControl.h" +#include "CameraCommon.h" +#include "GonkCameraParameters.h" +#include "mozilla/ReentrantMonitor.h" + +#ifdef MOZ_WIDGET_GONK #include #include #include #include - -#include "GonkCameraControl.h" -#include "CameraCommon.h" - #include "GonkCameraListener.h" #include "GonkNativeWindow.h" -#include "GonkCameraParameters.h" -#include "mozilla/ReentrantMonitor.h" +#else +#include "FallbackCameraPlatform.h" +#endif namespace mozilla { class nsGonkCameraControl; @@ -37,9 +40,18 @@ namespace mozilla { namespace android { -class GonkCameraHardware : public GonkNativeWindowNewFrameCallback - , public CameraListener +class GonkCameraHardware +#ifdef MOZ_WIDGET_GONK + : public GonkNativeWindowNewFrameCallback + , public CameraListener +#else + : public nsISupports +#endif { +#ifndef MOZ_WIDGET_GONK + NS_DECL_ISUPPORTS +#endif + protected: GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp& aCamera); virtual ~GonkCameraHardware(); @@ -57,6 +69,7 @@ public: virtual void OnRateLimitPreview(bool aLimit); +#ifdef MOZ_WIDGET_GONK // derived from GonkNativeWindowNewFrameCallback virtual void OnNewFrame() override; @@ -64,6 +77,7 @@ public: virtual void notify(int32_t aMsgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t aMsgType, const sp& aDataPtr, camera_frame_metadata_t* metadata); virtual void postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, const sp& aDataPtr); +#endif /** * The physical orientation of the camera sensor: 0, 90, 180, or 270. @@ -103,13 +117,15 @@ public: virtual int StartPreview(); virtual void StopPreview(); virtual int PushParameters(const mozilla::GonkCameraParameters& aParams); - virtual int PushParameters(const CameraParameters& aParams); virtual nsresult PullParameters(mozilla::GonkCameraParameters& aParams); +#ifdef MOZ_WIDGET_GONK + virtual int PushParameters(const CameraParameters& aParams); virtual void PullParameters(CameraParameters& aParams); - virtual int StartRecording(); - virtual int StopRecording(); virtual int SetListener(const sp& aListener); virtual void ReleaseRecordingFrame(const sp& aFrame); +#endif + virtual int StartRecording(); + virtual int StopRecording(); virtual int StoreMetaDataInBuffers(bool aEnabled); protected: @@ -118,8 +134,10 @@ protected: uint32_t mNumFrames; sp mCamera; mozilla::nsGonkCameraControl* mTarget; +#ifdef MOZ_WIDGET_GONK sp mNativeWindow; sp mListener; +#endif int mRawSensorOrientation; int mSensorOrientation; diff --git a/dom/camera/GonkCameraManager.cpp b/dom/camera/GonkCameraManager.cpp index 41d0b6d774..95bbad15eb 100644 --- a/dom/camera/GonkCameraManager.cpp +++ b/dom/camera/GonkCameraManager.cpp @@ -15,14 +15,17 @@ */ #include "ICameraControl.h" - -#include - #include "CameraCommon.h" #include "GonkCameraControl.h" #include "CameraPreferences.h" #include "TestGonkCameraControl.h" +#ifdef MOZ_WIDGET_GONK +#include +#else +#include "FallbackCameraPlatform.h" +#endif + using namespace mozilla; // From ICameraControl, gonk-specific management functions diff --git a/dom/camera/GonkCameraParameters.cpp b/dom/camera/GonkCameraParameters.cpp index dceda0e43f..3c3f7beedb 100644 --- a/dom/camera/GonkCameraParameters.cpp +++ b/dom/camera/GonkCameraParameters.cpp @@ -15,12 +15,12 @@ */ #include "GonkCameraParameters.h" -#include "camera/CameraParameters.h" #include "CameraPreferences.h" #include "ICameraControl.h" #include "CameraCommon.h" #include "mozilla/Hal.h" #include "nsDataHashtable.h" +#include "nsPrintfCString.h" using namespace mozilla; using namespace android; @@ -52,13 +52,13 @@ GonkCameraParameters::IsLowMemoryPlatform() } const char* -GonkCameraParameters::Parameters::FindVendorSpecificKey(const char* aPotentialKeys[], - size_t aPotentialKeyCount) +GonkCameraParameters::FindVendorSpecificKey(const char* aPotentialKeys[], + size_t aPotentialKeyCount) { const char* val; for (size_t i = 0; i < aPotentialKeyCount; ++i) { - get(aPotentialKeys[i], val); + GetImpl(aPotentialKeys[i], val); if (val) { // We received a value (potentially an empty-string one), // which indicates that this key exists. @@ -69,59 +69,122 @@ GonkCameraParameters::Parameters::FindVendorSpecificKey(const char* aPotentialKe return nullptr; } +/* static */ PLDHashOperator +GonkCameraParameters::EnumerateFlatten(const nsACString& aKey, + nsCString* aValue, + void* aUserArg) +{ + nsCString* data = static_cast(aUserArg); + if (!data->IsEmpty()) { + data->Append(';'); + } + data->Append(aKey); + data->Append('='); + data->Append(*aValue); + return PL_DHASH_NEXT; +} + +String8 +GonkCameraParameters::Flatten() const +{ + MutexAutoLock lock(mLock); + nsCString data; + mParams.EnumerateRead(EnumerateFlatten, static_cast(&data)); + return String8(data.Data()); +} + +nsresult +GonkCameraParameters::Unflatten(const String8& aFlatParameters) +{ + MutexAutoLock lock(mLock); + mParams.Clear(); + + const char* data = aFlatParameters.string(); + while (data && *data) { + const char* pos = strchr(data, '='); + if (!pos) { + break; + } + + nsAutoCString key(data, pos - data); + data = pos + 1; + + nsCString* value; + pos = strchr(data, ';'); + if (pos) { + value = new nsCString(data, pos - data); + data = pos + 1; + } else { + value = new nsCString(data); + data = nullptr; + } + + mParams.Put(key, value); + } + + if (mInitialized) { + return NS_OK; + } + + // We call Initialize() once when the parameter set is first loaded, + // to set up any constant values this class requires internally, + // e.g. the exposure compensation step and limits. + return Initialize(); +} + const char* -GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey) +GonkCameraParameters::GetTextKey(uint32_t aKey) { switch (aKey) { case CAMERA_PARAM_PREVIEWSIZE: - return KEY_PREVIEW_SIZE; + return CameraParameters::KEY_PREVIEW_SIZE; case CAMERA_PARAM_PREVIEWFORMAT: - return KEY_PREVIEW_FORMAT; + return CameraParameters::KEY_PREVIEW_FORMAT; case CAMERA_PARAM_PREVIEWFRAMERATE: - return KEY_PREVIEW_FRAME_RATE; + return CameraParameters::KEY_PREVIEW_FRAME_RATE; case CAMERA_PARAM_EFFECT: - return KEY_EFFECT; + return CameraParameters::KEY_EFFECT; case CAMERA_PARAM_WHITEBALANCE: - return KEY_WHITE_BALANCE; + return CameraParameters::KEY_WHITE_BALANCE; case CAMERA_PARAM_SCENEMODE: - return KEY_SCENE_MODE; + return CameraParameters::KEY_SCENE_MODE; case CAMERA_PARAM_FLASHMODE: - return KEY_FLASH_MODE; + return CameraParameters::KEY_FLASH_MODE; case CAMERA_PARAM_FOCUSMODE: - return KEY_FOCUS_MODE; + return CameraParameters::KEY_FOCUS_MODE; case CAMERA_PARAM_ZOOM: - return KEY_ZOOM; + return CameraParameters::KEY_ZOOM; case CAMERA_PARAM_METERINGAREAS: - return KEY_METERING_AREAS; + return CameraParameters::KEY_METERING_AREAS; case CAMERA_PARAM_FOCUSAREAS: - return KEY_FOCUS_AREAS; + return CameraParameters::KEY_FOCUS_AREAS; case CAMERA_PARAM_FOCALLENGTH: - return KEY_FOCAL_LENGTH; + return CameraParameters::KEY_FOCAL_LENGTH; case CAMERA_PARAM_FOCUSDISTANCENEAR: - return KEY_FOCUS_DISTANCES; + return CameraParameters::KEY_FOCUS_DISTANCES; case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM: - return KEY_FOCUS_DISTANCES; + return CameraParameters::KEY_FOCUS_DISTANCES; case CAMERA_PARAM_FOCUSDISTANCEFAR: - return KEY_FOCUS_DISTANCES; + return CameraParameters::KEY_FOCUS_DISTANCES; case CAMERA_PARAM_EXPOSURECOMPENSATION: - return KEY_EXPOSURE_COMPENSATION; + return CameraParameters::KEY_EXPOSURE_COMPENSATION; case CAMERA_PARAM_THUMBNAILQUALITY: - return KEY_JPEG_THUMBNAIL_QUALITY; + return CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY; case CAMERA_PARAM_PICTURE_SIZE: - return KEY_PICTURE_SIZE; + return CameraParameters::KEY_PICTURE_SIZE; case CAMERA_PARAM_PICTURE_FILEFORMAT: - return KEY_PICTURE_FORMAT; + return CameraParameters::KEY_PICTURE_FORMAT; case CAMERA_PARAM_PICTURE_ROTATION: - return KEY_ROTATION; + return CameraParameters::KEY_ROTATION; case CAMERA_PARAM_PICTURE_DATETIME: - // Not every platform defines a KEY_EXIF_DATETIME; + // Not every platform defines a CameraParameters::EXIF_DATETIME; // for those that don't, we use the raw string key, and if the platform // doesn't support it, it will be ignored. // // See bug 832494. return "exif-datetime"; case CAMERA_PARAM_VIDEOSIZE: - return KEY_VIDEO_SIZE; + return CameraParameters::KEY_VIDEO_SIZE; case CAMERA_PARAM_ISOMODE: if (!mVendorSpecificKeyIsoMode) { const char* isoModeKeys[] = { @@ -135,55 +198,55 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey) case CAMERA_PARAM_LUMINANCE: return "luminance-condition"; case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE: - // Not every platform defines KEY_QC_HDR_NEED_1X; + // Not every platform defines CameraParameters::QC_HDR_NEED_1X; // for those that don't, we use the raw string key. return "hdr-need-1x"; case CAMERA_PARAM_RECORDINGHINT: - return KEY_RECORDING_HINT; + return CameraParameters::KEY_RECORDING_HINT; case CAMERA_PARAM_PICTURE_QUALITY: - return KEY_JPEG_QUALITY; + return CameraParameters::KEY_JPEG_QUALITY; case CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO: - return KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO; + return CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO; case CAMERA_PARAM_METERINGMODE: - // Not every platform defines KEY_AUTO_EXPOSURE. + // Not every platform defines CameraParameters::AUTO_EXPOSURE. return "auto-exposure"; case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES: - return KEY_SUPPORTED_PREVIEW_SIZES; + return CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES; case CAMERA_PARAM_SUPPORTED_PICTURESIZES: - return KEY_SUPPORTED_PICTURE_SIZES; + return CameraParameters::KEY_SUPPORTED_PICTURE_SIZES; case CAMERA_PARAM_SUPPORTED_VIDEOSIZES: - return KEY_SUPPORTED_VIDEO_SIZES; + return CameraParameters::KEY_SUPPORTED_VIDEO_SIZES; case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS: - return KEY_SUPPORTED_PICTURE_FORMATS; + return CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS; case CAMERA_PARAM_SUPPORTED_WHITEBALANCES: - return KEY_SUPPORTED_WHITE_BALANCE; + return CameraParameters::KEY_SUPPORTED_WHITE_BALANCE; case CAMERA_PARAM_SUPPORTED_SCENEMODES: - return KEY_SUPPORTED_SCENE_MODES; + return CameraParameters::KEY_SUPPORTED_SCENE_MODES; case CAMERA_PARAM_SUPPORTED_EFFECTS: - return KEY_SUPPORTED_EFFECTS; + return CameraParameters::KEY_SUPPORTED_EFFECTS; case CAMERA_PARAM_SUPPORTED_FLASHMODES: - return KEY_SUPPORTED_FLASH_MODES; + return CameraParameters::KEY_SUPPORTED_FLASH_MODES; case CAMERA_PARAM_SUPPORTED_FOCUSMODES: - return KEY_SUPPORTED_FOCUS_MODES; + return CameraParameters::KEY_SUPPORTED_FOCUS_MODES; case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS: - return KEY_MAX_NUM_FOCUS_AREAS; + return CameraParameters::KEY_MAX_NUM_FOCUS_AREAS; case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS: - return KEY_MAX_NUM_METERING_AREAS; + return CameraParameters::KEY_MAX_NUM_METERING_AREAS; case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION: - return KEY_MIN_EXPOSURE_COMPENSATION; + return CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION; case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION: - return KEY_MAX_EXPOSURE_COMPENSATION; + return CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION; case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP: - return KEY_EXPOSURE_COMPENSATION_STEP; + return CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP; case CAMERA_PARAM_SUPPORTED_ZOOM: - return KEY_ZOOM_SUPPORTED; + return CameraParameters::KEY_ZOOM_SUPPORTED; case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS: - return KEY_ZOOM_RATIOS; + return CameraParameters::KEY_ZOOM_RATIOS; case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES: - return KEY_MAX_NUM_DETECTED_FACES_HW; + return CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW; case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES: - return KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES; + return CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES; case CAMERA_PARAM_SUPPORTED_ISOMODES: if (!mVendorSpecificKeySupportedIsoModes) { const char* supportedIsoModesKeys[] = { @@ -196,7 +259,7 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey) } return mVendorSpecificKeySupportedIsoModes; case CAMERA_PARAM_SUPPORTED_METERINGMODES: - // Not every platform defines KEY_SUPPORTED_AUTO_EXPOSURE. + // Not every platform defines CameraParameters::SUPPORTED_AUTO_EXPOSURE. return "auto-exposure-values"; default: DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey); @@ -205,26 +268,20 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey) } GonkCameraParameters::GonkCameraParameters() - : mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock")) + : mLock("mozilla::camera::GonkCameraParameters") , mDirty(false) , mInitialized(false) , mExposureCompensationStep(0.0) + , mVendorSpecificKeyIsoMode(nullptr) + , mVendorSpecificKeySupportedIsoModes(nullptr) { MOZ_COUNT_CTOR(GonkCameraParameters); - if (!mLock) { - MOZ_CRASH("Out of memory getting new PRRWLock"); - } } GonkCameraParameters::~GonkCameraParameters() { MOZ_COUNT_DTOR(GonkCameraParameters); mIsoModeMap.Clear(); - MOZ_ASSERT(mLock, "mLock missing in ~GonkCameraParameters()"); - if (mLock) { - PR_DestroyRWLock(mLock); - mLock = nullptr; - } } nsresult @@ -278,17 +335,17 @@ GonkCameraParameters::Initialize() { nsresult rv; - rv = GetImpl(Parameters::KEY_EXPOSURE_COMPENSATION_STEP, mExposureCompensationStep); + rv = GetImpl(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mExposureCompensationStep); if (NS_FAILED(rv)) { NS_WARNING("Failed to initialize exposure compensation step size"); mExposureCompensationStep = 0.0; } - rv = GetImpl(Parameters::KEY_MIN_EXPOSURE_COMPENSATION, mExposureCompensationMinIndex); + rv = GetImpl(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mExposureCompensationMinIndex); if (NS_FAILED(rv)) { NS_WARNING("Failed to initialize minimum exposure compensation index"); mExposureCompensationMinIndex = 0; } - rv = GetImpl(Parameters::KEY_MAX_EXPOSURE_COMPENSATION, mExposureCompensationMaxIndex); + rv = GetImpl(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mExposureCompensationMaxIndex); if (NS_FAILED(rv)) { NS_WARNING("Failed to initialize maximum exposure compensation index"); mExposureCompensationMaxIndex = 0; @@ -425,9 +482,9 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& a // This is a special case--for some reason the thumbnail size // is accessed as two separate values instead of a tuple. // XXXmikeh - make this restore the original values on error - rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast(aSize.width)); + rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast(aSize.width)); if (NS_SUCCEEDED(rv)) { - rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast(aSize.height)); + rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast(aSize.height)); } break; @@ -461,14 +518,14 @@ GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize) int width; int height; - rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width); + rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width); if (NS_FAILED(rv)) { return rv; } if (width < 0) { return NS_ERROR_NOT_AVAILABLE; } - rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height); + rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height); if (NS_FAILED(rv)) { return rv; } @@ -572,27 +629,27 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Positio // Add any specified location information -- we don't care if these fail. if (!isnan(aPosition.latitude)) { DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude); - SetImpl(Parameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get()); + SetImpl(CameraParameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get()); } else { - ClearImpl(Parameters::KEY_GPS_LATITUDE); + ClearImpl(CameraParameters::KEY_GPS_LATITUDE); } if (!isnan(aPosition.longitude)) { DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude); - SetImpl(Parameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get()); + SetImpl(CameraParameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get()); } else { - ClearImpl(Parameters::KEY_GPS_LONGITUDE); + ClearImpl(CameraParameters::KEY_GPS_LONGITUDE); } if (!isnan(aPosition.altitude)) { DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude); - SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get()); + SetImpl(CameraParameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get()); } else { - ClearImpl(Parameters::KEY_GPS_ALTITUDE); + ClearImpl(CameraParameters::KEY_GPS_ALTITUDE); } if (!isnan(aPosition.timestamp)) { DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp); - SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get()); + SetImpl(CameraParameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get()); } else { - ClearImpl(Parameters::KEY_GPS_TIMESTAMP); + ClearImpl(CameraParameters::KEY_GPS_TIMESTAMP); } return NS_OK; diff --git a/dom/camera/GonkCameraParameters.h b/dom/camera/GonkCameraParameters.h index d4fbae21f6..cd7f20cc68 100644 --- a/dom/camera/GonkCameraParameters.h +++ b/dom/camera/GonkCameraParameters.h @@ -18,14 +18,18 @@ #define DOM_CAMERA_GONKCAMERAPARAMETERS_H #include -#include "camera/CameraParameters.h" #include "nsTArray.h" #include "nsString.h" -#include "AutoRwLock.h" -#include "nsPrintfCString.h" +#include "mozilla/Mutex.h" #include "nsClassHashtable.h" #include "ICameraControl.h" +#ifdef MOZ_WIDGET_GONK +#include +#else +#include "FallbackCameraPlatform.h" +#endif + namespace mozilla { class GonkCameraParameters @@ -44,7 +48,7 @@ public: template nsresult Set(uint32_t aKey, const T& aValue) { - RwLockAutoEnterWrite lock(mLock); + MutexAutoLock lock(mLock); nsresult rv = SetTranslated(aKey, aValue); mDirty = mDirty || NS_SUCCEEDED(rv); return rv; @@ -53,7 +57,7 @@ public: template nsresult Get(uint32_t aKey, T& aValue) { - RwLockAutoEnterRead lock(mLock); + MutexAutoLock lock(mLock); return GetTranslated(aKey, aValue); } @@ -62,36 +66,17 @@ public: { bool dirty; - RwLockAutoEnterWrite lock(mLock); + MutexAutoLock lock(mLock); dirty = mDirty; mDirty = false; return dirty; } - android::String8 - Flatten() const - { - RwLockAutoEnterRead lock(mLock); - return mParams.flatten(); - } - - nsresult - Unflatten(const android::String8& aFlatParameters) - { - RwLockAutoEnterWrite lock(mLock); - mParams.unflatten(aFlatParameters); - if (mInitialized) { - return NS_OK; - } - - // We call Initialize() once when the parameter set is first loaded, - // to set up any constant values this class requires internally, - // e.g. the exposure compensation step and limits. - return Initialize(); - } + android::String8 Flatten() const; + nsresult Unflatten(const android::String8& aFlatParameters); protected: - PRRWLock* mLock; + mutable Mutex mLock; bool mDirty; bool mInitialized; @@ -99,55 +84,123 @@ protected: double mExposureCompensationStep; int32_t mExposureCompensationMinIndex; int32_t mExposureCompensationMaxIndex; + const char* mVendorSpecificKeyIsoMode; + const char* mVendorSpecificKeySupportedIsoModes; nsTArray mZoomRatios; nsTArray mIsoModes; nsTArray mSceneModes; nsTArray mMeteringModes; nsClassHashtable mIsoModeMap; + nsClassHashtable mParams; - // This subclass of android::CameraParameters just gives - // all of the AOSP getters and setters the same signature. - class Parameters : public android::CameraParameters + static PLDHashOperator EnumerateFlatten(const nsACString& aKey, nsCString* aValue, void* aUserArg); + + nsresult SetImpl(const char* aKey, const char* aValue) { - public: - Parameters() - : mVendorSpecificKeyIsoMode(nullptr) - , mVendorSpecificKeySupportedIsoModes(nullptr) - { } - virtual ~Parameters() { } + nsCString key(aKey); + mParams.Put(key, new nsCString(aValue)); + return NS_OK; + } - using android::CameraParameters::set; - using android::CameraParameters::get; - using android::CameraParameters::TRUE; - using android::CameraParameters::FALSE; + nsresult SetImpl(const char* aKey, int aValue) + { + nsCString key(aKey); + nsCString* value = new nsCString(); + value->AppendInt(aValue); + mParams.Put(key, value); + return NS_OK; + } - void set(const char* aKey, float aValue) { setFloat(aKey, aValue); } - void set(const char* aKey, double aValue) { setFloat(aKey, aValue); } - void set(const char* aKey, bool aValue) { set(aKey, aValue ? TRUE : FALSE); } - void get(const char* aKey, float& aRet) { aRet = getFloat(aKey); } - void get(const char* aKey, double& aRet) { aRet = getFloat(aKey); } - void get(const char* aKey, const char*& aRet) { aRet = get(aKey); } - void get(const char* aKey, int& aRet) { aRet = getInt(aKey); } + nsresult SetImpl(const char* aKey, double aValue) + { + nsCString key(aKey); + nsCString* value = new nsCString(); + value->AppendFloat(aValue); + mParams.Put(key, value); + return NS_OK; + } - void - get(const char* aKey, bool& aRet) - { - const char* value = get(aKey); - aRet = value ? strcmp(value, TRUE) == 0 : false; + nsresult SetImpl(const char* aKey, float aValue) + { + nsCString key(aKey); + nsCString* value = new nsCString(); + value->AppendFloat(aValue); + mParams.Put(key, value); + return NS_OK; + } + + nsresult SetImpl(const char* aKey, bool aValue) + { + nsCString key(aKey); + mParams.Put(key, new nsCString(aValue ? "true" : "false")); + return NS_OK; + } + + nsresult GetImpl(const char* aKey, const char*& aRet) + { + nsCString key(aKey); + nsCString* value; + if (!mParams.Get(key, &value)) { + aRet = nullptr; + return NS_ERROR_FAILURE; } + aRet = value->Data(); + return NS_OK; + } - void remove(const char* aKey) { android::CameraParameters::remove(aKey); } + nsresult GetImpl(const char* aKey, float& aRet) + { + nsCString key(aKey); + nsCString* value; + nsresult rv = NS_ERROR_FAILURE; + if (mParams.Get(key, &value)) { + aRet = value->ToFloat(&rv); + } else { + aRet = 0.0; + } + return rv; + } - const char* GetTextKey(uint32_t aKey); + nsresult GetImpl(const char* aKey, double& aRet) + { + nsCString key(aKey); + nsCString* value; + nsresult rv = NS_ERROR_FAILURE; + if (mParams.Get(key, &value)) { + aRet = value->ToFloat(&rv); + } else { + aRet = 0.0; + } + return rv; + } - protected: - const char* FindVendorSpecificKey(const char* aPotentialKeys[], size_t aPotentialKeyCount); + nsresult GetImpl(const char* aKey, int& aRet) + { + nsCString key(aKey); + nsCString* value; + nsresult rv = NS_ERROR_FAILURE; + if (mParams.Get(key, &value)) { + aRet = value->ToInteger(&rv); + } else { + aRet = 0.0; + } + return rv; + } - const char* mVendorSpecificKeyIsoMode; - const char* mVendorSpecificKeySupportedIsoModes; - }; + nsresult GetImpl(const char* aKey, bool& aRet) + { + nsCString key(aKey); + nsCString* value; + if (!mParams.Get(key, &value)) { + aRet = false; + return NS_ERROR_FAILURE; + } + aRet = value->EqualsLiteral("true"); + return NS_OK; + } - Parameters mParams; + const char* GetTextKey(uint32_t aKey); + const char* FindVendorSpecificKey(const char* aPotentialKeys[], size_t aPotentialKeyCount); // The *Impl() templates handle converting the parameter keys from // their enum values to string types, if necessary. These are the @@ -159,41 +212,24 @@ protected: template nsresult SetImpl(uint32_t aKey, const T& aValue) { - const char* key = mParams.GetTextKey(aKey); + const char* key = GetTextKey(aKey); NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED); - - mParams.set(key, aValue); - return NS_OK; + return SetImpl(key, aValue); } template nsresult GetImpl(uint32_t aKey, T& aValue) { - const char* key = mParams.GetTextKey(aKey); + const char* key = GetTextKey(aKey); NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED); - - mParams.get(key, aValue); - return NS_OK; - } - - template nsresult - SetImpl(const char* aKey, const T& aValue) - { - mParams.set(aKey, aValue); - return NS_OK; - } - - template nsresult - GetImpl(const char* aKey, T& aValue) - { - mParams.get(aKey, aValue); - return NS_OK; + return GetImpl(key, aValue); } nsresult ClearImpl(const char* aKey) { - mParams.remove(aKey); + nsCString key(aKey); + mParams.Remove(key); return NS_OK; } diff --git a/dom/camera/GonkRecorderProfiles.cpp b/dom/camera/GonkRecorderProfiles.cpp index 96bb548e01..ef1a85c28a 100644 --- a/dom/camera/GonkRecorderProfiles.cpp +++ b/dom/camera/GonkRecorderProfiles.cpp @@ -15,12 +15,14 @@ */ #include "GonkRecorderProfiles.h" -#include #include "nsMimeTypes.h" -#include "GonkRecorder.h" #include "CameraControlImpl.h" #include "CameraCommon.h" +#ifdef MOZ_WIDGET_GONK +#include "GonkRecorder.h" +#endif + using namespace mozilla; using namespace android; @@ -374,10 +376,11 @@ GonkRecorderProfile::GetAll(uint32_t aCameraId, aProfiles.Clear(); profiles->EnumerateRead(Enumerate, static_cast(&aProfiles)); - + return NS_OK; } +#ifdef MOZ_WIDGET_GONK nsresult GonkRecorderProfile::ConfigureRecorder(GonkRecorder& aRecorder) { @@ -425,3 +428,4 @@ GonkRecorderProfile::ConfigureRecorder(android::GonkRecorder& aRecorder, return profile->ConfigureRecorder(aRecorder); } +#endif diff --git a/dom/camera/GonkRecorderProfiles.h b/dom/camera/GonkRecorderProfiles.h index a3156d9227..32dd00f2a0 100644 --- a/dom/camera/GonkRecorderProfiles.h +++ b/dom/camera/GonkRecorderProfiles.h @@ -5,7 +5,12 @@ #ifndef DOM_CAMERA_GONK_RECORDER_PROFILES_H #define DOM_CAMERA_GONK_RECORDER_PROFILES_H +#ifdef MOZ_WIDGET_GONK #include +#else +#include "FallbackCameraPlatform.h" +#endif + #include "ICameraControl.h" #include "nsClassHashtable.h" #include "nsRefPtrHashtable.h" @@ -109,6 +114,7 @@ public: static nsresult GetAll(uint32_t aCameraId, nsTArray>& aProfiles); +#ifdef MOZ_WIDGET_GONK // Configures the specified recorder using the specified profile. // // Return values: @@ -118,6 +124,7 @@ public: static nsresult ConfigureRecorder(android::GonkRecorder& aRecorder, uint32_t aCameraId, const nsAString& aProfileName); +#endif protected: GonkRecorderProfile(uint32_t aCameraId, @@ -129,7 +136,9 @@ protected: bool GetMimeType(android::output_format aContainer, nsAString& aMimeType); bool IsValid() const { return mIsValid; }; +#ifdef MOZ_WIDGET_GONK nsresult ConfigureRecorder(android::GonkRecorder& aRecorder); +#endif static already_AddRefed CreateProfile(uint32_t aCameraId, int aQuality); static ProfileHashtable* GetProfileHashtable(uint32_t aCameraId); diff --git a/dom/camera/TestGonkCameraHardware.cpp b/dom/camera/TestGonkCameraHardware.cpp index 88823331ba..9932fd5c56 100644 --- a/dom/camera/TestGonkCameraHardware.cpp +++ b/dom/camera/TestGonkCameraHardware.cpp @@ -31,6 +31,10 @@ using namespace android; using namespace mozilla; using namespace mozilla::dom; +#ifndef MOZ_WIDGET_GONK +NS_IMPL_ISUPPORTS_INHERITED0(TestGonkCameraHardware, GonkCameraHardware); +#endif + static void CopyFaceFeature(int32_t (&aDst)[2], bool aExists, const DOMPoint* aSrc) { @@ -633,6 +637,7 @@ TestGonkCameraHardware::PullParameters(GonkCameraParameters& aParams) return NS_OK; } +#ifdef MOZ_WIDGET_GONK int TestGonkCameraHardware::PushParameters(const CameraParameters& aParams) { @@ -658,6 +663,7 @@ TestGonkCameraHardware::PullParameters(CameraParameters& aParams) String8 s(NS_LossyConvertUTF16toASCII(as).get()); aParams.unflatten(s); } +#endif int TestGonkCameraHardware::StartRecording() diff --git a/dom/camera/TestGonkCameraHardware.h b/dom/camera/TestGonkCameraHardware.h index b8a623c4dd..ef15265dd0 100644 --- a/dom/camera/TestGonkCameraHardware.h +++ b/dom/camera/TestGonkCameraHardware.h @@ -26,6 +26,10 @@ namespace mozilla { class TestGonkCameraHardware : public android::GonkCameraHardware { +#ifndef MOZ_WIDGET_GONK + NS_DECL_ISUPPORTS_INHERITED +#endif + public: virtual nsresult Init() override; virtual int AutoFocus() override; @@ -40,8 +44,10 @@ public: virtual int StartRecording() override; virtual int StopRecording() override; virtual int StoreMetaDataInBuffers(bool aEnabled) override; +#ifdef MOZ_WIDGET_GONK virtual int PushParameters(const android::CameraParameters& aParams) override; virtual void PullParameters(android::CameraParameters& aParams) override; +#endif TestGonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, diff --git a/dom/camera/moz.build b/dom/camera/moz.build index ebb2b0e641..e2648cf21e 100644 --- a/dom/camera/moz.build +++ b/dom/camera/moz.build @@ -4,7 +4,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': +if CONFIG['MOZ_B2G_CAMERA']: MOCHITEST_MANIFESTS += ['test/mochitest.ini'] EXPORTS += [ @@ -36,13 +36,21 @@ if CONFIG['MOZ_B2G_CAMERA']: 'GonkCameraHwMgr.cpp', 'GonkCameraManager.cpp', 'GonkCameraParameters.cpp', - 'GonkCameraSource.cpp', - 'GonkRecorder.cpp', 'GonkRecorderProfiles.cpp', 'TestGonkCameraControl.cpp', 'TestGonkCameraHardware.cpp', ] + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': + UNIFIED_SOURCES += [ + 'GonkCameraSource.cpp', + 'GonkRecorder.cpp', + ] + else: + UNIFIED_SOURCES += [ + 'FallbackCameraPlatform.cpp', + ] + EXTRA_COMPONENTS += [ 'CameraTestHardware.js', 'CameraTestHardware.manifest', diff --git a/dom/camera/test/camera_common.js b/dom/camera/test/camera_common.js index 4673f8aae1..110e8c5948 100644 --- a/dom/camera/test/camera_common.js +++ b/dom/camera/test/camera_common.js @@ -68,12 +68,18 @@ function CameraTestSuite() { this.logError = this._logError.bind(this); this.expectedError = this._expectedError.bind(this); this.expectedRejectGetCamera = this._expectedRejectGetCamera.bind(this); + this.expectedRejectConfigure = this._expectedRejectConfigure.bind(this); this.expectedRejectAutoFocus = this._expectedRejectAutoFocus.bind(this); this.expectedRejectTakePicture = this._expectedRejectTakePicture.bind(this); + this.expectedRejectStartRecording = this._expectedRejectStartRecording.bind(this); + this.expectedRejectStopRecording = this._expectedRejectStopRecording.bind(this); this.rejectGetCamera = this._rejectGetCamera.bind(this); + this.rejectConfigure = this._rejectConfigure.bind(this); this.rejectRelease = this._rejectRelease.bind(this); this.rejectAutoFocus = this._rejectAutoFocus.bind(this); this.rejectTakePicture = this._rejectTakePicture.bind(this); + this.rejectStartRecording = this._rejectStartRecording.bind(this); + this.rejectStopRecording = this._rejectStopRecording.bind(this); this.rejectPreviewStarted = this._rejectPreviewStarted.bind(this); var self = this; @@ -95,20 +101,35 @@ CameraTestSuite.prototype = { camera: null, hw: null, _lowMemSet: false, + _reloading: false, /* Returns a promise which is resolved when the test suite is ready to be executing individual test cases. One may provide the expected hardware type here if desired; the default is to use the JS test hardware. Use '' for the native emulated camera hardware. */ _setup: function(hwType) { + /* Depending on how we run the mochitest, we may not have the necessary + permissions yet. If we do need to request them, then we have to reload + the window to ensure the reconfiguration propogated properly. */ + if (!SpecialPowers.hasPermission("camera", document)) { + info("requesting camera permission"); + this._reloading = true; + SpecialPowers.addPermission("camera", true, document); + window.location.reload(); + return Promise.reject(); + } + + info("has camera permission"); if (!isDefined(hwType)) { hwType = 'hardware'; } this._hwType = hwType; return new Promise(function(resolve, reject) { - SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() { - resolve(); + SpecialPowers.pushPrefEnv({'set': [['camera.control.test.permission', true]]}, function() { + SpecialPowers.pushPrefEnv({'set': [['camera.control.test.enabled', hwType]]}, function() { + resolve(); + }); }); }); }, @@ -158,6 +179,10 @@ CameraTestSuite.prototype = { /* Execute all test cases (after setup is called). */ _run: function() { + if (this._reloading) { + return; + } + var test = this._tests.shift(); var self = this; if (test) { @@ -348,6 +373,10 @@ CameraTestSuite.prototype = { return this.logError('get camera failed', e); }, + _rejectConfigure: function(e) { + return this.logError('set configuration failed', e); + }, + _rejectRelease: function(e) { return this.logError('release camera failed', e); }, @@ -360,6 +389,14 @@ CameraTestSuite.prototype = { return this.logError('take picture failed', e); }, + _rejectStartRecording: function(e) { + return this.logError('start recording failed', e); + }, + + _rejectStopRecording: function(e) { + return this.logError('stop recording failed', e); + }, + _rejectPreviewStarted: function(e) { return this.logError('preview start failed', e); }, @@ -384,6 +421,10 @@ CameraTestSuite.prototype = { return this.expectedError('expected get camera to fail'); }, + _expectedRejectConfigure: function(p) { + return this.expectedError('expected set configuration to fail'); + }, + _expectedRejectAutoFocus: function(p) { return this.expectedError('expected auto focus to fail'); }, @@ -391,6 +432,14 @@ CameraTestSuite.prototype = { _expectedRejectTakePicture: function(p) { return this.expectedError('expected take picture to fail'); }, + + _expectedRejectStartRecording: function(p) { + return this.expectedError('expected start recording to fail'); + }, + + _expectedRejectStopRecording: function(p) { + return this.expectedError('expected stop recording to fail'); + }, }; ise(SpecialPowers.sanityCheck(), "foo", "SpecialPowers passed sanity check"); diff --git a/dom/camera/test/mochitest.ini b/dom/camera/test/mochitest.ini index 6e8d415543..e08690af47 100644 --- a/dom/camera/test/mochitest.ini +++ b/dom/camera/test/mochitest.ini @@ -2,8 +2,11 @@ support-files = camera_common.js [test_camera.html] +skip-if = toolkit != 'gonk' [test_camera_2.html] +skip-if = toolkit != 'gonk' [test_camera_3.html] +skip-if = toolkit != 'gonk' [test_camera_hardware_init_failure.html] [test_camera_hardware_failures.html] [test_bug975472.html] @@ -14,4 +17,5 @@ support-files = camera_common.js [test_bug1037322.html] [test_bug1099390.html] [test_bug1104913.html] +skip-if = toolkit != 'gonk' [test_camera_bad_initial_config.html] diff --git a/dom/camera/test/test_bug1037322.html b/dom/camera/test/test_bug1037322.html index 9628227cac..e304fa6060 100644 --- a/dom/camera/test/test_bug1037322.html +++ b/dom/camera/test/test_bug1037322.html @@ -12,76 +12,56 @@ This image is going to load diff --git a/dom/camera/test/test_bug1099390.html b/dom/camera/test/test_bug1099390.html index 945e3ea10e..56646cb709 100644 --- a/dom/camera/test/test_bug1099390.html +++ b/dom/camera/test/test_bug1099390.html @@ -12,95 +12,42 @@ This image is going to load diff --git a/dom/camera/test/test_bug975472.html b/dom/camera/test/test_bug975472.html index ff223553c7..0a2121fdc7 100644 --- a/dom/camera/test/test_bug975472.html +++ b/dom/camera/test/test_bug975472.html @@ -12,237 +12,170 @@ This image is going to load diff --git a/dom/camera/test/test_camera_bad_initial_config.html b/dom/camera/test/test_camera_bad_initial_config.html index ffe772cc1d..dcde06d343 100644 --- a/dom/camera/test/test_camera_bad_initial_config.html +++ b/dom/camera/test/test_camera_bad_initial_config.html @@ -12,45 +12,31 @@ This image is going to load diff --git a/dom/events/DataTransfer.cpp b/dom/events/DataTransfer.cpp index 0e686f470d..34e0a7efe8 100644 --- a/dom/events/DataTransfer.cpp +++ b/dom/events/DataTransfer.cpp @@ -24,6 +24,7 @@ #include "nsIScriptContext.h" #include "nsIDocument.h" #include "nsIScriptGlobalObject.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/DataTransferBinding.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/BindingUtils.h" @@ -82,7 +83,6 @@ DataTransfer::DataTransfer(nsISupports* aParent, uint32_t aEventType, mDragImageX(0), mDragImageY(0) { - MOZ_ASSERT(mParent); // For these events, we want to be able to add data to the data transfer, so // clear the readonly state. Otherwise, the data is already present. For // external usage, cache the data from the native clipboard or drag. @@ -300,10 +300,16 @@ DataTransfer::GetFiles(ErrorResult& aRv) nsCOMPtr file = do_QueryInterface(supports); - if (!file) - continue; - - nsRefPtr domFile = File::CreateFromFile(GetParentObject(), file); + nsRefPtr domFile; + if (file) { + domFile = File::CreateFromFile(GetParentObject(), file); + } else { + nsCOMPtr fileImpl = do_QueryInterface(supports); + if (!fileImpl) { + continue; + } + domFile = new File(GetParentObject(), static_cast(fileImpl.get())); + } if (!mFiles->Append(domFile)) { aRv.Throw(NS_ERROR_FAILURE); @@ -875,13 +881,6 @@ DataTransfer::GetTransferables(nsIDOMNode* aDragTarget) { MOZ_ASSERT(aDragTarget); - nsCOMPtr transArray = - do_CreateInstance("@mozilla.org/supports-array;1"); - if (!transArray) { - return nullptr; - } - - nsCOMPtr dragNode = do_QueryInterface(aDragTarget); if (!dragNode) { return nullptr; @@ -891,12 +890,23 @@ DataTransfer::GetTransferables(nsIDOMNode* aDragTarget) if (!doc) { return nullptr; } - - nsILoadContext* loadContext = doc->GetLoadContext(); + + return GetTransferables(doc->GetLoadContext()); +} + +already_AddRefed +DataTransfer::GetTransferables(nsILoadContext* aLoadContext) +{ + + nsCOMPtr transArray = + do_CreateInstance("@mozilla.org/supports-array;1"); + if (!transArray) { + return nullptr; + } uint32_t count = mItems.Length(); for (uint32_t i = 0; i < count; i++) { - nsCOMPtr transferable = GetTransferable(i, loadContext); + nsCOMPtr transferable = GetTransferable(i, aLoadContext); if (transferable) { transArray->AppendElement(transferable); } @@ -1273,5 +1283,20 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex) aItem.mData = variant; } +void +DataTransfer::FillAllExternalData() +{ + if (mIsExternal) { + for (uint32_t i = 0; i < mItems.Length(); ++i) { + nsTArray& itemArray = mItems[i]; + for (uint32_t j = 0; j < itemArray.Length(); ++j) { + if (!itemArray[j].mData) { + FillInExternalData(itemArray[j], i); + } + } + } + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/events/DataTransfer.h b/dom/events/DataTransfer.h index ce6c9ef9ea..ebcf88f492 100644 --- a/dom/events/DataTransfer.h +++ b/dom/events/DataTransfer.h @@ -185,6 +185,7 @@ public: // converts the data into an array of nsITransferable objects to be used for // drag and drop or clipboard operations. already_AddRefed GetTransferables(nsIDOMNode* aDragTarget); + already_AddRefed GetTransferables(nsILoadContext* aLoadContext); // converts the data for a single item at aIndex into an nsITransferable object. already_AddRefed GetTransferable(uint32_t aIndex, @@ -239,6 +240,9 @@ protected: // clipboard for a given index. void FillInExternalData(TransferItem& aItem, uint32_t aIndex); + friend class ContentParent; + void FillAllExternalData(); + void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex, mozilla::ErrorResult& aRv); diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index 62c6b44deb..3514f1be48 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -15,6 +15,7 @@ #include "mozilla/TextComposition.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/UIEvent.h" @@ -81,6 +82,7 @@ #include "nsIController.h" #include "nsICommandParams.h" #include "mozilla/Services.h" +#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/HTMLLabelElement.h" #include "mozilla/Preferences.h" @@ -1133,6 +1135,29 @@ EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent, *aStatus = nsEventStatus_eConsumeNoDefault; return remote->SendRealTouchEvent(*aEvent->AsTouchEvent()); } + case eDragEventClass: { + if (remote->Manager()->IsContentParent()) { + remote->Manager()->AsContentParent()->MaybeInvokeDragSession(remote); + } + + nsCOMPtr dragSession = nsContentUtils::GetDragSession(); + uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE; + uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE; + if (dragSession) { + dragSession->DragEventDispatchedToChildProcess(); + dragSession->GetDragAction(&action); + nsCOMPtr initialDataTransfer; + dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer)); + if (initialDataTransfer) { + initialDataTransfer->GetDropEffectInt(&dropEffect); + } + } + + bool retval = remote->SendRealDragEvent(*aEvent->AsDragEvent(), + action, dropEffect); + + return retval; + } default: { MOZ_CRASH("Attempt to send non-whitelisted event?"); } @@ -1189,6 +1214,13 @@ CrossProcessSafeEvent(const WidgetEvent& aEvent) default: return false; } + case eDragEventClass: + switch (aEvent.message) { + case NS_DRAGDROP_OVER: + case NS_DRAGDROP_EXIT: + case NS_DRAGDROP_DROP: + return true; + } default: return false; } @@ -1522,6 +1554,12 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext, } } +void +EventStateManager::BeginTrackingRemoteDragGesture(nsIContent* aContent) +{ + mGestureDownContent = aContent; + mGestureDownFrameOwner = aContent; +} // // StopTrackingDragGesture @@ -1623,8 +1661,9 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext, nsCOMPtr eventContent, targetContent; mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent)); if (eventContent) - DetermineDragTarget(window, eventContent, dataTransfer, - getter_AddRefs(selection), getter_AddRefs(targetContent)); + DetermineDragTargetAndDefaultData(window, eventContent, dataTransfer, + getter_AddRefs(selection), + getter_AddRefs(targetContent)); // Stop tracking the drag gesture now. This should stop us from // reentering GenerateDragGesture inside DOM event processing. @@ -1720,11 +1759,11 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext, } // GenerateDragGesture void -EventStateManager::DetermineDragTarget(nsPIDOMWindow* aWindow, - nsIContent* aSelectionTarget, - DataTransfer* aDataTransfer, - nsISelection** aSelection, - nsIContent** aTargetNode) +EventStateManager::DetermineDragTargetAndDefaultData(nsPIDOMWindow* aWindow, + nsIContent* aSelectionTarget, + DataTransfer* aDataTransfer, + nsISelection** aSelection, + nsIContent** aTargetNode) { *aTargetNode = nullptr; @@ -3177,6 +3216,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // "none". This way, if the event is just ignored, no drop will be // allowed. uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE; + uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE; if (nsEventStatus_eConsumeNoDefault == *aStatus) { // if the event has a dataTransfer set, use it. if (dragEvent->dataTransfer) { @@ -3194,7 +3234,6 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // based on the effectAllowed below. dataTransfer = initialDataTransfer; - uint32_t action; dragSession->GetDragAction(&action); // filter the drop effect based on the action. Use UNINITIALIZED as @@ -3216,7 +3255,6 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // effectAllowed state doesn't include that type of action. If the // dropEffect is "none", then the action will be 'none' so a drop will // not be allowed. - uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE; if (effectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED || dropEffect & effectAllowed) action = dropEffect; @@ -3240,6 +3278,12 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // No one called preventDefault(), so handle drop only in chrome. dragSession->SetOnlyChromeDrop(true); } + if (ContentChild* child = ContentChild::GetSingleton()) { + child->SendUpdateDropEffect(action, dropEffect); + } + if (dispatchedToContentProcess) { + dragSession->SetCanDrop(true); + } // now set the drop effect in the initial dataTransfer. This ensures // that we can get the desired drop effect in the drop event. diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h index 3abc247a33..8dced2a27e 100644 --- a/dom/events/EventStateManager.h +++ b/dom/events/EventStateManager.h @@ -753,6 +753,9 @@ protected: void BeginTrackingDragGesture(nsPresContext* aPresContext, WidgetMouseEvent* aDownEvent, nsIFrame* aDownFrame); + + friend class mozilla::dom::TabParent; + void BeginTrackingRemoteDragGesture(nsIContent* aContent); void StopTrackingDragGesture(); void GenerateDragGesture(nsPresContext* aPresContext, WidgetMouseEvent* aEvent); @@ -767,11 +770,11 @@ protected: * aSelection - [out] set to the selection to be dragged * aTargetNode - [out] the draggable node, or null if there isn't one */ - void DetermineDragTarget(nsPIDOMWindow* aWindow, - nsIContent* aSelectionTarget, - dom::DataTransfer* aDataTransfer, - nsISelection** aSelection, - nsIContent** aTargetNode); + void DetermineDragTargetAndDefaultData(nsPIDOMWindow* aWindow, + nsIContent* aSelectionTarget, + dom::DataTransfer* aDataTransfer, + nsISelection** aSelection, + nsIContent** aTargetNode); /* * Perform the default handling for the dragstart/draggesture event and set up a diff --git a/dom/filehandle/FileStreamWrappers.cpp b/dom/filehandle/FileStreamWrappers.cpp index 2350e15787..1c8e6e57d6 100644 --- a/dom/filehandle/FileStreamWrappers.cpp +++ b/dom/filehandle/FileStreamWrappers.cpp @@ -263,9 +263,6 @@ FileOutputStreamWrapper::FileOutputStreamWrapper(nsISupports* aFileStream, uint64_t aLimit, uint32_t aFlags) : FileStreamWrapper(aFileStream, aFileHelper, aOffset, aLimit, aFlags) -#ifdef DEBUG -, mWriteThread(nullptr) -#endif { mOutputStream = do_QueryInterface(mFileStream); NS_ASSERTION(mOutputStream, "This should always succeed!"); @@ -282,12 +279,6 @@ FileOutputStreamWrapper::Close() nsresult rv = NS_OK; - if (!mFirstTime) { - NS_ASSERTION(PR_GetCurrentThread() == mWriteThread, - "Unsetting thread locals on wrong thread!"); - mFileHelper->mMutableFile->UnsetThreadLocals(); - } - if (mFlags & NOTIFY_CLOSE) { nsCOMPtr runnable = new CloseRunnable(mFileHelper); @@ -313,11 +304,6 @@ FileOutputStreamWrapper::Write(const char* aBuf, uint32_t aCount, if (mFirstTime) { mFirstTime = false; -#ifdef DEBUG - mWriteThread = PR_GetCurrentThread(); -#endif - mFileHelper->mMutableFile->SetThreadLocals(); - nsCOMPtr seekable = do_QueryInterface(mOutputStream); if (seekable) { if (mOffset == UINT64_MAX) { diff --git a/dom/filehandle/FileStreamWrappers.h b/dom/filehandle/FileStreamWrappers.h index de847ec8c2..f8fc79082c 100644 --- a/dom/filehandle/FileStreamWrappers.h +++ b/dom/filehandle/FileStreamWrappers.h @@ -94,9 +94,6 @@ protected: private: nsCOMPtr mOutputStream; -#ifdef DEBUG - void* mWriteThread; -#endif }; } // namespace dom diff --git a/dom/filehandle/MutableFile.h b/dom/filehandle/MutableFile.h index e91d9cd39f..c11e073da1 100644 --- a/dom/filehandle/MutableFile.h +++ b/dom/filehandle/MutableFile.h @@ -20,8 +20,7 @@ class FileService; /** * This class provides a base for MutableFile implementations. - * The subclasses can override implementation of IsInvalid, CreateStream, - * SetThreadLocals and UnsetThreadLocals. + * The subclasses can override implementation of IsInvalid and CreateStream. * (for example IDBMutableFile provides IndexedDB specific implementation). */ class MutableFileBase @@ -49,15 +48,6 @@ public: virtual already_AddRefed CreateStream(bool aReadOnly); - virtual void - SetThreadLocals() - { - } - - virtual void - UnsetThreadLocals() - { - } protected: MutableFileBase(); diff --git a/dom/indexedDB/IDBMutableFile.cpp b/dom/indexedDB/IDBMutableFile.cpp index 0d8dff5a55..672eb3cb5d 100644 --- a/dom/indexedDB/IDBMutableFile.cpp +++ b/dom/indexedDB/IDBMutableFile.cpp @@ -275,23 +275,6 @@ IDBMutableFile::CreateStream(bool aReadOnly) return result.forget(); } -void -IDBMutableFile::SetThreadLocals() -{ - MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess()); - MOZ_ASSERT(mDatabase->GetOwner(), "Should have owner!"); - - QuotaManager::SetCurrentWindow(mDatabase->GetOwner()); -} - -void -IDBMutableFile::UnsetThreadLocals() -{ - MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess()); - - QuotaManager::SetCurrentWindow(nullptr); -} - JSObject* IDBMutableFile::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { diff --git a/dom/indexedDB/IDBMutableFile.h b/dom/indexedDB/IDBMutableFile.h index 5d64a35aae..38ce4d739c 100644 --- a/dom/indexedDB/IDBMutableFile.h +++ b/dom/indexedDB/IDBMutableFile.h @@ -102,12 +102,6 @@ public: virtual already_AddRefed CreateStream(bool aReadOnly) override; - virtual void - SetThreadLocals() override; - - virtual void - UnsetThreadLocals() override; - // nsWrapperCache virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index cfe4add503..fc7373d034 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -28,6 +28,7 @@ #include "mozilla/dom/ContentBridgeChild.h" #include "mozilla/dom/ContentBridgeParent.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/ExternalHelperAppChild.h" #include "mozilla/dom/ProcessGlobal.h" @@ -68,6 +69,7 @@ #include "mozInlineSpellChecker.h" #include "nsIConsoleListener.h" #include "nsICycleCollectorListener.h" +#include "nsIDragService.h" #include "nsIIPCBackgroundChildCreateCallback.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIMemoryReporter.h" @@ -176,7 +178,9 @@ #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/dom/voicemail/VoicemailIPCService.h" #include "mozilla/net/NeckoMessageUtils.h" +#include "mozilla/widget/PuppetBidiKeyboard.h" #include "mozilla/RemoteSpellCheckEngineChild.h" +#include "GMPServiceChild.h" using namespace mozilla; using namespace mozilla::docshell; @@ -189,11 +193,13 @@ using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::telephony; using namespace mozilla::dom::voicemail; using namespace mozilla::embedding; +using namespace mozilla::gmp; using namespace mozilla::hal_sandbox; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::net; using namespace mozilla::jsipc; +using namespace mozilla::widget; #if defined(MOZ_WIDGET_GONK) using namespace mozilla::system; #endif @@ -750,12 +756,14 @@ ContentChild::InitXPCOM() if (NS_FAILED(svc->RegisterListener(mConsoleListener))) NS_WARNING("Couldn't register console listener for child process"); - bool isOffline; + bool isOffline, isLangRTL; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - SendGetXPCOMProcessAttributes(&isOffline, &mAvailableDictionaries, &clipboardCaps, &domainPolicy); + SendGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &mAvailableDictionaries, + &clipboardCaps, &domainPolicy); RecvSetOffline(isOffline); + RecvBidiKeyboardNotify(isLangRTL); if (domainPolicy.active()) { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); @@ -997,6 +1005,13 @@ ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport, return mLastBridge; } +PGMPServiceChild* +ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport, + base::ProcessId aOtherProcess) +{ + return GMPServiceChild::Create(aTransport, aOtherProcess); +} + PCompositorChild* ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) @@ -1257,6 +1272,18 @@ ContentChild::RecvUpdateServiceWorkerRegistrations() return true; } +bool +ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL) +{ + // bidi is always of type PuppetBidiKeyboard* (because in the child, the only + // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard). + PuppetBidiKeyboard* bidi = static_cast(nsContentUtils::GetBidiKeyboard()); + if (bidi) { + bidi->SetIsLangRTL(aIsLangRTL); + } + return true; +} + static CancelableTask* sFirstIdleTask; static void FirstIdle(void) @@ -2725,6 +2752,64 @@ NextWindowID() return (processBits << kWindowIDWindowBits) | windowBits; } +bool +ContentChild::RecvInvokeDragSession(nsTArray&& aTransfers, + const uint32_t& aAction) +{ + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1"); + if (dragService) { + dragService->StartDragSession(); + nsCOMPtr session; + dragService->GetCurrentSession(getter_AddRefs(session)); + if (session) { + session->SetDragAction(aAction); + nsCOMPtr dataTransfer = + new DataTransfer(nullptr, NS_DRAGDROP_START, false, -1); + for (uint32_t i = 0; i < aTransfers.Length(); ++i) { + auto& items = aTransfers[i].items(); + for (uint32_t j = 0; j < items.Length(); ++j) { + const IPCDataTransferItem& item = items[j]; + nsCOMPtr variant = + do_CreateInstance(NS_VARIANT_CONTRACTID); + NS_ENSURE_TRUE(variant, false); + if (item.data().type() == IPCDataTransferData::TnsString) { + const nsString& data = item.data().get_nsString(); + variant->SetAsAString(data); + } else if (item.data().type() == IPCDataTransferData::TPBlobChild) { + BlobChild* blob = static_cast(item.data().get_PBlobChild()); + nsRefPtr fileImpl = blob->GetBlobImpl(); + variant->SetAsISupports(fileImpl); + } + dataTransfer->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.flavor()), + variant, i, + nsContentUtils::GetSystemPrincipal()); + } + } + session->SetDataTransfer(dataTransfer); + } + } + return true; +} + +bool +ContentChild::RecvEndDragSession(const bool& aDoneDrag, + const bool& aUserCancelled) +{ + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1"); + if (dragService) { + if (aUserCancelled) { + nsCOMPtr dragSession = nsContentUtils::GetDragSession(); + if (dragSession) { + dragSession->UserCancelled(); + } + } + dragService->EndDragSession(aDoneDrag); + } + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 19bbb72c2f..f26b6a6b5a 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -115,6 +115,10 @@ public: AllocPContentBridgeChild(mozilla::ipc::Transport* transport, base::ProcessId otherProcess) override; + PGMPServiceChild* + AllocPGMPServiceChild(mozilla::ipc::Transport* transport, + base::ProcessId otherProcess) override; + PCompositorChild* AllocPCompositorChild(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) override; @@ -289,6 +293,8 @@ public: virtual bool RecvUpdateServiceWorkerRegistrations() override; + virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override; + virtual bool RecvNotifyVisited(const URIParams& aURI) override; // auto remove when alertfinished is received. nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver); @@ -386,6 +392,11 @@ public: const OptionalURIParams& aDomain) override; virtual bool RecvShutdown() override; + virtual bool + RecvInvokeDragSession(nsTArray&& aTransfers, + const uint32_t& aAction) override; + virtual bool RecvEndDragSession(const bool& aDoneDrag, + const bool& aUserCancelled) override; #ifdef ANDROID gfxIntSize GetScreenSize() { return mScreenSize; } #endif diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index b52da42687..63e3168cf3 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -27,6 +27,7 @@ #include "AppProcessChecker.h" #include "AudioChannelService.h" #include "BlobParent.h" +#include "GMPServiceParent.h" #include "IHistory.h" #include "mozIApplication.h" #ifdef ACCESSIBILITY @@ -36,6 +37,7 @@ #include "mozilla/ClearOnShutdown.h" #include "mozilla/docshell/OfflineCacheUpdateParent.h" #include "mozilla/dom/DataStoreService.h" +#include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/DOMStorageIPC.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/File.h" @@ -100,6 +102,7 @@ #include "nsIDocument.h" #include "nsIDOMGeoGeolocation.h" #include "nsIDOMGeoPositionError.h" +#include "nsIDragService.h" #include "mozilla/dom/WakeLock.h" #include "nsIDOMWindow.h" #include "nsIExternalProtocolService.h" @@ -146,6 +149,8 @@ #include "private/pprio.h" #include "ContentProcessManager.h" +#include "nsIBidiKeyboard.h" + #if defined(ANDROID) || defined(LINUX) #include "nsSystemInfo.h" #endif @@ -222,6 +227,7 @@ using namespace mozilla::dom::mobilemessage; using namespace mozilla::dom::telephony; using namespace mozilla::dom::voicemail; using namespace mozilla::embedding; +using namespace mozilla::gmp; using namespace mozilla::hal; using namespace mozilla::ipc; using namespace mozilla::layers; @@ -986,6 +992,23 @@ static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement) return docShell; } +bool +ContentParent::RecvCreateGMPService() +{ + return PGMPService::Open(this); +} + +bool +ContentParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI, + nsTArray&& aTags, + bool* aHasVersion, + nsCString* aVersion) +{ + return GMPServiceParent::RecvGetGMPPluginVersionForAPI(aAPI, Move(aTags), + aHasVersion, + aVersion); +} + bool ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) { @@ -2742,11 +2765,11 @@ ContentParent::RecvAddNewProcess(const uint32_t& aPid, } // Update offline settings. - bool isOffline; + bool isOffline, isLangRTL; InfallibleTArray unusedDictionaries; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - RecvGetXPCOMProcessAttributes(&isOffline, &unusedDictionaries, + RecvGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &unusedDictionaries, &clipboardCaps, &domainPolicy); mozilla::unused << content->SendSetOffline(isOffline); MOZ_ASSERT(!clipboardCaps.supportsSelectionClipboard() && @@ -3008,6 +3031,13 @@ ContentParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAcc return true; } +PGMPServiceParent* +ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport, + base::ProcessId aOtherProcess) +{ + return GMPServiceParent::Create(aTransport, aOtherProcess); +} + PCompositorParent* ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) @@ -3057,6 +3087,7 @@ ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId, bool ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, + bool* aIsLangRTL, InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy) @@ -3066,6 +3097,13 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, DebugOnly rv = io->GetOffline(aIsOffline); MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?"); + nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard(); + + *aIsLangRTL = false; + if (bidi) { + bidi->IsLangRTL(aIsLangRTL); + } + nsCOMPtr spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID)); MOZ_ASSERT(spellChecker, "No spell checker?"); @@ -4620,6 +4658,62 @@ ContentParent::RecvSetOfflinePermission(const Principal& aPrincipal) return true; } +void +ContentParent::MaybeInvokeDragSession(TabParent* aParent) +{ + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1"); + if (dragService && dragService->MaybeAddChildProcess(this)) { + // We need to send transferable data to child process. + nsCOMPtr session; + dragService->GetCurrentSession(getter_AddRefs(session)); + if (session) { + nsTArray dataTransfers; + nsCOMPtr domTransfer; + session->GetDataTransfer(getter_AddRefs(domTransfer)); + nsCOMPtr transfer = do_QueryInterface(domTransfer); + if (!transfer) { + // Pass NS_DRAGDROP_DROP to get DataTransfer with external + // drag formats cached. + transfer = new DataTransfer(nullptr, NS_DRAGDROP_DROP, true, -1); + session->SetDataTransfer(transfer); + } + // Note, even though this fills the DataTransfer object with + // external data, the data is usually transfered over IPC lazily when + // needed. + transfer->FillAllExternalData(); + nsCOMPtr lc = aParent ? + aParent->GetLoadContext() : nullptr; + nsCOMPtr transferables = + transfer->GetTransferables(lc); + nsContentUtils::TransferablesToIPCTransferables(transferables, + dataTransfers, + nullptr, + this); + uint32_t action; + session->GetDragAction(&action); + mozilla::unused << SendInvokeDragSession(dataTransfers, action); + } + } +} + +bool +ContentParent::RecvUpdateDropEffect(const uint32_t& aDragAction, + const uint32_t& aDropEffect) +{ + nsCOMPtr dragSession = nsContentUtils::GetDragSession(); + if (dragSession) { + dragSession->SetDragAction(aDragAction); + nsCOMPtr dt; + dragSession->GetDataTransfer(getter_AddRefs(dt)); + if (dt) { + dt->SetDropEffectInt(aDropEffect); + } + dragSession->UpdateDragEffect(); + } + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index d12359fc88..9d6d4d814f 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -168,6 +168,12 @@ public: TabId* aTabId) override; virtual bool RecvBridgeToChildProcess(const ContentParentId& aCpId) override; + virtual bool RecvCreateGMPService() override; + virtual bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI, + nsTArray&& aTags, + bool* aHasPlugin, + nsCString* aVersion) override; + virtual bool RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) override; virtual bool RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv) override; virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch, @@ -357,6 +363,7 @@ public: virtual bool RecvFinishShutdown() override; + void MaybeInvokeDragSession(TabParent* aParent); protected: void OnChannelConnected(int32_t pid) override; virtual void ActorDestroy(ActorDestroyReason why) override; @@ -495,6 +502,9 @@ private: static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); + PGMPServiceParent* + AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport, + base::ProcessId aOtherProcess) override; PCompositorParent* AllocPCompositorParent(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherProcess) override; @@ -517,6 +527,7 @@ private: bool* aIsForApp, bool* aIsForBrowser) override; virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline, + bool* aIsLangRTL, InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy) @@ -800,6 +811,8 @@ private: virtual bool RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAccessibleParent* aParentDoc, const uint64_t& aParentID) override; + virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction, + const uint32_t& aDropEffect) override; // If you add strong pointers to cycle collected objects here, be sure to // release these objects in ShutDownProcess. See the comment there for more // details. diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index d1a2c73c32..58657e2ff6 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -135,5 +135,22 @@ union BlobConstructorParams ParentBlobConstructorParams; }; +union IPCDataTransferData +{ + nsString; + PBlob; +}; + +struct IPCDataTransferItem +{ + nsCString flavor; + IPCDataTransferData data; +}; + +struct IPCDataTransfer +{ + IPCDataTransferItem[] items; +}; + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index a8ad3aa2ae..7bd5d52821 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -44,6 +44,7 @@ using struct nsIntSize from "nsSize.h"; using class mozilla::WidgetKeyboardEvent from "ipc/nsGUIEventIPC.h"; using class mozilla::WidgetMouseEvent from "ipc/nsGUIEventIPC.h"; using class mozilla::WidgetWheelEvent from "ipc/nsGUIEventIPC.h"; +using class mozilla::WidgetDragEvent from "ipc/nsGUIEventIPC.h"; using struct nsRect from "nsRect.h"; using class mozilla::WidgetSelectionEvent from "ipc/nsGUIEventIPC.h"; using class mozilla::WidgetTouchEvent from "ipc/nsGUIEventIPC.h"; @@ -496,6 +497,9 @@ parent: prio(high) sync DispatchMouseEvent(WidgetMouseEvent event); prio(high) sync DispatchKeyboardEvent(WidgetKeyboardEvent event); + InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action, + nsCString visualData, uint32_t width, uint32_t height, + uint32_t stride, uint8_t format, int32_t dragAreaX, int32_t dragAreaY); child: /** * Notify the remote browser that it has been Show()n on this @@ -564,6 +568,7 @@ child: MouseWheelEvent(WidgetWheelEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId); RealTouchEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId); RealTouchMoveEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId); + RealDragEvent(WidgetDragEvent aEvent, uint32_t aDragAction, uint32_t aDropEffect); /** * @see nsIDOMWindowUtils sendKeyEvent. diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 8064e90d16..1e98b1f640 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -25,7 +25,15 @@ include protocol PImageBridge; include protocol PMemoryReportRequest; include protocol PMobileConnection; include protocol PNecko; +// FIXME This is pretty ridiculous, but we have to keep the order of the +// following 4 includes, or the parser is confused about PGMPContent +// bridging PContent and PGMP. As soon as it registers the bridge between +// PContent and PPluginModule it seems to think that PContent's parent and +// child live in the same process! +include protocol PGMPContent; +include protocol PGMPService; include protocol PPluginModule; +include protocol PGMP; include protocol PPrinting; include protocol POfflineCacheUpdate; include protocol PScreenManager; @@ -362,6 +370,7 @@ prio(normal upto urgent) sync protocol PContent parent opens PProcessHangMonitor; parent opens PSharedBufferManager; parent opens PImageBridge; + parent opens PGMPService; child opens PBackground; manages PAsmJSCacheEntry; @@ -443,6 +452,12 @@ child: async SpeakerManagerNotify(); + /** + * Communication between the PuppetBidiKeyboard and the actual + * BidiKeyboard hosted by the parent + */ + async BidiKeyboardNotify(bool isLangRTL); + async UpdateServiceWorkerRegistrations(); async DataStoreNotify(uint32_t aAppId, nsString aName, @@ -559,6 +574,9 @@ child: prio(high) sync GetProfile() returns (nsCString aProfile); + InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action); + + EndDragSession(bool aDoneDrag, bool aUserCancelled); NuwaFreeze(); async DomainSetChanged(uint32_t aSetType, uint32_t aChangeType, OptionalURIParams aDomain); @@ -602,7 +620,7 @@ parent: sync GetProcessAttributes() returns (ContentParentId cpId, bool isForApp, bool isForBrowser); sync GetXPCOMProcessAttributes() - returns (bool isOffline, nsString[] dictionaries, + returns (bool isOffline, bool isLangRTL, nsString[] dictionaries, ClipboardCapabilities clipboardCaps, DomainPolicyClone domainPolicy); @@ -612,6 +630,10 @@ parent: returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId); sync BridgeToChildProcess(ContentParentId cpId); + async CreateGMPService(); + sync GetGMPPluginVersionForAPI(nsCString api, nsCString[] tags) + returns (bool hasPlugin, nsCString version); + /** * This call connects the content process to a plugin process. While this * call runs, a new PluginModuleParent will be created in the ContentChild @@ -922,6 +944,7 @@ parent: */ async FinishShutdown(); + UpdateDropEffect(uint32_t aDragAction, uint32_t aDropEffect); both: AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal); diff --git a/dom/ipc/ProcessPriorityManager.cpp b/dom/ipc/ProcessPriorityManager.cpp index f4b1a15ea8..4ddebcf229 100644 --- a/dom/ipc/ProcessPriorityManager.cpp +++ b/dom/ipc/ProcessPriorityManager.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/Element.h" #include "mozilla/dom/TabParent.h" #include "mozilla/Hal.h" +#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/unused.h" @@ -49,22 +50,23 @@ # include # define LOG(fmt, ...) \ __android_log_print(ANDROID_LOG_INFO, \ - "Goanna:ProcessPriorityManager", \ + "Gecko:ProcessPriorityManager", \ fmt, ## __VA_ARGS__) # define LOGP(fmt, ...) \ __android_log_print(ANDROID_LOG_INFO, \ - "Goanna:ProcessPriorityManager", \ - "[%schild-id=%llu, pid=%d] " fmt, \ + "Gecko:ProcessPriorityManager", \ + "[%schild-id=%" PRIu64 ", pid=%d] " fmt, \ NameWithComma().get(), \ - (long long unsigned) ChildID(), Pid(), ## __VA_ARGS__) + static_cast(ChildID()), Pid(), ## __VA_ARGS__) #elif defined(ENABLE_LOGGING) # define LOG(fmt, ...) \ printf("ProcessPriorityManager - " fmt "\n", ##__VA_ARGS__) # define LOGP(fmt, ...) \ - printf("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt "\n", \ + printf("ProcessPriorityManager[%schild-id=%" PRIu64 ", pid=%d] - " \ + fmt "\n", \ NameWithComma().get(), \ - (unsigned long long) ChildID(), Pid(), ##__VA_ARGS__) + static_cast(ChildID()), Pid(), ##__VA_ARGS__) #elif defined(PR_LOGGING) static PRLogModuleInfo* @@ -80,9 +82,9 @@ ("ProcessPriorityManager - " fmt, ##__VA_ARGS__)) # define LOGP(fmt, ...) \ PR_LOG(GetPPMLog(), PR_LOG_DEBUG, \ - ("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt, \ + ("ProcessPriorityManager[%schild-id=%" PRIu64 ", pid=%d] - " fmt, \ NameWithComma().get(), \ - (unsigned long long) ChildID(), Pid(), ##__VA_ARGS__)) + static_cast(ChildID()), Pid(), ##__VA_ARGS__)) #else #define LOG(fmt, ...) #define LOGP(fmt, ...) @@ -96,6 +98,42 @@ namespace { class ParticularProcessPriorityManager; +class ProcessLRUPool final +{ +public: + /** + * Creates a new process LRU pool for the specified priority. + */ + ProcessLRUPool(ProcessPriority aPriority, uint32_t aBias); + + /** + * Used to remove a particular process priority manager from the LRU pool + * when the associated ContentParent is destroyed or its priority changes. + */ + void Remove(ParticularProcessPriorityManager* aParticularManager); + + /** + * Used to add a particular process priority manager into the LRU pool when + * the associated ContentParent's priority changes. + */ + void Add(ParticularProcessPriorityManager* aParticularManager); + +private: + ProcessPriority mPriority; + uint32_t mLRUPoolLevels; + uint32_t mLRUPoolSize; + uint32_t mBias; + nsTArray mLRUPool; + + uint32_t CalculateLRULevel(uint32_t aLRUPoolIndex); + + void AdjustLRUValues( + nsTArray::index_type aStart, + bool removed); + + DISALLOW_EVIL_CONSTRUCTORS(ProcessLRUPool); +}; + /** * This singleton class does the work to implement the process priority manager * in the main process. This class may not be used in child processes. (You @@ -129,7 +167,7 @@ public: */ void SetProcessPriority(ContentParent* aContentParent, ProcessPriority aPriority, - uint32_t aBackgroundLRU = 0); + uint32_t aLRU = 0); /** * If a magic testing-only pref is set, notify the observer service on the @@ -138,13 +176,6 @@ public: void FireTestOnlyObserverNotification(const char* aTopic, const nsACString& aData = EmptyCString()); - /** - * Does some process, other than the one handled by aParticularManager, have - * priority FOREGROUND_HIGH? - */ - bool OtherProcessHasHighPriority( - ParticularProcessPriorityManager* aParticularManager); - /** * Does one of the child processes have priority FOREGROUND_HIGH? */ @@ -182,13 +213,21 @@ private: void ObserveContentParentCreated(nsISupports* aContentParent); void ObserveContentParentDestroyed(nsISupports* aSubject); - void ResetAllCPUPriorities(); nsDataHashtable > mParticularManagers; + /** True if the main process is holding a high-priority wakelock */ bool mHighPriority; + + /** Contains the PIDs of child processes holding high-priority wakelocks */ nsTHashtable mHighPriorityChildIDs; + + /** Contains a pseudo-LRU list of background processes */ + ProcessLRUPool mBackgroundLRUPool; + + /** Contains a pseudo-LRU list of foreground processes */ + ProcessLRUPool mForegroundLRUPool; }; /** @@ -267,23 +306,11 @@ public: ProcessPriority CurrentPriority(); ProcessPriority ComputePriority(); - ProcessCPUPriority ComputeCPUPriority(ProcessPriority aPriority); void ScheduleResetPriority(const char* aTimeoutPref); void ResetPriority(); void ResetPriorityNow(); - void ResetCPUPriorityNow(); - - /** - * This overload is equivalent to SetPriorityNow(aPriority, - * ComputeCPUPriority()). - */ - void SetPriorityNow(ProcessPriority aPriority, - uint32_t aBackgroundLRU = 0); - - void SetPriorityNow(ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU = 0); + void SetPriorityNow(ProcessPriority aPriority, uint32_t aLRU = 0); void ShutDown(); @@ -299,7 +326,7 @@ private: ContentParent* mContentParent; uint64_t mChildID; ProcessPriority mPriority; - ProcessCPUPriority mCPUPriority; + uint32_t mLRU; bool mHoldsCPUWakeLock; bool mHoldsHighPriorityWakeLock; @@ -311,46 +338,6 @@ private: nsCOMPtr mResetPriorityTimer; }; -class BackgroundProcessLRUPool final -{ -public: - static BackgroundProcessLRUPool* Singleton(); - - /** - * Used to remove a ContentParent from background LRU pool when - * it is destroyed or its priority changed from BACKGROUND to others. - */ - void RemoveFromBackgroundLRUPool(ContentParent* aContentParent); - - /** - * Used to add a ContentParent into background LRU pool when - * its priority changed to BACKGROUND from others. - */ - void AddIntoBackgroundLRUPool(ContentParent* aContentParent); - -private: - static StaticAutoPtr sSingleton; - - int32_t mLRUPoolLevels; - int32_t mLRUPoolSize; - int32_t mLRUPoolAvailableIndex; - nsTArray mLRUPool; - - uint32_t CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex); - - nsresult UpdateAvailableIndexInLRUPool( - ContentParent* aContentParent, - int32_t aTargetIndex = -1); - - void ShiftLRUPool(); - - void EnsureLRUPool(); - - BackgroundProcessLRUPool(); - DISALLOW_EVIL_CONSTRUCTORS(BackgroundProcessLRUPool); - -}; - /* static */ bool ProcessPriorityManagerImpl::sInitialized = false; /* static */ bool ProcessPriorityManagerImpl::sPrefListenersRegistered = false; /* static */ StaticRefPtr @@ -421,6 +408,8 @@ ProcessPriorityManagerImpl::GetSingleton() ProcessPriorityManagerImpl::ProcessPriorityManagerImpl() : mHighPriority(false) + , mBackgroundLRUPool(PROCESS_PRIORITY_BACKGROUND, 1) + , mForegroundLRUPool(PROCESS_PRIORITY_FOREGROUND, 0) { MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); RegisterWakeLockObserver(this); @@ -439,8 +428,7 @@ ProcessPriorityManagerImpl::Init() // The master process's priority never changes; set it here and then forget // about it. We'll manage only subprocesses' priorities using the process // priority manager. - hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER, - PROCESS_CPU_PRIORITY_NORMAL); + hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER); nsCOMPtr os = services::GetObserverService(); if (os) { @@ -496,13 +484,13 @@ ProcessPriorityManagerImpl::GetParticularProcessPriorityManager( void ProcessPriorityManagerImpl::SetProcessPriority(ContentParent* aContentParent, ProcessPriority aPriority, - uint32_t aBackgroundLRU) + uint32_t aLRU) { MOZ_ASSERT(aContentParent); nsRefPtr pppm = GetParticularProcessPriorityManager(aContentParent); if (pppm) { - pppm->SetPriorityNow(aPriority, aBackgroundLRU); + pppm->SetPriorityNow(aPriority, aLRU); } } @@ -517,18 +505,6 @@ ProcessPriorityManagerImpl::ObserveContentParentCreated( GetParticularProcessPriorityManager(cp->AsContentParent()); } -static PLDHashOperator -EnumerateParticularProcessPriorityManagers( - const uint64_t& aKey, - nsRefPtr aValue, - void* aUserData) -{ - nsTArray >* aArray = - static_cast >*>(aUserData); - aArray->AppendElement(aValue); - return PL_DHASH_NEXT; -} - void ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject) { @@ -542,44 +518,20 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject) nsRefPtr pppm; mParticularManagers.Get(childID, &pppm); if (pppm) { + // Unconditionally remove the manager from the pools + mBackgroundLRUPool.Remove(pppm); + mForegroundLRUPool.Remove(pppm); + pppm->ShutDown(); mParticularManagers.Remove(childID); if (mHighPriorityChildIDs.Contains(childID)) { mHighPriorityChildIDs.RemoveEntry(childID); - - // We just lost a high-priority process; reset everyone's CPU priorities. - ResetAllCPUPriorities(); } } } -void -ProcessPriorityManagerImpl::ResetAllCPUPriorities( void ) -{ - nsTArray > pppms; - mParticularManagers.EnumerateRead( - &EnumerateParticularProcessPriorityManagers, - &pppms); - - for (uint32_t i = 0; i < pppms.Length(); i++) { - pppms[i]->ResetCPUPriorityNow(); - } -} - -bool -ProcessPriorityManagerImpl::OtherProcessHasHighPriority( - ParticularProcessPriorityManager* aParticularManager) -{ - if (mHighPriority) { - return true; - } else if (mHighPriorityChildIDs.Contains(aParticularManager->ChildID())) { - return mHighPriorityChildIDs.Count() > 1; - } - return mHighPriorityChildIDs.Count() > 0; -} - bool ProcessPriorityManagerImpl::ChildProcessHasHighPriority( void ) { @@ -591,33 +543,34 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged( ParticularProcessPriorityManager* aParticularManager, ProcessPriority aOldPriority) { - // This priority change can only affect other processes' priorities if we're - // changing to/from FOREGROUND_HIGH. + ProcessPriority newPriority = aParticularManager->CurrentPriority(); + bool isPreallocated = aParticularManager->IsPreallocated(); - if (aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH && - aParticularManager->CurrentPriority() < - PROCESS_PRIORITY_FOREGROUND_HIGH) { - - return; + if (newPriority == PROCESS_PRIORITY_BACKGROUND && + aOldPriority != PROCESS_PRIORITY_BACKGROUND && + !isPreallocated) { + mBackgroundLRUPool.Add(aParticularManager); + } else if (newPriority != PROCESS_PRIORITY_BACKGROUND && + aOldPriority == PROCESS_PRIORITY_BACKGROUND && + !isPreallocated) { + mBackgroundLRUPool.Remove(aParticularManager); } - if (aParticularManager->CurrentPriority() >= - PROCESS_PRIORITY_FOREGROUND_HIGH) { + if (newPriority == PROCESS_PRIORITY_FOREGROUND && + aOldPriority != PROCESS_PRIORITY_FOREGROUND) { + mForegroundLRUPool.Add(aParticularManager); + } else if (newPriority != PROCESS_PRIORITY_FOREGROUND && + aOldPriority == PROCESS_PRIORITY_FOREGROUND) { + mForegroundLRUPool.Remove(aParticularManager); + } + + if (newPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH && + aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH) { mHighPriorityChildIDs.PutEntry(aParticularManager->ChildID()); - } else { + } else if (newPriority < PROCESS_PRIORITY_FOREGROUND_HIGH && + aOldPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) { mHighPriorityChildIDs.RemoveEntry(aParticularManager->ChildID()); } - - nsTArray > pppms; - mParticularManagers.EnumerateRead( - &EnumerateParticularProcessPriorityManagers, - &pppms); - - for (uint32_t i = 0; i < pppms.Length(); i++) { - if (pppms[i] != aParticularManager) { - pppms[i]->ResetCPUPriorityNow(); - } - } } /* virtual */ void @@ -633,10 +586,6 @@ ProcessPriorityManagerImpl::Notify(const WakeLockInformation& aInfo) mHighPriority = false; } - /* The main process got a high-priority wakelock change; reset everyone's - * CPU priorities. */ - ResetAllCPUPriorities(); - LOG("Got wake lock changed event. " "Now mHighPriorityParent = %d\n", mHighPriority); } @@ -653,7 +602,7 @@ ParticularProcessPriorityManager::ParticularProcessPriorityManager( : mContentParent(aContentParent) , mChildID(aContentParent->ChildID()) , mPriority(PROCESS_PRIORITY_UNKNOWN) - , mCPUPriority(PROCESS_CPU_PRIORITY_NORMAL) + , mLRU(0) , mHoldsCPUWakeLock(false) , mHoldsHighPriorityWakeLock(false) { @@ -1015,96 +964,46 @@ ParticularProcessPriorityManager::ComputePriority() PROCESS_PRIORITY_BACKGROUND; } -ProcessCPUPriority -ParticularProcessPriorityManager::ComputeCPUPriority(ProcessPriority aPriority) -{ - if (aPriority == PROCESS_PRIORITY_PREALLOC) { - return PROCESS_CPU_PRIORITY_LOW; - } - - if (aPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) { - return PROCESS_CPU_PRIORITY_NORMAL; - } - - return ProcessPriorityManagerImpl::GetSingleton()-> - OtherProcessHasHighPriority(this) ? - PROCESS_CPU_PRIORITY_LOW : - PROCESS_CPU_PRIORITY_NORMAL; -} - -void -ParticularProcessPriorityManager::ResetCPUPriorityNow() -{ - SetPriorityNow(mPriority); -} - void ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority, - uint32_t aBackgroundLRU) -{ - SetPriorityNow(aPriority, ComputeCPUPriority(aPriority), aBackgroundLRU); -} - -void -ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU) + uint32_t aLRU) { if (aPriority == PROCESS_PRIORITY_UNKNOWN) { MOZ_ASSERT(false); return; } - if (aBackgroundLRU > 0 && - aPriority == PROCESS_PRIORITY_BACKGROUND && - mPriority == PROCESS_PRIORITY_BACKGROUND) { - hal::SetProcessPriority(Pid(), mPriority, mCPUPriority, aBackgroundLRU); - - nsPrintfCString ProcessPriorityWithBackgroundLRU("%s:%d", - ProcessPriorityToString(mPriority, mCPUPriority), - aBackgroundLRU); - - FireTestOnlyObserverNotification("process-priority-with-background-LRU-set", - ProcessPriorityWithBackgroundLRU.get()); - } - - if (!mContentParent || - !ProcessPriorityManagerImpl::PrefsEnabled() || - (mPriority == aPriority && mCPUPriority == aCPUPriority)) { + if (!ProcessPriorityManagerImpl::PrefsEnabled() || + !mContentParent || + ((mPriority == aPriority) && (mLRU == aLRU))) { return; } - // If the prefs were disabled after this ParticularProcessPriorityManager was - // created, we can at least avoid any further calls to - // hal::SetProcessPriority. Supporting dynamic enabling/disabling of the - // ProcessPriorityManager is mostly for testing. - if (!ProcessPriorityManagerImpl::PrefsEnabled()) { + if ((mPriority == aPriority) && (mLRU != aLRU)) { + mLRU = aLRU; + hal::SetProcessPriority(Pid(), mPriority, aLRU); + + nsPrintfCString processPriorityWithLRU("%s:%d", + ProcessPriorityToString(mPriority), aLRU); + + FireTestOnlyObserverNotification("process-priority-with-LRU-set", + processPriorityWithLRU.get()); return; } - if (aPriority == PROCESS_PRIORITY_BACKGROUND && - mPriority != PROCESS_PRIORITY_BACKGROUND && - !IsPreallocated()) { - ProcessPriorityManager::AddIntoBackgroundLRUPool(mContentParent); - } - - if (aPriority != PROCESS_PRIORITY_BACKGROUND && - mPriority == PROCESS_PRIORITY_BACKGROUND && - !IsPreallocated()) { - ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent); - } - LOGP("Changing priority from %s to %s.", - ProcessPriorityToString(mPriority, mCPUPriority), - ProcessPriorityToString(aPriority, aCPUPriority)); + ProcessPriorityToString(mPriority), + ProcessPriorityToString(aPriority)); ProcessPriority oldPriority = mPriority; mPriority = aPriority; - mCPUPriority = aCPUPriority; - hal::SetProcessPriority(Pid(), mPriority, mCPUPriority); + hal::SetProcessPriority(Pid(), mPriority); if (oldPriority != mPriority) { + ProcessPriorityManagerImpl::GetSingleton()-> + NotifyProcessPriorityChanged(this, oldPriority); + unused << mContentParent->SendNotifyProcessPriorityChanged(mPriority); } @@ -1113,12 +1012,7 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority, } FireTestOnlyObserverNotification("process-priority-set", - ProcessPriorityToString(mPriority, mCPUPriority)); - - if (oldPriority != mPriority) { - ProcessPriorityManagerImpl::GetSingleton()-> - NotifyProcessPriorityChanged(this, oldPriority); - } + ProcessPriorityToString(mPriority)); } void @@ -1133,10 +1027,6 @@ ParticularProcessPriorityManager::ShutDown() mResetPriorityTimer = nullptr; } - if (mPriority == PROCESS_PRIORITY_BACKGROUND && !IsPreallocated()) { - ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent); - } - mContentParent = nullptr; } @@ -1277,179 +1167,112 @@ ProcessPriorityManagerChild::CurrentProcessIsHighPriority() mCachedPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH; } -/* static */ StaticAutoPtr -BackgroundProcessLRUPool::sSingleton; - -/* static */ BackgroundProcessLRUPool* -BackgroundProcessLRUPool::Singleton() +ProcessLRUPool::ProcessLRUPool(ProcessPriority aPriority, uint32_t aBias) + : mPriority(aPriority) + , mLRUPoolLevels(1) + , mBias(aBias) { - if (!sSingleton) { - sSingleton = new BackgroundProcessLRUPool(); - ClearOnShutdown(&sSingleton); - } - return sSingleton; -} - -BackgroundProcessLRUPool::BackgroundProcessLRUPool() -{ - EnsureLRUPool(); -} - -uint32_t -BackgroundProcessLRUPool::CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex) -{ - // Set LRU level of each background process and maintain LRU buffer as below: - - // Priority background : LRU0 - // Priority background+1: LRU1, LRU2 - // Priority background+2: LRU3, LRU4, LRU5, LRU6 - // Priority background+3: LRU7, LRU8, LRU9, LRU10, LRU11, LRU12, LRU13, LRU14 - // ... - // Priority background+L-1: 2^(number of background LRU pool levels - 1) - // (End of buffer) - - return (uint32_t)(log((float)aBackgroundLRUPoolIndex) / log(2.0)); -} - -void -BackgroundProcessLRUPool::EnsureLRUPool() -{ - // We set mBackgroundLRUPoolLevels according to our pref. + // We set mLRUPoolLevels according to our pref. // This value is used to set background process LRU pool - if (!NS_SUCCEEDED(Preferences::GetInt( - "dom.ipc.processPriorityManager.backgroundLRUPoolLevels", - &mLRUPoolLevels))) { - mLRUPoolLevels = 1; - } + const char* str = ProcessPriorityToString(aPriority); + nsPrintfCString pref("dom.ipc.processPriorityManager.%s.LRUPoolLevels", str); - if (mLRUPoolLevels <= 0) { - MOZ_CRASH(); - } + Preferences::GetUint(pref.get(), &mLRUPoolLevels); // GonkHal defines OOM_ADJUST_MAX is 15 and b2g.js defines // PROCESS_PRIORITY_BACKGROUND's oom_score_adj is 667 and oom_adj is 10. // This means we can only have at most (15 -10 + 1) = 6 background LRU levels. - // See bug 822325 comment 49 - MOZ_ASSERT(mLRUPoolLevels <= 6); + // Similarly we can have at most 4 foreground LRU levels. We should really be + // getting rid of oom_adj and just rely on oom_score_adj only which would + // lift this constraint. + MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND || mLRUPoolLevels <= 6); + MOZ_ASSERT(aPriority != PROCESS_PRIORITY_FOREGROUND || mLRUPoolLevels <= 4); // LRU pool size = 2 ^ (number of background LRU pool levels) - 1 mLRUPoolSize = (1 << mLRUPoolLevels) - 1; - mLRUPoolAvailableIndex = 0; + LOG("Making %s LRU pool with size(%d)", str, mLRUPoolSize); +} - LOG("Making background LRU pool with size(%d)", mLRUPoolSize); +uint32_t +ProcessLRUPool::CalculateLRULevel(uint32_t aLRU) +{ + // This is used to compute the LRU adjustment for the specified LRU position. + // We use power-of-two groups with increasing adjustments that look like the + // following: - mLRUPool.InsertElementsAt(0, mLRUPoolSize, (ContentParent*)nullptr); + // Priority : LRU0, LRU1 + // Priority+1: LRU2, LRU3 + // Priority+2: LRU4, LRU5, LRU6, LRU7 + // Priority+3: LRU8, LRU9, LRU10, LRU11, LRU12, LRU12, LRU13, LRU14, LRU15 + // ... + // Priority+L-1: 2^(number of LRU pool levels - 1) + // (End of buffer) + + // Biasing the input can be used to shift the assignment + + int exp; + unused << frexp(static_cast(aLRU), &exp); + uint32_t level = std::max(exp - 1, 0); + + return std::min(mLRUPoolLevels - 1, level); } void -BackgroundProcessLRUPool::RemoveFromBackgroundLRUPool( - ContentParent* aContentParent) +ProcessLRUPool::Remove(ParticularProcessPriorityManager* aParticularManager) { - for (int32_t i = 0; i < mLRUPoolSize; i++) { - if (mLRUPool[i]) { - if (mLRUPool[i]->ChildID() == aContentParent->ChildID()) { + nsTArray::index_type index = + mLRUPool.IndexOf(aParticularManager); - mLRUPool[i] = nullptr; - LOG("Remove ChildID(%llu) from LRU pool", aContentParent->ChildID()); - - // After we remove this ContentParent from LRU pool, we still need to - // update the available index if the index of removed one is less than - // the available index we already have. - UpdateAvailableIndexInLRUPool(aContentParent, i); - break; - } - } - } -} - -nsresult -BackgroundProcessLRUPool::UpdateAvailableIndexInLRUPool( - ContentParent* aContentParent, - int32_t aTargetIndex) -{ - // If we specify which index we want to assign to mLRUPoolAvailableIndex, - // We have to make sure the index in LRUPool doesn't point to any - // ContentParent. - if (aTargetIndex >= 0 && aTargetIndex < mLRUPoolSize && - aTargetIndex < mLRUPoolAvailableIndex && - !mLRUPool[aTargetIndex]) { - mLRUPoolAvailableIndex = aTargetIndex; - return NS_OK; - } - - // When we didn't specify any legal aTargetIndex, then we just check - // whether current mLRUPoolAvailableIndex points to any ContentParent or not. - if (mLRUPoolAvailableIndex >= 0 && mLRUPoolAvailableIndex < mLRUPoolSize && - !(mLRUPool[mLRUPoolAvailableIndex])) { - return NS_OK; - } - - // Both above way failed. So now we have to find proper value - // for mLRUPoolAvailableIndex. - // We are looking for an available index. We only shift process with - // LRU less than the available index should have, so we stop update - // mLRUPoolAvailableIndex from the for loop once we got a candidate. - mLRUPoolAvailableIndex = -1; - - for (int32_t i = 0; i < mLRUPoolSize; i++) { - if (mLRUPool[i]) { - if (mLRUPool[i]->ChildID() == aContentParent->ChildID()) { - LOG("ChildID(%llu) already in LRU pool", aContentParent->ChildID()); - MOZ_ASSERT(false); - return NS_ERROR_UNEXPECTED; - } - continue; - } else { - if (mLRUPoolAvailableIndex == -1) { - mLRUPoolAvailableIndex = i; - } - } - } - - // If the LRUPool is already full, mLRUPoolAvailableIndex is still -1 after - // above loop finished. We should set mLRUPoolAvailableIndex - // to mLRUPoolSize - 1 in this case. Here uses the mod operator to do it: - // New mLRUPoolAvailableIndex either equals old mLRUPoolAvailableIndex, or - // mLRUPoolSize - 1 if old mLRUPoolAvailableIndex is -1. - mLRUPoolAvailableIndex = - (mLRUPoolAvailableIndex + mLRUPoolSize) % mLRUPoolSize; - - return NS_OK; -} - -void -BackgroundProcessLRUPool::ShiftLRUPool() -{ - for (int32_t i = mLRUPoolAvailableIndex; i > 0; i--) { - mLRUPool[i] = mLRUPool[i - 1]; - // Check whether i+1 is power of Two. - // If so, then it crossed a LRU group boundary and - // we need to assign its new process priority LRU. - if (!((i + 1) & i)) { - ProcessPriorityManagerImpl::GetSingleton()->SetProcessPriority( - mLRUPool[i], PROCESS_PRIORITY_BACKGROUND, CalculateLRULevel(i + 1)); - } - } -} - -void -BackgroundProcessLRUPool::AddIntoBackgroundLRUPool( - ContentParent* aContentParent) -{ - // We have to make sure that we have correct available index in LRU pool - if (!NS_SUCCEEDED( - UpdateAvailableIndexInLRUPool(aContentParent))) { + if (index == nsTArray::NoIndex) { return; } + mLRUPool.RemoveElementAt(index); + AdjustLRUValues(index, /* removed */ true); + + LOG("Remove ChildID(%" PRIu64 ") from %s LRU pool", + static_cast(aParticularManager->ChildID()), + ProcessPriorityToString(mPriority)); +} + +/* + * Adjust the LRU values of all the processes in an LRU pool. When true the + * `removed` parameter indicates that the processes were shifted left because + * an element was removed; otherwise it means the elements were shifted right + * as an element was added. + */ +void +ProcessLRUPool::AdjustLRUValues( + nsTArray::index_type aStart, + bool removed) +{ + uint32_t adj = (removed ? 1 : 0) + mBias; + + for (nsTArray::index_type i = aStart; + i < mLRUPool.Length(); + i++) { + /* Check whether i is a power of two. If so, then it crossed a LRU group + * boundary and we need to assign its new process priority LRU. Note that + * depending on the direction and the bias this test will pick different + * elements. */ + if (((i + adj) & (i + adj - 1)) == 0) { + mLRUPool[i]->SetPriorityNow(mPriority, CalculateLRULevel(i + mBias)); + } + } +} + +void +ProcessLRUPool::Add(ParticularProcessPriorityManager* aParticularManager) +{ // Shift the list in the pool, so we have room at index 0 for the newly added - // ContentParent - ShiftLRUPool(); + // manager + mLRUPool.InsertElementAt(0, aParticularManager); + AdjustLRUValues(1, /* removed */ false); - mLRUPool[0] = aContentParent; - - LOG("Add ChildID(%llu) into LRU pool", aContentParent->ChildID()); + LOG("Add ChildID(%" PRIu64 ") into %s LRU pool", + static_cast(aParticularManager->ChildID()), + ProcessPriorityToString(mPriority)); } } // namespace @@ -1476,31 +1299,6 @@ ProcessPriorityManager::SetProcessPriority(ContentParent* aContentParent, } } -/* static */ void -ProcessPriorityManager::RemoveFromBackgroundLRUPool( - ContentParent* aContentParent) -{ - MOZ_ASSERT(aContentParent); - - BackgroundProcessLRUPool* singleton = - BackgroundProcessLRUPool::Singleton(); - if (singleton) { - singleton->RemoveFromBackgroundLRUPool(aContentParent); - } -} - -/* static */ void -ProcessPriorityManager::AddIntoBackgroundLRUPool(ContentParent* aContentParent) -{ - MOZ_ASSERT(aContentParent); - - BackgroundProcessLRUPool* singleton = - BackgroundProcessLRUPool::Singleton(); - if (singleton) { - singleton->AddIntoBackgroundLRUPool(aContentParent); - } -} - /* static */ bool ProcessPriorityManager::CurrentProcessIsForeground() { diff --git a/dom/ipc/ProcessPriorityManager.h b/dom/ipc/ProcessPriorityManager.h index f85f14bd0c..785cce6df2 100644 --- a/dom/ipc/ProcessPriorityManager.h +++ b/dom/ipc/ProcessPriorityManager.h @@ -74,18 +74,6 @@ public: */ static bool AnyProcessHasHighPriority(); - /** - * Used to remove a ContentParent from background LRU pool when - * it is destroyed or its priority changed from BACKGROUND to others. - */ - static void RemoveFromBackgroundLRUPool(dom::ContentParent* aContentParent); - - /** - * Used to add a ContentParent into background LRU pool when - * its priority changed to BACKGROUND from others. - */ - static void AddIntoBackgroundLRUPool(dom::ContentParent* aContentParent); - private: ProcessPriorityManager(); DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManager); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 533717ce12..f3c7548cbc 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2406,6 +2406,44 @@ TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent, return RecvRealTouchEvent(aEvent, aGuid, aInputBlockId); } +bool +TabChild::RecvRealDragEvent(const WidgetDragEvent& aEvent, + const uint32_t& aDragAction, + const uint32_t& aDropEffect) +{ + WidgetDragEvent localEvent(aEvent); + localEvent.widget = mWidget; + + nsCOMPtr dragSession = nsContentUtils::GetDragSession(); + if (dragSession) { + dragSession->SetDragAction(aDragAction); + nsCOMPtr initialDataTransfer; + dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer)); + if (initialDataTransfer) { + initialDataTransfer->SetDropEffectInt(aDropEffect); + } + } + + if (aEvent.message == NS_DRAGDROP_DROP) { + bool canDrop = true; + if (!dragSession || NS_FAILED(dragSession->GetCanDrop(&canDrop)) || + !canDrop) { + localEvent.message = NS_DRAGDROP_EXIT; + } + } else if (aEvent.message == NS_DRAGDROP_OVER) { + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1"); + if (dragService) { + // This will dispatch 'drag' event at the source if the + // drag transaction started in this process. + dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG); + } + } + + APZCCallbackHelper::DispatchWidgetEvent(localEvent); + return true; +} + void TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache, WidgetKeyboardEvent* aEvent) diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 51c08ac0e4..2e64abc7a9 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -353,6 +353,9 @@ public: const bool& aIgnoreRootScrollFrame) override; virtual bool RecvRealMouseMoveEvent(const mozilla::WidgetMouseEvent& event) override; virtual bool RecvRealMouseButtonEvent(const mozilla::WidgetMouseEvent& event) override; + virtual bool RecvRealDragEvent(const WidgetDragEvent& aEvent, + const uint32_t& aDragAction, + const uint32_t& aDropEffect) override; virtual bool RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& event, const MaybeNativeKeyBinding& aBindings) override; virtual bool RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& event, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 01a8f4b15d..0f9da458ee 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -12,11 +12,13 @@ #include "mozIApplication.h" #include "mozilla/BrowserElementParent.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/PContentPermissionRequestParent.h" #include "mozilla/dom/ServiceWorkerRegistrar.h" #include "mozilla/dom/indexedDB/ActorsParent.h" #include "mozilla/plugins/PluginWidgetParent.h" #include "mozilla/EventStateManager.h" +#include "mozilla/gfx/2D.h" #include "mozilla/Hal.h" #include "mozilla/ipc/DocumentRendererParent.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" @@ -29,7 +31,9 @@ #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/unused.h" +#include "BlobParent.h" #include "nsCOMPtr.h" +#include "nsContentAreaDragDrop.h" #include "nsContentPermissionHelper.h" #include "nsContentUtils.h" #include "nsDebug.h" @@ -76,6 +80,7 @@ #include "nsNetCID.h" #include "nsIAuthInformation.h" #include "nsIAuthPromptCallback.h" +#include "SourceSurfaceRawData.h" #include "nsAuthInformationHolder.h" #include "nsICancelable.h" #include "gfxPrefs.h" @@ -275,6 +280,8 @@ TabParent::TabParent(nsIContentParent* aManager, , mAppPackageFileDescriptorSent(false) , mSendOfflineStatus(true) , mChromeFlags(aChromeFlags) + , mDragAreaX(0) + , mDragAreaY(0) , mInitedByParent(false) , mTabId(aTabId) , mCreatingWindow(false) @@ -1220,6 +1227,17 @@ TabParent::GetLayoutDeviceToCSSScale() : 0.0f); } +bool +TabParent::SendRealDragEvent(WidgetDragEvent& event, uint32_t aDragAction, + uint32_t aDropEffect) +{ + if (mIsDestroyed) { + return false; + } + event.refPoint += GetChildProcessOffset(); + return PBrowserParent::SendRealDragEvent(event, aDragAction, aDropEffect); +} + CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint) { return aPoint + (LayoutDevicePoint(mChildProcessOffsetAtTouchStart) * GetLayoutDeviceToCSSScale()); @@ -2939,6 +2957,109 @@ TabParent::RecvAsyncAuthPrompt(const nsCString& aUri, return rv == NS_OK; } +bool +TabParent::RecvInvokeDragSession(nsTArray&& aTransfers, + const uint32_t& aAction, + const nsCString& aVisualDnDData, + const uint32_t& aWidth, const uint32_t& aHeight, + const uint32_t& aStride, const uint8_t& aFormat, + const int32_t& aDragAreaX, const int32_t& aDragAreaY) +{ + mInitialDataTransferItems.Clear(); + nsPresContext* pc = mFrameElement->OwnerDoc()->GetShell()->GetPresContext(); + EventStateManager* esm = pc->EventStateManager(); + + for (uint32_t i = 0; i < aTransfers.Length(); ++i) { + auto& items = aTransfers[i].items(); + nsTArray* itemArray = mInitialDataTransferItems.AppendElement(); + for (uint32_t j = 0; j < items.Length(); ++j) { + const IPCDataTransferItem& item = items[j]; + DataTransferItem* localItem = itemArray->AppendElement(); + localItem->mFlavor = item.flavor(); + if (item.data().type() == IPCDataTransferData::TnsString) { + localItem->mType = DataTransferItem::DataType::eString; + localItem->mStringData = item.data().get_nsString(); + } else { + localItem->mType = DataTransferItem::DataType::eBlob; + BlobParent* blobParent = + static_cast(item.data().get_PBlobParent()); + if (blobParent) { + localItem->mBlobData = blobParent->GetBlobImpl(); + } + } + } + } + if (Manager()->IsContentParent()) { + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1"); + if (dragService) { + dragService->MaybeAddChildProcess(Manager()->AsContentParent()); + } + } + + if (aVisualDnDData.IsEmpty()) { + mDnDVisualization = nullptr; + } else { + mDnDVisualization = + new mozilla::gfx::SourceSurfaceRawData(); + mozilla::gfx::SourceSurfaceRawData* raw = + static_cast(mDnDVisualization.get()); + raw->InitWrappingData( + reinterpret_cast(const_cast(aVisualDnDData).BeginWriting()), + mozilla::gfx::IntSize(aWidth, aHeight), aStride, + static_cast(aFormat), false); + raw->GuaranteePersistance(); + } + mDragAreaX = aDragAreaX; + mDragAreaY = aDragAreaY; + + esm->BeginTrackingRemoteDragGesture(mFrameElement); + + return true; +} + +void +TabParent::AddInitialDnDDataTo(DataTransfer* aDataTransfer) +{ + for (uint32_t i = 0; i < mInitialDataTransferItems.Length(); ++i) { + nsTArray& itemArray = mInitialDataTransferItems[i]; + for (uint32_t j = 0; j < itemArray.Length(); ++j) { + DataTransferItem& item = itemArray[j]; + nsCOMPtr variant = + do_CreateInstance(NS_VARIANT_CONTRACTID); + if (!variant) { + break; + } + // Special case kFilePromiseMime so that we get the right + // nsIFlavorDataProvider for it. + if (item.mFlavor.EqualsLiteral(kFilePromiseMime)) { + nsRefPtr flavorDataProvider = + new nsContentAreaDragDropDataProvider(); + variant->SetAsISupports(flavorDataProvider); + } else if (item.mType == DataTransferItem::DataType::eString) { + variant->SetAsAString(item.mStringData); + } else if (item.mType == DataTransferItem::DataType::eBlob) { + variant->SetAsISupports(item.mBlobData); + } + // Using system principal here, since once the data is on parent process + // side, it can be handled as being from browser chrome or OS. + aDataTransfer->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.mFlavor), + variant, i, + nsContentUtils::GetSystemPrincipal()); + } + } + mInitialDataTransferItems.Clear(); +} + +void +TabParent::TakeDragVisualization(RefPtr& aSurface, + int32_t& aDragAreaX, int32_t& aDragAreaY) +{ + aSurface = mDnDVisualization.forget(); + aDragAreaX = mDragAreaX; + aDragAreaY = mDragAreaY; +} + NS_IMETHODIMP FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo) { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 5aad117aef..08e1cdc7d9 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -13,7 +13,9 @@ #include "mozilla/dom/PFilePickerParent.h" #include "mozilla/dom/TabContext.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/File.h" #include "mozilla/WritingModes.h" +#include "mozilla/RefPtr.h" #include "nsCOMPtr.h" #include "nsIAuthPromptProvider.h" #include "nsIBrowserDOMWindow.h" @@ -52,11 +54,17 @@ namespace widget { struct IMENotification; } +namespace gfx { +class SourceSurface; +class DataSourceSurface; +} + namespace dom { class ClonedMessageData; class nsIContentParent; class Element; +class DataTransfer; struct StructuredCloneData; class TabParent final : public PBrowserParent @@ -271,6 +279,8 @@ public: int32_t aCharCode, int32_t aModifiers, bool aPreventDefault); bool SendRealMouseEvent(mozilla::WidgetMouseEvent& event); + bool SendRealDragEvent(mozilla::WidgetDragEvent& aEvent, uint32_t aDragAction, + uint32_t aDropEffect); bool SendMouseWheelEvent(mozilla::WidgetWheelEvent& event); bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event); bool SendRealTouchEvent(WidgetTouchEvent& event); @@ -368,6 +378,18 @@ public: bool RequestNotifyLayerTreeCleared(); bool LayerTreeUpdate(bool aActive); + virtual bool + RecvInvokeDragSession(nsTArray&& aTransfers, + const uint32_t& aAction, + const nsCString& aVisualDnDData, + const uint32_t& aWidth, const uint32_t& aHeight, + const uint32_t& aStride, const uint8_t& aFormat, + const int32_t& aDragAreaX, const int32_t& aDragAreaY) override; + + void AddInitialDnDDataTo(DataTransfer* aDataTransfer); + + void TakeDragVisualization(RefPtr& aSurface, + int32_t& aDragAreaX, int32_t& aDragAreaY); protected: bool ReceiveMessage(const nsString& aMessage, bool aSync, @@ -474,6 +496,24 @@ private: uint32_t mChromeFlags; + struct DataTransferItem + { + nsCString mFlavor; + nsString mStringData; + nsRefPtr mBlobData; + enum DataType + { + eString, + eBlob + }; + DataType mType; + }; + nsTArray> mInitialDataTransferItems; + + mozilla::RefPtr mDnDVisualization; + int32_t mDragAreaX; + int32_t mDragAreaY; + // When true, the TabParent is initialized without child side's request. // When false, the TabParent is initialized by window.open() from child side. bool mInitedByParent; diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index c0eac562e2..6d82ac66b4 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -123,6 +123,7 @@ LOCAL_INCLUDES += [ '/embedding/components/printingui/ipc', '/extensions/cookie', '/extensions/spellcheck/src', + '/gfx/2d', '/hal/sandbox', '/layout/base', '/netwerk/base', diff --git a/dom/ipc/tests/test_NuwaProcessCreation.html b/dom/ipc/tests/test_NuwaProcessCreation.html index ea005d857a..9ee6223885 100644 --- a/dom/ipc/tests/test_NuwaProcessCreation.html +++ b/dom/ipc/tests/test_NuwaProcessCreation.html @@ -51,7 +51,7 @@ function setPref(pref, value) { setPref('dom.ipc.processPriorityManager.testMode', true); setPref('dom.ipc.processPriorityManager.enabled', true); -setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2); +setPref('dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2); function runTest() { diff --git a/dom/ipc/tests/test_NuwaProcessDeadlock.html b/dom/ipc/tests/test_NuwaProcessDeadlock.html index 63aefdd7b4..8dd13075cd 100644 --- a/dom/ipc/tests/test_NuwaProcessDeadlock.html +++ b/dom/ipc/tests/test_NuwaProcessDeadlock.html @@ -51,7 +51,7 @@ function setPref(pref, value) { setPref('dom.ipc.processPriorityManager.testMode', true); setPref('dom.ipc.processPriorityManager.enabled', true); -setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2); +setPref('dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2); setPref('dom.ipc.processPrelaunch.testMode', true); // For testing deadlock. function runTest() diff --git a/dom/media/AudioSink.cpp b/dom/media/AudioSink.cpp index ee494dafdb..26af58aee0 100644 --- a/dom/media/AudioSink.cpp +++ b/dom/media/AudioSink.cpp @@ -14,12 +14,8 @@ namespace mozilla { extern PRLogModuleInfo* gMediaDecoderLog; #define SINK_LOG(msg, ...) \ PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, ("AudioSink=%p " msg, this, ##__VA_ARGS__)) -#define SINK_LOG_V(msg, ...) \ - PR_BEGIN_MACRO \ - if (!PR_GetEnv("MOZ_QUIET")) { \ - SINK_LOG(msg, ##__VA_ARGS__); \ - } \ - PR_END_MACRO +#define SINK_LOG_V(msg, ...) \ + PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG+1, ("AudioSink=%p " msg, this, ##__VA_ARGS__)) #else #define SINK_LOG(msg, ...) #define SINK_LOG_V(msg, ...) diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 4b50c59f87..6bb6e17bb5 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -126,6 +126,7 @@ StaticRefPtr MediaMemoryTracker::sUniqueInstance; PRLogModuleInfo* gStateWatchingLog; PRLogModuleInfo* gMediaPromiseLog; PRLogModuleInfo* gMediaTimerLog; +PRLogModuleInfo* gMediaSampleLog; void MediaDecoder::InitStatics() @@ -134,11 +135,11 @@ MediaDecoder::InitStatics() SharedThreadPool::InitStatics(); // Log modules. -#ifdef PR_LOGGING gMediaDecoderLog = PR_NewLogModule("MediaDecoder"); -#endif gMediaPromiseLog = PR_NewLogModule("MediaPromise"); gStateWatchingLog = PR_NewLogModule("StateWatching"); + gMediaTimerLog = PR_NewLogModule("MediaTimer"); + gMediaSampleLog = PR_NewLogModule("MediaSample"); } NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 8090b6272a..74b632f4c5 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -52,25 +52,21 @@ using namespace mozilla::media; #define NS_DispatchToMainThread(...) CompileError_UseAbstractThreadDispatchInstead // avoid redefined macro in unified build +#undef LOG #undef DECODER_LOG #undef VERBOSE_LOG #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaDecoderLog; +extern PRLogModuleInfo* gMediaSampleLog; +#define LOG(m, l, x, ...) \ + PR_LOG(m, l, ("Decoder=%p " x, mDecoder.get(), ##__VA_ARGS__)) #define DECODER_LOG(x, ...) \ - PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, ("Decoder=%p " x, mDecoder.get(), ##__VA_ARGS__)) -#define VERBOSE_LOG(x, ...) \ - PR_BEGIN_MACRO \ - if (!PR_GetEnv("MOZ_QUIET")) { \ - DECODER_LOG(x, ##__VA_ARGS__); \ - } \ - PR_END_MACRO -#define SAMPLE_LOG(x, ...) \ - PR_BEGIN_MACRO \ - if (PR_GetEnv("MEDIA_LOG_SAMPLES")) { \ - DECODER_LOG(x, ##__VA_ARGS__); \ - } \ - PR_END_MACRO + LOG(gMediaDecoderLog, PR_LOG_DEBUG, x, ##__VA_ARGS__) +#define VERBOSE_LOG(x, ...) \ + LOG(gMediaDecoderLog, PR_LOG_DEBUG+1, x, ##__VA_ARGS__) +#define SAMPLE_LOG(x, ...) \ + LOG(gMediaSampleLog, PR_LOG_DEBUG, x, ##__VA_ARGS__) #else #define DECODER_LOG(x, ...) #define VERBOSE_LOG(x, ...) @@ -3592,6 +3588,7 @@ void MediaDecoderStateMachine::RecreateDecodedStream(int64_t aInitialTime) } // namespace mozilla // avoid redefined macro in unified build +#undef LOG #undef DECODER_LOG #undef VERBOSE_LOG #undef DECODER_WARN diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 00908c54d6..f93110db4b 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -26,6 +26,12 @@ #include "nsIIDNService.h" #include "nsNetUtil.h" #include "nsPrincipal.h" +#include "nsICryptoHash.h" +#include "nsICryptoHMAC.h" +#include "nsIKeyModule.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIInputStream.h" +#include "nsILineInputStream.h" #include "mozilla/Types.h" #include "mozilla/PeerIdentity.h" #include "mozilla/dom/ContentChild.h" @@ -34,7 +40,11 @@ #include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/GetUserMediaRequestBinding.h" #include "mozilla/Preferences.h" +#include "mozilla/Base64.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/media/MediaChild.h" #include "MediaTrackConstraints.h" +#include "VideoUtils.h" #include "Latency.h" #include "nsProxyRelease.h" @@ -117,8 +127,8 @@ using dom::SupportedVideoConstraints; static bool HostInDomain(const nsCString &aHost, const nsCString &aPattern) { - PRInt32 patternOffset = 0; - PRInt32 hostOffset = 0; + int32_t patternOffset = 0; + int32_t hostOffset = 0; // Act on '*.' wildcard in the left-most position in a domain pattern. if (aPattern.Length() > 2 && aPattern[0] == '*' && aPattern[1] == '.') { @@ -335,6 +345,50 @@ public: } } + nsresult + AnonymizeId(nsAString& aId, const nsACString& aOriginKey) + { + nsresult rv; + nsCOMPtr factory = + do_GetService("@mozilla.org/security/keyobjectfactory;1", &rv); + if (NS_FAILED(rv)) { + return rv; + } + nsCString rawKey; + rv = Base64Decode(aOriginKey, rawKey); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr key; + rv = factory->KeyFromString(nsIKeyObject::HMAC, rawKey, getter_AddRefs(key)); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr hasher = + do_CreateInstance(NS_CRYPTO_HMAC_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + return rv; + } + rv = hasher->Init(nsICryptoHMAC::SHA256, key); + if (NS_FAILED(rv)) { + return rv; + } + NS_ConvertUTF16toUTF8 id(aId); + rv = hasher->Update(reinterpret_cast (id.get()), id.Length()); + if (NS_FAILED(rv)) { + return rv; + } + nsCString mac; + rv = hasher->Finish(true, mac); + if (NS_FAILED(rv)) { + return rv; + } + + aId = NS_ConvertUTF8toUTF16(mac); + return NS_OK; + } + NS_IMETHOD Run() { @@ -348,7 +402,7 @@ public: nsCOMPtr devices = do_CreateInstance("@mozilla.org/variant;1"); - int32_t len = mDevices->Length(); + size_t len = mDevices->Length(); if (len == 0) { // XXX // We should in the future return an empty array, and dynamically add @@ -364,8 +418,14 @@ public: } nsTArray tmp(len); - for (int32_t i = 0; i < len; i++) { - tmp.AppendElement(mDevices->ElementAt(i)); + for (auto& device : *mDevices) { + if (!mOriginKey.IsEmpty()) { + nsString id; + device->GetId(id); + AnonymizeId(id, mOriginKey); + device->SetId(id); + } + tmp.AppendElement(device); } devices->SetAsArray(nsIDataType::VTYPE_INTERFACE, @@ -379,6 +439,7 @@ public: return NS_OK; } + nsCString mOriginKey; private: nsCOMPtr mOnSuccess; nsCOMPtr mOnFailure; @@ -424,7 +485,7 @@ MediaDevice::MediaDevice(MediaEngineSource* aSource) VideoDevice::VideoDevice(MediaEngineVideoSource* aSource) : MediaDevice(aSource) { -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) if (mName.EqualsLiteral("back")) { mHasFacingMode = true; mFacingMode = dom::VideoFacingModeEnum::Environment; @@ -1167,7 +1228,7 @@ public: void Run() { - NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); + MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mOnSuccess); MOZ_ASSERT(mOnFailure); @@ -1371,121 +1432,33 @@ private: }; #endif +class SanitizeDeviceIdsTask : public Task +{ +public: + explicit SanitizeDeviceIdsTask(int64_t aSinceWhen) + : mSinceWhen(aSinceWhen) {} + + void // NS_IMETHOD + Run() + { + MOZ_ASSERT(!NS_IsMainThread()); + nsRefPtr> p = + mozilla::media::SanitizeOriginKeys(mSinceWhen); // we fire and forget + } +private: + int64_t mSinceWhen; +}; + /** * Similar to GetUserMediaTask, but used for the chrome-only * GetUserMediaDevices function. Enumerates a list of audio & video devices, * wraps them up in nsIMediaDevice objects and returns it to the success * callback. + * + * All code in this class runs on the MediaManager thread. */ class GetUserMediaDevicesTask : public Task { - static unsigned char* unconst_uchar_cast(const char *s) { - return reinterpret_cast(const_cast(s)); - } - - // Cribbed from nricectx.cpp - static nsresult - hmac_sha1(const char *key, int keyl, const char *buf, int bufl, - unsigned char *result) { - const CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC; - PK11SlotInfo *slot = 0; - MOZ_ASSERT(keyl > 0); - SECItem keyi = { siBuffer, unconst_uchar_cast(key), - static_cast(keyl) }; - PK11SymKey *skey = 0; - PK11Context *hmac_ctx = 0; - SECStatus status; - unsigned int hmac_len; - SECItem param = { siBuffer, nullptr, 0 }; - nsresult rv = NS_ERROR_UNEXPECTED; - - slot = PK11_GetInternalKeySlot(); - if (!slot) { - goto abort; - } - skey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_SIGN, &keyi, - nullptr); - if (!skey) { - goto abort; - } - - hmac_ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, skey, ¶m); - if (!hmac_ctx) { - goto abort; - } - status = PK11_DigestBegin(hmac_ctx); - if (status != SECSuccess) { - goto abort; - } - status = PK11_DigestOp(hmac_ctx, unconst_uchar_cast(buf), bufl); - if (status != SECSuccess) { - goto abort; - } - status = PK11_DigestFinal(hmac_ctx, result, &hmac_len, 20); - if (status != SECSuccess) { - goto abort; - } - MOZ_ASSERT(hmac_len == 20); - rv = NS_OK; - - abort: - if (hmac_ctx) { - PK11_DestroyContext(hmac_ctx, PR_TRUE); - } - if (skey) { - PK11_FreeSymKey(skey); - } - if (slot) { - PK11_FreeSlot(slot); - } - return rv; - } - - nsresult AnonymizeId(nsAString& aId, const nsACString& origin) { - // deviceId would be a supercookie if we returned it. Anonymize it: - // 1. Get (or create) a persistent uuid for this origin. - // 2. Return hmac_sha1(uuid, id) - an anonymized id unique to origin. - - static bool loaded = false; - if (!loaded) { - // load OriginUuids from disk. - } - OriginUuid* originUuid; - if (!mManager->mOriginUuids.Get(origin, &originUuid)) { - char uuid[NSID_LENGTH]; - { - nsresult rv; - nsID id; - { - nsCOMPtr uuidgen = - do_GetService("@mozilla.org/uuid-generator;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - rv = uuidgen->GenerateUUIDInPlace(&id); - NS_ENSURE_SUCCESS(rv, rv); - } - id.ToProvidedString(uuid); - } - originUuid = new OriginUuid(uuid, false); - mManager->mOriginUuids.Put(origin, originUuid); - } - - unsigned char mac[20]; - { - NS_ConvertUTF16toUTF8 id(aId); - hmac_sha1(originUuid->mUuid.get(), originUuid->mUuid.Length(), - id.get(), id.Length(), mac); - } - char hex[sizeof(mac) * 2 + 1]; - auto& m = mac; - PR_snprintf(hex, sizeof(hex), // Use first 16 bytes of hmac as id - "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x" - "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", - m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], - m[8], m[9], m[10],m[11], m[12], m[13], m[14], m[15]); - aId = NS_ConvertUTF8toUTF16(hex); - return NS_OK; - } - public: GetUserMediaDevicesTask( const MediaStreamConstraints& aConstraints, @@ -1493,7 +1466,7 @@ public: already_AddRefed aOnFailure, uint64_t aWindowId, nsACString& aAudioLoopbackDev, nsACString& aVideoLoopbackDev, bool aPrivileged, const nsACString& aOrigin, - bool aUseFakeDevices) + bool aInPrivateBrowsing, bool aUseFakeDevices) : mConstraints(aConstraints) , mOnSuccess(aOnSuccess) , mOnFailure(aOnFailure) @@ -1503,12 +1476,13 @@ public: , mLoopbackVideoDevice(aVideoLoopbackDev) , mPrivileged(aPrivileged) , mOrigin(aOrigin) + , mInPrivateBrowsing(aInPrivateBrowsing) , mUseFakeDevices(aUseFakeDevices) {} void // NS_IMETHOD Run() { - NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); + MOZ_ASSERT(!NS_IsMainThread()); nsRefPtr backend; if (mConstraints.mFake || mUseFakeDevices) @@ -1537,35 +1511,29 @@ public: result->AppendElement(source); } } - - nsresult rv = NS_OK; - if (!mPrivileged) { - for (auto& source : *result) { - nsString id; - source->GetId(id); - rv = AnonymizeId(id, mOrigin); - if (NS_FAILED(rv)) { - break; - } - source->SetId(id); - } - } - if (NS_SUCCEEDED(rv)) { - NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId, - mOnSuccess, - mOnFailure, - result.forget())); + // In the case of failure with this newly allocated runnable, we + // intentionally leak the runnable, because we've pawned mOnSuccess and + // mOnFailure onto it which are main thread objects unsafe to release here. + DeviceSuccessCallbackRunnable* runnable = + new DeviceSuccessCallbackRunnable(mWindowId, mOnSuccess, mOnFailure, + result.forget()); + if (mPrivileged) { + NS_DispatchToMainThread(runnable); } else { - nsRefPtr error = new - MediaMgrError(NS_LITERAL_STRING("InternalError"), - NS_LITERAL_STRING("Unexpected error")); - NS_DispatchToMainThread( - new ErrorCallbackRunnable(mOnSuccess, - mOnFailure, - *error, - mWindowId)); + // Get persistent origin-unique uuid to anonymize deviceIds back on main. + // + // GetOriginKey is an async API that returns a pledge (as promise-like + // pattern). We use .Then() to pass in a lambda to run back on this + // thread once GetOriginKey resolves asynchronously . The "runnable" + // pointer is "captured" (passed by value) into the lambda. + nsRefPtr> p = + media::GetOriginKey(mOrigin, mInPrivateBrowsing); + p->Then([runnable](nsCString result) mutable { + runnable->mOriginKey = result; + NS_DispatchToMainThread(runnable); + }); } - // DeviceSuccessCallbackRunnable should have taken these. + // One of the Runnables have taken these. MOZ_ASSERT(!mOnSuccess && !mOnFailure); } @@ -1583,6 +1551,7 @@ private: nsCString mLoopbackVideoDevice; bool mPrivileged; nsCString mOrigin; + bool mInPrivateBrowsing; bool mUseFakeDevices; }; @@ -1611,6 +1580,16 @@ NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver) /* static */ StaticRefPtr MediaManager::sSingleton; +#ifdef DEBUG +/* static */ bool +MediaManager::IsInMediaThread() +{ + return sSingleton? + (sSingleton->mMediaThread->thread_id() == PlatformThread::CurrentId()) : + false; +} +#endif + // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread // from MediaManager thread. @@ -1618,7 +1597,11 @@ NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver) MediaManager::Get() { if (!sSingleton) { NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread"); - +#ifdef DEBUG + static int timesCreated = 0; + timesCreated++; + MOZ_ASSERT(timesCreated == 1); +#endif sSingleton = new MediaManager(); sSingleton->mMediaThread = new base::Thread("MediaManager"); @@ -1654,6 +1637,11 @@ MediaManager::Get() { return sSingleton; } +/* static */ MediaManager* +MediaManager::GetIfExists() { + return sSingleton; +} + /* static */ already_AddRefed MediaManager::GetInstance() { @@ -1897,7 +1885,7 @@ MediaManager::GetUserMedia( } } -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) if (mCameraManager == nullptr) { mCameraManager = nsDOMCameraManager::CreateInstance(aWindow); } @@ -2006,13 +1994,18 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow, nsCString origin; nsPrincipal::GetOriginForURI(aWindow->GetDocumentURI(), getter_Copies(origin)); - + bool inPrivateBrowsing; + { + nsCOMPtr doc = aWindow->GetDoc(); + nsCOMPtr loadContext = doc->GetLoadContext(); + inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing(); + } MediaManager::GetMessageLoop()->PostTask(FROM_HERE, new GetUserMediaDevicesTask( aConstraints, onSuccess.forget(), onFailure.forget(), (aInnerWindowID ? aInnerWindowID : aWindow->WindowID()), loopbackAudioDevice, loopbackVideoDevice, aPrivileged, origin, - useFakeStreams)); + inPrivateBrowsing, useFakeStreams)); return NS_OK; } @@ -2229,8 +2222,34 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, prefs->RemoveObserver("media.navigator.video.default_minfps", this); } - // Close off any remaining active windows. + // Because mMediaThread is not an nsThread, we must dispatch to it so it can + // clean up BackgroundChild. Continue stopping thread once this is done. + + class ShutdownTask : public Task { + public: + explicit ShutdownTask(nsRunnable* aReply) : mReply(aReply) {} + private: + virtual void + Run() + { + MOZ_ASSERT(MediaManager::IsInMediaThread()); + mozilla::ipc::BackgroundChild::CloseForCurrentThread(); + NS_DispatchToMainThread(mReply); + } + nsRefPtr mReply; + }; + + // Post ShutdownTask to execute on mMediaThread and pass in a lambda + // callback to be executed back on this thread once it is done. + // + // The lambda callback "captures" the 'this' pointer for member access. + // This is safe since this is guaranteed to be here since sSingleton isn't + // cleared until the lambda function clears it. + + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, new ShutdownTask( + media::CallbackRunnable::New([this]() mutable { + // Close off any remaining active windows. MutexAutoLock lock(mMutex); GetActiveWindows()->Clear(); mActiveCallbacks.Clear(); @@ -2242,11 +2261,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, mMediaThread->Stop(); } mBackend = nullptr; - } - -#ifdef MOZ_WEBRTC - StopWebRtcLog(); -#endif + return NS_OK; + }))); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:response:allow")) { @@ -2482,6 +2498,17 @@ MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo, return NS_OK; } +NS_IMETHODIMP +MediaManager::SanitizeDeviceIds(int64_t aSinceWhen) +{ + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + LOG(("%s: sinceWhen = %llu", __FUNCTION__, aSinceWhen)); + + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new SanitizeDeviceIdsTask(aSinceWhen)); + return NS_OK; +} + static void StopScreensharingCallback(MediaManager *aThis, uint64_t aWindowID, diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index ec80198479..dc36ef6f8d 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -458,17 +458,6 @@ private: nsCOMPtr mOnFailure; }; -class OriginUuid -{ -public: - OriginUuid(char *aUuid, bool aPrivateBrowsing) - : mPrivateBrowsing(aPrivateBrowsing) { - mUuid.Append(aUuid); - } - nsCString mUuid; - bool mPrivateBrowsing; -}; - typedef nsTArray > StreamListeners; typedef nsClassHashtable WindowTable; @@ -520,13 +509,9 @@ typedef void (*WindowListenerCallback)(MediaManager *aThis, StreamListeners *aListeners, void *aData); -class GetUserMediaDevicesTask; - class MediaManager final : public nsIMediaManagerService, public nsIObserver { - friend GetUserMediaDevicesTask; - public: static already_AddRefed GetInstance(); @@ -534,7 +519,11 @@ public: // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread // from MediaManager thread. static MediaManager* Get(); + static MediaManager* GetIfExists(); static MessageLoop* GetMessageLoop(); +#ifdef DEBUG + static bool IsInMediaThread(); +#endif static bool Exists() { @@ -612,9 +601,6 @@ private: void StopMediaStreams(); - // ONLY access from MediaManagerThread so we don't need to lock - nsClassHashtable mOriginUuids; - // ONLY access from MainThread so we don't need to lock WindowTable mActiveWindows; nsClassHashtable mActiveCallbacks; @@ -629,7 +615,7 @@ private: static StaticRefPtr sSingleton; -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) nsRefPtr mCameraManager; #endif }; diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index 05643c2f49..559baac8aa 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -279,18 +279,16 @@ ExtractH264CodecDetails(const nsAString& aCodec, } nsresult -GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength) +GenerateRandomName(nsCString& aOutSalt, uint32_t aLength) { nsresult rv; nsCOMPtr rg = do_GetService("@mozilla.org/security/random-generator;1", &rv); if (NS_FAILED(rv)) return rv; - // For each three bytes of random data we will get four bytes of - // ASCII. Request a bit more to be safe and truncate to the length - // we want at the end. + // For each three bytes of random data we will get four bytes of ASCII. const uint32_t requiredBytesLength = - static_cast((aLength + 1) / 4 * 3); + static_cast((aLength + 3) / 4 * 3); uint8_t* buffer; rv = rg->GenerateRandomBytes(requiredBytesLength, &buffer); @@ -304,14 +302,19 @@ GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength) buffer = nullptr; if (NS_FAILED (rv)) return rv; - temp.Truncate(aLength); + aOutSalt = temp; + return NS_OK; +} + +nsresult +GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength) +{ + nsresult rv = GenerateRandomName(aOutSalt, aLength); + if (NS_FAILED(rv)) return rv; // Base64 characters are alphanumeric (a-zA-Z0-9) and '+' and '/', so we need // to replace illegal characters -- notably '/' - temp.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_'); - - aOutSalt = temp; - + aOutSalt.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_'); return NS_OK; } diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index 6fb711784b..63c6aa3e7d 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -265,7 +265,11 @@ ExtractH264CodecDetails(const nsAString& aCodecs, int16_t& aLevel); // Use a cryptographic quality PRNG to generate raw random bytes -// and convert that to a base64 string suitable for use as a file or URL +// and convert that to a base64 string. +nsresult +GenerateRandomName(nsCString& aOutSalt, uint32_t aLength); + +// This version returns a string suitable for use as a file or URL // path. This is based on code from nsExternalAppHandler::SetUpTempFile. nsresult GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength); diff --git a/dom/media/gmp/GMPAudioDecoderChild.cpp b/dom/media/gmp/GMPAudioDecoderChild.cpp index 72ce0710d1..90a2a861a4 100644 --- a/dom/media/gmp/GMPAudioDecoderChild.cpp +++ b/dom/media/gmp/GMPAudioDecoderChild.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPAudioDecoderChild.h" -#include "GMPChild.h" +#include "GMPContentChild.h" #include "GMPAudioHost.h" #include "mozilla/unused.h" #include @@ -12,7 +12,7 @@ namespace mozilla { namespace gmp { -GMPAudioDecoderChild::GMPAudioDecoderChild(GMPChild* aPlugin) +GMPAudioDecoderChild::GMPAudioDecoderChild(GMPContentChild* aPlugin) : mPlugin(aPlugin) , mAudioDecoder(nullptr) { diff --git a/dom/media/gmp/GMPAudioDecoderChild.h b/dom/media/gmp/GMPAudioDecoderChild.h index b186925f23..1fb843fcaf 100644 --- a/dom/media/gmp/GMPAudioDecoderChild.h +++ b/dom/media/gmp/GMPAudioDecoderChild.h @@ -13,13 +13,13 @@ namespace mozilla { namespace gmp { -class GMPChild; +class GMPContentChild; class GMPAudioDecoderChild : public PGMPAudioDecoderChild, public GMPAudioDecoderCallback { public: - explicit GMPAudioDecoderChild(GMPChild* aPlugin); + explicit GMPAudioDecoderChild(GMPContentChild* aPlugin); virtual ~GMPAudioDecoderChild(); void Init(GMPAudioDecoder* aDecoder); @@ -40,7 +40,7 @@ private: virtual bool RecvDrain() override; virtual bool RecvDecodingComplete() override; - GMPChild* mPlugin; + GMPContentChild* mPlugin; GMPAudioDecoder* mAudioDecoder; GMPAudioHostImpl mAudioHost; }; diff --git a/dom/media/gmp/GMPAudioDecoderParent.cpp b/dom/media/gmp/GMPAudioDecoderParent.cpp index f7d1312a31..e75357572c 100644 --- a/dom/media/gmp/GMPAudioDecoderParent.cpp +++ b/dom/media/gmp/GMPAudioDecoderParent.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPAudioDecoderParent.h" -#include "GMPParent.h" +#include "GMPContentParent.h" #include #include "mozilla/unused.h" #include "GMPMessageUtils.h" @@ -29,7 +29,7 @@ extern PRLogModuleInfo* GetGMPLog(); namespace gmp { -GMPAudioDecoderParent::GMPAudioDecoderParent(GMPParent* aPlugin) +GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin) : mIsOpen(false) , mShuttingDown(false) , mPlugin(aPlugin) @@ -263,6 +263,13 @@ GMPAudioDecoderParent::RecvError(const GMPErr& aError) return true; } +bool +GMPAudioDecoderParent::RecvShutdown() +{ + Shutdown(); + return true; +} + bool GMPAudioDecoderParent::Recv__delete__() { diff --git a/dom/media/gmp/GMPAudioDecoderParent.h b/dom/media/gmp/GMPAudioDecoderParent.h index 66fc4da94e..075b820c13 100644 --- a/dom/media/gmp/GMPAudioDecoderParent.h +++ b/dom/media/gmp/GMPAudioDecoderParent.h @@ -16,7 +16,7 @@ namespace mozilla { namespace gmp { -class GMPParent; +class GMPContentParent; class GMPAudioDecoderParent final : public GMPAudioDecoderProxy , public PGMPAudioDecoderParent @@ -24,7 +24,7 @@ class GMPAudioDecoderParent final : public GMPAudioDecoderProxy public: NS_INLINE_DECL_REFCOUNTING(GMPAudioDecoderParent) - explicit GMPAudioDecoderParent(GMPParent *aPlugin); + explicit GMPAudioDecoderParent(GMPContentParent *aPlugin); nsresult Shutdown(); @@ -50,11 +50,12 @@ private: virtual bool RecvDrainComplete() override; virtual bool RecvResetComplete() override; virtual bool RecvError(const GMPErr& aError) override; + virtual bool RecvShutdown() override; virtual bool Recv__delete__() override; bool mIsOpen; bool mShuttingDown; - nsRefPtr mPlugin; + nsRefPtr mPlugin; GMPAudioDecoderCallbackProxy* mCallback; }; diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp index e8a6be972d..a06a50afe8 100644 --- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPChild.h" +#include "GMPContentChild.h" #include "GMPProcessChild.h" #include "GMPLoader.h" #include "GMPVideoDecoderChild.h" @@ -252,12 +253,6 @@ GMPChild::StartMacSandbox() } #endif // XP_MACOSX && MOZ_GMP_SANDBOX -void -GMPChild::CheckThread() -{ - MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current()); -} - bool GMPChild::Init(const std::string& aPluginPath, const std::string& aVoucherPath, @@ -463,6 +458,11 @@ GMPChild::ActorDestroy(ActorDestroyReason aWhy) { LOGD("%s reason=%d", __FUNCTION__, aWhy); + for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { + MOZ_ASSERT_IF(aWhy == NormalShutdown, !mGMPContentChildren[i - 1]->IsUsed()); + mGMPContentChildren[i - 1]->Close(); + } + if (mGMPLoader) { mGMPLoader->Shutdown(); } @@ -497,133 +497,6 @@ GMPChild::ProcessingError(Result aCode, const char* aReason) } } -PGMPAudioDecoderChild* -GMPChild::AllocPGMPAudioDecoderChild() -{ - return new GMPAudioDecoderChild(this); -} - -bool -GMPChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) -{ - delete aActor; - return true; -} - -PGMPVideoDecoderChild* -GMPChild::AllocPGMPVideoDecoderChild() -{ - return new GMPVideoDecoderChild(this); -} - -bool -GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) -{ - delete aActor; - return true; -} - -PGMPDecryptorChild* -GMPChild::AllocPGMPDecryptorChild() -{ - GMPDecryptorChild* actor = new GMPDecryptorChild(this, mPluginVoucher, mSandboxVoucher); - actor->AddRef(); - return actor; -} - -bool -GMPChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) -{ - static_cast(aActor)->Release(); - return true; -} - -bool -GMPChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) -{ - auto vdc = static_cast(aActor); - - void* vd = nullptr; - GMPErr err = GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd); - if (err != GMPNoErr || !vd) { - return false; - } - - vdc->Init(static_cast(vd)); - - return true; -} - -PGMPVideoEncoderChild* -GMPChild::AllocPGMPVideoEncoderChild() -{ - return new GMPVideoEncoderChild(this); -} - -bool -GMPChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) -{ - delete aActor; - return true; -} - -bool -GMPChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) -{ - auto vdc = static_cast(aActor); - - void* vd = nullptr; - GMPErr err = GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd); - if (err != GMPNoErr || !vd) { - NS_WARNING("GMPGetAPI call failed trying to construct decoder."); - return false; - } - - vdc->Init(static_cast(vd)); - - return true; -} - -bool -GMPChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) -{ - auto vec = static_cast(aActor); - - void* ve = nullptr; - GMPErr err = GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve); - if (err != GMPNoErr || !ve) { - NS_WARNING("GMPGetAPI call failed trying to construct encoder."); - return false; - } - - vec->Init(static_cast(ve)); - - return true; -} - -bool -GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) -{ - GMPDecryptorChild* child = static_cast(aActor); - GMPDecryptorHost* host = static_cast(child); - - void* session = nullptr; - GMPErr err = GetAPI(GMP_API_DECRYPTOR, host, &session); - - if (err != GMPNoErr && !session) { - // XXX to remove in bug 1147692 - err = GetAPI(GMP_API_DECRYPTOR_COMPAT, host, &session); - } - - if (err != GMPNoErr || !session) { - return false; - } - - child->Init(static_cast(session)); - - return true; -} - PGMPTimerChild* GMPChild::AllocPGMPTimerChild() { @@ -698,6 +571,15 @@ GMPChild::RecvBeginAsyncShutdown() return true; } +bool +GMPChild::RecvCloseActive() +{ + for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { + mGMPContentChildren[i - 1]->CloseActive(); + } + return true; +} + void GMPChild::ShutdownComplete() { @@ -780,6 +662,32 @@ GMPChild::PreLoadSandboxVoucher() } } +PGMPContentChild* +GMPChild::AllocPGMPContentChild(Transport* aTransport, + ProcessId aOtherPid) +{ + GMPContentChild* child = + mGMPContentChildren.AppendElement(new GMPContentChild(this))->get(); + child->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ChildSide); + + return child; +} + +void +GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild) +{ + for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { + UniquePtr& toDestroy = mGMPContentChildren[i - 1]; + if (toDestroy.get() == aGMPContentChild) { + SendPGMPContentChildDestroyed(); + MessageLoop::current()->PostTask(FROM_HERE, + new DeleteTask(toDestroy.release())); + mGMPContentChildren.RemoveElementAt(i - 1); + break; + } + } +} + } // namespace gmp } // namespace mozilla diff --git a/dom/media/gmp/GMPChild.h b/dom/media/gmp/GMPChild.h index a5d72c38b0..6a80b6717e 100644 --- a/dom/media/gmp/GMPChild.h +++ b/dom/media/gmp/GMPChild.h @@ -7,7 +7,6 @@ #define GMPChild_h_ #include "mozilla/gmp/PGMPChild.h" -#include "GMPSharedMemManager.h" #include "GMPTimerChild.h" #include "GMPStorageChild.h" #include "GMPLoader.h" @@ -18,8 +17,9 @@ namespace mozilla { namespace gmp { +class GMPContentChild; + class GMPChild : public PGMPChild - , public GMPSharedMem , public GMPAsyncShutdownHost { public: @@ -40,9 +40,6 @@ public: GMPTimerChild* GetGMPTimers(); GMPStorageChild* GetGMPStorage(); - // GMPSharedMem - virtual void CheckThread() override; - // GMPAsyncShutdownHost void ShutdownComplete() override; @@ -51,6 +48,7 @@ public: #endif private: + friend class GMPContentChild; bool PreLoadPluginVoucher(const std::string& aPluginPath); void PreLoadSandboxVoucher(); @@ -60,36 +58,27 @@ private: virtual bool RecvSetNodeId(const nsCString& aNodeId) override; virtual bool RecvStartPlugin() override; - virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() override; - virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) override; - virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) override; - - virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() override; - virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) override; - virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override; - - virtual PGMPDecryptorChild* AllocPGMPDecryptorChild() override; - virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override; - virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override; - - virtual PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override; - virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override; - virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override; - virtual PGMPTimerChild* AllocPGMPTimerChild() override; virtual bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override; virtual PGMPStorageChild* AllocPGMPStorageChild() override; virtual bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override; + virtual PGMPContentChild* AllocPGMPContentChild(Transport* aTransport, + ProcessId aOtherPid) override; + void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild); + virtual bool RecvCrashPluginNow() override; virtual bool RecvBeginAsyncShutdown() override; + virtual bool RecvCloseActive() override; virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual void ProcessingError(Result aCode, const char* aReason) override; GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI); + nsTArray> mGMPContentChildren; + GMPAsyncShutdown* mAsyncShutdown; nsRefPtr mTimerChild; nsRefPtr mStorage; diff --git a/dom/media/gmp/GMPContentChild.cpp b/dom/media/gmp/GMPContentChild.cpp new file mode 100644 index 0000000000..a2737870a4 --- /dev/null +++ b/dom/media/gmp/GMPContentChild.cpp @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GMPContentChild.h" + +namespace mozilla { +namespace gmp { + +GMPContentChild::GMPContentChild(GMPChild* aChild) + : mGMPChild(aChild) +{ + MOZ_COUNT_CTOR(GMPContentChild); +} + +GMPContentChild::~GMPContentChild() +{ + MOZ_COUNT_DTOR(GMPContentChild); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, + new DeleteTask(GetTransport())); +} + +MessageLoop* +GMPContentChild::GMPMessageLoop() +{ + return mGMPChild->GMPMessageLoop(); +} + +void +GMPContentChild::CheckThread() +{ + MOZ_ASSERT(mGMPChild->mGMPMessageLoop == MessageLoop::current()); +} + +void +GMPContentChild::ActorDestroy(ActorDestroyReason aWhy) +{ + mGMPChild->GMPContentChildActorDestroy(this); +} + +void +GMPContentChild::ProcessingError(Result aCode, const char* aReason) +{ + mGMPChild->ProcessingError(aCode, aReason); +} + +PGMPAudioDecoderChild* +GMPContentChild::AllocPGMPAudioDecoderChild() +{ + return new GMPAudioDecoderChild(this); +} + +bool +GMPContentChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) +{ + delete aActor; + return true; +} + +PGMPDecryptorChild* +GMPContentChild::AllocPGMPDecryptorChild() +{ + GMPDecryptorChild* actor = new GMPDecryptorChild(this, + mGMPChild->mPluginVoucher, + mGMPChild->mSandboxVoucher); + actor->AddRef(); + return actor; +} + +bool +GMPContentChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) +{ + static_cast(aActor)->Release(); + return true; +} + +PGMPVideoDecoderChild* +GMPContentChild::AllocPGMPVideoDecoderChild() +{ + return new GMPVideoDecoderChild(this); +} + +bool +GMPContentChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) +{ + delete aActor; + return true; +} + +PGMPVideoEncoderChild* +GMPContentChild::AllocPGMPVideoEncoderChild() +{ + return new GMPVideoEncoderChild(this); +} + +bool +GMPContentChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) +{ + delete aActor; + return true; +} + +bool +GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) +{ + GMPDecryptorChild* child = static_cast(aActor); + GMPDecryptorHost* host = static_cast(child); + + void* session = nullptr; + GMPErr err = mGMPChild->GetAPI(GMP_API_DECRYPTOR, host, &session); + if (err != GMPNoErr && !session) { + // XXX to remove in bug 1147692 + err = mGMPChild->GetAPI(GMP_API_DECRYPTOR_COMPAT, host, &session); + } + + if (err != GMPNoErr || !session) { + return false; + } + + child->Init(static_cast(session)); + + return true; +} + +bool +GMPContentChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) +{ + auto vdc = static_cast(aActor); + + void* vd = nullptr; + GMPErr err = mGMPChild->GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd); + if (err != GMPNoErr || !vd) { + return false; + } + + vdc->Init(static_cast(vd)); + + return true; +} + +bool +GMPContentChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) +{ + auto vdc = static_cast(aActor); + + void* vd = nullptr; + GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd); + if (err != GMPNoErr || !vd) { + NS_WARNING("GMPGetAPI call failed trying to construct decoder."); + return false; + } + + vdc->Init(static_cast(vd)); + + return true; +} + +bool +GMPContentChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) +{ + auto vec = static_cast(aActor); + + void* ve = nullptr; + GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve); + if (err != GMPNoErr || !ve) { + NS_WARNING("GMPGetAPI call failed trying to construct encoder."); + return false; + } + + vec->Init(static_cast(ve)); + + return true; +} + +void +GMPContentChild::CloseActive() +{ + // Invalidate and remove any remaining API objects. + const nsTArray& audioDecoders = + ManagedPGMPAudioDecoderChild(); + for (uint32_t i = audioDecoders.Length(); i > 0; i--) { + audioDecoders[i - 1]->SendShutdown(); + } + + const nsTArray& decryptors = + ManagedPGMPDecryptorChild(); + for (uint32_t i = decryptors.Length(); i > 0; i--) { + decryptors[i - 1]->SendShutdown(); + } + + const nsTArray& videoDecoders = + ManagedPGMPVideoDecoderChild(); + for (uint32_t i = videoDecoders.Length(); i > 0; i--) { + videoDecoders[i - 1]->SendShutdown(); + } + + const nsTArray& videoEncoders = + ManagedPGMPVideoEncoderChild(); + for (uint32_t i = videoEncoders.Length(); i > 0; i--) { + videoEncoders[i - 1]->SendShutdown(); + } +} + +bool +GMPContentChild::IsUsed() +{ + return !ManagedPGMPAudioDecoderChild().IsEmpty() || + !ManagedPGMPDecryptorChild().IsEmpty() || + !ManagedPGMPVideoDecoderChild().IsEmpty() || + !ManagedPGMPVideoEncoderChild().IsEmpty(); +} + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/GMPContentChild.h b/dom/media/gmp/GMPContentChild.h new file mode 100644 index 0000000000..1170a533b2 --- /dev/null +++ b/dom/media/gmp/GMPContentChild.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GMPContentChild_h_ +#define GMPContentChild_h_ + +#include "mozilla/gmp/PGMPContentChild.h" +#include "GMPSharedMemManager.h" + +namespace mozilla { +namespace gmp { + +class GMPChild; + +class GMPContentChild : public PGMPContentChild + , public GMPSharedMem +{ +public: + explicit GMPContentChild(GMPChild* aChild); + virtual ~GMPContentChild(); + + MessageLoop* GMPMessageLoop(); + + virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override; + virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override; + virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) override; + virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override; + + virtual PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override; + virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override; + + virtual PGMPDecryptorChild* AllocPGMPDecryptorChild() override; + virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override; + + virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() override; + virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) override; + + virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() override; + virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) override; + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + virtual void ProcessingError(Result aCode, const char* aReason) override; + + // GMPSharedMem + virtual void CheckThread() override; + + void CloseActive(); + bool IsUsed(); + + GMPChild* mGMPChild; +}; + +} // namespace gmp +} // namespace mozilla + +#endif // GMPContentChild_h_ diff --git a/dom/media/gmp/GMPContentParent.cpp b/dom/media/gmp/GMPContentParent.cpp new file mode 100644 index 0000000000..8363c5cac8 --- /dev/null +++ b/dom/media/gmp/GMPContentParent.cpp @@ -0,0 +1,302 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GMPContentParent.h" +#include "GMPAudioDecoderParent.h" +#include "GMPDecryptorParent.h" +#include "GMPParent.h" +#include "GMPServiceChild.h" +#include "GMPVideoDecoderParent.h" +#include "GMPVideoEncoderParent.h" +#include "mozIGeckoMediaPluginService.h" +#include "prlog.h" + +namespace mozilla { + +#ifdef LOG +#undef LOG +#endif + +#ifdef PR_LOGGING +extern PRLogModuleInfo* GetGMPLog(); + +#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg) +#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg) +#else +#define LOGD(msg) +#define LOG(level, msg) +#endif + +#ifdef __CLASS__ +#undef __CLASS__ +#endif +#define __CLASS__ "GMPContentParent" + +namespace gmp { + +GMPContentParent::GMPContentParent(GMPParent* aParent) + : mParent(aParent) +{ + if (mParent) { + SetDisplayName(mParent->GetDisplayName()); + SetPluginId(mParent->GetPluginId()); + } +} + +GMPContentParent::~GMPContentParent() +{ + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, + new DeleteTask(GetTransport())); +} + +class ReleaseGMPContentParent : public nsRunnable +{ +public: + explicit ReleaseGMPContentParent(GMPContentParent* aToRelease) + : mToRelease(aToRelease) + { + } + + NS_IMETHOD Run() + { + return NS_OK; + } + +private: + nsRefPtr mToRelease; +}; + +void +GMPContentParent::ActorDestroy(ActorDestroyReason aWhy) +{ + MOZ_ASSERT(mAudioDecoders.IsEmpty() && + mDecryptors.IsEmpty() && + mVideoDecoders.IsEmpty() && + mVideoEncoders.IsEmpty()); + NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this)); +} + +void +GMPContentParent::CheckThread() +{ + MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); +} + +void +GMPContentParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder) +{ + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + + MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder)); + CloseIfUnused(); +} + +void +GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder) +{ + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + + // If the constructor fails, we'll get called before it's added + unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder)); + CloseIfUnused(); +} + +void +GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder) +{ + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + + // If the constructor fails, we'll get called before it's added + unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder)); + CloseIfUnused(); +} + +void +GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession) +{ + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + + MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession)); + CloseIfUnused(); +} + +void +GMPContentParent::CloseIfUnused() +{ + if (mAudioDecoders.IsEmpty() && + mDecryptors.IsEmpty() && + mVideoDecoders.IsEmpty() && + mVideoEncoders.IsEmpty()) { + nsRefPtr toClose; + if (mParent) { + toClose = mParent->ForgetGMPContentParent(); + } else { + toClose = this; + nsRefPtr gmp( + GeckoMediaPluginServiceChild::GetSingleton()); + gmp->RemoveGMPContentParent(toClose); + } + NS_DispatchToCurrentThread(NS_NewRunnableMethod(toClose, + &GMPContentParent::Close)); + } +} + +nsresult +GMPContentParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP) +{ + PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor(); + if (!pdp) { + return NS_ERROR_FAILURE; + } + GMPDecryptorParent* dp = static_cast(pdp); + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + NS_ADDREF(dp); + mDecryptors.AppendElement(dp); + *aGMPDP = dp; + + return NS_OK; +} + +nsIThread* +GMPContentParent::GMPThread() +{ + if (!mGMPThread) { + nsCOMPtr mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); + MOZ_ASSERT(mps); + if (!mps) { + return nullptr; + } + // Not really safe if we just grab to the mGMPThread, as we don't know + // what thread we're running on and other threads may be trying to + // access this without locks! However, debug only, and primary failure + // mode outside of compiler-helped TSAN is a leak. But better would be + // to use swap() under a lock. + mps->GetThread(getter_AddRefs(mGMPThread)); + MOZ_ASSERT(mGMPThread); + } + + return mGMPThread; +} + +nsresult +GMPContentParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD) +{ + PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor(); + if (!pvap) { + return NS_ERROR_FAILURE; + } + GMPAudioDecoderParent* vap = static_cast(pvap); + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + NS_ADDREF(vap); + *aGMPAD = vap; + mAudioDecoders.AppendElement(vap); + + return NS_OK; +} + +nsresult +GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD) +{ + // returned with one anonymous AddRef that locks it until Destroy + PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor(); + if (!pvdp) { + return NS_ERROR_FAILURE; + } + GMPVideoDecoderParent *vdp = static_cast(pvdp); + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + NS_ADDREF(vdp); + *aGMPVD = vdp; + mVideoDecoders.AppendElement(vdp); + + return NS_OK; +} + +nsresult +GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE) +{ + // returned with one anonymous AddRef that locks it until Destroy + PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor(); + if (!pvep) { + return NS_ERROR_FAILURE; + } + GMPVideoEncoderParent *vep = static_cast(pvep); + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + NS_ADDREF(vep); + *aGMPVE = vep; + mVideoEncoders.AppendElement(vep); + + return NS_OK; +} + +PGMPVideoDecoderParent* +GMPContentParent::AllocPGMPVideoDecoderParent() +{ + GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this); + NS_ADDREF(vdp); + return vdp; +} + +bool +GMPContentParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) +{ + GMPVideoDecoderParent* vdp = static_cast(aActor); + NS_RELEASE(vdp); + return true; +} + +PGMPVideoEncoderParent* +GMPContentParent::AllocPGMPVideoEncoderParent() +{ + GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this); + NS_ADDREF(vep); + return vep; +} + +bool +GMPContentParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) +{ + GMPVideoEncoderParent* vep = static_cast(aActor); + NS_RELEASE(vep); + return true; +} + +PGMPDecryptorParent* +GMPContentParent::AllocPGMPDecryptorParent() +{ + GMPDecryptorParent* ksp = new GMPDecryptorParent(this); + NS_ADDREF(ksp); + return ksp; +} + +bool +GMPContentParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) +{ + GMPDecryptorParent* ksp = static_cast(aActor); + NS_RELEASE(ksp); + return true; +} + +PGMPAudioDecoderParent* +GMPContentParent::AllocPGMPAudioDecoderParent() +{ + GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this); + NS_ADDREF(vdp); + return vdp; +} + +bool +GMPContentParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) +{ + GMPAudioDecoderParent* vdp = static_cast(aActor); + NS_RELEASE(vdp); + return true; +} + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/GMPContentParent.h b/dom/media/gmp/GMPContentParent.h new file mode 100644 index 0000000000..67cb81e623 --- /dev/null +++ b/dom/media/gmp/GMPContentParent.h @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GMPContentParent_h_ +#define GMPContentParent_h_ + +#include "mozilla/gmp/PGMPContentParent.h" +#include "nsISupportsImpl.h" + +class nsITimer; + +namespace mozilla { +namespace gmp { + +class GeckoMediaPluginService; +class GMPAudioDecoderParent; +class GMPCapability; +class GMPDecryptorParent; +class GMPParent; +class GMPVideoDecoderParent; +class GMPVideoEncoderParent; + +class GMPContentParent final : public PGMPContentParent, + public GMPSharedMem +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPContentParent) + + explicit GMPContentParent(GMPParent* aParent = nullptr); + + nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD); + void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder); + + nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE); + void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder); + + nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS); + void DecryptorDestroyed(GMPDecryptorParent* aSession); + + nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD); + void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder); + + nsIThread* GMPThread(); + + // GMPSharedMem + virtual void CheckThread() override; + + void SetDisplayName(const nsCString& aDisplayName) + { + mDisplayName = aDisplayName; + } + const nsCString& GetDisplayName() + { + return mDisplayName; + } + void SetPluginId(const nsCString& aPluginId) + { + mPluginId = aPluginId; + } + const nsCString& GetPluginId() + { + return mPluginId; + } + +private: + ~GMPContentParent(); + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + + virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() override; + virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) override; + + virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() override; + virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) override; + + virtual PGMPDecryptorParent* AllocPGMPDecryptorParent() override; + virtual bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override; + + virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override; + virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override; + + void CloseIfUnused(); + // Needed because NS_NewRunnableMethod tried to use the class that the method + // lives on to store the receiver, but PGMPContentParent isn't refcounted. + void Close() + { + PGMPContentParent::Close(); + } + + nsTArray> mVideoDecoders; + nsTArray> mVideoEncoders; + nsTArray> mDecryptors; + nsTArray> mAudioDecoders; + nsCOMPtr mGMPThread; + nsRefPtr mParent; + nsCString mDisplayName; + nsCString mPluginId; +}; + +} // namespace gmp +} // namespace mozilla + +#endif // GMPParent_h_ diff --git a/dom/media/gmp/GMPDecryptorChild.cpp b/dom/media/gmp/GMPDecryptorChild.cpp index 4c17065b6f..20e801198a 100644 --- a/dom/media/gmp/GMPDecryptorChild.cpp +++ b/dom/media/gmp/GMPDecryptorChild.cpp @@ -26,7 +26,7 @@ namespace mozilla { namespace gmp { -GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin, +GMPDecryptorChild::GMPDecryptorChild(GMPContentChild* aPlugin, const nsTArray& aPluginVoucher, const nsTArray& aSandboxVoucher) : mSession(nullptr) diff --git a/dom/media/gmp/GMPDecryptorChild.h b/dom/media/gmp/GMPDecryptorChild.h index b0f9848498..880bbc034a 100644 --- a/dom/media/gmp/GMPDecryptorChild.h +++ b/dom/media/gmp/GMPDecryptorChild.h @@ -15,7 +15,7 @@ namespace mozilla { namespace gmp { -class GMPChild; +class GMPContentChild; class GMPDecryptorChild : public GMPDecryptorCallback , public GMPDecryptorHost @@ -24,7 +24,7 @@ class GMPDecryptorChild : public GMPDecryptorCallback public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPDecryptorChild); - explicit GMPDecryptorChild(GMPChild* aPlugin, + explicit GMPDecryptorChild(GMPContentChild* aPlugin, const nsTArray& aPluginVoucher, const nsTArray& aSandboxVoucher); @@ -117,7 +117,7 @@ private: // GMP's GMPDecryptor implementation. // Only call into this on the (GMP process) main thread. GMPDecryptor* mSession; - GMPChild* mPlugin; + GMPContentChild* mPlugin; // Reference to the vouchers owned by the GMPChild. const nsTArray& mPluginVoucher; diff --git a/dom/media/gmp/GMPDecryptorParent.cpp b/dom/media/gmp/GMPDecryptorParent.cpp index 165c9784a8..250cac74af 100644 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ b/dom/media/gmp/GMPDecryptorParent.cpp @@ -4,14 +4,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPDecryptorParent.h" -#include "GMPParent.h" +#include "GMPContentParent.h" #include "MediaData.h" #include "mozilla/unused.h" namespace mozilla { namespace gmp { -GMPDecryptorParent::GMPDecryptorParent(GMPParent* aPlugin) +GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin) : mIsOpen(false) , mShuttingDown(false) , mPlugin(aPlugin) @@ -307,6 +307,13 @@ GMPDecryptorParent::RecvDecrypted(const uint32_t& aId, return true; } +bool +GMPDecryptorParent::RecvShutdown() +{ + Shutdown(); + return true; +} + // Note: may be called via Terminated() void GMPDecryptorParent::Close() diff --git a/dom/media/gmp/GMPDecryptorParent.h b/dom/media/gmp/GMPDecryptorParent.h index 4d2a291a3a..cbb975e1d3 100644 --- a/dom/media/gmp/GMPDecryptorParent.h +++ b/dom/media/gmp/GMPDecryptorParent.h @@ -17,7 +17,7 @@ class CryptoSample; namespace gmp { -class GMPParent; +class GMPContentParent; class GMPDecryptorParent final : public GMPDecryptorProxy , public PGMPDecryptorParent @@ -25,7 +25,7 @@ class GMPDecryptorParent final : public GMPDecryptorProxy public: NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent) - explicit GMPDecryptorParent(GMPParent *aPlugin); + explicit GMPDecryptorParent(GMPContentParent *aPlugin); // GMPDecryptorProxy virtual const nsACString& GetPluginId() const override; @@ -103,12 +103,14 @@ private: virtual bool RecvSetCaps(const uint64_t& aCaps) override; + virtual bool RecvShutdown() override; + virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual bool Recv__delete__() override; bool mIsOpen; bool mShuttingDown; - nsRefPtr mPlugin; + nsRefPtr mPlugin; nsCString mPluginId; GMPDecryptorProxyCallback* mCallback; #ifdef DEBUG diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp index b98cb74a11..56b38b444b 100644 --- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -14,6 +14,7 @@ #include "nsThreadUtils.h" #include "nsIRunnable.h" #include "mozIGeckoMediaPluginService.h" +#include "mozilla/SyncRunnable.h" #include "mozilla/unused.h" #include "nsIObserverService.h" #include "GMPTimerParent.h" @@ -26,25 +27,18 @@ namespace mozilla { -#ifdef LOG #undef LOG -#endif +#undef LOGD #ifdef PR_LOGGING extern PRLogModuleInfo* GetGMPLog(); - -#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg) -#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg) +#define LOG(level, x, ...) PR_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__)) +#define LOGD(x, ...) LOG(PR_LOG_DEBUG, "GMPParent[%p|childPid=%d] " x, this, mChildPid, ##__VA_ARGS__) #else -#define LOGD(msg) -#define LOG(level, msg) +#define LOG(level, x, ...) +#define LOGD(x, ...) #endif -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPParent" - namespace gmp { GMPParent::GMPParent() @@ -54,9 +48,14 @@ GMPParent::GMPParent() , mAbnormalShutdownInProgress(false) , mIsBlockingDeletion(false) , mCanDecrypt(false) + , mGMPContentChildCount(0) , mAsyncShutdownRequired(false) , mAsyncShutdownInProgress(false) +#ifdef PR_LOGGING + , mChildPid(0) +#endif { + LOGD("GMPParent ctor"); // Use the parent address to identify it. // We could use any unique-to-the-parent value. mPluginId.AppendInt(reinterpret_cast(this)); @@ -66,12 +65,7 @@ GMPParent::~GMPParent() { // Can't Close or Destroy the process here, since destruction is MainThread only MOZ_ASSERT(NS_IsMainThread()); -} - -void -GMPParent::CheckThread() -{ - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); + LOGD("GMPParent dtor"); } nsresult @@ -83,7 +77,7 @@ GMPParent::CloneFrom(const GMPParent* aOther) } nsresult -GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir) +GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir) { MOZ_ASSERT(aPluginDir); MOZ_ASSERT(aService); @@ -104,8 +98,7 @@ GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir) if (NS_FAILED(rv)) { return rv; } - LOGD(("%s::%s: %p for %s", __CLASS__, __FUNCTION__, this, - NS_LossyConvertUTF16toASCII(parentLeafName).get())); + LOGD("%s: for %s", __FUNCTION__, NS_LossyConvertUTF16toASCII(parentLeafName).get()); MOZ_ASSERT(parentLeafName.Length() > 4); mName = Substring(parentLeafName, 4); @@ -132,7 +125,7 @@ GMPParent::LoadProcess() if (NS_FAILED(mDirectory->GetPath(path))) { return NS_ERROR_FAILURE; } - LOGD(("%s::%s: %p for %s", __CLASS__, __FUNCTION__, this, path.get())); + LOGD("%s: for %s", __FUNCTION__, NS_ConvertUTF16toUTF8(path).get()); if (!mProcess) { mProcess = new GMPProcessParent(NS_ConvertUTF16toUTF8(path).get()); @@ -142,33 +135,37 @@ GMPParent::LoadProcess() return NS_ERROR_FAILURE; } +#ifdef PR_LOGGING + mChildPid = base::GetProcId(mProcess->GetChildProcessHandle()); +#endif + bool opened = Open(mProcess->GetChannel(), base::GetProcId(mProcess->GetChildProcessHandle())); if (!opened) { - LOGD(("%s::%s: Failed to create new child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Failed to create new child process", __FUNCTION__); mProcess->Delete(); mProcess = nullptr; return NS_ERROR_FAILURE; } - LOGD(("%s::%s: Created new child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Created new child process", __FUNCTION__); bool ok = SendSetNodeId(mNodeId); if (!ok) { - LOGD(("%s::%s: Failed to send node id to child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Failed to send node id to child process", __FUNCTION__); mProcess->Delete(); mProcess = nullptr; return NS_ERROR_FAILURE; } - LOGD(("%s::%s: Sent node id to child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Sent node id to child process", __FUNCTION__); ok = SendStartPlugin(); if (!ok) { - LOGD(("%s::%s: Failed to send start to child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Failed to send start to child process", __FUNCTION__); mProcess->Delete(); mProcess = nullptr; return NS_ERROR_FAILURE; } - LOGD(("%s::%s: Sent StartPlugin to child process %p", __CLASS__, __FUNCTION__, (void *)mProcess)); + LOGD("%s: Sent StartPlugin to child process", __FUNCTION__); } mState = GMPStateLoaded; @@ -181,8 +178,8 @@ AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure) { NS_WARNING("Timed out waiting for GMP async shutdown!"); GMPParent* parent = reinterpret_cast(aClosure); - nsRefPtr service = - GeckoMediaPluginService::GetGeckoMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); if (service) { service->AsyncShutdownComplete(parent); } @@ -209,8 +206,8 @@ GMPParent::EnsureAsyncShutdownTimeoutSet() } int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT; - nsRefPtr service = - GeckoMediaPluginService::GetGeckoMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); if (service) { timeout = service->AsyncShutdownTimeoutMs(); } @@ -219,21 +216,26 @@ GMPParent::EnsureAsyncShutdownTimeoutSet() nsITimer::TYPE_ONE_SHOT); } +bool +GMPParent::RecvPGMPContentChildDestroyed() +{ + --mGMPContentChildCount; + if (!IsUsed()) { + CloseIfUnused(); + } + return true; +} + void GMPParent::CloseIfUnused() { MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - LOGD(("%s::%s: %p mAsyncShutdownRequired=%d", __CLASS__, __FUNCTION__, this, - mAsyncShutdownRequired)); + LOGD("%s: mAsyncShutdownRequired=%d", __FUNCTION__, mAsyncShutdownRequired); if ((mDeleteProcessOnlyOnUnload || mState == GMPStateLoaded || mState == GMPStateUnloading) && - mVideoDecoders.IsEmpty() && - mVideoEncoders.IsEmpty() && - mDecryptors.IsEmpty() && - mAudioDecoders.IsEmpty()) { - + !IsUsed()) { // Ensure all timers are killed. for (uint32_t i = mTimers.Length(); i > 0; i--) { mTimers[i - 1]->Shutdown(); @@ -241,8 +243,7 @@ GMPParent::CloseIfUnused() if (mAsyncShutdownRequired) { if (!mAsyncShutdownInProgress) { - LOGD(("%s::%s: %p sending async shutdown notification", __CLASS__, - __FUNCTION__, this)); + LOGD("%s: sending async shutdown notification", __FUNCTION__); mAsyncShutdownInProgress = true; if (!SendBeginAsyncShutdown() || NS_FAILED(EnsureAsyncShutdownTimeoutSet())) { @@ -263,7 +264,7 @@ void GMPParent::AbortAsyncShutdown() { MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); + LOGD("%s", __FUNCTION__); if (mAsyncShutdownTimeout) { mAsyncShutdownTimeout->Cancel(); @@ -281,57 +282,21 @@ GMPParent::AbortAsyncShutdown() CloseIfUnused(); } -void -GMPParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder)); - - // Recv__delete__ is on the stack, don't potentially destroy the top-level actor - // until after this has completed. - nsCOMPtr event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused); - NS_DispatchToCurrentThread(event); -} - void GMPParent::CloseActive(bool aDieWhenUnloaded) { - LOGD(("%s::%s: %p state %d", __CLASS__, __FUNCTION__, this, mState)); + LOGD("%s: state %d", __FUNCTION__, mState); + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + if (aDieWhenUnloaded) { mDeleteProcessOnlyOnUnload = true; // don't allow this to go back... } if (mState == GMPStateLoaded) { mState = GMPStateUnloading; } - - // Invalidate and remove any remaining API objects. - for (uint32_t i = mVideoDecoders.Length(); i > 0; i--) { - mVideoDecoders[i - 1]->Shutdown(); + if (mState != GMPStateNotLoaded && IsUsed()) { + unused << SendCloseActive(); } - - for (uint32_t i = mVideoEncoders.Length(); i > 0; i--) { - mVideoEncoders[i - 1]->Shutdown(); - } - - for (uint32_t i = mDecryptors.Length(); i > 0; i--) { - mDecryptors[i - 1]->Shutdown(); - } - - for (uint32_t i = mAudioDecoders.Length(); i > 0; i--) { - mAudioDecoders[i - 1]->Shutdown(); - } - - // Note: we don't shutdown timers here, we do that in CloseIfUnused(), - // as there are multiple entry points to CloseIfUnused(). - - // Note: We don't shutdown storage API objects here, as they need to - // work during async shutdown of GMPs. - - // Note: the shutdown of the codecs is async! don't kill - // the plugin-container until they're all safely shut down via - // CloseIfUnused(); - CloseIfUnused(); } void @@ -350,7 +315,7 @@ GMPParent::IsMarkedForDeletion() void GMPParent::Shutdown() { - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); + LOGD("%s", __FUNCTION__); MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); MOZ_ASSERT(!mAsyncShutdownTimeout, "Should have canceled shutdown timeout"); @@ -358,7 +323,8 @@ GMPParent::Shutdown() if (mAbnormalShutdownInProgress) { return; } - MOZ_ASSERT(mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty()); + + MOZ_ASSERT(!IsUsed()); if (mState == GMPStateNotLoaded || mState == GMPStateClosing) { return; } @@ -395,18 +361,29 @@ public: void GMPParent::ChildTerminated() { - nsRefPtr self(this); - GMPThread()->Dispatch(NS_NewRunnableMethodWithArg>( - mService, - &GeckoMediaPluginService::PluginTerminated, - self), - NS_DISPATCH_NORMAL); + RefPtr self(this); + nsIThread* gmpThread = GMPThread(); + + if (!gmpThread) { + // Bug 1163239 - this can happen on shutdown. + // PluginTerminated removes the GMP from the GMPService. + // On shutdown we can have this case where it is already been + // removed so there is no harm in not trying to remove it again. + //LOGD("%s::%s: GMPThread() returned nullptr.", __CLASS__, __FUNCTION__); + LOGD("%s: GMPThread() returned nullptr.", __FUNCTION__); + } else { + gmpThread->Dispatch(NS_NewRunnableMethodWithArg>( + mService, + &GeckoMediaPluginServiceParent::PluginTerminated, + self), + NS_DISPATCH_NORMAL); + } } void GMPParent::DeleteProcess() { - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); + LOGD("%s", __FUNCTION__); if (mState != GMPStateClosing) { // Don't Close() twice! @@ -415,7 +392,7 @@ GMPParent::DeleteProcess() Close(); } mProcess->Delete(NS_NewRunnableMethod(this, &GMPParent::ChildTerminated)); - LOGD(("%s::%s: Shut down process %p", __CLASS__, __FUNCTION__, (void *) mProcess)); + LOGD("%s: Shut down process", __FUNCTION__); mProcess = nullptr; mState = GMPStateNotLoaded; @@ -425,78 +402,6 @@ GMPParent::DeleteProcess() } -void -GMPParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - // If the constructor fails, we'll get called before it's added - unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder)); - - if (mVideoDecoders.IsEmpty() && - mVideoEncoders.IsEmpty()) { - // Recv__delete__ is on the stack, don't potentially destroy the top-level actor - // until after this has completed. - nsCOMPtr event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused); - NS_DispatchToCurrentThread(event); - } -} - -void -GMPParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - // If the constructor fails, we'll get called before it's added - unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder)); - - if (mVideoDecoders.IsEmpty() && - mVideoEncoders.IsEmpty()) { - // Recv__delete__ is on the stack, don't potentially destroy the top-level actor - // until after this has completed. - nsCOMPtr event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused); - NS_DispatchToCurrentThread(event); - } -} - -void -GMPParent::DecryptorDestroyed(GMPDecryptorParent* aSession) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession)); - - // Recv__delete__ is on the stack, don't potentially destroy the top-level actor - // until after this has completed. - if (mDecryptors.IsEmpty()) { - nsCOMPtr event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused); - NS_DispatchToCurrentThread(event); - } -} - -nsresult -GMPParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (!EnsureProcessLoaded()) { - return NS_ERROR_FAILURE; - } - - PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor(); - if (!pdp) { - return NS_ERROR_FAILURE; - } - GMPDecryptorParent* dp = static_cast(pdp); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(dp); - mDecryptors.AppendElement(dp); - *aGMPDP = dp; - - return NS_OK; -} - GMPState GMPParent::State() const { @@ -558,81 +463,10 @@ GMPParent::EnsureProcessLoaded() return NS_SUCCEEDED(rv); } -nsresult -GMPParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (!EnsureProcessLoaded()) { - return NS_ERROR_FAILURE; - } - - PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor(); - if (!pvap) { - return NS_ERROR_FAILURE; - } - GMPAudioDecoderParent* vap = static_cast(pvap); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vap); - *aGMPAD = vap; - mAudioDecoders.AppendElement(vap); - - return NS_OK; -} - -nsresult -GMPParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (!EnsureProcessLoaded()) { - return NS_ERROR_FAILURE; - } - - // returned with one anonymous AddRef that locks it until Destroy - PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor(); - if (!pvdp) { - return NS_ERROR_FAILURE; - } - GMPVideoDecoderParent *vdp = static_cast(pvdp); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vdp); - *aGMPVD = vdp; - mVideoDecoders.AppendElement(vdp); - - return NS_OK; -} - -nsresult -GMPParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (!EnsureProcessLoaded()) { - return NS_ERROR_FAILURE; - } - - // returned with one anonymous AddRef that locks it until Destroy - PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor(); - if (!pvep) { - return NS_ERROR_FAILURE; - } - GMPVideoEncoderParent *vep = static_cast(pvep); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vep); - *aGMPVE = vep; - mVideoEncoders.AppendElement(vep); - - return NS_OK; -} - void GMPParent::ActorDestroy(ActorDestroyReason aWhy) { - LOGD(("%s::%s: %p (%d)", __CLASS__, __FUNCTION__, this, (int) aWhy)); + LOGD("%s: (%d)", __FUNCTION__, (int)aWhy); // warn us off trying to close again mState = GMPStateClosing; mAbnormalShutdownInProgress = true; @@ -654,70 +488,6 @@ GMPParent::ActorDestroy(ActorDestroyReason aWhy) } } -PGMPVideoDecoderParent* -GMPParent::AllocPGMPVideoDecoderParent() -{ - GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this); - NS_ADDREF(vdp); - return vdp; -} - -bool -GMPParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) -{ - GMPVideoDecoderParent* vdp = static_cast(aActor); - NS_RELEASE(vdp); - return true; -} - -PGMPVideoEncoderParent* -GMPParent::AllocPGMPVideoEncoderParent() -{ - GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this); - NS_ADDREF(vep); - return vep; -} - -bool -GMPParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) -{ - GMPVideoEncoderParent* vep = static_cast(aActor); - NS_RELEASE(vep); - return true; -} - -PGMPDecryptorParent* -GMPParent::AllocPGMPDecryptorParent() -{ - GMPDecryptorParent* ksp = new GMPDecryptorParent(this); - NS_ADDREF(ksp); - return ksp; -} - -bool -GMPParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) -{ - GMPDecryptorParent* ksp = static_cast(aActor); - NS_RELEASE(ksp); - return true; -} - -PGMPAudioDecoderParent* -GMPParent::AllocPGMPAudioDecoderParent() -{ - GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this); - NS_ADDREF(vdp); - return vdp; -} - -bool -GMPParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) -{ - GMPAudioDecoderParent* vdp = static_cast(aActor); - NS_RELEASE(vdp); - return true; -} - PGMPStorageParent* GMPParent::AllocPGMPStorageParent() { @@ -963,7 +733,7 @@ GMPParent::GetVersion() const return mVersion; } -const nsACString& +const nsCString& GMPParent::GetPluginId() const { return mPluginId; @@ -972,7 +742,7 @@ GMPParent::GetPluginId() const bool GMPParent::RecvAsyncShutdownRequired() { - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); + LOGD("%s", __FUNCTION__); if (mAsyncShutdownRequired) { NS_WARNING("Received AsyncShutdownRequired message more than once!"); return true; @@ -985,12 +755,116 @@ GMPParent::RecvAsyncShutdownRequired() bool GMPParent::RecvAsyncShutdownComplete() { - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); + LOGD("%s", __FUNCTION__); MOZ_ASSERT(mAsyncShutdownRequired); AbortAsyncShutdown(); return true; } +class RunCreateContentParentCallbacks : public nsRunnable +{ +public: + explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent) + : mGMPContentParent(aGMPContentParent) + { + } + + void TakeCallbacks(nsTArray>& aCallbacks) + { + mCallbacks.SwapElements(aCallbacks); + } + + NS_IMETHOD + Run() + { + for (uint32_t i = 0, length = mCallbacks.Length(); i < length; ++i) { + mCallbacks[i]->Done(mGMPContentParent); + } + return NS_OK; + } + +private: + nsRefPtr mGMPContentParent; + nsTArray> mCallbacks; +}; + +PGMPContentParent* +GMPParent::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid) +{ + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + MOZ_ASSERT(!mGMPContentParent); + + mGMPContentParent = new GMPContentParent(this); + mGMPContentParent->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), + ipc::ParentSide); + + nsRefPtr runCallbacks = + new RunCreateContentParentCallbacks(mGMPContentParent); + runCallbacks->TakeCallbacks(mCallbacks); + NS_DispatchToCurrentThread(runCallbacks); + MOZ_ASSERT(mCallbacks.IsEmpty()); + + return mGMPContentParent; +} + +bool +GMPParent::GetGMPContentParent(UniquePtr&& aCallback) +{ + LOGD("%s %p", __FUNCTION__, this); + MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); + + if (mGMPContentParent) { + aCallback->Done(mGMPContentParent); + } else { + mCallbacks.AppendElement(Move(aCallback)); + // If we don't have a GMPContentParent and we try to get one for the first + // time (mCallbacks.Length() == 1) then call PGMPContent::Open. If more + // calls to GetGMPContentParent happen before mGMPContentParent has been + // set then we should just store them, so that they get called when we set + // mGMPContentParent as a result of the PGMPContent::Open call. + if (mCallbacks.Length() == 1) { + if (!EnsureProcessLoaded() || !PGMPContent::Open(this)) { + return false; + } + // We want to increment this as soon as possible, to avoid that we'd try + // to shut down the GMP process while we're still trying to get a + // PGMPContentParent actor. + ++mGMPContentChildCount; + } + } + return true; +} + +already_AddRefed +GMPParent::ForgetGMPContentParent() +{ + MOZ_ASSERT(mCallbacks.IsEmpty()); + return Move(mGMPContentParent.forget()); +} + +bool +GMPParent::EnsureProcessLoaded(base::ProcessId* aID) +{ + if (!EnsureProcessLoaded()) { + return false; + } + *aID = OtherPid(); + return true; +} + +bool +GMPParent::Bridge(GMPServiceParent* aGMPServiceParent) +{ + if (!PGMPContent::Bridge(aGMPServiceParent, this)) { + return false; + } + ++mGMPContentChildCount; + return true; +} + } // namespace gmp } // namespace mozilla + +#undef LOG +#undef LOGD diff --git a/dom/media/gmp/GMPParent.h b/dom/media/gmp/GMPParent.h index 734faaa086..76101cd7bf 100644 --- a/dom/media/gmp/GMPParent.h +++ b/dom/media/gmp/GMPParent.h @@ -7,7 +7,7 @@ #define GMPParent_h_ #include "GMPProcessParent.h" -#include "GMPService.h" +#include "GMPServiceParent.h" #include "GMPAudioDecoderParent.h" #include "GMPDecryptorParent.h" #include "GMPVideoDecoderParent.h" @@ -43,15 +43,30 @@ enum GMPState { GMPStateClosing }; -class GMPParent final : public PGMPParent, - public GMPSharedMem +class GMPContentParent; + +class GetGMPContentParentCallback +{ +public: + GetGMPContentParentCallback() + { + MOZ_COUNT_CTOR(GetGMPContentParentCallback); + }; + virtual ~GetGMPContentParentCallback() + { + MOZ_COUNT_DTOR(GetGMPContentParentCallback); + }; + virtual void Done(GMPContentParent* aGMPContentParent) = 0; +}; + +class GMPParent final : public PGMPParent { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent) GMPParent(); - nsresult Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir); + nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir); nsresult CloneFrom(const GMPParent* aOther); void Crash(); @@ -77,18 +92,6 @@ public: bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag); - nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD); - void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder); - - nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE); - void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder); - - nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS); - void DecryptorDestroyed(GMPDecryptorParent* aSession); - - nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD); - void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder); - GMPState State() const; nsIThread* GMPThread(); @@ -110,7 +113,7 @@ public: const nsCString& GetDisplayName() const; const nsCString& GetVersion() const; - const nsACString& GetPluginId() const; + const nsCString& GetPluginId() const; // Returns true if a plugin can be or is being used across multiple NodeIds. bool CanBeSharedCrossNodeIds() const; @@ -124,37 +127,32 @@ public: return nsCOMPtr(mDirectory).forget(); } - // GMPSharedMem - virtual void CheckThread() override; - void AbortAsyncShutdown(); // Called when the child process has died. void ChildTerminated(); + bool GetGMPContentParent(UniquePtr&& aCallback); + already_AddRefed ForgetGMPContentParent(); + + bool EnsureProcessLoaded(base::ProcessId* aID); + + bool Bridge(GMPServiceParent* aGMPServiceParent); + private: ~GMPParent(); - nsRefPtr mService; + nsRefPtr mService; bool EnsureProcessLoaded(); nsresult ReadGMPMetaData(); virtual void ActorDestroy(ActorDestroyReason aWhy) override; - virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() override; - virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) override; - - virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() override; - virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) override; - - virtual PGMPDecryptorParent* AllocPGMPDecryptorParent() override; - virtual bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override; - - virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override; - virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override; - virtual bool RecvPGMPStorageConstructor(PGMPStorageParent* actor) override; virtual PGMPStorageParent* AllocPGMPStorageParent() override; virtual bool DeallocPGMPStorageParent(PGMPStorageParent* aActor) override; + virtual PGMPContentParent* AllocPGMPContentParent(Transport* aTransport, + ProcessId aOtherPid) override; + virtual bool RecvPGMPTimerConstructor(PGMPTimerParent* actor) override; virtual PGMPTimerParent* AllocPGMPTimerParent() override; virtual bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) override; @@ -162,6 +160,13 @@ private: virtual bool RecvAsyncShutdownComplete() override; virtual bool RecvAsyncShutdownRequired() override; + virtual bool RecvPGMPContentChildDestroyed() override; + bool IsUsed() + { + return mGMPContentChildCount > 0; + } + + nsresult EnsureAsyncShutdownTimeoutSet(); GMPState mState; @@ -179,10 +184,6 @@ private: bool mCanDecrypt; - nsTArray> mVideoDecoders; - nsTArray> mVideoEncoders; - nsTArray> mDecryptors; - nsTArray> mAudioDecoders; nsTArray> mTimers; nsTArray> mStorage; nsCOMPtr mGMPThread; @@ -190,9 +191,18 @@ private: // NodeId the plugin is assigned to, or empty if the the plugin is not // assigned to a NodeId. nsAutoCString mNodeId; + // This is used for GMP content in the parent, there may be more of these in + // the content processes. + nsRefPtr mGMPContentParent; + nsTArray> mCallbacks; + uint32_t mGMPContentChildCount; bool mAsyncShutdownRequired; bool mAsyncShutdownInProgress; + +#ifdef PR_LOGGING + int mChildPid; +#endif }; } // namespace gmp diff --git a/dom/media/gmp/GMPService.cpp b/dom/media/gmp/GMPService.cpp index 25060f3b3a..74b1c768ca 100644 --- a/dom/media/gmp/GMPService.cpp +++ b/dom/media/gmp/GMPService.cpp @@ -3,7 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "GMPService.h" +#include "GMPServiceParent.h" +#include "GMPServiceChild.h" #include "prio.h" #include "prlog.h" #include "GMPParent.h" @@ -64,7 +65,6 @@ GetGMPLog() namespace gmp { -static const uint32_t NodeIdSaltLength = 32; static StaticRefPtr sSingletonService; class GMPServiceCreateHelper final : public nsRunnable @@ -108,15 +108,23 @@ private: { MOZ_ASSERT(NS_IsMainThread()); - nsRefPtr service = sSingletonService.get(); - if (!service) { - service = new GeckoMediaPluginService(); - service->Init(); + if (!sSingletonService) { + if (XRE_GetProcessType() == GeckoProcessType_Default) { + nsRefPtr service = + new GeckoMediaPluginServiceParent(); + service->Init(); + sSingletonService = service; + } else { + nsRefPtr service = + new GeckoMediaPluginServiceChild(); + service->Init(); + sSingletonService = service; + } - sSingletonService = service; ClearOnShutdown(&sSingletonService); } + nsRefPtr service = sSingletonService.get(); return service.forget(); } @@ -138,36 +146,16 @@ GeckoMediaPluginService::GetGeckoMediaPluginService() NS_IMPL_ISUPPORTS(GeckoMediaPluginService, mozIGeckoMediaPluginService, nsIObserver) -static int32_t sMaxAsyncShutdownWaitMs = 0; -static bool sHaveSetTimeoutPrefCache = false; - GeckoMediaPluginService::GeckoMediaPluginService() : mMutex("GeckoMediaPluginService::mMutex") - , mShuttingDown(false) + , mGMPThreadShutdown(false) , mShuttingDownOnGMPThread(false) - , mScannedPluginOnDisk(false) - , mWaitingForPluginsAsyncShutdown(false) { MOZ_ASSERT(NS_IsMainThread()); - if (!sHaveSetTimeoutPrefCache) { - sHaveSetTimeoutPrefCache = true; - Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs, - "media.gmp.async-shutdown-timeout", - GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT); - } } GeckoMediaPluginService::~GeckoMediaPluginService() { - MOZ_ASSERT(mPlugins.IsEmpty()); - MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty()); -} - -int32_t -GeckoMediaPluginService::AsyncShutdownTimeoutMs() -{ - MOZ_ASSERT(sHaveSetTimeoutPrefCache); - return sMaxAsyncShutdownWaitMs; } void @@ -236,176 +224,27 @@ GeckoMediaPluginService::Init() nsCOMPtr obsService = mozilla::services::GetObserverService(); MOZ_ASSERT(obsService); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "profile-change-teardown", false))); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false))); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "last-pb-context-exited", false))); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "browser:purge-session-history", false))); - -#ifdef DEBUG - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "mediakeys-request", false))); -#endif - - nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - if (prefs) { - prefs->AddObserver("media.gmp.plugin.crash", this, false); - } - -#ifndef MOZ_WIDGET_GONK - // Directory service is main thread only, so cache the profile dir here - // so that we can use it off main thread. - // We only do this on non-B2G, as this fails in multi-process Gecko. - // TODO: Make this work in multi-process Gecko. - nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mStorageBaseDir->AppendNative(NS_LITERAL_CSTRING("gmp")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) { - return rv; - } -#endif // Kick off scanning for plugins nsCOMPtr thread; return GetThread(getter_AddRefs(thread)); } -NS_IMETHODIMP -GeckoMediaPluginService::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aSomeData) +void +GeckoMediaPluginService::ShutdownGMPThread() { - LOGD(("%s::%s topic='%s' data='%s'", __CLASS__, __FUNCTION__, - aTopic, NS_ConvertUTF16toUTF8(aSomeData).get())); - if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { - nsCOMPtr branch( do_QueryInterface(aSubject) ); - if (branch) { - bool crashNow = false; - if (NS_LITERAL_STRING("media.gmp.plugin.crash").Equals(aSomeData)) { - branch->GetBoolPref("media.gmp.plugin.crash", &crashNow); - } - if (crashNow) { - nsCOMPtr gmpThread; - { - MutexAutoLock lock(mMutex); - gmpThread = mGMPThread; - } - if (gmpThread) { - gmpThread->Dispatch(WrapRunnable(this, &GeckoMediaPluginService::CrashPlugins), - NS_DISPATCH_NORMAL); - } - } - } - } else if (!strcmp("profile-change-teardown", aTopic)) { - - // How shutdown works: - // - // Some GMPs require time to do bookkeeping upon shutdown. These GMPs - // need to be given time to access storage during shutdown. To signal - // that time to shutdown is required, those GMPs implement the - // GMPAsyncShutdown interface. - // - // When we startup the child process, we query the GMP for the - // GMPAsyncShutdown interface, and if it's present, we send a message - // back to the GMPParent, which then registers the GMPParent by calling - // GMPService::AsyncShutdownNeeded(). - // - // On shutdown, we set mWaitingForPluginsAsyncShutdown to true, and then - // call UnloadPlugins on the GMPThread, and process events on the main - // thread until an event sets mWaitingForPluginsAsyncShutdown=false on - // the main thread. - // - // UnloadPlugins() sends close messages for all plugins' API objects to - // the GMP interfaces in the child process, and then sends the async - // shutdown notifications to child GMPs. When a GMP has completed its - // shutdown, it calls GMPAsyncShutdownHost::ShutdownComplete(), which - // sends a message back to the parent, which calls - // GMPService::AsyncShutdownComplete(). If all plugins requiring async - // shutdown have called AsyncShutdownComplete() we stick an event on the - // main thread to set mWaitingForPluginsAsyncShutdown=false. We must use - // an event to do this, as we must ensure the main thread processes an - // event to run its loop. This will unblock the main thread, and shutdown - // of other components will proceed. - // - // We set a timer in UnloadPlugins(), and abort waiting for async - // shutdown if the GMPs are taking too long to shutdown. - // - // We shutdown in "profile-change-teardown", as the profile dir is - // still writable then, and it's required for GMPStorage. We block the - // shutdown process by spinning the main thread event loop until all GMPs - // have shutdown, or timeout has occurred. - // - // GMPStorage needs to work up until the shutdown-complete notification - // arrives from the GMP process. - - mWaitingForPluginsAsyncShutdown = true; - - nsCOMPtr gmpThread; - { - MutexAutoLock lock(mMutex); - MOZ_ASSERT(!mShuttingDown); - mShuttingDown = true; - gmpThread = mGMPThread; - } - - if (gmpThread) { - gmpThread->Dispatch( - NS_NewRunnableMethod(this, &GeckoMediaPluginService::UnloadPlugins), - NS_DISPATCH_NORMAL); - } else { - MOZ_ASSERT(mPlugins.IsEmpty()); - } - - // Wait for plugins to do async shutdown... - while (mWaitingForPluginsAsyncShutdown) { - NS_ProcessNextEvent(NS_GetCurrentThread(), true); - } - - } else if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) { - nsCOMPtr gmpThread; - { - MutexAutoLock lock(mMutex); - // XXX The content process never gets profile-change-teardown, so mShuttingDown - // will always be false here. GMPService needs to be proxied to the parent. - // See bug 1057908. - MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default || mShuttingDown); - mGMPThread.swap(gmpThread); - } - - if (gmpThread) { - gmpThread->Shutdown(); - } - } else if (!strcmp("last-pb-context-exited", aTopic)) { - // When Private Browsing mode exits, all we need to do is clear - // mTempNodeIds. This drops all the node ids we've cached in memory - // for PB origin-pairs. If we try to open an origin-pair for non-PB - // mode, we'll get the NodeId salt stored on-disk, and if we try to - // open a PB mode origin-pair, we'll re-generate new salt. - mTempNodeIds.Clear(); - } else if (!strcmp("browser:purge-session-history", aTopic)) { - // Clear everything! - if (!aSomeData || nsDependentString(aSomeData).IsEmpty()) { - return GMPDispatch(NS_NewRunnableMethod( - this, &GeckoMediaPluginService::ClearStorage)); - } - - // Clear nodeIds/records modified after |t|. - nsresult rv; - PRTime t = nsDependentString(aSomeData).ToInteger64(&rv, 10); - if (NS_FAILED(rv)) { - return rv; - } - return GMPDispatch(NS_NewRunnableMethodWithArg( - this, &GeckoMediaPluginService::ClearRecentHistoryOnGMPThread, t)); + LOGD(("%s::%s", __CLASS__, __FUNCTION__)); + nsCOMPtr gmpThread; + { + MutexAutoLock lock(mMutex); + mGMPThreadShutdown = true; + mGMPThread.swap(gmpThread); } - return NS_OK; + if (gmpThread) { + gmpThread->Shutdown(); + } } nsresult @@ -431,7 +270,7 @@ GeckoMediaPluginService::GetThread(nsIThread** aThread) if (!mGMPThread) { // Don't allow the thread to be created after shutdown has started. - if (mShuttingDown) { + if (mGMPThreadShutdown) { return NS_ERROR_FAILURE; } @@ -441,7 +280,7 @@ GeckoMediaPluginService::GetThread(nsIThread** aThread) } // Tell the thread to initialize plugins - mGMPThread->Dispatch(NS_NewRunnableMethod(this, &GeckoMediaPluginService::LoadFromEnvironment), NS_DISPATCH_NORMAL); + InitializePlugins(); } NS_ADDREF(mGMPThread); @@ -450,118 +289,165 @@ GeckoMediaPluginService::GetThread(nsIThread** aThread) return NS_OK; } +class GetGMPContentParentForAudioDecoderDone : public GetGMPContentParentCallback +{ +public: + explicit GetGMPContentParentForAudioDecoderDone(UniquePtr&& aCallback) + : mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPContentParent* aGMPParent) override + { + GMPAudioDecoderParent* gmpADP = nullptr; + if (aGMPParent) { + aGMPParent->GetGMPAudioDecoder(&gmpADP); + } + mCallback->Done(gmpADP); + } + +private: + UniquePtr mCallback; +}; + NS_IMETHODIMP GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray* aTags, const nsACString& aNodeId, - GMPAudioDecoderProxy** aGMPAD) + UniquePtr&& aCallback) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aGMPAD); + NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - nsRefPtr gmp = SelectPluginForAPI(aNodeId, - NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), - *aTags); - if (!gmp) { + UniquePtr callback( + new GetGMPContentParentForAudioDecoderDone(Move(aCallback))); + if (!GetContentParentFrom(aNodeId, NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), + *aTags, Move(callback))) { return NS_ERROR_FAILURE; } - GMPAudioDecoderParent* gmpADP; - nsresult rv = gmp->GetGMPAudioDecoder(&gmpADP); - if (NS_FAILED(rv)) { - return rv; - } - - *aGMPAD = gmpADP; - return NS_OK; } +class GetGMPContentParentForVideoDecoderDone : public GetGMPContentParentCallback +{ +public: + explicit GetGMPContentParentForVideoDecoderDone(UniquePtr&& aCallback) + : mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPContentParent* aGMPParent) override + { + GMPVideoDecoderParent* gmpVDP = nullptr; + GMPVideoHostImpl* videoHost = nullptr; + if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoDecoder(&gmpVDP))) { + videoHost = &gmpVDP->Host(); + } + mCallback->Done(gmpVDP, videoHost); + } + +private: + UniquePtr mCallback; +}; + NS_IMETHODIMP GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray* aTags, const nsACString& aNodeId, - GMPVideoHost** aOutVideoHost, - GMPVideoDecoderProxy** aGMPVD) + UniquePtr&& aCallback) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aOutVideoHost); - NS_ENSURE_ARG(aGMPVD); + NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - nsRefPtr gmp = SelectPluginForAPI(aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - *aTags); -#ifdef PR_LOGGING - nsCString api = (*aTags)[0]; - LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get())); -#endif - if (!gmp) { + UniquePtr callback( + new GetGMPContentParentForVideoDecoderDone(Move(aCallback))); + if (!GetContentParentFrom(aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), + *aTags, Move(callback))) { return NS_ERROR_FAILURE; } - - GMPVideoDecoderParent* gmpVDP; - nsresult rv = gmp->GetGMPVideoDecoder(&gmpVDP); - if (NS_FAILED(rv)) { - return rv; - } - - *aGMPVD = gmpVDP; - *aOutVideoHost = &gmpVDP->Host(); - return NS_OK; } +class GetGMPContentParentForVideoEncoderDone : public GetGMPContentParentCallback +{ +public: + explicit GetGMPContentParentForVideoEncoderDone(UniquePtr&& aCallback) + : mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPContentParent* aGMPParent) override + { + GMPVideoEncoderParent* gmpVEP = nullptr; + GMPVideoHostImpl* videoHost = nullptr; + if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoEncoder(&gmpVEP))) { + videoHost = &gmpVEP->Host(); + } + mCallback->Done(gmpVEP, videoHost); + } + +private: + UniquePtr mCallback; +}; + NS_IMETHODIMP GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray* aTags, const nsACString& aNodeId, - GMPVideoHost** aOutVideoHost, - GMPVideoEncoderProxy** aGMPVE) + UniquePtr&& aCallback) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aOutVideoHost); - NS_ENSURE_ARG(aGMPVE); + NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - nsRefPtr gmp = SelectPluginForAPI(aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), - *aTags); -#ifdef PR_LOGGING - nsCString api = (*aTags)[0]; - LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get())); -#endif - if (!gmp) { + UniquePtr callback( + new GetGMPContentParentForVideoEncoderDone(Move(aCallback))); + if (!GetContentParentFrom(aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), + *aTags, Move(callback))) { return NS_ERROR_FAILURE; } - GMPVideoEncoderParent* gmpVEP; - nsresult rv = gmp->GetGMPVideoEncoder(&gmpVEP); - if (NS_FAILED(rv)) { - return rv; - } - - *aGMPVE = gmpVEP; - *aOutVideoHost = &gmpVEP->Host(); - return NS_OK; } +class GetGMPContentParentForDecryptorDone : public GetGMPContentParentCallback +{ +public: + explicit GetGMPContentParentForDecryptorDone(UniquePtr&& aCallback) + : mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPContentParent* aGMPParent) override + { + GMPDecryptorParent* ksp = nullptr; + if (aGMPParent) { + aGMPParent->GetGMPDecryptor(&ksp); + } + mCallback->Done(ksp); + } + +private: + UniquePtr mCallback; +}; + NS_IMETHODIMP GeckoMediaPluginService::GetGMPDecryptor(nsTArray* aTags, const nsACString& aNodeId, - GMPDecryptorProxy** aDecryptor) + UniquePtr&& aCallback) { #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) if (!SandboxInfo::Get().CanSandboxMedia()) { @@ -573,242 +459,19 @@ GeckoMediaPluginService::GetGMPDecryptor(nsTArray* aTags, MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aDecryptor); + NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - nsRefPtr gmp = SelectPluginForAPI(aNodeId, - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - *aTags); - - if (!gmp) { - // XXX to remove in bug 1147692 - gmp = SelectPluginForAPI(aNodeId, - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), - *aTags); - } - - if (!gmp) { + UniquePtr callback( + new GetGMPContentParentForDecryptorDone(Move(aCallback))); + if (!GetContentParentFrom(aNodeId, NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), + *aTags, Move(callback))) { return NS_ERROR_FAILURE; } - GMPDecryptorParent* ksp; - nsresult rv = gmp->GetGMPDecryptor(&ksp); - if (NS_FAILED(rv)) { - return rv; - } - - *aDecryptor = static_cast(ksp); - - return NS_OK; -} - -void -GeckoMediaPluginService::AsyncShutdownNeeded(GMPParent* aParent) -{ - LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent)); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - MOZ_ASSERT(!mAsyncShutdownPlugins.Contains(aParent)); - mAsyncShutdownPlugins.AppendElement(aParent); -} - -void -GeckoMediaPluginService::AsyncShutdownComplete(GMPParent* aParent) -{ - LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent)); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - mAsyncShutdownPlugins.RemoveElement(aParent); - if (mAsyncShutdownPlugins.IsEmpty() && mShuttingDownOnGMPThread) { - // The main thread may be waiting for async shutdown of plugins, - // which has completed. Break the main thread out of its waiting loop. - nsCOMPtr task(NS_NewRunnableMethod( - this, &GeckoMediaPluginService::SetAsyncShutdownComplete)); - NS_DispatchToMainThread(task); - } -} - -void -GeckoMediaPluginService::SetAsyncShutdownComplete() -{ - MOZ_ASSERT(NS_IsMainThread()); - mWaitingForPluginsAsyncShutdown = false; -} - -void -GeckoMediaPluginService::UnloadPlugins() -{ - LOGD(("%s::%s async_shutdown=%d", __CLASS__, __FUNCTION__, - mAsyncShutdownPlugins.Length())); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - MOZ_ASSERT(!mShuttingDownOnGMPThread); - mShuttingDownOnGMPThread = true; - - { - MutexAutoLock lock(mMutex); - // Note: CloseActive is async; it will actually finish - // shutting down when all the plugins have unloaded. - for (size_t i = 0; i < mPlugins.Length(); i++) { - mPlugins[i]->CloseActive(true); - } - mPlugins.Clear(); - } - - if (mAsyncShutdownPlugins.IsEmpty()) { - nsCOMPtr task(NS_NewRunnableMethod( - this, &GeckoMediaPluginService::SetAsyncShutdownComplete)); - NS_DispatchToMainThread(task); - } -} - -void -GeckoMediaPluginService::CrashPlugins() -{ - LOGD(("%s::%s", __CLASS__, __FUNCTION__)); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - MutexAutoLock lock(mMutex); - for (size_t i = 0; i < mPlugins.Length(); i++) { - mPlugins[i]->Crash(); - } -} - -void -GeckoMediaPluginService::LoadFromEnvironment() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - const char* env = PR_GetEnv("MOZ_GMP_PATH"); - if (!env || !*env) { - return; - } - - nsString allpaths; - if (NS_WARN_IF(NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(env), allpaths)))) { - return; - } - - uint32_t pos = 0; - while (pos < allpaths.Length()) { - // Loop over multiple path entries separated by colons (*nix) or - // semicolons (Windows) - int32_t next = allpaths.FindChar(XPCOM_ENV_PATH_SEPARATOR[0], pos); - if (next == -1) { - AddOnGMPThread(nsDependentSubstring(allpaths, pos)); - break; - } else { - AddOnGMPThread(nsDependentSubstring(allpaths, pos, next - pos)); - pos = next + 1; - } - } - - mScannedPluginOnDisk = true; -} - -NS_IMETHODIMP -GeckoMediaPluginService::PathRunnable::Run() -{ - if (mOperation == ADD) { - mService->AddOnGMPThread(mPath); - } else { - mService->RemoveOnGMPThread(mPath, - mOperation == REMOVE_AND_DELETE_FROM_DISK, - mDefer); - } - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch(new PathRunnable(this, aDirectory, - PathRunnable::EOperation::ADD)); -} - -NS_IMETHODIMP -GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch(new PathRunnable(this, aDirectory, - PathRunnable::EOperation::REMOVE)); -} - -NS_IMETHODIMP -GeckoMediaPluginService::RemoveAndDeletePluginDirectory( - const nsAString& aDirectory, const bool aDefer) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch( - new PathRunnable(this, aDirectory, - PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK, - aDefer)); -} - -class DummyRunnable : public nsRunnable { -public: - NS_IMETHOD Run() { return NS_OK; } -}; - -NS_IMETHODIMP -GeckoMediaPluginService::GetPluginVersionForAPI(const nsACString& aAPI, - nsTArray* aTags, - nsACString& aOutVersion) -{ - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aOutVersion.IsEmpty()); - - nsresult rv = EnsurePluginsOnDiskScanned(); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to load GMPs from disk."); - return rv; - } - - { - MutexAutoLock lock(mMutex); - nsCString api(aAPI); - size_t index = 0; - - // We must parse the version number into a float for comparison. Yuck. - double maxParsedVersion = -1.; - - while (GMPParent* gmp = FindPluginForAPIFrom(index, api, *aTags, &index)) { - double parsedVersion = atof(gmp->GetVersion().get()); - if (maxParsedVersion < 0 || parsedVersion > maxParsedVersion) { - maxParsedVersion = parsedVersion; - aOutVersion = gmp->GetVersion(); - } - index++; - } - - if (maxParsedVersion < 0) { - return NS_ERROR_FAILURE; - } - } - - return NS_OK; -} - -nsresult -GeckoMediaPluginService::EnsurePluginsOnDiskScanned() -{ - const char* env = nullptr; - if (!mScannedPluginOnDisk && (env = PR_GetEnv("MOZ_GMP_PATH")) && *env) { - // We have a MOZ_GMP_PATH environment variable which may specify the - // location of plugins to load, and we haven't yet scanned the disk to - // see if there are plugins there. Get the GMP thread, which will - // cause an event to be dispatched to which scans for plugins. We - // dispatch a sync event to the GMP thread here in order to wait until - // after the GMP thread has scanned any paths in MOZ_GMP_PATH. - nsresult rv = GMPDispatch(new DummyRunnable(), NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now"); - } - return NS_OK; } @@ -817,890 +480,8 @@ GeckoMediaPluginService::HasPluginForAPI(const nsACString& aAPI, nsTArray* aTags, bool* aOutHavePlugin) { - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aOutHavePlugin); - - nsresult rv = EnsurePluginsOnDiskScanned(); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to load GMPs from disk."); - return rv; - } - - { - MutexAutoLock lock(mMutex); - nsCString api(aAPI); - GMPParent* gmp = FindPluginForAPIFrom(0, api, *aTags, nullptr); - *aOutHavePlugin = (gmp != nullptr); - } - - return NS_OK; -} - -GMPParent* -GeckoMediaPluginService::FindPluginForAPIFrom(size_t aSearchStartIndex, - const nsCString& aAPI, - const nsTArray& aTags, - size_t* aOutPluginIndex) -{ - mMutex.AssertCurrentThreadOwns(); - for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) { - GMPParent* gmp = mPlugins[i]; - bool supportsAllTags = true; - for (size_t t = 0; t < aTags.Length(); t++) { - const nsCString& tag = aTags.ElementAt(t); - if (!gmp->SupportsAPI(aAPI, tag)) { - supportsAllTags = false; - break; - } - } - if (!supportsAllTags) { - continue; - } - if (aOutPluginIndex) { - *aOutPluginIndex = i; - } - return gmp; - } - return nullptr; -} - -GMPParent* -GeckoMediaPluginService::SelectPluginForAPI(const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray& aTags) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread, - "Can't clone GMP plugins on non-GMP threads."); - - GMPParent* gmpToClone = nullptr; - { - MutexAutoLock lock(mMutex); - size_t index = 0; - GMPParent* gmp = nullptr; - while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) { - if (aNodeId.IsEmpty()) { - if (gmp->CanBeSharedCrossNodeIds()) { - return gmp; - } - } else if (gmp->CanBeUsedFrom(aNodeId)) { - MOZ_ASSERT(!aNodeId.IsEmpty()); - gmp->SetNodeId(aNodeId); - return gmp; - } - - if (!gmpToClone || - (gmpToClone->IsMarkedForDeletion() && !gmp->IsMarkedForDeletion())) { - // This GMP has the correct type but has the wrong nodeId; hold on to it - // in case we need to clone it. - // Prefer GMPs in-use for the case where an upgraded plugin version is - // waiting for the old one to die. If the old plugin is in use, we - // should continue using it so that any persistent state remains - // consistent. Otherwise, just check that the plugin isn't scheduled - // for deletion. - gmpToClone = gmp; - } - // Loop around and try the next plugin; it may be usable from aNodeId. - index++; - } - } - - // Plugin exists, but we can't use it due to cross-origin separation. Create a - // new one. - if (gmpToClone) { - GMPParent* clone = ClonePlugin(gmpToClone); - if (!aNodeId.IsEmpty()) { - clone->SetNodeId(aNodeId); - } - return clone; - } - - return nullptr; -} - -class CreateGMPParentTask : public nsRunnable { -public: - NS_IMETHOD Run() { - MOZ_ASSERT(NS_IsMainThread()); -#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) - if (!SandboxInfo::Get().CanSandboxMedia()) { - if (!Preferences::GetBool("media.gmp.insecure.allow")) { - NS_WARNING("Denying media plugin load due to lack of sandboxing."); - return NS_ERROR_NOT_AVAILABLE; - } - NS_WARNING("Loading media plugin despite lack of sandboxing."); - } -#endif - mParent = new GMPParent(); - return NS_OK; - } - already_AddRefed GetParent() { - return mParent.forget(); - } -private: - nsRefPtr mParent; -}; - -GMPParent* -GeckoMediaPluginService::ClonePlugin(const GMPParent* aOriginal) -{ - MOZ_ASSERT(aOriginal); - - // The GMPParent inherits from IToplevelProtocol, which must be created - // on the main thread to be threadsafe. See Bug 1035653. - nsRefPtr task(new CreateGMPParentTask()); - if (!NS_IsMainThread()) { - nsCOMPtr mainThread = do_GetMainThread(); - MOZ_ASSERT(mainThread); - mozilla::SyncRunnable::DispatchToThread(mainThread, task); - } - - nsRefPtr gmp = task->GetParent(); - nsresult rv = gmp->CloneFrom(aOriginal); - - if (NS_FAILED(rv)) { - NS_WARNING("Can't Create GMPParent"); - return nullptr; - } - - MutexAutoLock lock(mMutex); - mPlugins.AppendElement(gmp); - - return gmp.get(); -} - -class NotifyObserversTask final : public nsRunnable { -public: - explicit NotifyObserversTask(const char* aTopic) - : mTopic(aTopic) - {} - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread()); - nsCOMPtr obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - if (obsService) { - obsService->NotifyObservers(nullptr, mTopic, nullptr); - } - return NS_OK; - } -private: - ~NotifyObserversTask() {} - const char* mTopic; -}; - -void -GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get())); - - nsCOMPtr directory; - nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - // The GMPParent inherits from IToplevelProtocol, which must be created - // on the main thread to be threadsafe. See Bug 1035653. - nsRefPtr task(new CreateGMPParentTask()); - nsCOMPtr mainThread = do_GetMainThread(); - MOZ_ASSERT(mainThread); - mozilla::SyncRunnable::DispatchToThread(mainThread, task); - nsRefPtr gmp = task->GetParent(); - rv = gmp ? gmp->Init(this, directory) : NS_ERROR_NOT_AVAILABLE; - if (NS_FAILED(rv)) { - NS_WARNING("Can't Create GMPParent"); - return; - } - - { - MutexAutoLock lock(mMutex); - mPlugins.AppendElement(gmp); - } - - NS_DispatchToMainThread(new NotifyObserversTask("gmp-path-added"), NS_DISPATCH_NORMAL); -} - -void -GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory, - const bool aDeleteFromDisk, - const bool aCanDefer) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get())); - - nsCOMPtr directory; - nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - MutexAutoLock lock(mMutex); - for (size_t i = mPlugins.Length() - 1; i < mPlugins.Length(); i--) { - nsCOMPtr pluginpath = mPlugins[i]->GetDirectory(); - bool equals; - if (NS_FAILED(directory->Equals(pluginpath, &equals)) || !equals) { - continue; - } - - nsRefPtr gmp = mPlugins[i]; - if (aDeleteFromDisk && gmp->State() != GMPStateNotLoaded) { - // We have to wait for the child process to release its lib handle - // before we can delete the GMP. - gmp->MarkForDeletion(); - - if (!mPluginsWaitingForDeletion.Contains(aDirectory)) { - mPluginsWaitingForDeletion.AppendElement(aDirectory); - } - } - - if (gmp->State() == GMPStateNotLoaded || !aCanDefer) { - // GMP not in use or shutdown is being forced; can shut it down now. - gmp->AbortAsyncShutdown(); - gmp->CloseActive(true); - mPlugins.RemoveElementAt(i); - } - } - - if (aDeleteFromDisk) { - if (NS_SUCCEEDED(directory->Remove(true))) { - mPluginsWaitingForDeletion.RemoveElement(aDirectory); - } - } -} - -// May remove when Bug 1043671 is fixed -static void Dummy(nsRefPtr& aOnDeathsDoor) -{ - // exists solely to do nothing and let the Runnable kill the GMPParent - // when done. -} - -void -GeckoMediaPluginService::PluginTerminated(const nsRefPtr& aPlugin) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - if (aPlugin->IsMarkedForDeletion()) { - nsCString path8; - nsRefPtr dir = aPlugin->GetDirectory(); - nsresult rv = dir->GetNativePath(path8); - NS_ENSURE_SUCCESS_VOID(rv); - - nsString path = NS_ConvertUTF8toUTF16(path8); - if (mPluginsWaitingForDeletion.Contains(path)) { - RemoveOnGMPThread(path, true /* delete */, true /* can defer */); - } - } -} - -void -GeckoMediaPluginService::ReAddOnGMPThread(const nsRefPtr& aOld) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld)); - - nsRefPtr gmp; - if (!mShuttingDownOnGMPThread) { - // Don't re-add plugin if we're shutting down. Let the old plugin die. - gmp = ClonePlugin(aOld); - } - // Note: both are now in the list - // Until we give up the GMPThread, we're safe even if we unlock temporarily - // since off-main-thread users just test for existance; they don't modify the list. - MutexAutoLock lock(mMutex); - mPlugins.RemoveElement(aOld); - - // Schedule aOld to be destroyed. We can't destroy it from here since we - // may be inside ActorDestroyed() for it. - NS_DispatchToCurrentThread(WrapRunnableNM(&Dummy, aOld)); -} - -NS_IMETHODIMP -GeckoMediaPluginService::GetStorageDir(nsIFile** aOutFile) -{ -#ifndef MOZ_WIDGET_GONK - if (NS_WARN_IF(!mStorageBaseDir)) { - return NS_ERROR_FAILURE; - } - return mStorageBaseDir->Clone(aOutFile); -#else - return NS_ERROR_NOT_IMPLEMENTED; -#endif -} - -static nsresult -WriteToFile(nsIFile* aPath, - const nsCString& aFileName, - const nsCString& aData) -{ - nsCOMPtr path; - nsresult rv = aPath->Clone(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(aFileName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - PRFileDesc* f = nullptr; - rv = path->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, PR_IRWXU, &f); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - int32_t len = PR_Write(f, aData.get(), aData.Length()); - PR_Close(f); - if (NS_WARN_IF(len < 0 || (size_t)len != aData.Length())) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -static nsresult -ReadFromFile(nsIFile* aPath, - const nsACString& aFileName, - nsACString& aOutData, - int32_t aMaxLength) -{ - nsCOMPtr path; - nsresult rv = aPath->Clone(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(aFileName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - PRFileDesc* f = nullptr; - rv = path->OpenNSPRFileDesc(PR_RDONLY | PR_CREATE_FILE, PR_IRWXU, &f); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - auto size = PR_Seek(f, 0, PR_SEEK_END); - PR_Seek(f, 0, PR_SEEK_SET); - - if (size > aMaxLength) { - return NS_ERROR_FAILURE; - } - aOutData.SetLength(size); - - auto len = PR_Read(f, aOutData.BeginWriting(), size); - PR_Close(f); - if (NS_WARN_IF(len != size)) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -nsresult -ReadSalt(nsIFile* aPath, nsACString& aOutData) -{ - return ReadFromFile(aPath, NS_LITERAL_CSTRING("salt"), - aOutData, NodeIdSaltLength); - -} - -NS_IMETHODIMP -GeckoMediaPluginService::IsPersistentStorageAllowed(const nsACString& aNodeId, - bool* aOutAllowed) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aOutAllowed); - *aOutAllowed = mPersistentStorageAllowed.Get(aNodeId); - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginService::GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - bool aInPrivateBrowsing, - nsACString& aOutId) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__, - NS_ConvertUTF16toUTF8(aOrigin).get(), - NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), - (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"))); - -#ifdef MOZ_WIDGET_GONK - NS_WARNING("GeckoMediaPluginService::GetNodeId Not implemented on B2G"); - return NS_ERROR_NOT_IMPLEMENTED; -#endif - - nsresult rv; - - if (aOrigin.EqualsLiteral("null") || - aOrigin.IsEmpty() || - aTopLevelOrigin.EqualsLiteral("null") || - aTopLevelOrigin.IsEmpty()) { - // At least one of the (origin, topLevelOrigin) is null or empty; - // probably a local file. Generate a random node id, and don't store - // it so that the GMP's storage is temporary and not shared. - nsAutoCString salt; - rv = GenerateRandomPathName(salt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - aOutId = salt; - mPersistentStorageAllowed.Put(salt, false); - return NS_OK; - } - - const uint32_t hash = AddToHash(HashString(aOrigin), - HashString(aTopLevelOrigin)); - - if (aInPrivateBrowsing) { - // For PB mode, we store the node id, indexed by the origin pair, - // so that if the same origin pair is opened in this session, it gets - // the same node id. - nsCString* salt = nullptr; - if (!(salt = mTempNodeIds.Get(hash))) { - // No salt stored, generate and temporarily store some for this id. - nsAutoCString newSalt; - rv = GenerateRandomPathName(newSalt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - salt = new nsCString(newSalt); - mTempNodeIds.Put(hash, salt); - mPersistentStorageAllowed.Put(*salt, false); - } - aOutId = *salt; - return NS_OK; - } - - // Otherwise, try to see if we've previously generated and stored salt - // for this origin pair. - nsCOMPtr path; // $profileDir/gmp/ - rv = GetStorageDir(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(NS_LITERAL_CSTRING("id")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/id/ - rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsAutoCString hashStr; - hashStr.AppendInt((int64_t)hash); - - // $profileDir/gmp/id/$hash - rv = path->AppendNative(hashStr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr saltFile; - rv = path->Clone(getter_AddRefs(saltFile)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = saltFile->AppendNative(NS_LITERAL_CSTRING("salt")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsAutoCString salt; - bool exists = false; - rv = saltFile->Exists(&exists); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - if (!exists) { - // No stored salt for this origin. Generate salt, and store it and - // the origin on disk. - nsresult rv = GenerateRandomPathName(salt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - MOZ_ASSERT(salt.Length() == NodeIdSaltLength); - - // $profileDir/gmp/id/$hash/salt - rv = WriteToFile(path, NS_LITERAL_CSTRING("salt"), salt); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/id/$hash/origin - rv = WriteToFile(path, - NS_LITERAL_CSTRING("origin"), - NS_ConvertUTF16toUTF8(aOrigin)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/id/$hash/topLevelOrigin - rv = WriteToFile(path, - NS_LITERAL_CSTRING("topLevelOrigin"), - NS_ConvertUTF16toUTF8(aTopLevelOrigin)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - } else { - rv = ReadSalt(path, salt); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - aOutId = salt; - mPersistentStorageAllowed.Put(salt, true); - - return NS_OK; -} - -static bool -ExtractHostName(const nsACString& aOrigin, nsACString& aOutData) -{ - nsCString str; - str.Assign(aOrigin); - int begin = str.Find("://"); - // The scheme is missing! - if (begin == -1) { - return false; - } - - int end = str.RFind(":"); - // Remove the port number - if (end != begin) { - str.SetLength(end); - } - - nsDependentCSubstring host(str, begin + 3); - aOutData.Assign(host); - return true; -} - -bool -MatchOrigin(nsIFile* aPath, const nsACString& aSite) -{ - // http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax - static const uint32_t MaxDomainLength = 253; - - nsresult rv; - nsCString str; - rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("origin"), str, MaxDomainLength); - if (NS_SUCCEEDED(rv) && ExtractHostName(str, str) && str.Equals(aSite)) { - return true; - } - rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("topLevelOrigin"), str, MaxDomainLength); - if (NS_SUCCEEDED(rv) && ExtractHostName(str, str) && str.Equals(aSite)) { - return true; - } - return false; -} - -template static void -KillPlugins(const nsTArray>& aPlugins, - Mutex& aMutex, T&& aFilter) -{ - // Shutdown the plugins when |aFilter| evaluates to true. - // After we clear storage data, node IDs will become invalid and shouldn't be - // used anymore. We need to kill plugins with such nodeIDs. - // Note: we can't shut them down while holding the lock, - // as the lock is not re-entrant and shutdown requires taking the lock. - // The plugin list is only edited on the GMP thread, so this should be OK. - nsTArray> pluginsToKill; - { - MutexAutoLock lock(aMutex); - for (size_t i = 0; i < aPlugins.Length(); i++) { - nsRefPtr parent(aPlugins[i]); - if (aFilter(parent)) { - pluginsToKill.AppendElement(parent); - } - } - } - - for (size_t i = 0; i < pluginsToKill.Length(); i++) { - pluginsToKill[i]->CloseActive(false); - // Abort async shutdown because we're going to wipe the plugin's storage, - // so we don't want it writing more data in its async shutdown path. - pluginsToKill[i]->AbortAsyncShutdown(); - } -} - -static nsresult -DeleteDir(nsIFile* aPath) -{ - bool exists = false; - nsresult rv = aPath->Exists(&exists); - if (NS_FAILED(rv)) { - return rv; - } - if (exists) { - return aPath->Remove(true); - } - return NS_OK; -} - -struct NodeFilter { - explicit NodeFilter(const nsTArray& nodeIDs) : mNodeIDs(nodeIDs) {} - bool operator()(GMPParent* aParent) { - return mNodeIDs.Contains(aParent->GetNodeId()); - } -private: - const nsTArray& mNodeIDs; -}; - -void -GeckoMediaPluginService::ClearNodeIdAndPlugin(DirectoryFilter& aFilter) -{ - nsresult rv; - nsCOMPtr path; - - // $profileDir/gmp/ - rv = GetStorageDir(getter_AddRefs(path)); - if (NS_FAILED(rv)) { - return; - } - - // $profileDir/gmp/id/ - rv = path->AppendNative(NS_LITERAL_CSTRING("id")); - if (NS_FAILED(rv)) { - return; - } - - // Iterate all sub-folders of $profileDir/gmp/id/ - nsCOMPtr iter; - rv = path->GetDirectoryEntries(getter_AddRefs(iter)); - if (NS_FAILED(rv)) { - return; - } - - bool hasMore = false; - nsTArray nodeIDsToClear; - while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) { - nsCOMPtr supports; - rv = iter->GetNext(getter_AddRefs(supports)); - if (NS_FAILED(rv)) { - continue; - } - - // $profileDir/gmp/id/$hash - nsCOMPtr dirEntry(do_QueryInterface(supports, &rv)); - if (NS_FAILED(rv)) { - continue; - } - - // Skip non-directory files. - bool isDirectory = false; - rv = dirEntry->IsDirectory(&isDirectory); - if (NS_FAILED(rv) || !isDirectory) { - continue; - } - - if (!aFilter(dirEntry)) { - continue; - } - - nsAutoCString salt; - if (NS_SUCCEEDED(ReadSalt(dirEntry, salt))) { - // Keep node IDs to clear data/plugins associated with them later. - nodeIDsToClear.AppendElement(salt); - // Also remove node IDs from the table. - mPersistentStorageAllowed.Remove(salt); - } - // Now we can remove the directory for the origin pair. - if (NS_FAILED(dirEntry->Remove(true))) { - NS_WARNING("Failed to delete the directory for the origin pair"); - } - } - - // Kill plugins that have node IDs to be cleared. - KillPlugins(mPlugins, mMutex, NodeFilter(nodeIDsToClear)); - - // Clear all matching $profileDir/gmp/storage/$nodeId/ - rv = GetStorageDir(getter_AddRefs(path)); - if (NS_FAILED(rv)) { - return; - } - - rv = path->AppendNative(NS_LITERAL_CSTRING("storage")); - if (NS_FAILED(rv)) { - return; - } - - for (size_t i = 0; i < nodeIDsToClear.Length(); i++) { - nsCOMPtr dirEntry; - rv = path->Clone(getter_AddRefs(dirEntry)); - if (NS_FAILED(rv)) { - continue; - } - - rv = dirEntry->AppendNative(nodeIDsToClear[i]); - if (NS_FAILED(rv)) { - continue; - } - - if (NS_FAILED(DeleteDir(dirEntry))) { - NS_WARNING("Failed to delete GMP storage directory for the node"); - } - } -} - -void -GeckoMediaPluginService::ForgetThisSiteOnGMPThread(const nsACString& aSite) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: origin=%s", __CLASS__, __FUNCTION__, aSite.Data())); - - struct OriginFilter : public DirectoryFilter { - explicit OriginFilter(const nsACString& aSite) : mSite(aSite) {} - virtual bool operator()(nsIFile* aPath) { - return MatchOrigin(aPath, mSite); - } - private: - const nsACString& mSite; - } filter(aSite); - - ClearNodeIdAndPlugin(filter); -} - -void -GeckoMediaPluginService::ClearRecentHistoryOnGMPThread(PRTime aSince) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: since=%lld", __CLASS__, __FUNCTION__, (int64_t)aSince)); - - nsCOMPtr storagePath; - nsCOMPtr temp; - if (NS_SUCCEEDED(GetStorageDir(getter_AddRefs(temp))) && - NS_SUCCEEDED(temp->AppendNative(NS_LITERAL_CSTRING("storage")))) { - storagePath = temp.forget(); - } - - struct MTimeFilter : public DirectoryFilter { - explicit MTimeFilter(PRTime aSince, already_AddRefed aPath) - : mSince(aSince), mStoragePath(aPath) {} - - // Return true if any files under aPath is modified after |mSince|. - bool IsModifiedAfter(nsIFile* aPath) { - PRTime lastModified; - nsresult rv = aPath->GetLastModifiedTime(&lastModified); - if (NS_SUCCEEDED(rv) && lastModified >= mSince) { - return true; - } - // Check sub-directories recursively - nsCOMPtr iter; - rv = aPath->GetDirectoryEntries(getter_AddRefs(iter)); - if (NS_FAILED(rv)) { - return false; - } - - bool hasMore = false; - while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) { - nsCOMPtr supports; - rv = iter->GetNext(getter_AddRefs(supports)); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr path(do_QueryInterface(supports, &rv)); - if (NS_FAILED(rv)) { - continue; - } - - if (IsModifiedAfter(path)) { - return true; - } - } - return false; - } - - // |aPath| is $profileDir/gmp/id/$hash - virtual bool operator()(nsIFile* aPath) { - if (IsModifiedAfter(aPath)) { - return true; - } - - nsAutoCString salt; - nsresult rv = ReadSalt(aPath, salt); - if (NS_FAILED(rv)) { - return false; - } - - // $profileDir/gmp/storage/ - if (!mStoragePath) { - return false; - } - // $profileDir/gmp/storage/$nodeId/ - nsCOMPtr path; - rv = mStoragePath->Clone(getter_AddRefs(path)); - if (NS_FAILED(rv)) { - return false; - } - - rv = path->AppendNative(salt); - return NS_SUCCEEDED(rv) && IsModifiedAfter(path); - } - private: - const PRTime mSince; - const nsCOMPtr mStoragePath; - } filter(aSince, storagePath.forget()); - - ClearNodeIdAndPlugin(filter); - - NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); -} - -NS_IMETHODIMP -GeckoMediaPluginService::ForgetThisSite(const nsAString& aSite) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch(NS_NewRunnableMethodWithArg( - this, &GeckoMediaPluginService::ForgetThisSiteOnGMPThread, - NS_ConvertUTF16toUTF8(aSite))); -} - -static bool IsNodeIdValid(GMPParent* aParent) { - return !aParent->GetNodeId().IsEmpty(); -} - -void -GeckoMediaPluginService::ClearStorage() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s", __CLASS__, __FUNCTION__)); - -#ifdef MOZ_WIDGET_GONK - NS_WARNING("GeckoMediaPluginService::ClearStorage not implemented on B2G"); - return; -#endif - - // Kill plugins with valid nodeIDs. - KillPlugins(mPlugins, mMutex, &IsNodeIdValid); - - nsCOMPtr path; // $profileDir/gmp/ - nsresult rv = GetStorageDir(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - if (NS_FAILED(DeleteDir(path))) { - NS_WARNING("Failed to delete GMP storage directory"); - } - NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); + nsCString unused; + return GetPluginVersionForAPI(aAPI, aTags, aOutHavePlugin, unused); } } // namespace gmp diff --git a/dom/media/gmp/GMPService.h b/dom/media/gmp/GMPService.h index 1efa3c3246..349f33af00 100644 --- a/dom/media/gmp/GMPService.h +++ b/dom/media/gmp/GMPService.h @@ -15,37 +15,49 @@ #include "nsString.h" #include "nsCOMPtr.h" #include "nsIThread.h" -#include "nsThreadUtils.h" -#include "nsITimer.h" -#include "nsClassHashtable.h" -#include "nsDataHashtable.h" -#include "mozilla/Atomics.h" template struct already_AddRefed; namespace mozilla { + +extern PRLogModuleInfo* GetGMPLog(); + namespace gmp { -class GMPParent; +class GetGMPContentParentCallback; #define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000 -class GeckoMediaPluginService final : public mozIGeckoMediaPluginService - , public nsIObserver +class GeckoMediaPluginService : public mozIGeckoMediaPluginService + , public nsIObserver { public: static already_AddRefed GetGeckoMediaPluginService(); - GeckoMediaPluginService(); - nsresult Init(); + virtual nsresult Init(); NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_MOZIGECKOMEDIAPLUGINSERVICE - NS_DECL_NSIOBSERVER - void AsyncShutdownNeeded(GMPParent* aParent); - void AsyncShutdownComplete(GMPParent* aParent); - void AbortAsyncShutdown(); + // mozIGeckoMediaPluginService + NS_IMETHOD GetThread(nsIThread** aThread) override; + NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, nsTArray* aTags, + bool *aRetVal) override; + NS_IMETHOD GetGMPVideoDecoder(nsTArray* aTags, + const nsACString& aNodeId, + UniquePtr&& aCallback) + override; + NS_IMETHOD GetGMPVideoEncoder(nsTArray* aTags, + const nsACString& aNodeId, + UniquePtr&& aCallback) + override; + NS_IMETHOD GetGMPAudioDecoder(nsTArray* aTags, + const nsACString& aNodeId, + UniquePtr&& aCallback) + override; + NS_IMETHOD GetGMPDecryptor(nsTArray* aTags, + const nsACString& aNodeId, + UniquePtr&& aCallback) + override; int32_t AsyncShutdownTimeoutMs(); @@ -77,127 +89,29 @@ public: const nsACString& aPluginName, const nsAString& aPluginDumpId); -private: - ~GeckoMediaPluginService(); +protected: + GeckoMediaPluginService(); + virtual ~GeckoMediaPluginService(); + + virtual void InitializePlugins() = 0; + virtual bool GetContentParentFrom(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) = 0; nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL); - - void ClearStorage(); - - GMPParent* SelectPluginForAPI(const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray& aTags); - GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex, - const nsCString& aAPI, - const nsTArray& aTags, - size_t* aOutPluginIndex); - - void UnloadPlugins(); - void CrashPlugins(); - void SetAsyncShutdownComplete(); - - void LoadFromEnvironment(); - void ProcessPossiblePlugin(nsIFile* aDir); - - void AddOnGMPThread(const nsAString& aDirectory); - void RemoveOnGMPThread(const nsAString& aDirectory, - const bool aDeleteFromDisk, - const bool aCanDefer); - - nsresult SetAsyncShutdownTimeout(); - - struct DirectoryFilter { - virtual bool operator()(nsIFile* aPath) = 0; - ~DirectoryFilter() {} - }; - void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); - - void ForgetThisSiteOnGMPThread(const nsACString& aOrigin); - void ClearRecentHistoryOnGMPThread(PRTime aSince); + void ShutdownGMPThread(); protected: - friend class GMPParent; - void ReAddOnGMPThread(const nsRefPtr& aOld); - void PluginTerminated(const nsRefPtr& aOld); -private: - GMPParent* ClonePlugin(const GMPParent* aOriginal); - nsresult EnsurePluginsOnDiskScanned(); - - class PathRunnable : public nsRunnable - { - public: - enum EOperation { - ADD, - REMOVE, - REMOVE_AND_DELETE_FROM_DISK, - }; - - PathRunnable(GeckoMediaPluginService* aService, const nsAString& aPath, - EOperation aOperation, bool aDefer = false) - : mService(aService) - , mPath(aPath) - , mOperation(aOperation) - , mDefer(aDefer) - { } - - NS_DECL_NSIRUNNABLE - - private: - nsRefPtr mService; - nsString mPath; - EOperation mOperation; - bool mDefer; - }; - - Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins - nsTArray> mPlugins; + Mutex mMutex; // Protects mGMPThread and mGMPThreadShutdown and some members + // in derived classes. nsCOMPtr mGMPThread; - bool mShuttingDown; + bool mGMPThreadShutdown; bool mShuttingDownOnGMPThread; nsTArray> mPluginCrashCallbacks; - - // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any - // plugins found there into mPlugins. - Atomic mScannedPluginOnDisk; - - template - class MainThreadOnly { - public: - MOZ_IMPLICIT MainThreadOnly(T aValue) - : mValue(aValue) - {} - operator T&() { - MOZ_ASSERT(NS_IsMainThread()); - return mValue; - } - - private: - T mValue; - }; - - MainThreadOnly mWaitingForPluginsAsyncShutdown; - - nsTArray> mAsyncShutdownPlugins; // GMP Thread only. - - nsTArray mPluginsWaitingForDeletion; - -#ifndef MOZ_WIDGET_GONK - nsCOMPtr mStorageBaseDir; -#endif - - // Hashes of (origin,topLevelOrigin) to the node id for - // non-persistent sessions. - nsClassHashtable mTempNodeIds; - - // Hashes node id to whether that node id is allowed to store data - // persistently on disk. - nsDataHashtable mPersistentStorageAllowed; }; -nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); -bool MatchOrigin(nsIFile* aPath, const nsACString& aSite); - } // namespace gmp } // namespace mozilla diff --git a/dom/media/gmp/GMPServiceChild.cpp b/dom/media/gmp/GMPServiceChild.cpp new file mode 100644 index 0000000000..80976af0bf --- /dev/null +++ b/dom/media/gmp/GMPServiceChild.cpp @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GMPService.h" +#include "mozilla/dom/ContentChild.h" + +namespace mozilla { + +#ifdef LOG +#undef LOG +#endif + +#ifdef PR_LOGGING +#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg) +#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg) +#else +#define LOGD(msg) +#define LOG(leve1, msg) +#endif + +#ifdef __CLASS__ +#undef __CLASS__ +#endif +#define __CLASS__ "GMPService" + +namespace gmp { + +already_AddRefed +GeckoMediaPluginServiceChild::GetSingleton() +{ + MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default); + nsRefPtr service( + GeckoMediaPluginService::GetGeckoMediaPluginService()); +#ifdef DEBUG + if (service) { + nsCOMPtr chromeService; + CallQueryInterface(service.get(), getter_AddRefs(chromeService)); + MOZ_ASSERT(!chromeService); + } +#endif + return service.forget().downcast(); +} + +class GetServiceChildCallback +{ +public: + GetServiceChildCallback() + { + MOZ_COUNT_CTOR(GetServiceChildCallback); + } + virtual ~GetServiceChildCallback() + { + MOZ_COUNT_DTOR(GetServiceChildCallback); + } + virtual void Done(GMPServiceChild* aGMPServiceChild) = 0; +}; + +class GetContentParentFromDone : public GetServiceChildCallback +{ +public: + GetContentParentFromDone(const nsACString& aNodeId, const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) + : mNodeId(aNodeId), + mAPI(aAPI), + mTags(aTags), + mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPServiceChild* aGMPServiceChild) + { + if (!aGMPServiceChild) { + mCallback->Done(nullptr); + return; + } + + nsTArray alreadyBridgedTo; + aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo); + + base::ProcessId otherProcess; + nsCString displayName; + nsCString pluginId; + bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags, + alreadyBridgedTo, &otherProcess, + &displayName, &pluginId); + if (!ok) { + mCallback->Done(nullptr); + return; + } + + nsRefPtr parent; + aGMPServiceChild->GetBridgedGMPContentParent(otherProcess, + getter_AddRefs(parent)); + if (!alreadyBridgedTo.Contains(otherProcess)) { + parent->SetDisplayName(displayName); + parent->SetPluginId(pluginId); + } + + mCallback->Done(parent); + } + +private: + nsCString mNodeId; + nsCString mAPI; + const nsTArray mTags; + UniquePtr mCallback; +}; + +bool +GeckoMediaPluginServiceChild::GetContentParentFrom(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + UniquePtr callback( + new GetContentParentFromDone(aNodeId, aAPI, aTags, Move(aCallback))); + GetServiceChild(Move(callback)); + + return true; +} + +NS_IMETHODIMP +GeckoMediaPluginServiceChild::GetPluginVersionForAPI(const nsACString& aAPI, + nsTArray* aTags, + bool* aHasPlugin, + nsACString& aOutVersion) +{ + dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); + if (!contentChild) { + return NS_ERROR_FAILURE; + } + + MOZ_ASSERT(NS_IsMainThread()); + + nsCString version; + bool ok = contentChild->SendGetGMPPluginVersionForAPI(nsCString(aAPI), *aTags, + aHasPlugin, &version); + aOutVersion = version; + return ok ? NS_OK : NS_ERROR_FAILURE; +} + +class GetNodeIdDone : public GetServiceChildCallback +{ +public: + GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsing, + UniquePtr&& aCallback) + : mOrigin(aOrigin), + mTopLevelOrigin(aTopLevelOrigin), + mInPrivateBrowsing(aInPrivateBrowsing), + mCallback(Move(aCallback)) + { + } + + virtual void Done(GMPServiceChild* aGMPServiceChild) + { + if (!aGMPServiceChild) { + mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); + return; + } + + nsCString outId; + if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin, + mInPrivateBrowsing, &outId)) { + mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); + return; + } + + mCallback->Done(NS_OK, outId); + } + +private: + nsString mOrigin; + nsString mTopLevelOrigin; + bool mInPrivateBrowsing; + UniquePtr mCallback; +}; + +NS_IMETHODIMP +GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsing, + UniquePtr&& aCallback) +{ + UniquePtr callback( + new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, + Move(aCallback))); + GetServiceChild(Move(callback)); + return NS_OK; +} + +NS_IMETHODIMP +GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aSomeData) +{ + LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, aTopic)); + if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) { + if (mServiceChild) { + mozilla::SyncRunnable::DispatchToThread(mGMPThread, + WrapRunnable(mServiceChild.get(), + &PGMPServiceChild::Close)); + mServiceChild = nullptr; + } + ShutdownGMPThread(); + } + + return NS_OK; +} + +void +GeckoMediaPluginServiceChild::GetServiceChild(UniquePtr&& aCallback) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + if (!mServiceChild) { + dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); + if (!contentChild) { + return; + } + mGetServiceChildCallbacks.AppendElement(Move(aCallback)); + if (mGetServiceChildCallbacks.Length() == 1) { + NS_DispatchToMainThread(WrapRunnable(contentChild, + &dom::ContentChild::SendCreateGMPService)); + } + return; + } + + aCallback->Done(mServiceChild.get()); +} + +void +GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr&& aServiceChild) +{ + mServiceChild = Move(aServiceChild); + nsTArray> getServiceChildCallbacks; + getServiceChildCallbacks.SwapElements(mGetServiceChildCallbacks); + for (uint32_t i = 0, length = getServiceChildCallbacks.Length(); i < length; ++i) { + getServiceChildCallbacks[i]->Done(mServiceChild.get()); + } +} + +void +GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent) +{ + if (mServiceChild) { + mServiceChild->RemoveGMPContentParent(aGMPContentParent); + } +} + +GMPServiceChild::GMPServiceChild() +{ +} + +GMPServiceChild::~GMPServiceChild() +{ + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, + new DeleteTask(GetTransport())); +} + +PGMPContentParent* +GMPServiceChild::AllocPGMPContentParent(Transport* aTransport, + ProcessId aOtherPid) +{ + MOZ_ASSERT(!mContentParents.GetWeak(aOtherPid)); + + nsCOMPtr mainThread = do_GetMainThread(); + MOZ_ASSERT(mainThread); + + nsRefPtr parent = new GMPContentParent(); + + DebugOnly ok = parent->Open(aTransport, aOtherPid, + XRE_GetIOMessageLoop(), + mozilla::ipc::ParentSide); + MOZ_ASSERT(ok); + + mContentParents.Put(aOtherPid, parent); + return parent; +} + +void +GMPServiceChild::GetBridgedGMPContentParent(ProcessId aOtherPid, + GMPContentParent** aGMPContentParent) +{ + mContentParents.Get(aOtherPid, aGMPContentParent); +} + +static PLDHashOperator +FindAndRemoveGMPContentParent(const uint64_t& aKey, + nsRefPtr& aData, + void* aUserArg) +{ + return aData == aUserArg ? + (PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE) : + PL_DHASH_NEXT; +} + +void +GMPServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent) +{ + mContentParents.Enumerate(FindAndRemoveGMPContentParent, aGMPContentParent); +} + +static PLDHashOperator +FillProcessIDArray(const uint64_t& aKey, GMPContentParent*, void* aUserArg) +{ + static_cast*>(aUserArg)->AppendElement(aKey); + return PL_DHASH_NEXT; +} + +void +GMPServiceChild::GetAlreadyBridgedTo(nsTArray& aAlreadyBridgedTo) +{ + aAlreadyBridgedTo.SetCapacity(mContentParents.Count()); + mContentParents.EnumerateRead(FillProcessIDArray, &aAlreadyBridgedTo); +} + +class OpenPGMPServiceChild : public nsRunnable +{ +public: + OpenPGMPServiceChild(UniquePtr&& aGMPServiceChild, + mozilla::ipc::Transport* aTransport, + base::ProcessId aOtherPid) + : mGMPServiceChild(Move(aGMPServiceChild)), + mTransport(aTransport), + mOtherPid(aOtherPid) + { + } + + NS_IMETHOD Run() + { + nsRefPtr gmp = + GeckoMediaPluginServiceChild::GetSingleton(); + MOZ_ASSERT(!gmp->mServiceChild); + if (mGMPServiceChild->Open(mTransport, mOtherPid, XRE_GetIOMessageLoop(), + ipc::ChildSide)) { + gmp->SetServiceChild(Move(mGMPServiceChild)); + } else { + gmp->SetServiceChild(nullptr); + } + return NS_OK; + } + +private: + UniquePtr mGMPServiceChild; + mozilla::ipc::Transport* mTransport; + base::ProcessId mOtherPid; +}; + +/* static */ +PGMPServiceChild* +GMPServiceChild::Create(Transport* aTransport, ProcessId aOtherPid) +{ + nsRefPtr gmp = + GeckoMediaPluginServiceChild::GetSingleton(); + MOZ_ASSERT(!gmp->mServiceChild); + + UniquePtr serviceChild(new GMPServiceChild()); + + nsCOMPtr gmpThread; + nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread)); + NS_ENSURE_SUCCESS(rv, nullptr); + + GMPServiceChild* result = serviceChild.get(); + rv = gmpThread->Dispatch(new OpenPGMPServiceChild(Move(serviceChild), + aTransport, + aOtherPid), + NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + return nullptr; + } + + return result; +} + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/GMPServiceChild.h b/dom/media/gmp/GMPServiceChild.h new file mode 100644 index 0000000000..678423dfe1 --- /dev/null +++ b/dom/media/gmp/GMPServiceChild.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GMPServiceChild_h_ +#define GMPServiceChild_h_ + +#include "GMPService.h" +#include "base/process.h" +#include "mozilla/ipc/Transport.h" +#include "mozilla/gmp/PGMPServiceChild.h" + +namespace mozilla { +namespace gmp { + +#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000 + +class GMPContentParent; +class GMPServiceChild; +class GetServiceChildCallback; + +class GeckoMediaPluginServiceChild : public GeckoMediaPluginService +{ + friend class GMPServiceChild; + +public: + static already_AddRefed GetSingleton(); + + NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI, + nsTArray* aTags, + bool* aHasPlugin, + nsACString& aOutVersion) override; + NS_IMETHOD GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsingMode, + UniquePtr&& aCallback) override; + + NS_DECL_NSIOBSERVER + + void SetServiceChild(UniquePtr&& aServiceChild); + + void RemoveGMPContentParent(GMPContentParent* aGMPContentParent); + +protected: + virtual void InitializePlugins() override + { + // Nothing to do here. + } + virtual bool GetContentParentFrom(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) + override; + +private: + friend class OpenPGMPServiceChild; + + void GetServiceChild(UniquePtr&& aCallback); + + UniquePtr mServiceChild; + nsTArray> mGetServiceChildCallbacks; +}; + +class GMPServiceChild : public PGMPServiceChild +{ +public: + explicit GMPServiceChild(); + virtual ~GMPServiceChild(); + + virtual PGMPContentParent* AllocPGMPContentParent(Transport* aTransport, + ProcessId aOtherPid) + override; + + void GetBridgedGMPContentParent(ProcessId aOtherPid, + GMPContentParent** aGMPContentParent); + void RemoveGMPContentParent(GMPContentParent* aGMPContentParent); + + void GetAlreadyBridgedTo(nsTArray& aAlreadyBridgedTo); + + static PGMPServiceChild* Create(Transport* aTransport, ProcessId aOtherPid); + +private: + nsRefPtrHashtable mContentParents; +}; + +} // namespace gmp +} // namespace mozilla + +#endif // GMPServiceChild_h_ diff --git a/dom/media/gmp/GMPServiceParent.cpp b/dom/media/gmp/GMPServiceParent.cpp new file mode 100644 index 0000000000..0563116b37 --- /dev/null +++ b/dom/media/gmp/GMPServiceParent.cpp @@ -0,0 +1,1485 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GMPService.h" +#include "prio.h" +#include "prlog.h" +#include "GMPParent.h" +#include "GMPVideoDecoderParent.h" +#include "nsIObserverService.h" +#include "GeckoChildProcessHost.h" +#include "mozilla/Preferences.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/SyncRunnable.h" +#include "nsXPCOMPrivate.h" +#include "mozilla/Services.h" +#include "nsNativeCharsetUtils.h" +#include "nsIConsoleService.h" +#include "mozilla/unused.h" +#include "GMPDecryptorParent.h" +#include "GMPAudioDecoderParent.h" +#include "nsComponentManagerUtils.h" +#include "mozilla/Preferences.h" +#include "runnable_utils.h" +#include "VideoUtils.h" +#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) +#include "mozilla/SandboxInfo.h" +#endif +#include "nsAppDirectoryServiceDefs.h" +#include "nsDirectoryServiceUtils.h" +#include "nsDirectoryServiceDefs.h" +#include "nsHashKeys.h" +#include "nsIFile.h" +#include "nsISimpleEnumerator.h" + +namespace mozilla { + +#ifdef LOG +#undef LOG +#endif + +#ifdef PR_LOGGING +#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg) +#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg) +#else +#define LOGD(msg) +#define LOG(leve1, msg) +#endif + +#ifdef __CLASS__ +#undef __CLASS__ +#endif +#define __CLASS__ "GMPService" + +namespace gmp { + +static const uint32_t NodeIdSaltLength = 32; + +already_AddRefed +GeckoMediaPluginServiceParent::GetSingleton() +{ + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + nsRefPtr service( + GeckoMediaPluginServiceParent::GetGeckoMediaPluginService()); +#ifdef DEBUG + if (service) { + nsCOMPtr chromeService; + CallQueryInterface(service.get(), getter_AddRefs(chromeService)); + MOZ_ASSERT(chromeService); + } +#endif + return service.forget().downcast(); +} + +NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent, + GeckoMediaPluginService, + mozIGeckoMediaPluginChromeService) + +static int32_t sMaxAsyncShutdownWaitMs = 0; +static bool sHaveSetTimeoutPrefCache = false; + +GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent() + : mShuttingDown(false) + , mScannedPluginOnDisk(false) + , mWaitingForPluginsAsyncShutdown(false) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!sHaveSetTimeoutPrefCache) { + sHaveSetTimeoutPrefCache = true; + Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs, + "media.gmp.async-shutdown-timeout", + GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT); + } +} + +GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent() +{ + MOZ_ASSERT(mPlugins.IsEmpty()); + MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty()); +} + +int32_t +GeckoMediaPluginServiceParent::AsyncShutdownTimeoutMs() +{ + MOZ_ASSERT(sHaveSetTimeoutPrefCache); + return sMaxAsyncShutdownWaitMs; +} + +nsresult +GeckoMediaPluginServiceParent::Init() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr obsService = mozilla::services::GetObserverService(); + MOZ_ASSERT(obsService); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "profile-change-teardown", false))); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "last-pb-context-exited", false))); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "browser:purge-session-history", false))); + +#ifdef DEBUG + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, "mediakeys-request", false))); +#endif + + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + prefs->AddObserver("media.gmp.plugin.crash", this, false); + } + + nsresult rv = InitStorage(); + if (NS_FAILED(rv)) { + return rv; + } + + // Kick off scanning for plugins + nsCOMPtr thread; + return GetThread(getter_AddRefs(thread)); +} + + +nsresult +GeckoMediaPluginServiceParent::InitStorage() +{ + MOZ_ASSERT(NS_IsMainThread()); + + // GMP storage should be used in the chrome process only. + if (XRE_GetProcessType() != GeckoProcessType_Default) { + return NS_OK; + } + + // Directory service is main thread only, so cache the profile dir here + // so that we can use it off main thread. +#ifdef MOZ_WIDGET_GONK + nsresult rv = NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla"), false, getter_AddRefs(mStorageBaseDir)); +#else + nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir)); +#endif + + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = mStorageBaseDir->AppendNative(NS_LITERAL_CSTRING("gmp")); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700); + if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) { + return rv; + } + + return GeckoMediaPluginService::Init(); +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aSomeData) +{ + LOGD(("%s::%s topic='%s' data='%s'", __CLASS__, __FUNCTION__, + aTopic, NS_ConvertUTF16toUTF8(aSomeData).get())); + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + nsCOMPtr branch( do_QueryInterface(aSubject) ); + if (branch) { + bool crashNow = false; + if (NS_LITERAL_STRING("media.gmp.plugin.crash").Equals(aSomeData)) { + branch->GetBoolPref("media.gmp.plugin.crash", &crashNow); + } + if (crashNow) { + nsCOMPtr gmpThread; + { + MutexAutoLock lock(mMutex); + gmpThread = mGMPThread; + } + if (gmpThread) { + gmpThread->Dispatch(WrapRunnable(this, + &GeckoMediaPluginServiceParent::CrashPlugins), + NS_DISPATCH_NORMAL); + } + } + } + } else if (!strcmp("profile-change-teardown", aTopic)) { + + // How shutdown works: + // + // Some GMPs require time to do bookkeeping upon shutdown. These GMPs + // need to be given time to access storage during shutdown. To signal + // that time to shutdown is required, those GMPs implement the + // GMPAsyncShutdown interface. + // + // When we startup the child process, we query the GMP for the + // GMPAsyncShutdown interface, and if it's present, we send a message + // back to the GMPParent, which then registers the GMPParent by calling + // GMPService::AsyncShutdownNeeded(). + // + // On shutdown, we set mWaitingForPluginsAsyncShutdown to true, and then + // call UnloadPlugins on the GMPThread, and process events on the main + // thread until an event sets mWaitingForPluginsAsyncShutdown=false on + // the main thread. + // + // UnloadPlugins() sends close messages for all plugins' API objects to + // the GMP interfaces in the child process, and then sends the async + // shutdown notifications to child GMPs. When a GMP has completed its + // shutdown, it calls GMPAsyncShutdownHost::ShutdownComplete(), which + // sends a message back to the parent, which calls + // GMPService::AsyncShutdownComplete(). If all plugins requiring async + // shutdown have called AsyncShutdownComplete() we stick an event on the + // main thread to set mWaitingForPluginsAsyncShutdown=false. We must use + // an event to do this, as we must ensure the main thread processes an + // event to run its loop. This will unblock the main thread, and shutdown + // of other components will proceed. + // + // We set a timer in UnloadPlugins(), and abort waiting for async + // shutdown if the GMPs are taking too long to shutdown. + // + // We shutdown in "profile-change-teardown", as the profile dir is + // still writable then, and it's required for GMPStorage. We block the + // shutdown process by spinning the main thread event loop until all GMPs + // have shutdown, or timeout has occurred. + // + // GMPStorage needs to work up until the shutdown-complete notification + // arrives from the GMP process. + + mWaitingForPluginsAsyncShutdown = true; + + nsCOMPtr gmpThread; + { + MutexAutoLock lock(mMutex); + MOZ_ASSERT(!mShuttingDown); + mShuttingDown = true; + gmpThread = mGMPThread; + } + + if (gmpThread) { + gmpThread->Dispatch( + NS_NewRunnableMethod(this, + &GeckoMediaPluginServiceParent::UnloadPlugins), + NS_DISPATCH_NORMAL); + } else { + MOZ_ASSERT(mPlugins.IsEmpty()); + } + + // Wait for plugins to do async shutdown... + while (mWaitingForPluginsAsyncShutdown) { + NS_ProcessNextEvent(NS_GetCurrentThread(), true); + } + + } else if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) { + MOZ_ASSERT(mShuttingDown); + ShutdownGMPThread(); + } else if (!strcmp("last-pb-context-exited", aTopic)) { + // When Private Browsing mode exits, all we need to do is clear + // mTempNodeIds. This drops all the node ids we've cached in memory + // for PB origin-pairs. If we try to open an origin-pair for non-PB + // mode, we'll get the NodeId salt stored on-disk, and if we try to + // open a PB mode origin-pair, we'll re-generate new salt. + mTempNodeIds.Clear(); + } else if (!strcmp("browser:purge-session-history", aTopic)) { + // Clear everything! + if (!aSomeData || nsDependentString(aSomeData).IsEmpty()) { + return GMPDispatch(NS_NewRunnableMethod( + this, &GeckoMediaPluginServiceParent::ClearStorage)); + } + + // Clear nodeIds/records modified after |t|. + nsresult rv; + PRTime t = nsDependentString(aSomeData).ToInteger64(&rv, 10); + if (NS_FAILED(rv)) { + return rv; + } + return GMPDispatch(NS_NewRunnableMethodWithArg( + this, &GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread, + t)); + } + + return NS_OK; +} + +bool +GeckoMediaPluginServiceParent::GetContentParentFrom(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) +{ + nsRefPtr gmp = SelectPluginForAPI(aNodeId, aAPI, aTags); + +#ifdef PR_LOGGING + nsCString api = aTags[0]; + LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get())); +#endif + + if (!gmp) { + return false; + } + + return gmp->GetGMPContentParent(Move(aCallback)); +} + +void +GeckoMediaPluginServiceParent::InitializePlugins() +{ + mGMPThread->Dispatch( + NS_NewRunnableMethod(this, &GeckoMediaPluginServiceParent::LoadFromEnvironment), + NS_DISPATCH_NORMAL); +} + +void +GeckoMediaPluginServiceParent::AsyncShutdownNeeded(GMPParent* aParent) +{ + LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent)); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + MOZ_ASSERT(!mAsyncShutdownPlugins.Contains(aParent)); + mAsyncShutdownPlugins.AppendElement(aParent); +} + +void +GeckoMediaPluginServiceParent::AsyncShutdownComplete(GMPParent* aParent) +{ + LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent)); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + mAsyncShutdownPlugins.RemoveElement(aParent); + if (mAsyncShutdownPlugins.IsEmpty() && mShuttingDownOnGMPThread) { + // The main thread may be waiting for async shutdown of plugins, + // which has completed. Break the main thread out of its waiting loop. + nsCOMPtr task(NS_NewRunnableMethod( + this, &GeckoMediaPluginServiceParent::SetAsyncShutdownComplete)); + NS_DispatchToMainThread(task); + } +} + +void +GeckoMediaPluginServiceParent::SetAsyncShutdownComplete() +{ + MOZ_ASSERT(NS_IsMainThread()); + mWaitingForPluginsAsyncShutdown = false; +} + +void +GeckoMediaPluginServiceParent::UnloadPlugins() +{ + LOGD(("%s::%s async_shutdown=%d", __CLASS__, __FUNCTION__, + mAsyncShutdownPlugins.Length())); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + MOZ_ASSERT(!mShuttingDownOnGMPThread); + mShuttingDownOnGMPThread = true; + + { + MutexAutoLock lock(mMutex); + // Note: CloseActive is async; it will actually finish + // shutting down when all the plugins have unloaded. + for (size_t i = 0; i < mPlugins.Length(); i++) { + mPlugins[i]->CloseActive(true); + } + mPlugins.Clear(); + } + + if (mAsyncShutdownPlugins.IsEmpty()) { + nsCOMPtr task(NS_NewRunnableMethod( + this, &GeckoMediaPluginServiceParent::SetAsyncShutdownComplete)); + NS_DispatchToMainThread(task); + } +} + +void +GeckoMediaPluginServiceParent::CrashPlugins() +{ + LOGD(("%s::%s", __CLASS__, __FUNCTION__)); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + MutexAutoLock lock(mMutex); + for (size_t i = 0; i < mPlugins.Length(); i++) { + mPlugins[i]->Crash(); + } +} + +void +GeckoMediaPluginServiceParent::LoadFromEnvironment() +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + const char* env = PR_GetEnv("MOZ_GMP_PATH"); + if (!env || !*env) { + return; + } + + nsString allpaths; + if (NS_WARN_IF(NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(env), allpaths)))) { + return; + } + + uint32_t pos = 0; + while (pos < allpaths.Length()) { + // Loop over multiple path entries separated by colons (*nix) or + // semicolons (Windows) + int32_t next = allpaths.FindChar(XPCOM_ENV_PATH_SEPARATOR[0], pos); + if (next == -1) { + AddOnGMPThread(nsDependentSubstring(allpaths, pos)); + break; + } else { + AddOnGMPThread(nsDependentSubstring(allpaths, pos, next - pos)); + pos = next + 1; + } + } + + mScannedPluginOnDisk = true; +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::PathRunnable::Run() +{ + if (mOperation == ADD) { + mService->AddOnGMPThread(mPath); + } else { + mService->RemoveOnGMPThread(mPath, + mOperation == REMOVE_AND_DELETE_FROM_DISK); + } + return NS_OK; +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::AddPluginDirectory(const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_IsMainThread()); + return GMPDispatch(new PathRunnable(this, aDirectory, + PathRunnable::EOperation::ADD)); +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::RemovePluginDirectory(const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_IsMainThread()); + return GMPDispatch(new PathRunnable(this, aDirectory, + PathRunnable::EOperation::REMOVE)); +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::RemoveAndDeletePluginDirectory( + const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_IsMainThread()); + return GMPDispatch( + new PathRunnable(this, aDirectory, + PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK)); +} + +class DummyRunnable : public nsRunnable { +public: + NS_IMETHOD Run() { return NS_OK; } +}; + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::GetPluginVersionForAPI(const nsACString& aAPI, + nsTArray* aTags, + bool* aHasPlugin, + nsACString& aOutVersion) +{ + NS_ENSURE_ARG(aTags && aTags->Length() > 0); + NS_ENSURE_ARG(aHasPlugin); + + nsresult rv = EnsurePluginsOnDiskScanned(); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to load GMPs from disk."); + return rv; + } + + { + MutexAutoLock lock(mMutex); + nsCString api(aAPI); + GMPParent* gmp = FindPluginForAPIFrom(0, api, *aTags, nullptr); + if (gmp) { + *aHasPlugin = true; + aOutVersion = gmp->GetVersion(); + } else { + *aHasPlugin = false; + } + } + + return NS_OK; +} + +nsresult +GeckoMediaPluginServiceParent::EnsurePluginsOnDiskScanned() +{ + const char* env = nullptr; + if (!mScannedPluginOnDisk && (env = PR_GetEnv("MOZ_GMP_PATH")) && *env) { + // We have a MOZ_GMP_PATH environment variable which may specify the + // location of plugins to load, and we haven't yet scanned the disk to + // see if there are plugins there. Get the GMP thread, which will + // cause an event to be dispatched to which scans for plugins. We + // dispatch a sync event to the GMP thread here in order to wait until + // after the GMP thread has scanned any paths in MOZ_GMP_PATH. + nsresult rv = GMPDispatch(new DummyRunnable(), NS_DISPATCH_SYNC); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now"); + } + + return NS_OK; +} + +GMPParent* +GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex, + const nsCString& aAPI, + const nsTArray& aTags, + size_t* aOutPluginIndex) +{ + mMutex.AssertCurrentThreadOwns(); + for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) { + GMPParent* gmp = mPlugins[i]; + bool supportsAllTags = true; + for (size_t t = 0; t < aTags.Length(); t++) { + const nsCString& tag = aTags.ElementAt(t); + if (!gmp->SupportsAPI(aAPI, tag)) { + supportsAllTags = false; + break; + } + } + if (!supportsAllTags) { + continue; + } + if (aOutPluginIndex) { + *aOutPluginIndex = i; + } + return gmp; + } + return nullptr; +} + +GMPParent* +GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread, + "Can't clone GMP plugins on non-GMP threads."); + + GMPParent* gmpToClone = nullptr; + { + MutexAutoLock lock(mMutex); + size_t index = 0; + GMPParent* gmp = nullptr; + while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) { + if (aNodeId.IsEmpty()) { + if (gmp->CanBeSharedCrossNodeIds()) { + return gmp; + } + } else if (gmp->CanBeUsedFrom(aNodeId)) { + MOZ_ASSERT(!aNodeId.IsEmpty()); + gmp->SetNodeId(aNodeId); + return gmp; + } + + // This GMP has the correct type but has the wrong nodeId; hold on to it + // in case we need to clone it. + gmpToClone = gmp; + // Loop around and try the next plugin; it may be usable from aNodeId. + index++; + } + } + + // Plugin exists, but we can't use it due to cross-origin separation. Create a + // new one. + if (gmpToClone) { + GMPParent* clone = ClonePlugin(gmpToClone); + if (!aNodeId.IsEmpty()) { + clone->SetNodeId(aNodeId); + } + return clone; + } + + if (aAPI.EqualsLiteral(GMP_API_DECRYPTOR)) { + // XXX to remove in bug 1147692 + return SelectPluginForAPI(aNodeId, + NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), + aTags); + } + + return nullptr; +} + +class CreateGMPParentTask : public nsRunnable { +public: + NS_IMETHOD Run() { + MOZ_ASSERT(NS_IsMainThread()); +#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) + if (!SandboxInfo::Get().CanSandboxMedia()) { + if (!Preferences::GetBool("media.gmp.insecure.allow")) { + NS_WARNING("Denying media plugin load due to lack of sandboxing."); + return NS_ERROR_NOT_AVAILABLE; + } + NS_WARNING("Loading media plugin despite lack of sandboxing."); + } +#endif + mParent = new GMPParent(); + return NS_OK; + } + already_AddRefed GetParent() { + return mParent.forget(); + } +private: + nsRefPtr mParent; +}; + +GMPParent* +GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal) +{ + MOZ_ASSERT(aOriginal); + + // The GMPParent inherits from IToplevelProtocol, which must be created + // on the main thread to be threadsafe. See Bug 1035653. + nsRefPtr task(new CreateGMPParentTask()); + if (!NS_IsMainThread()) { + nsCOMPtr mainThread = do_GetMainThread(); + MOZ_ASSERT(mainThread); + mozilla::SyncRunnable::DispatchToThread(mainThread, task); + } + + nsRefPtr gmp = task->GetParent(); + nsresult rv = gmp->CloneFrom(aOriginal); + + if (NS_FAILED(rv)) { + NS_WARNING("Can't Create GMPParent"); + return nullptr; + } + + MutexAutoLock lock(mMutex); + mPlugins.AppendElement(gmp); + + return gmp.get(); +} + +class NotifyObserversTask final : public nsRunnable { +public: + explicit NotifyObserversTask(const char* aTopic) + : mTopic(aTopic) + {} + NS_IMETHOD Run() override { + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr obsService = mozilla::services::GetObserverService(); + MOZ_ASSERT(obsService); + if (obsService) { + obsService->NotifyObservers(nullptr, mTopic, nullptr); + } + return NS_OK; + } +private: + ~NotifyObserversTask() {} + const char* mTopic; +}; + +void +GeckoMediaPluginServiceParent::AddOnGMPThread(const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get())); + + nsCOMPtr directory; + nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + // The GMPParent inherits from IToplevelProtocol, which must be created + // on the main thread to be threadsafe. See Bug 1035653. + nsRefPtr task(new CreateGMPParentTask()); + nsCOMPtr mainThread = do_GetMainThread(); + MOZ_ASSERT(mainThread); + mozilla::SyncRunnable::DispatchToThread(mainThread, task); + nsRefPtr gmp = task->GetParent(); + rv = gmp ? gmp->Init(this, directory) : NS_ERROR_NOT_AVAILABLE; + if (NS_FAILED(rv)) { + NS_WARNING("Can't Create GMPParent"); + return; + } + + { + MutexAutoLock lock(mMutex); + mPlugins.AppendElement(gmp); + } + + NS_DispatchToMainThread(new NotifyObserversTask("gmp-path-added"), NS_DISPATCH_NORMAL); +} + +void +GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory, + const bool aDeleteFromDisk) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get())); + + nsCOMPtr directory; + nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + MutexAutoLock lock(mMutex); + for (size_t i = 0; i < mPlugins.Length(); ++i) { + nsCOMPtr pluginpath = mPlugins[i]->GetDirectory(); + bool equals; + if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) { + mPlugins[i]->AbortAsyncShutdown(); + mPlugins[i]->CloseActive(true); + if (aDeleteFromDisk) { + pluginpath->Remove(true); + } + mPlugins.RemoveElementAt(i); + return; + } + } + NS_WARNING("Removing GMP which was never added."); + nsCOMPtr cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID); + cs->LogStringMessage(MOZ_UTF16("Removing GMP which was never added.")); +} + +// May remove when Bug 1043671 is fixed +static void Dummy(nsRefPtr& aOnDeathsDoor) +{ + // exists solely to do nothing and let the Runnable kill the GMPParent + // when done. +} + +void +GeckoMediaPluginServiceParent::PluginTerminated(const RefPtr& aPlugin) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + if (aPlugin->IsMarkedForDeletion()) { + nsCString path8; + RefPtr dir = aPlugin->GetDirectory(); + nsresult rv = dir->GetNativePath(path8); + NS_ENSURE_SUCCESS_VOID(rv); + + nsString path = NS_ConvertUTF8toUTF16(path8); + if (mPluginsWaitingForDeletion.Contains(path)) { + RemoveOnGMPThread(path, true /* delete */); + //RemoveOnGMPThread(path, true /* delete */, true /* can defer */); + } + } +} + +void +GeckoMediaPluginServiceParent::ReAddOnGMPThread(nsRefPtr& aOld) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld)); + + nsRefPtr gmp; + if (!mShuttingDownOnGMPThread) { + // Don't re-add plugin if we're shutting down. Let the old plugin die. + gmp = ClonePlugin(aOld); + } + // Note: both are now in the list + // Until we give up the GMPThread, we're safe even if we unlock temporarily + // since off-main-thread users just test for existance; they don't modify the list. + MutexAutoLock lock(mMutex); + mPlugins.RemoveElement(aOld); + + // Schedule aOld to be destroyed. We can't destroy it from here since we + // may be inside ActorDestroyed() for it. + NS_DispatchToCurrentThread(WrapRunnableNM(&Dummy, aOld)); +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::GetStorageDir(nsIFile** aOutFile) +{ + if (NS_WARN_IF(!mStorageBaseDir)) { + return NS_ERROR_FAILURE; + } + return mStorageBaseDir->Clone(aOutFile); +} + +static nsresult +WriteToFile(nsIFile* aPath, + const nsCString& aFileName, + const nsCString& aData) +{ + nsCOMPtr path; + nsresult rv = aPath->Clone(getter_AddRefs(path)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = path->AppendNative(aFileName); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + PRFileDesc* f = nullptr; + rv = path->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, PR_IRWXU, &f); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + int32_t len = PR_Write(f, aData.get(), aData.Length()); + PR_Close(f); + if (NS_WARN_IF(len < 0 || (size_t)len != aData.Length())) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +static nsresult +ReadFromFile(nsIFile* aPath, + const nsACString& aFileName, + nsACString& aOutData, + int32_t aMaxLength) +{ + nsCOMPtr path; + nsresult rv = aPath->Clone(getter_AddRefs(path)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = path->AppendNative(aFileName); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + PRFileDesc* f = nullptr; + rv = path->OpenNSPRFileDesc(PR_RDONLY | PR_CREATE_FILE, PR_IRWXU, &f); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + auto size = PR_Seek(f, 0, PR_SEEK_END); + PR_Seek(f, 0, PR_SEEK_SET); + + if (size > aMaxLength) { + return NS_ERROR_FAILURE; + } + aOutData.SetLength(size); + + auto len = PR_Read(f, aOutData.BeginWriting(), size); + PR_Close(f); + if (NS_WARN_IF(len != size)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +ReadSalt(nsIFile* aPath, nsACString& aOutData) +{ + return ReadFromFile(aPath, NS_LITERAL_CSTRING("salt"), + aOutData, NodeIdSaltLength); + +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::IsPersistentStorageAllowed(const nsACString& aNodeId, + bool* aOutAllowed) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + NS_ENSURE_ARG(aOutAllowed); + *aOutAllowed = mPersistentStorageAllowed.Get(aNodeId); + return NS_OK; +} + +nsresult +GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsing, + nsACString& aOutId) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__, + NS_ConvertUTF16toUTF8(aOrigin).get(), + NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), + (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"))); + + nsresult rv; + + if (aOrigin.EqualsLiteral("null") || + aOrigin.IsEmpty() || + aTopLevelOrigin.EqualsLiteral("null") || + aTopLevelOrigin.IsEmpty()) { + // At least one of the (origin, topLevelOrigin) is null or empty; + // probably a local file. Generate a random node id, and don't store + // it so that the GMP's storage is temporary and not shared. + nsAutoCString salt; + rv = GenerateRandomPathName(salt, NodeIdSaltLength); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + aOutId = salt; + mPersistentStorageAllowed.Put(salt, false); + return NS_OK; + } + + const uint32_t hash = AddToHash(HashString(aOrigin), + HashString(aTopLevelOrigin)); + + if (aInPrivateBrowsing) { + // For PB mode, we store the node id, indexed by the origin pair, + // so that if the same origin pair is opened in this session, it gets + // the same node id. + nsCString* salt = nullptr; + if (!(salt = mTempNodeIds.Get(hash))) { + // No salt stored, generate and temporarily store some for this id. + nsAutoCString newSalt; + rv = GenerateRandomPathName(newSalt, NodeIdSaltLength); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + salt = new nsCString(newSalt); + mTempNodeIds.Put(hash, salt); + mPersistentStorageAllowed.Put(*salt, false); + } + aOutId = *salt; + return NS_OK; + } + + // Otherwise, try to see if we've previously generated and stored salt + // for this origin pair. + nsCOMPtr path; // $profileDir/gmp/ + rv = GetStorageDir(getter_AddRefs(path)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = path->AppendNative(NS_LITERAL_CSTRING("id")); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // $profileDir/gmp/id/ + rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); + if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsAutoCString hashStr; + hashStr.AppendInt((int64_t)hash); + + // $profileDir/gmp/id/$hash + rv = path->AppendNative(hashStr); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); + if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr saltFile; + rv = path->Clone(getter_AddRefs(saltFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = saltFile->AppendNative(NS_LITERAL_CSTRING("salt")); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsAutoCString salt; + bool exists = false; + rv = saltFile->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (!exists) { + // No stored salt for this origin. Generate salt, and store it and + // the origin on disk. + nsresult rv = GenerateRandomPathName(salt, NodeIdSaltLength); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + MOZ_ASSERT(salt.Length() == NodeIdSaltLength); + + // $profileDir/gmp/id/$hash/salt + rv = WriteToFile(path, NS_LITERAL_CSTRING("salt"), salt); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // $profileDir/gmp/id/$hash/origin + rv = WriteToFile(path, + NS_LITERAL_CSTRING("origin"), + NS_ConvertUTF16toUTF8(aOrigin)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // $profileDir/gmp/id/$hash/topLevelOrigin + rv = WriteToFile(path, + NS_LITERAL_CSTRING("topLevelOrigin"), + NS_ConvertUTF16toUTF8(aTopLevelOrigin)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + } else { + rv = ReadSalt(path, salt); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } + + aOutId = salt; + mPersistentStorageAllowed.Put(salt, true); + + return NS_OK; +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsing, + UniquePtr&& aCallback) +{ + nsCString nodeId; + nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, nodeId); + aCallback->Done(rv, nodeId); + return rv; +} + +bool +MatchOrigin(nsIFile* aPath, const nsACString& aOrigin) +{ + // http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax + static const uint32_t MaxDomainLength = 253; + + nsresult rv; + nsCString str; + rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("origin"), str, MaxDomainLength); + if (NS_SUCCEEDED(rv) && aOrigin.Equals(str)) { + return true; + } + rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("topLevelOrigin"), str, MaxDomainLength); + if (NS_SUCCEEDED(rv) && aOrigin.Equals(str)) { + return true; + } + return false; +} + +template static void +KillPlugins(const nsTArray>& aPlugins, + Mutex& aMutex, T&& aFilter) +{ + // Shutdown the plugins when |aFilter| evaluates to true. + // After we clear storage data, node IDs will become invalid and shouldn't be + // used anymore. We need to kill plugins with such nodeIDs. + // Note: we can't shut them down while holding the lock, + // as the lock is not re-entrant and shutdown requires taking the lock. + // The plugin list is only edited on the GMP thread, so this should be OK. + nsTArray> pluginsToKill; + { + MutexAutoLock lock(aMutex); + for (size_t i = 0; i < aPlugins.Length(); i++) { + nsRefPtr parent(aPlugins[i]); + if (aFilter(parent)) { + pluginsToKill.AppendElement(parent); + } + } + } + + for (size_t i = 0; i < pluginsToKill.Length(); i++) { + pluginsToKill[i]->CloseActive(false); + // Abort async shutdown because we're going to wipe the plugin's storage, + // so we don't want it writing more data in its async shutdown path. + pluginsToKill[i]->AbortAsyncShutdown(); + } +} + +static nsresult +DeleteDir(nsIFile* aPath) +{ + bool exists = false; + nsresult rv = aPath->Exists(&exists); + if (NS_FAILED(rv)) { + return rv; + } + if (exists) { + return aPath->Remove(true); + } + return NS_OK; +} + +struct NodeFilter { + explicit NodeFilter(const nsTArray& nodeIDs) : mNodeIDs(nodeIDs) {} + bool operator()(GMPParent* aParent) { + return mNodeIDs.Contains(aParent->GetNodeId()); + } +private: + const nsTArray& mNodeIDs; +}; + +void +GeckoMediaPluginServiceParent::ClearNodeIdAndPlugin(DirectoryFilter& aFilter) +{ + nsresult rv; + nsCOMPtr path; + + // $profileDir/gmp/ + rv = GetStorageDir(getter_AddRefs(path)); + if (NS_FAILED(rv)) { + return; + } + + // $profileDir/gmp/id/ + rv = path->AppendNative(NS_LITERAL_CSTRING("id")); + if (NS_FAILED(rv)) { + return; + } + + // Iterate all sub-folders of $profileDir/gmp/id/ + nsCOMPtr iter; + rv = path->GetDirectoryEntries(getter_AddRefs(iter)); + if (NS_FAILED(rv)) { + return; + } + + bool hasMore = false; + nsTArray nodeIDsToClear; + while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr supports; + rv = iter->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) { + continue; + } + + // $profileDir/gmp/id/$hash + nsCOMPtr dirEntry(do_QueryInterface(supports, &rv)); + if (NS_FAILED(rv)) { + continue; + } + + // Skip non-directory files. + bool isDirectory = false; + rv = dirEntry->IsDirectory(&isDirectory); + if (NS_FAILED(rv) || !isDirectory) { + continue; + } + + if (!aFilter(dirEntry)) { + continue; + } + + nsAutoCString salt; + if (NS_SUCCEEDED(ReadSalt(dirEntry, salt))) { + // Keep node IDs to clear data/plugins associated with them later. + nodeIDsToClear.AppendElement(salt); + // Also remove node IDs from the table. + mPersistentStorageAllowed.Remove(salt); + } + // Now we can remove the directory for the origin pair. + if (NS_FAILED(dirEntry->Remove(true))) { + NS_WARNING("Failed to delete the directory for the origin pair"); + } + } + + // Kill plugins that have node IDs to be cleared. + KillPlugins(mPlugins, mMutex, NodeFilter(nodeIDsToClear)); + + // Clear all matching $profileDir/gmp/storage/$nodeId/ + rv = GetStorageDir(getter_AddRefs(path)); + if (NS_FAILED(rv)) { + return; + } + + rv = path->AppendNative(NS_LITERAL_CSTRING("storage")); + if (NS_FAILED(rv)) { + return; + } + + for (size_t i = 0; i < nodeIDsToClear.Length(); i++) { + nsCOMPtr dirEntry; + rv = path->Clone(getter_AddRefs(dirEntry)); + if (NS_FAILED(rv)) { + continue; + } + + rv = dirEntry->AppendNative(nodeIDsToClear[i]); + if (NS_FAILED(rv)) { + continue; + } + + if (NS_FAILED(DeleteDir(dirEntry))) { + NS_WARNING("Failed to delete GMP storage directory for the node"); + } + } +} + +void +GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread(const nsACString& aOrigin) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: origin=%s", __CLASS__, __FUNCTION__, aOrigin.Data())); + + struct OriginFilter : public DirectoryFilter { + explicit OriginFilter(const nsACString& aOrigin) : mOrigin(aOrigin) {} + virtual bool operator()(nsIFile* aPath) { + return MatchOrigin(aPath, mOrigin); + } + private: + const nsACString& mOrigin; + } filter(aOrigin); + + ClearNodeIdAndPlugin(filter); +} + +void +GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread(PRTime aSince) +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s: since=%lld", __CLASS__, __FUNCTION__, (int64_t)aSince)); + + nsCOMPtr storagePath; + nsCOMPtr temp; + if (NS_SUCCEEDED(GetStorageDir(getter_AddRefs(temp))) && + NS_SUCCEEDED(temp->AppendNative(NS_LITERAL_CSTRING("storage")))) { + storagePath = temp.forget(); + } + + struct MTimeFilter : public DirectoryFilter { + explicit MTimeFilter(PRTime aSince, already_AddRefed aPath) + : mSince(aSince), mStoragePath(aPath) {} + + // Return true if any files under aPath is modified after |mSince|. + bool IsModifiedAfter(nsIFile* aPath) { + PRTime lastModified; + nsresult rv = aPath->GetLastModifiedTime(&lastModified); + if (NS_SUCCEEDED(rv) && lastModified >= mSince) { + return true; + } + // Check sub-directories recursively + nsCOMPtr iter; + rv = aPath->GetDirectoryEntries(getter_AddRefs(iter)); + if (NS_FAILED(rv)) { + return false; + } + + bool hasMore = false; + while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr supports; + rv = iter->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) { + continue; + } + + nsCOMPtr path(do_QueryInterface(supports, &rv)); + if (NS_FAILED(rv)) { + continue; + } + + if (IsModifiedAfter(path)) { + return true; + } + } + return false; + } + + // |aPath| is $profileDir/gmp/id/$hash + virtual bool operator()(nsIFile* aPath) { + if (IsModifiedAfter(aPath)) { + return true; + } + + nsAutoCString salt; + nsresult rv = ReadSalt(aPath, salt); + if (NS_FAILED(rv)) { + return false; + } + + // $profileDir/gmp/storage/ + if (!mStoragePath) { + return false; + } + // $profileDir/gmp/storage/$nodeId/ + nsCOMPtr path; + rv = mStoragePath->Clone(getter_AddRefs(path)); + if (NS_FAILED(rv)) { + return false; + } + + rv = path->AppendNative(salt); + return NS_SUCCEEDED(rv) && IsModifiedAfter(path); + } + private: + const PRTime mSince; + const nsCOMPtr mStoragePath; + } filter(aSince, storagePath.forget()); + + ClearNodeIdAndPlugin(filter); + + NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); +} + +NS_IMETHODIMP +GeckoMediaPluginServiceParent::ForgetThisSite(const nsAString& aOrigin) +{ + MOZ_ASSERT(NS_IsMainThread()); + return GMPDispatch(NS_NewRunnableMethodWithArg( + this, &GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread, + NS_ConvertUTF16toUTF8(aOrigin))); +} + +static bool IsNodeIdValid(GMPParent* aParent) { + return !aParent->GetNodeId().IsEmpty(); +} + +void +GeckoMediaPluginServiceParent::ClearStorage() +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + LOGD(("%s::%s", __CLASS__, __FUNCTION__)); + + // Kill plugins with valid nodeIDs. + KillPlugins(mPlugins, mMutex, &IsNodeIdValid); + + nsCOMPtr path; // $profileDir/gmp/ + nsresult rv = GetStorageDir(getter_AddRefs(path)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + if (NS_FAILED(DeleteDir(path))) { + NS_WARNING("Failed to delete GMP storage directory"); + } + NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); +} + +GMPServiceParent::~GMPServiceParent() +{ + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, + new DeleteTask(GetTransport())); +} + +bool +GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId, + const nsCString& aAPI, + nsTArray&& aTags, + nsTArray&& aAlreadyBridgedTo, + ProcessId* aId, + nsCString* aDisplayName, + nsCString* aPluginId) +{ + nsRefPtr gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags); + +#ifdef PR_LOGGING + nsCString api = aTags[0]; + LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get())); +#endif + + if (!gmp || !gmp->EnsureProcessLoaded(aId)) { + return false; + } + + *aDisplayName = gmp->GetDisplayName(); + *aPluginId = gmp->GetPluginId(); + + return aAlreadyBridgedTo.Contains(*aId) || gmp->Bridge(this); +} + +bool +GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin, + const nsString& aTopLevelOrigin, + const bool& aInPrivateBrowsing, + nsCString* aID) +{ + nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, + aInPrivateBrowsing, *aID); + return NS_SUCCEEDED(rv); +} + +/* static */ +bool +GMPServiceParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI, + nsTArray&& aTags, + bool* aHasPlugin, + nsCString* aVersion) +{ + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); + return service && + NS_SUCCEEDED(service->GetPluginVersionForAPI(aAPI, &aTags, aHasPlugin, + *aVersion)); +} + +class DeleteGMPServiceParent : public nsRunnable +{ +public: + explicit DeleteGMPServiceParent(GMPServiceParent* aToDelete) + : mToDelete(aToDelete) + { + } + + NS_IMETHODIMP Run() + { + return NS_OK; + } + +private: + nsAutoPtr mToDelete; +}; + +void +GMPServiceParent::ActorDestroy(ActorDestroyReason aWhy) +{ + NS_DispatchToCurrentThread(new DeleteGMPServiceParent(this)); +} + +class OpenPGMPServiceParent : public nsRunnable +{ +public: + OpenPGMPServiceParent(GMPServiceParent* aGMPServiceParent, + mozilla::ipc::Transport* aTransport, + base::ProcessId aOtherPid, + bool* aResult) + : mGMPServiceParent(aGMPServiceParent), + mTransport(aTransport), + mOtherPid(aOtherPid), + mResult(aResult) + { + } + + NS_IMETHOD Run() + { + *mResult = mGMPServiceParent->Open(mTransport, mOtherPid, + XRE_GetIOMessageLoop(), ipc::ParentSide); + return NS_OK; + } + +private: + GMPServiceParent* mGMPServiceParent; + mozilla::ipc::Transport* mTransport; + base::ProcessId mOtherPid; + bool* mResult; +}; + +/* static */ +PGMPServiceParent* +GMPServiceParent::Create(Transport* aTransport, ProcessId aOtherPid) +{ + nsRefPtr gmp = + GeckoMediaPluginServiceParent::GetSingleton(); + + nsAutoPtr serviceParent(new GMPServiceParent(gmp)); + + nsCOMPtr gmpThread; + nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread)); + NS_ENSURE_SUCCESS(rv, nullptr); + + bool ok; + rv = gmpThread->Dispatch(new OpenPGMPServiceParent(serviceParent, + aTransport, + aOtherPid, &ok), + NS_DISPATCH_SYNC); + if (NS_FAILED(rv) || !ok) { + return nullptr; + } + + return serviceParent.forget(); +} + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/GMPServiceParent.h b/dom/media/gmp/GMPServiceParent.h new file mode 100644 index 0000000000..152683d11b --- /dev/null +++ b/dom/media/gmp/GMPServiceParent.h @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GMPServiceParent_h_ +#define GMPServiceParent_h_ + +#include "GMPService.h" +#include "mozilla/gmp/PGMPServiceParent.h" +#include "mozIGeckoMediaPluginChromeService.h" +#include "nsClassHashtable.h" +#include "nsDataHashtable.h" +#include "mozilla/Atomics.h" +#include "nsThreadUtils.h" + +template struct already_AddRefed; + +namespace mozilla { +namespace gmp { + +class GMPParent; + +#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000 + +class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService + , public mozIGeckoMediaPluginChromeService +{ +public: + static already_AddRefed GetSingleton(); + + GeckoMediaPluginServiceParent(); + virtual nsresult Init() override; + + NS_DECL_ISUPPORTS_INHERITED + + // mozIGeckoMediaPluginService + NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI, + nsTArray* aTags, + bool* aHasPlugin, + nsACString& aOutVersion) override; + NS_IMETHOD GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsingMode, + UniquePtr&& aCallback) override; + + NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE + NS_DECL_NSIOBSERVER + + void AsyncShutdownNeeded(GMPParent* aParent); + void AsyncShutdownComplete(GMPParent* aParent); + void AbortAsyncShutdown(); + + int32_t AsyncShutdownTimeoutMs(); + +private: + friend class GMPServiceParent; + + virtual ~GeckoMediaPluginServiceParent(); + + void ClearStorage(); + + GMPParent* SelectPluginForAPI(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags); + GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex, + const nsCString& aAPI, + const nsTArray& aTags, + size_t* aOutPluginIndex); + + nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, + bool aInPrivateBrowsing, nsACString& aOutId); + + void UnloadPlugins(); + void CrashPlugins(); + void SetAsyncShutdownComplete(); + + void LoadFromEnvironment(); + void ProcessPossiblePlugin(nsIFile* aDir); + + void AddOnGMPThread(const nsAString& aDirectory); + void RemoveOnGMPThread(const nsAString& aDirectory, + const bool aDeleteFromDisk); + + nsresult SetAsyncShutdownTimeout(); + + struct DirectoryFilter { + virtual bool operator()(nsIFile* aPath) = 0; + ~DirectoryFilter() {} + }; + void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); + + void ForgetThisSiteOnGMPThread(const nsACString& aOrigin); + void ClearRecentHistoryOnGMPThread(PRTime aSince); + +protected: + friend class GMPParent; + void ReAddOnGMPThread(nsRefPtr& aOld); + void PluginTerminated(const RefPtr& aOld); + virtual void InitializePlugins() override; + virtual bool GetContentParentFrom(const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray& aTags, + UniquePtr&& aCallback) + override; +private: + GMPParent* ClonePlugin(const GMPParent* aOriginal); + nsresult EnsurePluginsOnDiskScanned(); + nsresult InitStorage(); + + class PathRunnable : public nsRunnable + { + public: + enum EOperation { + ADD, + REMOVE, + REMOVE_AND_DELETE_FROM_DISK, + }; + + PathRunnable(GeckoMediaPluginServiceParent* aService, const nsAString& aPath, + EOperation aOperation) + : mService(aService) + , mPath(aPath) + , mOperation(aOperation) + { } + + NS_DECL_NSIRUNNABLE + + private: + nsRefPtr mService; + nsString mPath; + EOperation mOperation; + }; + + // Protected by mMutex from the base class. + nsTArray> mPlugins; + bool mShuttingDown; + + // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any + // plugins found there into mPlugins. + Atomic mScannedPluginOnDisk; + + template + class MainThreadOnly { + public: + MOZ_IMPLICIT MainThreadOnly(T aValue) + : mValue(aValue) + {} + operator T&() { + MOZ_ASSERT(NS_IsMainThread()); + return mValue; + } + + private: + T mValue; + }; + + MainThreadOnly mWaitingForPluginsAsyncShutdown; + + nsTArray mPluginsWaitingForDeletion; + + nsTArray> mAsyncShutdownPlugins; // GMP Thread only. + + nsCOMPtr mStorageBaseDir; + + // Hashes of (origin,topLevelOrigin) to the node id for + // non-persistent sessions. + nsClassHashtable mTempNodeIds; + + // Hashes node id to whether that node id is allowed to store data + // persistently on disk. + nsDataHashtable mPersistentStorageAllowed; +}; + +nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); +bool MatchOrigin(nsIFile* aPath, const nsACString& aOrigin); + +class GMPServiceParent final : public PGMPServiceParent +{ +public: + explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService) + : mService(aService) + { + } + virtual ~GMPServiceParent(); + + virtual bool RecvLoadGMP(const nsCString& aNodeId, + const nsCString& aApi, + nsTArray&& aTags, + nsTArray&& aAlreadyBridgedTo, + base::ProcessId* aID, + nsCString* aDisplayName, + nsCString* aPluginId) override; + virtual bool RecvGetGMPNodeId(const nsString& aOrigin, + const nsString& aTopLevelOrigin, + const bool& aInPrivateBrowsing, + nsCString* aID) override; + static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI, + nsTArray&& aTags, + bool* aHasPlugin, + nsCString* aVersion); + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + + static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid); + +private: + nsRefPtr mService; +}; + +} // namespace gmp +} // namespace mozilla + +#endif // GMPServiceParent_h_ diff --git a/dom/media/gmp/GMPStorageParent.cpp b/dom/media/gmp/GMPStorageParent.cpp index 121db32d02..c151b65315 100644 --- a/dom/media/gmp/GMPStorageParent.cpp +++ b/dom/media/gmp/GMPStorageParent.cpp @@ -39,7 +39,7 @@ extern PRLogModuleInfo* GetGMPLog(); #ifdef __CLASS__ #undef __CLASS__ #endif -#define __CLASS__ "GMPParent" +#define __CLASS__ "GMPStorageParent" namespace gmp { @@ -52,7 +52,7 @@ GetGMPStorageDir(nsIFile** aTempDir, const nsCString& aNodeId) return NS_ERROR_INVALID_ARG; } - nsCOMPtr mps = + nsCOMPtr mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); if (NS_WARN_IF(!mps)) { return NS_ERROR_FAILURE; @@ -468,7 +468,7 @@ GMPStorageParent::Init() if (NS_WARN_IF(mNodeId.IsEmpty())) { return NS_ERROR_FAILURE; } - nsCOMPtr mps = + nsCOMPtr mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); if (NS_WARN_IF(!mps)) { return NS_ERROR_FAILURE; diff --git a/dom/media/gmp/GMPVideoDecoderChild.cpp b/dom/media/gmp/GMPVideoDecoderChild.cpp index bed62b923c..a52a7a8506 100644 --- a/dom/media/gmp/GMPVideoDecoderChild.cpp +++ b/dom/media/gmp/GMPVideoDecoderChild.cpp @@ -5,7 +5,7 @@ #include "GMPVideoDecoderChild.h" #include "GMPVideoi420FrameImpl.h" -#include "GMPChild.h" +#include "GMPContentChild.h" #include #include "mozilla/unused.h" #include "GMPVideoEncodedFrameImpl.h" @@ -13,7 +13,7 @@ namespace mozilla { namespace gmp { -GMPVideoDecoderChild::GMPVideoDecoderChild(GMPChild* aPlugin) +GMPVideoDecoderChild::GMPVideoDecoderChild(GMPContentChild* aPlugin) : GMPSharedMemManager(aPlugin), mPlugin(aPlugin), mVideoDecoder(nullptr), diff --git a/dom/media/gmp/GMPVideoDecoderChild.h b/dom/media/gmp/GMPVideoDecoderChild.h index aa2ff84c43..ae13283fbd 100644 --- a/dom/media/gmp/GMPVideoDecoderChild.h +++ b/dom/media/gmp/GMPVideoDecoderChild.h @@ -16,14 +16,14 @@ namespace mozilla { namespace gmp { -class GMPChild; +class GMPContentChild; class GMPVideoDecoderChild : public PGMPVideoDecoderChild, public GMPVideoDecoderCallback, public GMPSharedMemManager { public: - explicit GMPVideoDecoderChild(GMPChild* aPlugin); + explicit GMPVideoDecoderChild(GMPContentChild* aPlugin); virtual ~GMPVideoDecoderChild(); void Init(GMPVideoDecoder* aDecoder); @@ -74,7 +74,7 @@ private: virtual bool RecvDrain() override; virtual bool RecvDecodingComplete() override; - GMPChild* mPlugin; + GMPContentChild* mPlugin; GMPVideoDecoder* mVideoDecoder; GMPVideoHostImpl mVideoHost; }; diff --git a/dom/media/gmp/GMPVideoDecoderParent.cpp b/dom/media/gmp/GMPVideoDecoderParent.cpp index d5d157eb6c..422545bd8c 100644 --- a/dom/media/gmp/GMPVideoDecoderParent.cpp +++ b/dom/media/gmp/GMPVideoDecoderParent.cpp @@ -11,7 +11,7 @@ #include "GMPUtils.h" #include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoi420FrameImpl.h" -#include "GMPParent.h" +#include "GMPContentParent.h" #include "GMPMessageUtils.h" #include "mozilla/gmp/GMPTypes.h" @@ -43,7 +43,7 @@ namespace gmp { // on Shutdown -> Dead // Dead: mIsOpen == false -GMPVideoDecoderParent::GMPVideoDecoderParent(GMPParent* aPlugin) +GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin) : GMPSharedMemManager(aPlugin) , mIsOpen(false) , mShuttingDown(false) @@ -335,6 +335,13 @@ GMPVideoDecoderParent::RecvError(const GMPErr& aError) return true; } +bool +GMPVideoDecoderParent::RecvShutdown() +{ + Shutdown(); + return true; +} + bool GMPVideoDecoderParent::RecvParentShmemForPool(Shmem&& aEncodedBuffer) { diff --git a/dom/media/gmp/GMPVideoDecoderParent.h b/dom/media/gmp/GMPVideoDecoderParent.h index 42bcac1d0d..a231cd01a5 100644 --- a/dom/media/gmp/GMPVideoDecoderParent.h +++ b/dom/media/gmp/GMPVideoDecoderParent.h @@ -18,7 +18,7 @@ namespace mozilla { namespace gmp { -class GMPParent; +class GMPContentParent; class GMPVideoDecoderParent final : public PGMPVideoDecoderParent , public GMPVideoDecoderProxy @@ -27,7 +27,7 @@ class GMPVideoDecoderParent final : public PGMPVideoDecoderParent public: NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent) - explicit GMPVideoDecoderParent(GMPParent *aPlugin); + explicit GMPVideoDecoderParent(GMPContentParent *aPlugin); GMPVideoHostImpl& Host(); nsresult Shutdown(); @@ -73,6 +73,7 @@ private: virtual bool RecvDrainComplete() override; virtual bool RecvResetComplete() override; virtual bool RecvError(const GMPErr& aError) override; + virtual bool RecvShutdown() override; virtual bool RecvParentShmemForPool(Shmem&& aEncodedBuffer) override; virtual bool AnswerNeedShmem(const uint32_t& aFrameBufferSize, Shmem* aMem) override; @@ -80,7 +81,7 @@ private: bool mIsOpen; bool mShuttingDown; - nsRefPtr mPlugin; + nsRefPtr mPlugin; GMPVideoDecoderCallbackProxy* mCallback; GMPVideoHostImpl mVideoHost; }; diff --git a/dom/media/gmp/GMPVideoEncoderChild.cpp b/dom/media/gmp/GMPVideoEncoderChild.cpp index 14df35e28e..48c8bc7461 100644 --- a/dom/media/gmp/GMPVideoEncoderChild.cpp +++ b/dom/media/gmp/GMPVideoEncoderChild.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPVideoEncoderChild.h" -#include "GMPChild.h" +#include "GMPContentChild.h" #include #include "mozilla/unused.h" #include "GMPVideoEncodedFrameImpl.h" @@ -13,7 +13,7 @@ namespace mozilla { namespace gmp { -GMPVideoEncoderChild::GMPVideoEncoderChild(GMPChild* aPlugin) +GMPVideoEncoderChild::GMPVideoEncoderChild(GMPContentChild* aPlugin) : GMPSharedMemManager(aPlugin), mPlugin(aPlugin), mVideoEncoder(nullptr), diff --git a/dom/media/gmp/GMPVideoEncoderChild.h b/dom/media/gmp/GMPVideoEncoderChild.h index 6010fe37c1..3c1c3546e9 100644 --- a/dom/media/gmp/GMPVideoEncoderChild.h +++ b/dom/media/gmp/GMPVideoEncoderChild.h @@ -15,14 +15,14 @@ namespace mozilla { namespace gmp { -class GMPChild; +class GMPContentChild; class GMPVideoEncoderChild : public PGMPVideoEncoderChild, public GMPVideoEncoderCallback, public GMPSharedMemManager { public: - explicit GMPVideoEncoderChild(GMPChild* aPlugin); + explicit GMPVideoEncoderChild(GMPContentChild* aPlugin); virtual ~GMPVideoEncoderChild(); void Init(GMPVideoEncoder* aEncoder); @@ -73,7 +73,7 @@ private: virtual bool RecvSetPeriodicKeyFrames(const bool& aEnable) override; virtual bool RecvEncodingComplete() override; - GMPChild* mPlugin; + GMPContentChild* mPlugin; GMPVideoEncoder* mVideoEncoder; GMPVideoHostImpl mVideoHost; }; diff --git a/dom/media/gmp/GMPVideoEncoderParent.cpp b/dom/media/gmp/GMPVideoEncoderParent.cpp index 0585d699ba..3222778170 100644 --- a/dom/media/gmp/GMPVideoEncoderParent.cpp +++ b/dom/media/gmp/GMPVideoEncoderParent.cpp @@ -10,7 +10,7 @@ #include "mozilla/unused.h" #include "GMPMessageUtils.h" #include "nsAutoRef.h" -#include "GMPParent.h" +#include "GMPContentParent.h" #include "mozilla/gmp/GMPTypes.h" #include "nsThread.h" #include "nsThreadUtils.h" @@ -50,7 +50,7 @@ namespace gmp { // on Shutdown -> Dead // Dead: mIsOpen == false -GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin) +GMPVideoEncoderParent::GMPVideoEncoderParent(GMPContentParent *aPlugin) : GMPSharedMemManager(aPlugin), mIsOpen(false), mShuttingDown(false), @@ -320,6 +320,13 @@ GMPVideoEncoderParent::RecvError(const GMPErr& aError) return true; } +bool +GMPVideoEncoderParent::RecvShutdown() +{ + Shutdown(); + return true; +} + bool GMPVideoEncoderParent::RecvParentShmemForPool(Shmem&& aFrameBuffer) { diff --git a/dom/media/gmp/GMPVideoEncoderParent.h b/dom/media/gmp/GMPVideoEncoderParent.h index 2a7000a888..0485cb43ad 100644 --- a/dom/media/gmp/GMPVideoEncoderParent.h +++ b/dom/media/gmp/GMPVideoEncoderParent.h @@ -18,7 +18,7 @@ namespace mozilla { namespace gmp { -class GMPParent; +class GMPContentParent; class GMPVideoEncoderParent : public GMPVideoEncoderProxy, public PGMPVideoEncoderParent, @@ -27,7 +27,7 @@ class GMPVideoEncoderParent : public GMPVideoEncoderProxy, public: NS_INLINE_DECL_REFCOUNTING(GMPVideoEncoderParent) - explicit GMPVideoEncoderParent(GMPParent *aPlugin); + explicit GMPVideoEncoderParent(GMPContentParent *aPlugin); GMPVideoHostImpl& Host(); void Shutdown(); @@ -69,6 +69,7 @@ private: virtual bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame, InfallibleTArray&& aCodecSpecificInfo) override; virtual bool RecvError(const GMPErr& aError) override; + virtual bool RecvShutdown() override; virtual bool RecvParentShmemForPool(Shmem&& aFrameBuffer) override; virtual bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize, Shmem* aMem) override; @@ -76,7 +77,7 @@ private: bool mIsOpen; bool mShuttingDown; - nsRefPtr mPlugin; + nsRefPtr mPlugin; GMPVideoEncoderCallbackProxy* mCallback; GMPVideoHostImpl mVideoHost; nsCOMPtr mEncodedThread; diff --git a/dom/media/gmp/PGMP.ipdl b/dom/media/gmp/PGMP.ipdl index d40b990797..4dc4a864f2 100644 --- a/dom/media/gmp/PGMP.ipdl +++ b/dom/media/gmp/PGMP.ipdl @@ -3,10 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -include protocol PGMPVideoDecoder; -include protocol PGMPVideoEncoder; -include protocol PGMPDecryptor; -include protocol PGMPAudioDecoder; +include protocol PGMPContent; include protocol PGMPTimer; include protocol PGMPStorage; @@ -15,10 +12,8 @@ namespace gmp { intr protocol PGMP { - manages PGMPAudioDecoder; - manages PGMPDecryptor; - manages PGMPVideoDecoder; - manages PGMPVideoEncoder; + parent opens PGMPContent; + manages PGMPTimer; manages PGMPStorage; @@ -26,19 +21,17 @@ parent: async PGMPTimer(); async PGMPStorage(); + async PGMPContentChildDestroyed(); + async AsyncShutdownComplete(); async AsyncShutdownRequired(); child: - async PGMPAudioDecoder(); - async PGMPDecryptor(); - async PGMPVideoDecoder(); - async PGMPVideoEncoder(); - - async SetNodeId(nsCString nodeId); - async StartPlugin(); async BeginAsyncShutdown(); async CrashPluginNow(); + async StartPlugin(); + async SetNodeId(nsCString nodeId); + async CloseActive(); }; } // namespace gmp diff --git a/dom/media/gmp/PGMPAudioDecoder.ipdl b/dom/media/gmp/PGMPAudioDecoder.ipdl index 7b19125696..0c23145efe 100644 --- a/dom/media/gmp/PGMPAudioDecoder.ipdl +++ b/dom/media/gmp/PGMPAudioDecoder.ipdl @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -include protocol PGMP; +include protocol PGMPContent; include GMPTypes; using GMPCodecSpecificInfo from "gmp-audio-codec.h"; @@ -16,7 +16,7 @@ namespace gmp { async protocol PGMPAudioDecoder { - manager PGMP; + manager PGMPContent; child: InitDecode(GMPAudioCodecData aCodecSettings); Decode(GMPAudioEncodedSampleData aInput); @@ -30,6 +30,7 @@ parent: DrainComplete(); ResetComplete(); Error(GMPErr aErr); + async Shutdown(); }; } // namespace gmp diff --git a/dom/media/gmp/PGMPContent.ipdl b/dom/media/gmp/PGMPContent.ipdl new file mode 100644 index 0000000000..7dd1337c93 --- /dev/null +++ b/dom/media/gmp/PGMPContent.ipdl @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PGMP; +include protocol PGMPService; +include protocol PGMPVideoDecoder; +include protocol PGMPVideoEncoder; +include protocol PGMPDecryptor; +include protocol PGMPAudioDecoder; + +namespace mozilla { +namespace gmp { + +intr protocol PGMPContent +{ + bridges PGMPService, PGMP; + + manages PGMPAudioDecoder; + manages PGMPDecryptor; + manages PGMPVideoDecoder; + manages PGMPVideoEncoder; + +child: + async PGMPAudioDecoder(); + async PGMPDecryptor(); + async PGMPVideoDecoder(); + async PGMPVideoEncoder(); +}; + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/PGMPDecryptor.ipdl b/dom/media/gmp/PGMPDecryptor.ipdl index 03417a54e2..0ec39b2030 100644 --- a/dom/media/gmp/PGMPDecryptor.ipdl +++ b/dom/media/gmp/PGMPDecryptor.ipdl @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -include protocol PGMP; +include protocol PGMPContent; include GMPTypes; using GMPSessionMessageType from "gmp-decryption.h"; @@ -17,7 +17,7 @@ namespace gmp { async protocol PGMPDecryptor { - manager PGMP; + manager PGMPContent; child: Init(); @@ -84,6 +84,8 @@ parent: SetCaps(uint64_t aCaps); Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer); + + async Shutdown(); }; } // namespace gmp diff --git a/dom/media/gmp/PGMPService.ipdl b/dom/media/gmp/PGMPService.ipdl new file mode 100644 index 0000000000..80d24f7a6a --- /dev/null +++ b/dom/media/gmp/PGMPService.ipdl @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PGMP; + +using base::ProcessId from "base/process.h"; + +namespace mozilla { +namespace gmp { + +sync protocol PGMPService +{ + parent spawns PGMP as child; + +parent: + sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags, + ProcessId[] alreadyBridgedTo) + returns (ProcessId id, nsCString displayName, nsCString pluginId); + sync GetGMPNodeId(nsString origin, nsString topLevelOrigin, + bool inPrivateBrowsing) + returns (nsCString id); +}; + +} // namespace gmp +} // namespace mozilla diff --git a/dom/media/gmp/PGMPVideoDecoder.ipdl b/dom/media/gmp/PGMPVideoDecoder.ipdl index c25a9881b7..83ad8f700f 100644 --- a/dom/media/gmp/PGMPVideoDecoder.ipdl +++ b/dom/media/gmp/PGMPVideoDecoder.ipdl @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -include protocol PGMP; +include protocol PGMPContent; include GMPTypes; using GMPVideoCodec from "gmp-video-codec.h"; @@ -16,7 +16,7 @@ namespace gmp { intr protocol PGMPVideoDecoder { - manager PGMP; + manager PGMPContent; child: async InitDecode(GMPVideoCodec aCodecSettings, uint8_t[] aCodecSpecific, @@ -39,6 +39,7 @@ parent: async DrainComplete(); async ResetComplete(); async Error(GMPErr aErr); + async Shutdown(); async ParentShmemForPool(Shmem aEncodedBuffer); // MUST be intr - if sync and we create a new Shmem, when the returned // Shmem is received in the Child it will fail to Deserialize diff --git a/dom/media/gmp/PGMPVideoEncoder.ipdl b/dom/media/gmp/PGMPVideoEncoder.ipdl index f7b910bac1..ef013352a8 100644 --- a/dom/media/gmp/PGMPVideoEncoder.ipdl +++ b/dom/media/gmp/PGMPVideoEncoder.ipdl @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -include protocol PGMP; +include protocol PGMPContent; include GMPTypes; using GMPVideoCodec from "gmp-video-codec.h"; @@ -17,7 +17,7 @@ namespace gmp { intr protocol PGMPVideoEncoder { - manager PGMP; + manager PGMPContent; child: async InitEncode(GMPVideoCodec aCodecSettings, uint8_t[] aCodecSpecific, @@ -37,6 +37,7 @@ parent: async Encoded(GMPVideoEncodedFrameData aEncodedFrame, uint8_t[] aCodecSpecificInfo); async Error(GMPErr aErr); + async Shutdown(); async ParentShmemForPool(Shmem aFrameBuffer); // MUST be intr - if sync and we create a new Shmem, when the returned // Shmem is received in the Child it will fail to Deserialize diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index 1fe607f7ae..0320d8fb4f 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -7,6 +7,7 @@ XPIDL_MODULE = 'content_geckomediaplugins' XPIDL_SOURCES += [ + 'mozIGeckoMediaPluginChromeService.idl', 'mozIGeckoMediaPluginService.idl', ] @@ -35,6 +36,8 @@ EXPORTS += [ 'GMPAudioHost.h', 'GMPCallbackBase.h', 'GMPChild.h', + 'GMPContentChild.h', + 'GMPContentParent.h', 'GMPDecryptorChild.h', 'GMPDecryptorParent.h', 'GMPDecryptorProxy.h', @@ -46,6 +49,8 @@ EXPORTS += [ 'GMPProcessChild.h', 'GMPProcessParent.h', 'GMPService.h', + 'GMPServiceChild.h', + 'GMPServiceParent.h', 'GMPSharedMemManager.h', 'GMPStorageChild.h', 'GMPStorageParent.h', @@ -76,6 +81,8 @@ UNIFIED_SOURCES += [ 'GMPAudioDecoderParent.cpp', 'GMPAudioHost.cpp', 'GMPChild.cpp', + 'GMPContentChild.cpp', + 'GMPContentParent.cpp', 'GMPDecryptorChild.cpp', 'GMPDecryptorParent.cpp', 'GMPEncryptedBufferDataImpl.cpp', @@ -84,6 +91,8 @@ UNIFIED_SOURCES += [ 'GMPProcessChild.cpp', 'GMPProcessParent.cpp', 'GMPService.cpp', + 'GMPServiceChild.cpp', + 'GMPServiceParent.cpp', 'GMPSharedMemManager.cpp', 'GMPStorageChild.cpp', 'GMPStorageParent.cpp', @@ -109,7 +118,9 @@ IPDL_SOURCES += [ 'GMPTypes.ipdlh', 'PGMP.ipdl', 'PGMPAudioDecoder.ipdl', + 'PGMPContent.ipdl', 'PGMPDecryptor.ipdl', + 'PGMPService.ipdl', 'PGMPStorage.ipdl', 'PGMPTimer.ipdl', 'PGMPVideoDecoder.ipdl', diff --git a/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl b/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl new file mode 100644 index 0000000000..915c61b48c --- /dev/null +++ b/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" +#include "nsIFile.idl" + +[scriptable, uuid(5878366c-73f6-486e-ad2f-9aca602864e4)] +interface mozIGeckoMediaPluginChromeService : nsISupports +{ + /** + * Add a directory to scan for gecko media plugins. + * @note Main-thread API. + */ + void addPluginDirectory(in AString directory); + + /** + * Remove a directory for gecko media plugins. + * @note Main-thread API. + */ + void removePluginDirectory(in AString directory); + + /** + * Remove a directory for gecko media plugins and delete it from disk. + * @note Main-thread API. + */ + void removeAndDeletePluginDirectory(in AString directory); + + /** + * Clears storage data associated with the origin. + */ + void forgetThisSite(in AString origin); + + /** + * Returns true if the given node id is allowed to store things + * persistently on disk. Private Browsing and local content are not + * allowed to store persistent data. + */ + bool isPersistentStorageAllowed(in ACString nodeId); + + /** + * Returns the directory to use as the base for storing data about GMPs. + */ + nsIFile getStorageDir(); + +}; diff --git a/dom/media/gmp/mozIGeckoMediaPluginService.idl b/dom/media/gmp/mozIGeckoMediaPluginService.idl index c4c331da6e..b23a3d991d 100644 --- a/dom/media/gmp/mozIGeckoMediaPluginService.idl +++ b/dom/media/gmp/mozIGeckoMediaPluginService.idl @@ -5,10 +5,9 @@ #include "nsISupports.idl" #include "nsIThread.idl" -#include "nsIPrincipal.idl" -#include "nsIFile.idl" %{C++ +#include "mozilla/UniquePtr.h" #include "nsTArray.h" #include "nsStringGlue.h" class GMPAudioDecoderProxy; @@ -16,17 +15,44 @@ class GMPDecryptorProxy; class GMPVideoDecoderProxy; class GMPVideoEncoderProxy; class GMPVideoHost; + +template +class GMPGetterCallback +{ +public: + GMPGetterCallback() { MOZ_COUNT_CTOR(GMPGetterCallback); } + virtual ~GMPGetterCallback() { MOZ_COUNT_DTOR(GMPGetterCallback); } + virtual void Done(T*) = 0; +}; +template +class GMPVideoGetterCallback +{ +public: + GMPVideoGetterCallback() { MOZ_COUNT_CTOR(GMPVideoGetterCallback); } + virtual ~GMPVideoGetterCallback() { MOZ_COUNT_DTOR(GMPVideoGetterCallback); } + virtual void Done(T*, GMPVideoHost*) = 0; +}; +typedef GMPGetterCallback GetGMPDecryptorCallback; +typedef GMPGetterCallback GetGMPAudioDecoderCallback; +typedef GMPVideoGetterCallback GetGMPVideoDecoderCallback; +typedef GMPVideoGetterCallback GetGMPVideoEncoderCallback; +class GetNodeIdCallback +{ +public: + GetNodeIdCallback() { MOZ_COUNT_CTOR(GetNodeIdCallback); } + virtual ~GetNodeIdCallback() { MOZ_COUNT_DTOR(GetNodeIdCallback); } + virtual void Done(nsresult aResult, const nsACString& aNodeId) = 0; +}; %} -[ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy); -[ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy); -[ptr] native GMPVideoHost(GMPVideoHost); -[ptr] native MessageLoop(MessageLoop); [ptr] native TagArray(nsTArray); -[ptr] native GMPDecryptorProxy(GMPDecryptorProxy); -[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy); +native GetGMPDecryptorCallback(mozilla::UniquePtr&&); +native GetGMPAudioDecoderCallback(mozilla::UniquePtr&&); +native GetGMPVideoDecoderCallback(mozilla::UniquePtr&&); +native GetGMPVideoEncoderCallback(mozilla::UniquePtr&&); +native GetNodeIdCallback(mozilla::UniquePtr&&); -[scriptable, uuid(46c7cd80-a19d-49e7-a147-ca314ad8d8b0)] +[scriptable, uuid(2b0c90e1-df89-4583-a123-8bdb2f5f7e39)] interface mozIGeckoMediaPluginService : nsISupports { @@ -47,86 +73,78 @@ interface mozIGeckoMediaPluginService : nsISupports * Callable on any thread */ [noscript] - ACString getPluginVersionForAPI(in ACString api, - in TagArray tags); + void getPluginVersionForAPI(in ACString api, in TagArray tags, + out boolean hasPlugin, out ACString version); /** * Get a video decoder that supports the specified tags. * The array of tags should at least contain a codec tag, and optionally * other tags such as for EME keysystem. * Callable only on GMP thread. + * This is an asynchronous operation, the Done method of the callback object + * will be called on the GMP thread with the result (which might be null in + * the case of failure). This method always takes ownership of the callback + * object, but if this method returns an error then the Done method of the + * callback object will not be called at all. */ [noscript] - GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags, - [optional] in ACString nodeId, - out GMPVideoHost outVideoHost); + void getGMPVideoDecoder(in TagArray tags, + [optional] in ACString nodeId, + in GetGMPVideoDecoderCallback callback); /** * Get a video encoder that supports the specified tags. * The array of tags should at least contain a codec tag, and optionally * other tags. * Callable only on GMP thread. + * This is an asynchronous operation, the Done method of the callback object + * will be called on the GMP thread with the result (which might be null in + * the case of failure). This method always takes ownership of the callback + * object, but if this method returns an error then the Done method of the + * callback object will not be called at all. */ [noscript] - GMPVideoEncoderProxy getGMPVideoEncoder(in TagArray tags, - [optional] in ACString nodeId, - out GMPVideoHost outVideoHost); - - // Returns an audio decoder that supports the specified tags. - // The array of tags should at least contain a codec tag, and optionally - // other tags such as for EME keysystem. - // Callable only on GMP thread. - GMPAudioDecoderProxy getGMPAudioDecoder(in TagArray tags, - [optional] in ACString nodeId); - - // Returns a decryption session manager that supports the specified tags. - // The array of tags should at least contain a key system tag, and optionally - // other tags. - // Callable only on GMP thread. - GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in ACString nodeId); + void getGMPVideoEncoder(in TagArray tags, + [optional] in ACString nodeId, + in GetGMPVideoEncoderCallback callback); /** - * Add a directory to scan for goanna media plugins. - * @note Main-thread API. + * Returns an audio decoder that supports the specified tags. + * The array of tags should at least contain a codec tag, and optionally + * other tags such as for EME keysystem. + * Callable only on GMP thread. + * This is an asynchronous operation, the Done method of the callback object + * will be called on the GMP thread with the result (which might be null in + * the case of failure). This method always takes ownership of the callback + * object, but if this method returns an error then the Done method of the + * callback object will not be called at all. */ - void addPluginDirectory(in AString directory); + [noscript] + void getGMPAudioDecoder(in TagArray tags, + [optional] in ACString nodeId, + in GetGMPAudioDecoderCallback callback); /** - * Remove a directory for gecko media plugins. - * @note Main-thread API. + * Returns a decryption session manager that supports the specified tags. + * The array of tags should at least contain a key system tag, and optionally + * other tags. + * Callable only on GMP thread. + * This is an asynchronous operation, the Done method of the callback object + * will be called on the GMP thread with the result (which might be null in + * the case of failure). This method always takes ownership of the callback + * object, but if this method returns an error then the Done method of the + * callback object will not be called at all. */ - void removePluginDirectory(in AString directory); - - /** - * Remove a directory for goanna media plugins and delete it from disk. - * If |defer| is true, wait until the plugin is unused before removing. - * @note Main-thread API. - */ - void removeAndDeletePluginDirectory(in AString directory, - [optional] in bool defer); + [noscript] + void getGMPDecryptor(in TagArray tags, in ACString nodeId, + in GetGMPDecryptorCallback callback); /** * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple. */ - ACString getNodeId(in AString origin, - in AString topLevelOrigin, - in bool inPrivateBrowsingMode); - - /** - * Clears storage data associated with the site. - */ - void forgetThisSite(in AString site); - - /** - * Returns true if the given node id is allowed to store things - * persistently on disk. Private Browsing and local content are not - * allowed to store persistent data. - */ - bool isPersistentStorageAllowed(in ACString nodeId); - - /** - * Returns the directory to use as the base for storing data about GMPs. - */ - nsIFile getStorageDir(); - + [noscript] + void getNodeId(in AString origin, + in AString topLevelOrigin, + in bool inPrivateBrowsingMode, + in GetNodeIdCallback callback); }; diff --git a/dom/media/gtest/TestGMPCrossOrigin.cpp b/dom/media/gtest/TestGMPCrossOrigin.cpp index 1bff1e759d..336cd405d5 100644 --- a/dom/media/gtest/TestGMPCrossOrigin.cpp +++ b/dom/media/gtest/TestGMPCrossOrigin.cpp @@ -11,12 +11,13 @@ #include "GMPVideoDecoderProxy.h" #include "GMPVideoEncoderProxy.h" #include "GMPDecryptorProxy.h" -#include "GMPService.h" +#include "GMPServiceParent.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIFile.h" #include "nsISimpleEnumerator.h" #include "mozilla/Atomics.h" #include "nsNSSComponent.h" +#include "mozilla/DebugOnly.h" #if defined(XP_WIN) #include "mozilla/WindowsVersion.h" @@ -27,94 +28,241 @@ using namespace std; using namespace mozilla; using namespace mozilla::gmp; +class GMPTestMonitor +{ +public: + GMPTestMonitor() + : mFinished(false) + { + } + + void AwaitFinished() + { + MOZ_ASSERT(NS_IsMainThread()); + while (!mFinished) { + NS_ProcessNextEvent(nullptr, true); + } + mFinished = false; + } + +private: + void MarkFinished() + { + mFinished = true; + } + +public: + void SetFinished() + { + NS_DispatchToMainThread(NS_NewNonOwningRunnableMethod(this, + &GMPTestMonitor::MarkFinished)); + } + +private: + bool mFinished; +}; + struct GMPTestRunner { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner) - void DoTest(void (GMPTestRunner::*aTestMethod)()); - void RunTestGMPTestCodec(); - void RunTestGMPCrossOrigin(); + void DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&)); + void RunTestGMPTestCodec1(GMPTestMonitor& aMonitor); + void RunTestGMPTestCodec2(GMPTestMonitor& aMonitor); + void RunTestGMPTestCodec3(GMPTestMonitor& aMonitor); + void RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor); + void RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor); + void RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor); + void RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor); private: ~GMPTestRunner() { } }; -void -GMPTestRunner::RunTestGMPTestCodec() +template*, + const nsACString&, + UniquePtr&&)> +class RunTestGMPVideoCodec : public Base { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); +public: + virtual void Done(T* aGMP, GMPVideoHost* aHost) + { + EXPECT_TRUE(aGMP); + EXPECT_TRUE(aHost); + if (aGMP) { + aGMP->Close(); + } + mMonitor.SetFinished(); + } - GMPVideoHost* host = nullptr; - GMPVideoDecoderProxy* decoder = nullptr; - GMPVideoDecoderProxy* decoder2 = nullptr; - GMPVideoEncoderProxy* encoder = nullptr; + static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin) + { + UniquePtr callback(new RunTestGMPVideoCodec(aMonitor)); + Get(aOrigin, Move(callback)); + } - nsTArray tags; - tags.AppendElement(NS_LITERAL_CSTRING("h264")); +protected: + typedef T GMPCodecType; + typedef Base GMPCallbackType; - service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("o"), &host, &decoder2); - service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING(""), &host, &decoder); + explicit RunTestGMPVideoCodec(GMPTestMonitor& aMonitor) + : mMonitor(aMonitor) + { + } - service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING(""), &host, &encoder); + static nsresult Get(const nsACString& aNodeId, UniquePtr&& aCallback) + { + nsTArray tags; + tags.AppendElement(NS_LITERAL_CSTRING("h264")); - EXPECT_TRUE(host); - EXPECT_TRUE(decoder); - EXPECT_TRUE(decoder2); - EXPECT_TRUE(encoder); + nsRefPtr service = + GeckoMediaPluginService::GetGeckoMediaPluginService(); + return ((*service).*Getter)(&tags, aNodeId, Move(aCallback)); + } - if (decoder) decoder->Close(); - if (decoder2) decoder2->Close(); - if (encoder) encoder->Close(); +protected: + GMPTestMonitor& mMonitor; +}; + +typedef RunTestGMPVideoCodec + RunTestGMPVideoDecoder; +typedef RunTestGMPVideoCodec + RunTestGMPVideoEncoder; + +void +GMPTestRunner::RunTestGMPTestCodec1(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING("o")); } void -GMPTestRunner::RunTestGMPCrossOrigin() +GMPTestRunner::RunTestGMPTestCodec2(GMPTestMonitor& aMonitor) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING("")); +} - GMPVideoHost* host = nullptr; - nsTArray tags; - tags.AppendElement(NS_LITERAL_CSTRING("h264")); +void +GMPTestRunner::RunTestGMPTestCodec3(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoEncoder::Run(aMonitor, NS_LITERAL_CSTRING("")); +} - GMPVideoDecoderProxy* decoder1 = nullptr; - GMPVideoDecoderProxy* decoder2 = nullptr; - GMPVideoEncoderProxy* encoder1 = nullptr; - GMPVideoEncoderProxy* encoder2 = nullptr; +template +class RunTestGMPCrossOrigin : public Base +{ +public: + virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost) + { + EXPECT_TRUE(aGMP); - service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder1); - service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &decoder2); - EXPECT_TRUE(!!decoder1 && !!decoder2 && - decoder1->ParentID() != decoder2->ParentID()); + UniquePtr callback( + new Step2(Base::mMonitor, aGMP, mShouldBeEqual)); + nsresult rv = Base::Get(mOrigin2, Move(callback)); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + if (NS_FAILED(rv)) { + Base::mMonitor.SetFinished(); + } + } - service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder1); - service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &encoder2); - EXPECT_TRUE(!!encoder1 && !!encoder2 && - encoder1->ParentID() != encoder2->ParentID()); + static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin1, + const nsCString& aOrigin2) + { + UniquePtr callback( + new RunTestGMPCrossOrigin(aMonitor, aOrigin1, aOrigin2)); + nsresult rv = Base::Get(aOrigin1, Move(callback)); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + if (NS_FAILED(rv)) { + aMonitor.SetFinished(); + } + } - if (decoder2) decoder2->Close(); - if (encoder2) encoder2->Close(); +private: + RunTestGMPCrossOrigin(GMPTestMonitor& aMonitor, const nsCString& aOrigin1, + const nsCString& aOrigin2) + : Base(aMonitor), + mGMP(nullptr), + mOrigin2(aOrigin2), + mShouldBeEqual(aOrigin1.Equals(aOrigin2)) + { + } - service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder2); - EXPECT_TRUE(!!decoder1 && !!decoder2 && - decoder1->ParentID() == decoder2->ParentID()); + class Step2 : public Base + { + public: + Step2(GMPTestMonitor& aMonitor, + typename Base::GMPCodecType* aGMP, + bool aShouldBeEqual) + : Base(aMonitor), + mGMP(aGMP), + mShouldBeEqual(aShouldBeEqual) + { + } + virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost) + { + EXPECT_TRUE(aGMP); + if (aGMP) { + EXPECT_TRUE(mGMP && + (mGMP->ParentID() == aGMP->ParentID()) == mShouldBeEqual); + } + if (mGMP) { + mGMP->Close(); + } + Base::Done(aGMP, aHost); + } - service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder2); - EXPECT_TRUE(!!encoder1 && !!encoder2 && - encoder1->ParentID() == encoder2->ParentID()); + private: + typename Base::GMPCodecType* mGMP; + bool mShouldBeEqual; + }; - if (decoder1) decoder1->Close(); - if (decoder2) decoder2->Close(); - if (encoder1) encoder1->Close(); - if (encoder2) encoder2->Close(); + typename Base::GMPCodecType* mGMP; + nsCString mOrigin2; + bool mShouldBeEqual; +}; + +typedef RunTestGMPCrossOrigin + RunTestGMPVideoDecoderCrossOrigin; +typedef RunTestGMPCrossOrigin + RunTestGMPVideoEncoderCrossOrigin; + +void +GMPTestRunner::RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoDecoderCrossOrigin::Run( + aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2")); +} + +void +GMPTestRunner::RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoEncoderCrossOrigin::Run( + aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2")); +} + +void +GMPTestRunner::RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoDecoderCrossOrigin::Run( + aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1")); +} + +void +GMPTestRunner::RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor) +{ + RunTestGMPVideoEncoderCrossOrigin::Run( + aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1")); } static already_AddRefed GetGMPThread() { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginService::GetGeckoMediaPluginService(); nsCOMPtr thread; EXPECT_TRUE(NS_SUCCEEDED(service->GetThread(getter_AddRefs(thread)))); return thread.forget(); @@ -158,8 +306,8 @@ template static nsresult EnumerateGMPStorageDir(const nsACString& aDir, T&& aDirIter) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); MOZ_ASSERT(service); // $profileDir/gmp/ @@ -312,28 +460,53 @@ SimulatePBModeExit() NS_DispatchToMainThread(new NotifyObserversTask("last-pb-context-exited"), NS_DISPATCH_SYNC); } +class TestGetNodeIdCallback : public GetNodeIdCallback +{ +public: + TestGetNodeIdCallback(nsCString& aNodeId, nsresult& aResult) + : mNodeId(aNodeId), + mResult(aResult) + { + } + + void Done(nsresult aResult, const nsACString& aNodeId) + { + mResult = aResult; + mNodeId = aNodeId; + } + +private: + nsCString& mNodeId; + nsresult& mResult; +}; + static nsCString GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, bool aInPBMode) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); EXPECT_TRUE(service); nsCString nodeId; + nsresult result; + UniquePtr callback(new TestGetNodeIdCallback(nodeId, + result)); + // We rely on the fact that the GetNodeId implementation for + // GeckoMediaPluginServiceParent is synchronous. nsresult rv = service->GetNodeId(aOrigin, aTopLevelOrigin, aInPBMode, - nodeId); - EXPECT_TRUE(NS_SUCCEEDED(rv)); + Move(callback)); + EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result)); return nodeId; } static bool IsGMPStorageIsEmpty() { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); MOZ_ASSERT(service); nsCOMPtr storage; nsresult rv = service->GetStorageDir(getter_AddRefs(storage)); @@ -348,8 +521,8 @@ IsGMPStorageIsEmpty() static void AssertIsOnGMPThread() { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginService::GetGeckoMediaPluginService(); MOZ_ASSERT(service); nsCOMPtr thread; service->GetThread(getter_AddRefs(thread)); @@ -437,11 +610,75 @@ class GMPStorageTest : public GMPDecryptorProxyCallback SetFinished(); } + class CreateDecryptorDone : public GetGMPDecryptorCallback + { + public: + CreateDecryptorDone(GMPStorageTest* aRunner, nsIRunnable* aContinuation) + : mRunner(aRunner), + mContinuation(aContinuation) + { + } + + virtual void Done(GMPDecryptorProxy* aDecryptor) override + { + mRunner->mDecryptor = aDecryptor; + EXPECT_TRUE(!!mRunner->mDecryptor); + + if (mRunner->mDecryptor) { + mRunner->mDecryptor->Init(mRunner); + } + nsCOMPtr thread(GetGMPThread()); + thread->Dispatch(mContinuation, NS_DISPATCH_NORMAL); + } + + private: + nsRefPtr mRunner; + nsCOMPtr mContinuation; + }; + void CreateDecryptor(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, - bool aInPBMode) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + bool aInPBMode, + const nsCString& aUpdate) + { + nsTArray updates; + updates.AppendElement(aUpdate); + CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, Move(updates)); + } + class Updates : public nsRunnable + { + public: + Updates(GMPStorageTest* aRunner, nsTArray&& aUpdates) + : mRunner(aRunner), + mUpdates(aUpdates) + { + } + + NS_IMETHOD Run() + { + for (auto& update : mUpdates) { + mRunner->Update(update); + } + return NS_OK; + } + + private: + nsRefPtr mRunner; + nsTArray mUpdates; + }; + void CreateDecryptor(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPBMode, + nsTArray&& aUpdates) { + nsCOMPtr updates(new Updates(this, Move(aUpdates))); + CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, updates); + } + void CreateDecryptor(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + bool aInPBMode, + nsIRunnable* aContinuation) { + nsRefPtr service = + GeckoMediaPluginService::GetGeckoMediaPluginService(); EXPECT_TRUE(service); mNodeId = GetNodeId(aOrigin, aTopLevelOrigin, aInPBMode); @@ -450,32 +687,30 @@ class GMPStorageTest : public GMPDecryptorProxyCallback nsTArray tags; tags.AppendElement(NS_LITERAL_CSTRING("fake")); - nsresult rv = service->GetGMPDecryptor(&tags, mNodeId, &mDecryptor); + UniquePtr callback( + new CreateDecryptorDone(this, aContinuation)); + nsresult rv = + service->GetGMPDecryptor(&tags, mNodeId, Move(callback)); EXPECT_TRUE(NS_SUCCEEDED(rv)); - EXPECT_TRUE(!!mDecryptor); - - if (mDecryptor) { - mDecryptor->Init(this); - } } void TestBasicStorage() { AssertIsOnGMPThread(); EXPECT_TRUE(IsGMPStorageIsEmpty()); - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); - - CreateDecryptor(NS_LITERAL_STRING("example1.com"), - NS_LITERAL_STRING("example2.com"), - false); + nsRefPtr service = + GeckoMediaPluginService::GetGeckoMediaPluginService(); // Send a message to the fake GMP for it to run its own tests internally. // It sends us a "test-storage complete" message when its passed, or // some other message if its tests fail. Expect(NS_LITERAL_CSTRING("test-storage complete"), NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("test-storage")); + + CreateDecryptor(NS_LITERAL_STRING("example1.com"), + NS_LITERAL_STRING("example2.com"), + false, + NS_LITERAL_CSTRING("test-storage")); } /** @@ -489,28 +724,28 @@ class GMPStorageTest : public GMPDecryptorProxyCallback EXPECT_TRUE(IsGMPStorageIsEmpty()); // Generate storage data for some site. - CreateDecryptor(NS_LITERAL_STRING("example1.com"), - NS_LITERAL_STRING("example2.com"), - false); - nsCOMPtr r = NS_NewRunnableMethod( this, &GMPStorageTest::TestForgetThisSite_AnotherSite); Expect(NS_LITERAL_CSTRING("test-storage complete"), r); - Update(NS_LITERAL_CSTRING("test-storage")); + + CreateDecryptor(NS_LITERAL_STRING("example1.com"), + NS_LITERAL_STRING("example2.com"), + false, + NS_LITERAL_CSTRING("test-storage")); } void TestForgetThisSite_AnotherSite() { Shutdown(); // Generate storage data for another site. - CreateDecryptor(NS_LITERAL_STRING("example3.com"), - NS_LITERAL_STRING("example4.com"), - false); - nsCOMPtr r = NS_NewRunnableMethod( this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo); Expect(NS_LITERAL_CSTRING("test-storage complete"), r); - Update(NS_LITERAL_CSTRING("test-storage")); + + CreateDecryptor(NS_LITERAL_STRING("example3.com"), + NS_LITERAL_STRING("example4.com"), + false, + NS_LITERAL_CSTRING("test-storage")); } struct NodeInfo { @@ -545,8 +780,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback } void TestForgetThisSite_Forget(nsAutoPtr aSiteInfo) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); + nsRefPtr service = + GeckoMediaPluginServiceParent::GetSingleton(); service->ForgetThisSite(NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget)); nsCOMPtr thread; @@ -622,16 +857,15 @@ class GMPStorageTest : public GMPDecryptorProxyCallback EXPECT_TRUE(IsGMPStorageIsEmpty()); // Generate storage data for some site. - CreateDecryptor(NS_LITERAL_STRING("example1.com"), - NS_LITERAL_STRING("example2.com"), - false); - nsCOMPtr r = NS_NewRunnableMethod( this, &GMPStorageTest::TestClearRecentHistory1_Clear); Expect(NS_LITERAL_CSTRING("test-storage complete"), r); - Update(NS_LITERAL_CSTRING("test-storage")); - } + CreateDecryptor(NS_LITERAL_STRING("example1.com"), + NS_LITERAL_STRING("example2.com"), + false, + NS_LITERAL_CSTRING("test-storage")); +} /** * 1. Generate some storage data. @@ -645,15 +879,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback EXPECT_TRUE(IsGMPStorageIsEmpty()); // Generate storage data for some site. - CreateDecryptor(NS_LITERAL_STRING("example1.com"), - NS_LITERAL_STRING("example2.com"), - false); - nsCOMPtr r = NS_NewRunnableMethod( this, &GMPStorageTest::TestClearRecentHistory2_Clear); Expect(NS_LITERAL_CSTRING("test-storage complete"), r); - Update(NS_LITERAL_CSTRING("test-storage")); + CreateDecryptor(NS_LITERAL_STRING("example1.com"), + NS_LITERAL_STRING("example2.com"), + false, + NS_LITERAL_CSTRING("test-storage")); } /** @@ -668,15 +901,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback EXPECT_TRUE(IsGMPStorageIsEmpty()); // Generate storage data for some site. - CreateDecryptor(NS_LITERAL_STRING("example1.com"), - NS_LITERAL_STRING("example2.com"), - false); - nsCOMPtr r = NS_NewRunnableMethod( this, &GMPStorageTest::TestClearRecentHistory3_Clear); Expect(NS_LITERAL_CSTRING("test-storage complete"), r); - Update(NS_LITERAL_CSTRING("test-storage")); + CreateDecryptor(NS_LITERAL_STRING("example1.com"), + NS_LITERAL_STRING("example2.com"), + false, + NS_LITERAL_CSTRING("test-storage")); } class MaxMTimeFinder { @@ -774,12 +1006,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback void TestCrossOriginStorage() { EXPECT_TRUE(!mDecryptor); - // Open decryptor on one, origin, write a record, and test that that - // record can't be read on another origin. - CreateDecryptor(NS_LITERAL_STRING("example3.com"), - NS_LITERAL_STRING("example4.com"), - false); - // Send the decryptor the message "store recordid $time" // Wait for the decrytor to send us "stored recordid $time" auto t = time(0); @@ -790,7 +1016,13 @@ class GMPStorageTest : public GMPDecryptorProxyCallback nsCString update("store crossOriginTestRecordId "); update.AppendInt((int64_t)t); - Update(update); + + // Open decryptor on one, origin, write a record, and test that that + // record can't be read on another origin. + CreateDecryptor(NS_LITERAL_STRING("example3.com"), + NS_LITERAL_STRING("example4.com"), + false, + update); } void TestCrossOriginStorage_RecordStoredContinuation() { @@ -798,87 +1030,102 @@ class GMPStorageTest : public GMPDecryptorProxyCallback // and try to read the record. Shutdown(); - CreateDecryptor(NS_LITERAL_STRING("example5.com"), - NS_LITERAL_STRING("example6.com"), - false); - Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"), NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId")); + + CreateDecryptor(NS_LITERAL_STRING("example5.com"), + NS_LITERAL_STRING("example6.com"), + false, + NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId")); } void TestPBStorage() { - // Open decryptor on one, origin, write a record, close decryptor, - // open another, and test that record can be read, close decryptor, - // then send pb-last-context-closed notification, then open decryptor - // and check that it can't read that data; it should have been purged. - CreateDecryptor(NS_LITERAL_STRING("pb1.com"), - NS_LITERAL_STRING("pb2.com"), - true); - // Send the decryptor the message "store recordid $time" // Wait for the decrytor to send us "stored recordid $time" nsCString response("stored pbdata test-pb-data"); Expect(response, NS_NewRunnableMethod(this, &GMPStorageTest::TestPBStorage_RecordStoredContinuation)); - nsCString update("store pbdata test-pb-data"); - Update(update); + // Open decryptor on one, origin, write a record, close decryptor, + // open another, and test that record can be read, close decryptor, + // then send pb-last-context-closed notification, then open decryptor + // and check that it can't read that data; it should have been purged. + CreateDecryptor(NS_LITERAL_STRING("pb1.com"), + NS_LITERAL_STRING("pb2.com"), + true, + NS_LITERAL_CSTRING("store pbdata test-pb-data")); } void TestPBStorage_RecordStoredContinuation() { Shutdown(); - CreateDecryptor(NS_LITERAL_STRING("pb1.com"), - NS_LITERAL_STRING("pb2.com"), - true); - Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"), NS_NewRunnableMethod(this, &GMPStorageTest::TestPBStorage_RecordRetrievedContinuation)); - Update(NS_LITERAL_CSTRING("retrieve pbdata")); + + CreateDecryptor(NS_LITERAL_STRING("pb1.com"), + NS_LITERAL_STRING("pb2.com"), + true, + NS_LITERAL_CSTRING("retrieve pbdata")); } void TestPBStorage_RecordRetrievedContinuation() { Shutdown(); SimulatePBModeExit(); - CreateDecryptor(NS_LITERAL_STRING("pb1.com"), - NS_LITERAL_STRING("pb2.com"), - true); - Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"), NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("retrieve pbdata")); + + CreateDecryptor(NS_LITERAL_STRING("pb1.com"), + NS_LITERAL_STRING("pb2.com"), + true, + NS_LITERAL_CSTRING("retrieve pbdata")); + } + + void NextAsyncShutdownTimeoutTest(nsIRunnable* aContinuation) + { + if (mDecryptor) { + Update(NS_LITERAL_CSTRING("shutdown-mode timeout")); + Shutdown(); + } + nsCOMPtr thread(GetGMPThread()); + thread->Dispatch(aContinuation, NS_DISPATCH_NORMAL); } void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1, - const nsAString& aOrigin2) { - CreateDecryptor(aOrigin1, aOrigin2, false); - Update(NS_LITERAL_CSTRING("shutdown-mode timeout")); - Shutdown(); + const nsAString& aOrigin2, + void (GMPStorageTest::*aCallback)()) { + nsCOMPtr continuation( + NS_NewRunnableMethodWithArg>( + this, + &GMPStorageTest::NextAsyncShutdownTimeoutTest, + NS_NewRunnableMethod(this, aCallback))); + + CreateDecryptor(aOrigin1, aOrigin2, false, continuation); } void TestAsyncShutdownTimeout() { // Create decryptors that timeout in their async shutdown. // If the gtest hangs on shutdown, test fails! CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"), - NS_LITERAL_STRING("example8.com")); + NS_LITERAL_STRING("example8.com"), + &GMPStorageTest::TestAsyncShutdownTimeout2); + }; + + void TestAsyncShutdownTimeout2() { CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"), - NS_LITERAL_STRING("example10.com")); + NS_LITERAL_STRING("example10.com"), + &GMPStorageTest::TestAsyncShutdownTimeout3); + }; + + void TestAsyncShutdownTimeout3() { CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"), - NS_LITERAL_STRING("example12.com")); - SetFinished(); + NS_LITERAL_STRING("example12.com"), + &GMPStorageTest::SetFinished); }; void TestAsyncShutdownStorage() { - // Test that a GMP can write to storage during shutdown, and retrieve - // that written data in a subsequent session. - CreateDecryptor(NS_LITERAL_STRING("example13.com"), - NS_LITERAL_STRING("example14.com"), - false); - // Instruct the GMP to write a token (the current timestamp, so it's // unique) during async shutdown, then shutdown the plugin, re-create // it, and check that the token was successfully stored. @@ -895,7 +1142,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback Expect(response, NS_NewRunnableMethodWithArg(this, &GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token)); - Update(update); + // Test that a GMP can write to storage during shutdown, and retrieve + // that written data in a subsequent session. + CreateDecryptor(NS_LITERAL_STRING("example13.com"), + NS_LITERAL_STRING("example14.com"), + false, + update); } void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) { @@ -906,37 +1158,39 @@ class GMPStorageTest : public GMPDecryptorProxyCallback void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) { // Create a new instance of the plugin, retrieve the token written // during shutdown and verify it is correct. - CreateDecryptor(NS_LITERAL_STRING("example13.com"), - NS_LITERAL_STRING("example14.com"), - false); nsCString response("retrieved shutdown-token "); response.Append(aToken); Expect(response, NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("retrieve-shutdown-token")); + + CreateDecryptor(NS_LITERAL_STRING("example13.com"), + NS_LITERAL_STRING("example14.com"), + false, + NS_LITERAL_CSTRING("retrieve-shutdown-token")); } #if defined(XP_WIN) void TestOutputProtection() { Shutdown(); - CreateDecryptor(NS_LITERAL_STRING("example15.com"), - NS_LITERAL_STRING("example16.com"), - false); - Expect(NS_LITERAL_CSTRING("OP tests completed"), NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("test-op-apis")); + + CreateDecryptor(NS_LITERAL_STRING("example15.com"), + NS_LITERAL_STRING("example16.com"), + false, + NS_LITERAL_CSTRING("test-op-apis")); } #endif void TestPluginVoucher() { - CreateDecryptor(NS_LITERAL_STRING("example17.com"), - NS_LITERAL_STRING("example18.com"), - false); Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"), NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); - Update(NS_LITERAL_CSTRING("retrieve-plugin-voucher")); + + CreateDecryptor(NS_LITERAL_STRING("example17.com"), + NS_LITERAL_STRING("example18.com"), + false, + NS_LITERAL_CSTRING("retrieve-plugin-voucher")); } void TestGetRecordNamesInMemoryStorage() { @@ -953,12 +1207,9 @@ class GMPStorageTest : public GMPDecryptorProxyCallback } void TestGetRecordNames(bool aPrivateBrowsing) { - CreateDecryptor(NS_LITERAL_STRING("foo.com"), - NS_LITERAL_STRING("bar.com"), - aPrivateBrowsing); - // Create a number of records of different names. const uint32_t num = 100; + nsTArray updates(num); for (uint32_t i = 0; i < num; i++) { nsAutoCString response; response.AppendLiteral("stored data"); @@ -972,7 +1223,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback mRecordNames.AppendLiteral("data"); AppendIntPadded(mRecordNames, i); - nsAutoCString update; + nsCString& update = *updates.AppendElement(); update.AppendLiteral("store data"); AppendIntPadded(update, i); update.AppendLiteral(" test-data"); @@ -984,8 +1235,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback NS_NewRunnableMethod(this, &GMPStorageTest::TestGetRecordNames_QueryNames); } Expect(response, continuation); - Update(update); } + + CreateDecryptor(NS_LITERAL_STRING("foo.com"), + NS_LITERAL_STRING("bar.com"), + aPrivateBrowsing, + Move(updates)); } void TestGetRecordNames_QueryNames() { @@ -1025,10 +1280,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE); MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH - CreateDecryptor(NS_LITERAL_STRING("fuz.com"), - NS_LITERAL_STRING("baz.com"), - false); - nsCString response("stored "); response.Append(longRecordName); response.AppendLiteral(" "); @@ -1039,7 +1290,10 @@ class GMPStorageTest : public GMPDecryptorProxyCallback update.Append(longRecordName); update.AppendLiteral(" "); update.Append(data); - Update(update); + CreateDecryptor(NS_LITERAL_STRING("fuz.com"), + NS_LITERAL_STRING("baz.com"), + false, + update); } void Expect(const nsCString& aMessage, nsIRunnable* aContinuation) { @@ -1146,83 +1400,90 @@ private: }; void -GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)()) +GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&)) { - nsRefPtr service = - GoannaMediaPluginService::GetGoannaMediaPluginService(); - nsCOMPtr thread; + nsCOMPtr thread(GetGMPThread()); - service->GetThread(getter_AddRefs(thread)); - thread->Dispatch(NS_NewRunnableMethod(this, aTestMethod), NS_DISPATCH_SYNC); + GMPTestMonitor monitor; + thread->Dispatch(NS_NewRunnableMethodWithArg(this, + aTestMethod, + monitor), + NS_DISPATCH_NORMAL); + monitor.AwaitFinished(); } -TEST(GoannaMediaPlugins, GMPTestCodec) { +TEST(GeckoMediaPlugins, GMPTestCodec) { nsRefPtr runner = new GMPTestRunner(); - runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec); + runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec1); + runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec2); + runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec3); } -TEST(GoannaMediaPlugins, GMPCrossOrigin) { +TEST(GeckoMediaPlugins, GMPCrossOrigin) { nsRefPtr runner = new GMPTestRunner(); - runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin); + runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin1); + runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin2); + runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin3); + runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin4); } -TEST(GoannaMediaPlugins, GMPStorageGetNodeId) { +TEST(GeckoMediaPlugins, GMPStorageGetNodeId) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestGetNodeId); } -TEST(GoannaMediaPlugins, GMPStorageBasic) { +TEST(GeckoMediaPlugins, GMPStorageBasic) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestBasicStorage); } -TEST(GoannaMediaPlugins, GMPStorageForgetThisSite) { +TEST(GeckoMediaPlugins, GMPStorageForgetThisSite) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestForgetThisSite); } -TEST(GoannaMediaPlugins, GMPStorageClearRecentHistory1) { +TEST(GeckoMediaPlugins, GMPStorageClearRecentHistory1) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestClearRecentHistory1); } -TEST(GoannaMediaPlugins, GMPStorageClearRecentHistory2) { +TEST(GeckoMediaPlugins, GMPStorageClearRecentHistory2) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestClearRecentHistory2); } -TEST(GoannaMediaPlugins, GMPStorageClearRecentHistory3) { +TEST(GeckoMediaPlugins, GMPStorageClearRecentHistory3) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestClearRecentHistory3); } -TEST(GoannaMediaPlugins, GMPStorageCrossOrigin) { +TEST(GeckoMediaPlugins, GMPStorageCrossOrigin) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestCrossOriginStorage); } -TEST(GoannaMediaPlugins, GMPStoragePrivateBrowsing) { +TEST(GeckoMediaPlugins, GMPStoragePrivateBrowsing) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestPBStorage); } -TEST(GoannaMediaPlugins, GMPStorageAsyncShutdownTimeout) { +TEST(GeckoMediaPlugins, GMPStorageAsyncShutdownTimeout) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestAsyncShutdownTimeout); } -TEST(GoannaMediaPlugins, GMPStorageAsyncShutdownStorage) { +TEST(GeckoMediaPlugins, GMPStorageAsyncShutdownStorage) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestAsyncShutdownStorage); } -TEST(GoannaMediaPlugins, GMPPluginVoucher) { +TEST(GeckoMediaPlugins, GMPPluginVoucher) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestPluginVoucher); } #if defined(XP_WIN) -TEST(GoannaMediaPlugins, GMPOutputProtection) { +TEST(GeckoMediaPlugins, GMPOutputProtection) { // Output Protection is not available pre-Vista. if (!IsVistaOrLater()) { return; @@ -1233,17 +1494,17 @@ TEST(GoannaMediaPlugins, GMPOutputProtection) { } #endif -TEST(GoannaMediaPlugins, GMPStorageGetRecordNamesInMemoryStorage) { +TEST(GeckoMediaPlugins, GMPStorageGetRecordNamesInMemoryStorage) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestGetRecordNamesInMemoryStorage); } -TEST(GoannaMediaPlugins, GMPStorageGetRecordNamesPersistentStorage) { +TEST(GeckoMediaPlugins, GMPStorageGetRecordNamesPersistentStorage) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::GetRecordNamesPersistentStorage); } -TEST(GoannaMediaPlugins, GMPStorageLongRecordNames) { +TEST(GeckoMediaPlugins, GMPStorageLongRecordNames) { nsRefPtr runner = new GMPStorageTest(); runner->DoTest(&GMPStorageTest::TestLongRecordNames); } diff --git a/dom/media/mediasource/ResourceQueue.cpp b/dom/media/mediasource/ResourceQueue.cpp new file mode 100644 index 0000000000..778bbf905d --- /dev/null +++ b/dom/media/mediasource/ResourceQueue.cpp @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsDeque.h" +#include "MediaData.h" +#include "prlog.h" + +#ifdef PR_LOGGING +extern PRLogModuleInfo* GetSourceBufferResourceLog(); + +/* Polyfill __func__ on MSVC to pass to the log. */ +#ifdef _MSC_VER +#define __func__ __FUNCTION__ +#endif + +#define SBR_DEBUG(arg, ...) PR_LOG(GetSourceBufferResourceLog(), PR_LOG_DEBUG, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) +#define SBR_DEBUGV(arg, ...) PR_LOG(GetSourceBufferResourceLog(), PR_LOG_DEBUG+1, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) +#else +#define SBR_DEBUG(...) +#define SBR_DEBUGV(...) +#endif + +namespace mozilla { + +ResourceItem::ResourceItem(MediaLargeByteBuffer* aData) + : mData(aData) +{ +} + +size_t +ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +{ + // size including this + size_t size = aMallocSizeOf(this); + + // size excluding this + size += mData->SizeOfExcludingThis(aMallocSizeOf); + + return size; +} + +class ResourceQueueDeallocator : public nsDequeFunctor { + virtual void* operator() (void* aObject) { + delete static_cast(aObject); + return nullptr; + } +}; + +ResourceQueue::ResourceQueue() + : nsDeque(new ResourceQueueDeallocator()) + , mLogicalLength(0) + , mOffset(0) +{ +} + +uint64_t +ResourceQueue::GetOffset() +{ + return mOffset; +} + +uint64_t +ResourceQueue::GetLength() +{ + return mLogicalLength; +} + +void +ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) +{ + uint32_t offset = 0; + uint32_t start = GetAtOffset(aOffset, &offset); + uint32_t end = std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, uint32_t(GetSize())); + for (uint32_t i = start; i < end; ++i) { + ResourceItem* item = ResourceAt(i); + uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset)); + if (bytes != 0) { + memcpy(aDest, &(*item->mData)[offset], bytes); + offset = 0; + aCount -= bytes; + aDest += bytes; + } + } +} + +void +ResourceQueue::AppendItem(MediaLargeByteBuffer* aData) +{ + mLogicalLength += aData->Length(); + Push(new ResourceItem(aData)); +} + +uint32_t +ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict) +{ + SBR_DEBUG("Evict(aOffset=%llu, aSizeToEvict=%u)", + aOffset, aSizeToEvict); + return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict)); +} + +uint32_t ResourceQueue::EvictBefore(uint64_t aOffset) +{ + SBR_DEBUG("EvictBefore(%llu)", aOffset); + uint32_t evicted = 0; + while (ResourceItem* item = ResourceAt(0)) { + SBR_DEBUG("item=%p length=%d offset=%llu", + item, item->mData->Length(), mOffset); + if (item->mData->Length() + mOffset >= aOffset) { + if (aOffset <= mOffset) { + break; + } + uint32_t offset = aOffset - mOffset; + mOffset += offset; + evicted += offset; + nsRefPtr data = new MediaLargeByteBuffer; + data->AppendElements(item->mData->Elements() + offset, + item->mData->Length() - offset); + item->mData = data; + break; + } + mOffset += item->mData->Length(); + evicted += item->mData->Length(); + delete PopFront(); + } + return evicted; +} + +uint32_t +ResourceQueue::EvictAll() +{ + SBR_DEBUG("EvictAll()"); + uint32_t evicted = 0; + while (ResourceItem* item = ResourceAt(0)) { + SBR_DEBUG("item=%p length=%d offset=%llu", + item, item->mData->Length(), mOffset); + mOffset += item->mData->Length(); + evicted += item->mData->Length(); + delete PopFront(); + } + return evicted; +} + +size_t +ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + // Calculate the size of the internal deque. + size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf); + + // Sum the ResourceItems. + for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { + const ResourceItem* item = ResourceAt(i); + size += item->SizeOfIncludingThis(aMallocSizeOf); + } + + return size; +} + +#if defined(DEBUG) +void +ResourceQueue::Dump(const char* aPath) +{ + for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { + ResourceItem* item = ResourceAt(i); + + char buf[255]; + PR_snprintf(buf, sizeof(buf), "%s/%08u.bin", aPath, i); + FILE* fp = fopen(buf, "wb"); + if (!fp) { + return; + } + fwrite(item->mData->Elements(), item->mData->Length(), 1, fp); + fclose(fp); + } +} +#endif + +ResourceItem* +ResourceQueue::ResourceAt(uint32_t aIndex) const +{ + return static_cast(ObjectAt(aIndex)); +} + +uint32_t +ResourceQueue::GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) +{ + MOZ_RELEASE_ASSERT(aOffset >= mOffset); + uint64_t offset = mOffset; + for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { + ResourceItem* item = ResourceAt(i); + // If the item contains the start of the offset we want to + // break out of the loop. + if (item->mData->Length() + offset > aOffset) { + if (aResourceOffset) { + *aResourceOffset = aOffset - offset; + } + return i; + } + offset += item->mData->Length(); + } + return GetSize(); +} + +ResourceItem* +ResourceQueue::PopFront() +{ + return static_cast(nsDeque::PopFront()); +} + +#undef SBR_DEBUG +#undef SBR_DEBUGV + +} // namespace mozilla diff --git a/dom/media/mediasource/ResourceQueue.h b/dom/media/mediasource/ResourceQueue.h index 237bac1b2d..2690a91c8a 100644 --- a/dom/media/mediasource/ResourceQueue.h +++ b/dom/media/mediasource/ResourceQueue.h @@ -7,25 +7,8 @@ #ifndef MOZILLA_RESOURCEQUEUE_H_ #define MOZILLA_RESOURCEQUEUE_H_ -#include #include "nsDeque.h" #include "MediaData.h" -#include "prlog.h" - -#ifdef PR_LOGGING -extern PRLogModuleInfo* GetSourceBufferResourceLog(); - -/* Polyfill __func__ on MSVC to pass to the log. */ -#ifdef _MSC_VER -#define __func__ __FUNCTION__ -#endif - -#define SBR_DEBUG(arg, ...) PR_LOG(GetSourceBufferResourceLog(), PR_LOG_DEBUG, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) -#define SBR_DEBUGV(arg, ...) PR_LOG(GetSourceBufferResourceLog(), PR_LOG_DEBUG+1, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) -#else -#define SBR_DEBUG(...) -#define SBR_DEBUGV(...) -#endif namespace mozilla { @@ -41,181 +24,52 @@ namespace mozilla { // timepoint. struct ResourceItem { - explicit ResourceItem(MediaLargeByteBuffer* aData) - : mData(aData) - { - } - - size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { - // size including this - size_t size = aMallocSizeOf(this); - - // size excluding this - size += mData->SizeOfExcludingThis(aMallocSizeOf); - - return size; - } - + explicit ResourceItem(MediaLargeByteBuffer* aData); + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; nsRefPtr mData; }; -class ResourceQueueDeallocator : public nsDequeFunctor { - virtual void* operator() (void* aObject) { - delete static_cast(aObject); - return nullptr; - } -}; - class ResourceQueue : private nsDeque { public: - ResourceQueue() - : nsDeque(new ResourceQueueDeallocator()) - , mLogicalLength(0) - , mOffset(0) - { - } + ResourceQueue(); // Returns the logical byte offset of the start of the data. - uint64_t GetOffset() { - return mOffset; - } + uint64_t GetOffset(); // Returns the length of all items in the queue plus the offset. // This is the logical length of the resource. - uint64_t GetLength() { - return mLogicalLength; - } + uint64_t GetLength(); // Copies aCount bytes from aOffset in the queue into aDest. - void CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) { - uint32_t offset = 0; - uint32_t start = GetAtOffset(aOffset, &offset); - uint32_t end = std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, uint32_t(GetSize())); - for (uint32_t i = start; i < end; ++i) { - ResourceItem* item = ResourceAt(i); - uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset)); - if (bytes != 0) { - memcpy(aDest, &(*item->mData)[offset], bytes); - offset = 0; - aCount -= bytes; - aDest += bytes; - } - } - } + void CopyData(uint64_t aOffset, uint32_t aCount, char* aDest); - void AppendItem(MediaLargeByteBuffer* aData) { - mLogicalLength += aData->Length(); - Push(new ResourceItem(aData)); - } + void AppendItem(MediaLargeByteBuffer* aData); // Tries to evict at least aSizeToEvict from the queue up until // aOffset. Returns amount evicted. - uint32_t Evict(uint64_t aOffset, uint32_t aSizeToEvict) { - SBR_DEBUG("Evict(aOffset=%llu, aSizeToEvict=%u)", - aOffset, aSizeToEvict); - return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict)); - } + uint32_t Evict(uint64_t aOffset, uint32_t aSizeToEvict); - uint32_t EvictBefore(uint64_t aOffset) { - SBR_DEBUG("EvictBefore(%llu)", aOffset); - uint32_t evicted = 0; - while (ResourceItem* item = ResourceAt(0)) { - SBR_DEBUG("item=%p length=%d offset=%llu", - item, item->mData->Length(), mOffset); - if (item->mData->Length() + mOffset >= aOffset) { - if (aOffset <= mOffset) { - break; - } - uint32_t offset = aOffset - mOffset; - mOffset += offset; - evicted += offset; - nsRefPtr data = new MediaLargeByteBuffer; - data->AppendElements(item->mData->Elements() + offset, - item->mData->Length() - offset); - item->mData = data; - break; - } - mOffset += item->mData->Length(); - evicted += item->mData->Length(); - delete PopFront(); - } - return evicted; - } + uint32_t EvictBefore(uint64_t aOffset); - uint32_t EvictAll() { - SBR_DEBUG("EvictAll()"); - uint32_t evicted = 0; - while (ResourceItem* item = ResourceAt(0)) { - SBR_DEBUG("item=%p length=%d offset=%llu", - item, item->mData->Length(), mOffset); - mOffset += item->mData->Length(); - evicted += item->mData->Length(); - delete PopFront(); - } - return evicted; - } + uint32_t EvictAll(); - size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { - // Calculate the size of the internal deque. - size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf); - - // Sum the ResourceItems. - for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { - const ResourceItem* item = ResourceAt(i); - size += item->SizeOfIncludingThis(aMallocSizeOf); - } - - return size; - } + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; #if defined(DEBUG) - void Dump(const char* aPath) { - for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { - ResourceItem* item = ResourceAt(i); - - char buf[255]; - PR_snprintf(buf, sizeof(buf), "%s/%08u.bin", aPath, i); - FILE* fp = fopen(buf, "wb"); - if (!fp) { - return; - } - fwrite(item->mData->Elements(), item->mData->Length(), 1, fp); - fclose(fp); - } - } + void Dump(const char* aPath); #endif private: - ResourceItem* ResourceAt(uint32_t aIndex) const { - return static_cast(ObjectAt(aIndex)); - } + ResourceItem* ResourceAt(uint32_t aIndex) const; // Returns the index of the resource that contains the given // logical offset. aResourceOffset will contain the offset into // the resource at the given index returned if it is not null. If // no such resource exists, returns GetSize() and aOffset is // untouched. - uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) { - MOZ_RELEASE_ASSERT(aOffset >= mOffset); - uint64_t offset = mOffset; - for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { - ResourceItem* item = ResourceAt(i); - // If the item contains the start of the offset we want to - // break out of the loop. - if (item->mData->Length() + offset > aOffset) { - if (aResourceOffset) { - *aResourceOffset = aOffset - offset; - } - return i; - } - offset += item->mData->Length(); - } - return GetSize(); - } + uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset); - ResourceItem* PopFront() { - return static_cast(nsDeque::PopFront()); - } + ResourceItem* PopFront(); // Logical length of the resource. uint64_t mLogicalLength; @@ -224,9 +78,6 @@ private: uint64_t mOffset; }; -#undef SBR_DEBUG -#undef SBR_DEBUGV - } // namespace mozilla #endif /* MOZILLA_RESOURCEQUEUE_H_ */ diff --git a/dom/media/mediasource/moz.build b/dom/media/mediasource/moz.build index ec87898fb3..394dea31e4 100644 --- a/dom/media/mediasource/moz.build +++ b/dom/media/mediasource/moz.build @@ -26,6 +26,7 @@ UNIFIED_SOURCES += [ 'MediaSourceDemuxer.cpp', 'MediaSourceReader.cpp', 'MediaSourceUtils.cpp', + 'ResourceQueue.cpp', 'SourceBuffer.cpp', 'SourceBufferContentManager.cpp', 'SourceBufferDecoder.cpp', diff --git a/dom/media/nsIMediaManager.idl b/dom/media/nsIMediaManager.idl index 020cc511f3..aa947a8fa2 100644 --- a/dom/media/nsIMediaManager.idl +++ b/dom/media/nsIMediaManager.idl @@ -12,7 +12,7 @@ interface nsIDOMWindow; #define MEDIAMANAGERSERVICE_CONTRACTID "@mozilla.org/mediaManagerService;1" %} -[scriptable, builtinclass, uuid(9b10661f-77b3-47f7-a8de-ee58daaff5d2)] +[scriptable, builtinclass, uuid(24b23e01-33fd-401f-ba25-6e52658750b0)] interface nsIMediaManagerService : nsISupports { /* return a array of inner windows that have active captures */ @@ -22,4 +22,8 @@ interface nsIMediaManagerService : nsISupports void mediaCaptureWindowState(in nsIDOMWindow aWindow, out boolean aVideo, out boolean aAudio, [optional] out boolean aScreenShare, [optional] out boolean aWindowShare, [optional] out boolean aAppShare, [optional] out boolean aBrowserShare); + + /* Clear per-orgin list of persistent DeviceIds stored for enumerateDevices + sinceTime is milliseconds since 1 January 1970 00:00:00 UTC. 0 = clear all */ + void sanitizeDeviceIds(in long long sinceWhen); }; diff --git a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp index d402122634..6ae0a21bce 100644 --- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp +++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPAudioDecoder.h" +#include "nsServiceManagerUtils.h" #include "MediaInfo.h" namespace mozilla { @@ -133,6 +134,39 @@ GMPAudioDecoder::GetNodeId() return NS_LITERAL_CSTRING(""); } +void +GMPAudioDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone) +{ + MOZ_ASSERT(IsOnGMPThread()); + + nsTArray tags; + InitTags(tags); + UniquePtr callback( + new GMPInitDoneCallback(this, aInitDone)); + if (NS_FAILED(mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), Move(callback)))) { + aInitDone->Dispatch(); + } +} + +void +GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP) +{ + MOZ_ASSERT(aGMP); + nsTArray codecSpecific; + codecSpecific.AppendElements(mConfig.mCodecSpecificConfig->Elements(), + mConfig.mCodecSpecificConfig->Length()); + + nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC, + mConfig.mChannels, + mConfig.mBitDepth, + mConfig.mRate, + codecSpecific, + mAdapter); + if (NS_SUCCEEDED(rv)) { + mGMP = aGMP; + } +} + nsresult GMPAudioDecoder::Init() { @@ -141,25 +175,20 @@ GMPAudioDecoder::Init() mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); MOZ_ASSERT(mMPS); - nsTArray tags; - InitTags(tags); - nsresult rv = mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), &mGMP); - NS_ENSURE_SUCCESS(rv, rv); - MOZ_ASSERT(mGMP); + nsCOMPtr gmpThread = NS_GetCurrentThread(); - nsTArray codecSpecific; - codecSpecific.AppendElements(mConfig.mCodecSpecificConfig->Elements(), - mConfig.mCodecSpecificConfig->Length()); + nsRefPtr initDone(new GMPInitDoneRunnable()); + gmpThread->Dispatch( + NS_NewRunnableMethodWithArg(this, + &GMPAudioDecoder::GetGMPAPI, + initDone), + NS_DISPATCH_NORMAL); - rv = mGMP->InitDecode(kGMPAudioCodecAAC, - mConfig.mChannels, - mConfig.mBitDepth, - mConfig.mRate, - codecSpecific, - mAdapter); - NS_ENSURE_SUCCESS(rv, rv); + while (!initDone->IsDone()) { + NS_ProcessNextEvent(gmpThread, true); + } - return NS_OK; + return mGMP ? NS_OK : NS_ERROR_FAILURE; } nsresult diff --git a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h index 68d70b09bd..413d6a1a14 100644 --- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h +++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h @@ -80,6 +80,63 @@ protected: virtual nsCString GetNodeId(); private: + class GMPInitDoneRunnable : public nsRunnable + { + public: + GMPInitDoneRunnable() + : mInitDone(false), + mThread(do_GetCurrentThread()) + { + } + + NS_IMETHOD Run() + { + mInitDone = true; + return NS_OK; + } + + void Dispatch() + { + mThread->Dispatch(this, NS_DISPATCH_NORMAL); + } + + bool IsDone() + { + MOZ_ASSERT(nsCOMPtr(do_GetCurrentThread()) == mThread); + return mInitDone; + } + + private: + bool mInitDone; + nsCOMPtr mThread; + }; + + void GetGMPAPI(GMPInitDoneRunnable* aInitDone); + + class GMPInitDoneCallback : public GetGMPAudioDecoderCallback + { + public: + GMPInitDoneCallback(GMPAudioDecoder* aDecoder, + GMPInitDoneRunnable* aGMPInitDone) + : mDecoder(aDecoder) + , mGMPInitDone(aGMPInitDone) + { + } + + virtual void Done(GMPAudioDecoderProxy* aGMP) + { + if (aGMP) { + mDecoder->GMPInitDone(aGMP); + } + mGMPInitDone->Dispatch(); + } + + private: + nsRefPtr mDecoder; + nsRefPtr mGMPInitDone; + }; + void GMPInitDone(GMPAudioDecoderProxy* aGMP); + const AudioInfo& mConfig; MediaDataDecoderCallbackProxy* mCallback; nsCOMPtr mMPS; diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp index 591a98b649..b315bc03a7 100644 --- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp +++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp @@ -158,29 +158,24 @@ GMPVideoDecoder::CreateFrame(MediaRawData* aSample) return frame; } -nsresult -GMPVideoDecoder::Init() +void +GMPVideoDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone) { MOZ_ASSERT(IsOnGMPThread()); - mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mMPS); - nsTArray tags; InitTags(tags); - nsresult rv = mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), &mHost, &mGMP); - NS_ENSURE_SUCCESS(rv, rv); - MOZ_ASSERT(mHost && mGMP); + UniquePtr callback( + new GMPInitDoneCallback(this, aInitDone)); + if (NS_FAILED(mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), Move(callback)))) { + aInitDone->Dispatch(); + } +} - // GMP implementations have interpreted the meaning of GMP_BufferLength32 - // differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as - // specified in the GMP API, where each buffer is prefixed by a 32-bit - // host-endian buffer length that includes the size of the buffer length - // field. Other existing GMPs currently expect GMP_BufferLength32 (when - // combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to - // 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian - // and do not include the length of the buffer length field. - mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264"); +void +GMPVideoDecoder::GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) +{ + MOZ_ASSERT(aHost && aGMP); GMPVideoCodec codec; memset(&codec, 0, sizeof(codec)); @@ -196,13 +191,48 @@ GMPVideoDecoder::Init() codecSpecific.AppendElements(mConfig.mExtraData->Elements(), mConfig.mExtraData->Length()); - rv = mGMP->InitDecode(codec, - codecSpecific, - mAdapter, - PR_GetNumberOfProcessors()); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = aGMP->InitDecode(codec, + codecSpecific, + mAdapter, + PR_GetNumberOfProcessors()); + if (NS_SUCCEEDED(rv)) { + mGMP = aGMP; + mHost = aHost; - return NS_OK; + // GMP implementations have interpreted the meaning of GMP_BufferLength32 + // differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as + // specified in the GMP API, where each buffer is prefixed by a 32-bit + // host-endian buffer length that includes the size of the buffer length + // field. Other existing GMPs currently expect GMP_BufferLength32 (when + // combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to + // 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian + // and do not include the length of the buffer length field. + mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264"); + } +} + +nsresult +GMPVideoDecoder::Init() +{ + MOZ_ASSERT(IsOnGMPThread()); + + mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); + MOZ_ASSERT(mMPS); + + nsCOMPtr gmpThread = NS_GetCurrentThread(); + + nsRefPtr initDone(new GMPInitDoneRunnable()); + gmpThread->Dispatch( + NS_NewRunnableMethodWithArg(this, + &GMPVideoDecoder::GetGMPAPI, + initDone), + NS_DISPATCH_NORMAL); + + while (!initDone->IsDone()) { + NS_ProcessNextEvent(gmpThread, true); + } + + return mGMP ? NS_OK : NS_ERROR_FAILURE; } nsresult diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h index bcb2248bc4..f14cad5aaf 100644 --- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h +++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h @@ -96,6 +96,63 @@ protected: virtual GMPUnique::Ptr CreateFrame(MediaRawData* aSample); private: + class GMPInitDoneRunnable : public nsRunnable + { + public: + GMPInitDoneRunnable() + : mInitDone(false), + mThread(do_GetCurrentThread()) + { + } + + NS_IMETHOD Run() + { + mInitDone = true; + return NS_OK; + } + + void Dispatch() + { + mThread->Dispatch(this, NS_DISPATCH_NORMAL); + } + + bool IsDone() + { + MOZ_ASSERT(nsCOMPtr(do_GetCurrentThread()) == mThread); + return mInitDone; + } + + private: + bool mInitDone; + nsCOMPtr mThread; + }; + + void GetGMPAPI(GMPInitDoneRunnable* aInitDone); + + class GMPInitDoneCallback : public GetGMPVideoDecoderCallback + { + public: + GMPInitDoneCallback(GMPVideoDecoder* aDecoder, + GMPInitDoneRunnable* aGMPInitDone) + : mDecoder(aDecoder) + , mGMPInitDone(aGMPInitDone) + { + } + + virtual void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) + { + if (aGMP) { + mDecoder->GMPInitDone(aGMP, aHost); + } + mGMPInitDone->Dispatch(); + } + + private: + nsRefPtr mDecoder; + nsRefPtr mGMPInitDone; + }; + void GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost); + const VideoInfo& mConfig; MediaDataDecoderCallbackProxy* mCallback; nsCOMPtr mMPS; diff --git a/dom/media/platforms/wmf/WMFDecoderModule.cpp b/dom/media/platforms/wmf/WMFDecoderModule.cpp index 5b4f7d82a6..5381f32d18 100644 --- a/dom/media/platforms/wmf/WMFDecoderModule.cpp +++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp @@ -14,6 +14,7 @@ #include "WMFMediaDataDecoder.h" #include "nsIWindowsRegKey.h" #include "nsComponentManagerUtils.h" +#include "nsServiceManagerUtils.h" #include "nsIGfxInfo.h" #include "GfxDriverInfo.h" #include "nsServiceManagerUtils.h" // for do_GetService diff --git a/dom/media/systemservices/MediaChild.cpp b/dom/media/systemservices/MediaChild.cpp new file mode 100644 index 0000000000..adca365fa3 --- /dev/null +++ b/dom/media/systemservices/MediaChild.cpp @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaChild.h" + +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "nsGlobalWindow.h" +#include "mozilla/MediaManager.h" +#include "prlog.h" + +#undef LOG +#if defined(PR_LOGGING) +PRLogModuleInfo *gMediaChildLog; +#define LOG(args) PR_LOG(gMediaChildLog, PR_LOG_DEBUG, args) +#else +#define LOG(args) +#endif + + +namespace mozilla { +namespace media { + +static Child* sChild; + +template void +ChildPledge::ActorCreated(PBackgroundChild* aActor) +{ + if (!sChild) { + // Create PMedia by sending a message to the parent + sChild = static_cast(aActor->SendPMediaConstructor()); + } + Run(sChild); +} + +template void +ChildPledge::ActorFailed() +{ + Pledge::Reject(NS_ERROR_UNEXPECTED); +} + +template NS_IMPL_ADDREF(ChildPledge) +template NS_IMPL_RELEASE(ChildPledge) +template NS_INTERFACE_MAP_BEGIN(ChildPledge) +NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback) +NS_INTERFACE_MAP_END + +already_AddRefed> +GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing) +{ + class Pledge : public ChildPledge + { + public: + explicit Pledge(const nsCString& aOrigin, bool aPrivateBrowsing) + : mOrigin(aOrigin), mPrivateBrowsing(aPrivateBrowsing) {} + private: + ~Pledge() {} + void Run(PMediaChild* aChild) + { + Child* child = static_cast(aChild); + + uint32_t id = child->AddRequestPledge(*this); + child->SendGetOriginKey(id, mOrigin, mPrivateBrowsing); + } + const nsCString mOrigin; + const bool mPrivateBrowsing; + }; + + nsRefPtr> p = new Pledge(aOrigin, aPrivateBrowsing); + nsCOMPtr cb = do_QueryObject(p); + bool ok = ipc::BackgroundChild::GetOrCreateForCurrentThread(cb); + MOZ_RELEASE_ASSERT(ok); + return p.forget(); +} + +already_AddRefed> +SanitizeOriginKeys(const uint64_t& aSinceWhen) +{ + class Pledge : public ChildPledge + { + public: + explicit Pledge(const uint64_t& aSinceWhen) : mSinceWhen(aSinceWhen) {} + private: + void Run(PMediaChild* aMedia) + { + aMedia->SendSanitizeOriginKeys(mSinceWhen); + mValue = true; + LOG(("SanitizeOriginKeys since %llu", mSinceWhen)); + Resolve(); + } + const uint64_t mSinceWhen; + }; + + nsRefPtr> p = new Pledge(aSinceWhen); + nsCOMPtr cb = do_QueryObject(p); + bool ok = ipc::BackgroundChild::GetOrCreateForCurrentThread(cb); + MOZ_RELEASE_ASSERT(ok); + return p.forget(); +} + +Child::Child() +{ +#if defined(PR_LOGGING) + if (!gMediaChildLog) { + gMediaChildLog = PR_NewLogModule("MediaChild"); + } +#endif + LOG(("media::Child: %p", this)); + MOZ_COUNT_CTOR(Child); +} + +Child::~Child() +{ + LOG(("~media::Child: %p", this)); + sChild = nullptr; + MOZ_COUNT_DTOR(Child); +} + +uint32_t Child::sRequestCounter = 0; + +uint32_t +Child::AddRequestPledge(ChildPledge& aPledge) +{ + uint32_t id = ++sRequestCounter; + nsRefPtr> ptr(&aPledge); + mRequestPledges.AppendElement(PledgeEntry(id, ptr)); + return id; +} + +already_AddRefed> +Child::RemoveRequestPledge(uint32_t aRequestId) +{ + for (PledgeEntry& entry : mRequestPledges) { + if (entry.first == aRequestId) { + nsRefPtr> ref; + ref.swap(entry.second); + mRequestPledges.RemoveElement(entry); + return ref.forget(); + } + } + MOZ_ASSERT_UNREACHABLE("Received response with no matching media::ChildPledge!"); + return nullptr; +} + +bool +Child::RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey) +{ + nsRefPtr> pledge = RemoveRequestPledge(aRequestId); + if (pledge) { + pledge->Resolve(aKey); + } + return true; +} + +PMediaChild* +AllocPMediaChild() +{ + Child* obj = new Child(); + obj->AddRef(); + return obj; +} + +bool +DeallocPMediaChild(media::PMediaChild *aActor) +{ + static_cast(aActor)->Release(); + return true; +} + +} +} diff --git a/dom/media/systemservices/MediaChild.h b/dom/media/systemservices/MediaChild.h new file mode 100644 index 0000000000..044f8a1596 --- /dev/null +++ b/dom/media/systemservices/MediaChild.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_MediaChild_h +#define mozilla_MediaChild_h + +#include "mozilla/dom/ContentChild.h" +#include "mozilla/media/PMediaChild.h" +#include "mozilla/media/PMediaParent.h" +#include "nsIIPCBackgroundChildCreateCallback.h" +#include "MediaUtils.h" + +namespace mozilla { +namespace media { + +// media::Child implements proxying to the chrome process for some media-related +// functions, for the moment just: +// +// GetOriginKey() - get a cookie-like persisted unique key for a given origin. +// SanitizeOriginKeys() - reset persisted unique keys. + +// GetOriginKey and SanitizeOriginKeys are asynchronous APIs that return pledges +// (promise-like objects) with the future value. Use pledge.Then(func) to access. + +class Child; + +template +class ChildPledge : public Pledge, + public nsIIPCBackgroundChildCreateCallback +{ + friend Child; + NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK + NS_DECL_ISUPPORTS +public: + explicit ChildPledge() {}; +protected: + virtual ~ChildPledge() {} + virtual void Run(PMediaChild* aMedia) = 0; +}; + +already_AddRefed> +GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing); + +already_AddRefed> +SanitizeOriginKeys(const uint64_t& aSinceWhen); + +class Child : public PMediaChild +{ + NS_INLINE_DECL_REFCOUNTING(Child) +public: + Child(); + + bool RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey); + + uint32_t AddRequestPledge(ChildPledge& aPledge); + already_AddRefed> RemoveRequestPledge(uint32_t aRequestId); +private: + virtual ~Child(); + + typedef std::pair>> PledgeEntry; + static uint32_t sRequestCounter; + nsTArray mRequestPledges; +}; + +PMediaChild* AllocPMediaChild(); +bool DeallocPMediaChild(PMediaChild *aActor); + +} // namespace media +} // namespace mozilla + +#endif // mozilla_MediaChild_h diff --git a/dom/media/systemservices/MediaParent.cpp b/dom/media/systemservices/MediaParent.cpp new file mode 100644 index 0000000000..44990a3029 --- /dev/null +++ b/dom/media/systemservices/MediaParent.cpp @@ -0,0 +1,457 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaParent.h" + +#include "mozilla/Base64.h" +#include + +#include "MediaUtils.h" +#include "MediaEngine.h" +#include "VideoUtils.h" +#include "nsThreadUtils.h" +#include "nsNetUtil.h" +#include "nsILineInputStream.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsISupportsImpl.h" +#include "prlog.h" + +#undef LOG +#if defined(PR_LOGGING) +PRLogModuleInfo *gMediaParentLog; +#define LOG(args) PR_LOG(gMediaParentLog, PR_LOG_DEBUG, args) +#else +#define LOG(args) +#endif + +// A file in the profile dir is used to persist mOriginKeys used to anonymize +// deviceIds to be unique per origin, to avoid them being supercookies. + +#define ORIGINKEYS_FILE "enumerate_devices.txt" +#define ORIGINKEYS_VERSION "1" + +namespace mozilla { +namespace media { + +static StaticMutex gMutex; +static ParentSingleton* sParentSingleton = nullptr; + +class ParentSingleton : public nsISupports +{ + NS_DECL_THREADSAFE_ISUPPORTS + + class OriginKey + { + public: + static const size_t DecodedLength = 18; + static const size_t EncodedLength = DecodedLength * 4 / 3; + + OriginKey(const nsACString& aKey, int64_t aSecondsStamp) + : mKey(aKey) + , mSecondsStamp(aSecondsStamp) {} + + nsCString mKey; // Base64 encoded. + int64_t mSecondsStamp; + }; + + class OriginKeysTable + { + public: + OriginKeysTable() {} + + nsresult + GetOriginKey(const nsACString& aOrigin, nsCString& result) + { + OriginKey* key; + if (!mKeys.Get(aOrigin, &key)) { + nsCString salt; // Make a new one + nsresult rv = GenerateRandomName(salt, key->EncodedLength); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + key = new OriginKey(salt, PR_Now() / PR_USEC_PER_SEC); + mKeys.Put(aOrigin, key); + } + result = key->mKey; + return NS_OK; + } + + static PLDHashOperator + HashCleaner(const nsACString& aOrigin, nsAutoPtr& aOriginKey, + void *aUserArg) + { + OriginKey* since = static_cast(aUserArg); + + LOG((((aOriginKey->mSecondsStamp >= since->mSecondsStamp)? + "%s: REMOVE %lld >= %lld" : + "%s: KEEP %lld < %lld"), + __FUNCTION__, aOriginKey->mSecondsStamp, since->mSecondsStamp)); + + return (aOriginKey->mSecondsStamp >= since->mSecondsStamp)? + PL_DHASH_REMOVE : PL_DHASH_NEXT; + } + + void Clear(int64_t aSinceWhen) + { + // Avoid int64_t* <-> void* casting offset + OriginKey since(nsCString(), aSinceWhen / PR_USEC_PER_SEC); + mKeys.Enumerate(HashCleaner, &since); + } + + protected: + nsClassHashtable mKeys; + }; + + class OriginKeysLoader : public OriginKeysTable + { + public: + OriginKeysLoader() + { + Load(); + } + + nsresult + GetOriginKey(const nsACString& aOrigin, nsCString& result) + { + auto before = mKeys.Count(); + OriginKeysTable::GetOriginKey(aOrigin, result); + if (mKeys.Count() != before) { + Save(); + } + return NS_OK; + } + + already_AddRefed + GetFile() + { + if (!mProfileDir) { + nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, + getter_AddRefs(mProfileDir)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return nullptr; + } + } + nsCOMPtr file; + nsresult rv = mProfileDir->Clone(getter_AddRefs(file)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return nullptr; + } + file->Append(NS_LITERAL_STRING(ORIGINKEYS_FILE)); + return file.forget(); + } + + // Format of file is key secondsstamp origin (first line is version #): + // + // 1 + // rOMAAbFujNwKyIpj4RJ3Wt5Q 1424733961 http://fiddle.jshell.net + // rOMAAbFujNwKyIpj4RJ3Wt5Q 1424734841 http://mozilla.github.io + // etc. + + nsresult Read() + { + nsCOMPtr file = GetFile(); + if (NS_WARN_IF(!file)) { + return NS_ERROR_UNEXPECTED; + } + bool exists; + nsresult rv = file->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (!exists) { + return NS_OK; + } + + nsCOMPtr stream; + rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsCOMPtr i = do_QueryInterface(stream); + MOZ_ASSERT(i); + + nsCString line; + bool hasMoreLines; + rv = i->ReadLine(line, &hasMoreLines); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (!line.EqualsLiteral(ORIGINKEYS_VERSION)) { + // If version on disk is newer than we can understand then ignore it. + return NS_OK; + } + + while (hasMoreLines) { + rv = i->ReadLine(line, &hasMoreLines); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + // Read key secondsstamp origin. + // Ignore any lines that don't fit format in the comment above exactly. + int32_t f = line.FindChar(' '); + if (f < 0) { + continue; + } + const nsACString& key = Substring(line, 0, f); + const nsACString& s = Substring(line, f+1); + f = s.FindChar(' '); + if (f < 0) { + continue; + } + int64_t secondsstamp = nsCString(Substring(s, 0, f)).ToInteger64(&rv); + if (NS_FAILED(rv)) { + continue; + } + const nsACString& origin = Substring(s, f+1); + + // Validate key + if (key.Length() != OriginKey::EncodedLength) { + continue; + } + nsCString dummy; + rv = Base64Decode(key, dummy); + if (NS_FAILED(rv)) { + continue; + } + mKeys.Put(origin, new OriginKey(key, secondsstamp)); + } + return NS_OK; + } + + static PLDHashOperator + HashWriter(const nsACString& aOrigin, OriginKey* aOriginKey, void *aUserArg) + { + auto* stream = static_cast(aUserArg); + + nsCString buffer; + buffer.Append(aOriginKey->mKey); + buffer.Append(' '); + buffer.AppendInt(aOriginKey->mSecondsStamp); + buffer.Append(' '); + buffer.Append(aOrigin); + buffer.Append('\n'); + + uint32_t count; + nsresult rv = stream->Write(buffer.Data(), buffer.Length(), &count); + if (NS_WARN_IF(NS_FAILED(rv)) || count != buffer.Length()) { + return PL_DHASH_STOP; + } + return PL_DHASH_NEXT; + } + + nsresult + Write() + { + nsCOMPtr file = GetFile(); + if (NS_WARN_IF(!file)) { + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr stream; + nsresult rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(stream), file); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsAutoCString buffer; + buffer.AppendLiteral(ORIGINKEYS_VERSION); + buffer.Append('\n'); + + uint32_t count; + rv = stream->Write(buffer.Data(), buffer.Length(), &count); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (count != buffer.Length()) { + return NS_ERROR_UNEXPECTED; + } + mKeys.EnumerateRead(HashWriter, stream.get()); + + nsCOMPtr safeStream = do_QueryInterface(stream); + MOZ_ASSERT(safeStream); + + rv = safeStream->Finish(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; + } + + nsresult Load() + { + nsresult rv = Read(); + if (NS_WARN_IF(NS_FAILED(rv))) { + Delete(); + } + return rv; + } + + nsresult Save() + { + nsresult rv = Write(); + if (NS_WARN_IF(NS_FAILED(rv))) { + NS_WARNING("Failed to write data for EnumerateDevices id-persistence."); + Delete(); + } + return rv; + } + + void Clear(int64_t aSinceWhen) + { + OriginKeysTable::Clear(aSinceWhen); + Delete(); + Save(); + } + + nsresult Delete() + { + nsCOMPtr file = GetFile(); + if (NS_WARN_IF(!file)) { + return NS_ERROR_UNEXPECTED; + } + nsresult rv = file->Remove(false); + if (rv == NS_ERROR_FILE_NOT_FOUND) { + return NS_OK; + } + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; + } + + private: + nsCOMPtr mProfileDir; + }; + +private: + virtual ~ParentSingleton() + { + sParentSingleton = nullptr; + LOG((__FUNCTION__)); + } + +public: + static ParentSingleton* Get() + { + // Protect creation of singleton and access from multiple Background threads. + // + // Multiple Background threads happen because sanitize.js calls us from the + // chrome process and gets a thread separate from the one servicing ipc from + // the content process. + + StaticMutexAutoLock lock(gMutex); + if (!sParentSingleton) { + sParentSingleton = new ParentSingleton(); + } + return sParentSingleton; + } + + OriginKeysLoader mOriginKeys; + OriginKeysTable mPrivateBrowsingOriginKeys; +}; + +NS_IMPL_ISUPPORTS0(ParentSingleton) + +bool +Parent::RecvGetOriginKey(const uint32_t& aRequestId, + const nsCString& aOrigin, + const bool& aPrivateBrowsing) +{ + // Hand over to stream-transport thread. + + nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); + MOZ_ASSERT(sts); + nsRefPtr singleton(mSingleton); + + nsRefPtr> p = PledgeRunnable::New( + [singleton, aOrigin, aPrivateBrowsing](nsCString& aResult) { + if (aPrivateBrowsing) { + singleton->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, aResult); + } else { + singleton->mOriginKeys.GetOriginKey(aOrigin, aResult); + } + return NS_OK; + }); + nsresult rv = sts->Dispatch(p, NS_DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + nsRefPtr keepAlive(this); + p->Then([this, keepAlive, aRequestId](const nsCString& aKey) mutable { + if (!mDestroyed) { + unused << SendGetOriginKeyResponse(aRequestId, aKey); + } + return NS_OK; + }); + return true; +} + +bool +Parent::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) +{ + // Hand over to stream-transport thread. + + nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); + MOZ_ASSERT(sts); + nsRefPtr singleton(mSingleton); + + nsRefPtr> p = PledgeRunnable::New( + [singleton, aSinceWhen](bool) { + singleton->mPrivateBrowsingOriginKeys.Clear(aSinceWhen); + singleton->mOriginKeys.Clear(aSinceWhen); + return NS_OK; + }); + nsresult rv = sts->Dispatch(p, NS_DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + return true; +} + +void +Parent::ActorDestroy(ActorDestroyReason aWhy) +{ + // No more IPC from here + mDestroyed = true; + LOG((__FUNCTION__)); +} + +Parent::Parent() + : mSingleton(ParentSingleton::Get()) + , mDestroyed(false) +{ +#if defined(PR_LOGGING) + if (!gMediaParentLog) + gMediaParentLog = PR_NewLogModule("MediaParent"); +#endif + LOG(("media::Parent: %p", this)); + + MOZ_COUNT_CTOR(Parent); +} + +Parent::~Parent() +{ + LOG(("~media::Parent: %p", this)); + + MOZ_COUNT_DTOR(Parent); +} + +PMediaParent* +AllocPMediaParent() +{ + Parent* obj = new Parent(); + obj->AddRef(); + return obj; +} + +bool +DeallocPMediaParent(media::PMediaParent *aActor) +{ + static_cast(aActor)->Release(); + return true; +} + +} +} diff --git a/dom/media/systemservices/MediaParent.h b/dom/media/systemservices/MediaParent.h new file mode 100644 index 0000000000..b94c872f5a --- /dev/null +++ b/dom/media/systemservices/MediaParent.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_MediaParent_h +#define mozilla_MediaParent_h + +#include "MediaChild.h" + +#include "mozilla/dom/ContentParent.h" +#include "mozilla/media/PMediaParent.h" + +namespace mozilla { +namespace media { + +// media::Parent implements the chrome-process side of ipc for media::Child APIs + +class ParentSingleton; + +class Parent : public PMediaParent +{ + NS_INLINE_DECL_REFCOUNTING(Parent) +public: + virtual bool RecvGetOriginKey(const uint32_t& aRequestId, + const nsCString& aOrigin, + const bool& aPrivateBrowsing) override; + virtual bool RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) override; + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + + Parent(); +private: + virtual ~Parent(); + + nsRefPtr mSingleton; + bool mDestroyed; +}; + +PMediaParent* AllocPMediaParent(); +bool DeallocPMediaParent(PMediaParent *aActor); + +} // namespace media +} // namespace mozilla + +#endif // mozilla_MediaParent_h diff --git a/dom/media/systemservices/MediaUtils.cpp b/dom/media/systemservices/MediaUtils.cpp new file mode 100644 index 0000000000..17fb500efb --- /dev/null +++ b/dom/media/systemservices/MediaUtils.cpp @@ -0,0 +1,13 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaUtils.h" + +namespace mozilla { +namespace media { + +} +} diff --git a/dom/media/systemservices/MediaUtils.h b/dom/media/systemservices/MediaUtils.h new file mode 100644 index 0000000000..a6a5a83343 --- /dev/null +++ b/dom/media/systemservices/MediaUtils.h @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_MediaUtils_h +#define mozilla_MediaUtils_h + +#include "nsAutoPtr.h" +#include "nsThreadUtils.h" + +namespace mozilla { +namespace media { + +// A media::Pledge is a promise-like pattern for c++ that takes lambda functions. +// +// Asynchronous APIs that proxy to the chrome process and back, may return a +// pledge to allow callers to use pledge.Then() to specify a lambda function to +// invoke with the result once the asynchronous API resolves later back on the +// same thread. +// +// An advantage of this pattern is that lambdas allow "capturing" of local +// variables, much like closures in JavaScript. + +template +class Pledge +{ + // TODO: Remove workaround once mozilla allows std::function from + class FunctorsBase + { + public: + FunctorsBase() {} + virtual void Succeed(const ValueType& result) = 0; + virtual void Fail(nsresult rv) = 0; + virtual ~FunctorsBase() {}; + }; + +public: + explicit Pledge() : mDone(false), mResult(NS_OK) {} + + template + void Then(OnSuccessType aOnSuccess) + { + Then(aOnSuccess, [](nsresult){}); + } + + template + void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure) + { + class F : public FunctorsBase + { + public: + F(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure) + : mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {} + + void Succeed(const ValueType& result) + { + mOnSuccess(result); + } + void Fail(nsresult rv) + { + mOnFailure(rv); + }; + + OnSuccessType mOnSuccess; + OnFailureType mOnFailure; + }; + mFunctors = new F(aOnSuccess, aOnFailure); + + if (mDone) { + if (mResult == NS_OK) { + mFunctors->Succeed(mValue); + } else { + mFunctors->Fail(mResult); + } + } + } + +protected: + void Resolve(const ValueType& aValue) + { + mValue = aValue; + Resolve(); + } + + void Resolve() + { + if (!mDone) { + mDone = true; + MOZ_ASSERT(mResult == NS_OK); + if (mFunctors) { + mFunctors->Succeed(mValue); + } + } + } + + void Reject(nsresult rv) + { + if (!mDone) { + mDone = true; + mResult = rv; + if (mFunctors) { + mFunctors->Fail(mResult); + } + } + } + + ValueType mValue; +protected: + bool mDone; + nsresult mResult; +private: + nsAutoPtr mFunctors; +}; + +// General purpose runnable that also acts as a Pledge for the resulting value. +// Use PledgeRunnable<>::New() factory function to use with lambdas. + +template +class PledgeRunnable : public Pledge, public nsRunnable +{ +public: + template + static PledgeRunnable* + New(OnRunType aOnRun) + { + class P : public PledgeRunnable + { + public: + explicit P(OnRunType& aOnRun) + : mOriginThread(NS_GetCurrentThread()) + , mOnRun(aOnRun) + , mHasRun(false) {} + private: + virtual ~P() {} + NS_IMETHODIMP + Run() + { + if (!mHasRun) { + P::mResult = mOnRun(P::mValue); + mHasRun = true; + return mOriginThread->Dispatch(this, NS_DISPATCH_NORMAL); + } + bool on; + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(mOriginThread->IsOnCurrentThread(&on))); + MOZ_RELEASE_ASSERT(on); + + if (NS_SUCCEEDED(P::mResult)) { + P::Resolve(); + } else { + P::Reject(P::mResult); + } + return NS_OK; + } + nsCOMPtr mOriginThread; + OnRunType mOnRun; + bool mHasRun; + }; + + return new P(aOnRun); + } + +protected: + virtual ~PledgeRunnable() {} +}; + +// General purpose runnable with an eye toward lambdas + +namespace CallbackRunnable +{ +template +class Impl : public nsRunnable +{ +public: + explicit Impl(OnRunType& aOnRun) : mOnRun(aOnRun) {} +private: + NS_IMETHODIMP + Run() + { + return mOnRun(); + } + OnRunType mOnRun; +}; + +template +Impl* +New(OnRunType aOnRun) +{ + return new Impl(aOnRun); +} +} + +} +} + +#endif // mozilla_MediaUtils_h diff --git a/dom/media/systemservices/PMedia.ipdl b/dom/media/systemservices/PMedia.ipdl new file mode 100644 index 0000000000..b25423be35 --- /dev/null +++ b/dom/media/systemservices/PMedia.ipdl @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PContent; +include protocol PBackground; + +namespace mozilla { +namespace media { + +protocol PMedia +{ + manager PBackground; + +parent: + /** + * Requests a persistent unique secret key for each origin. + * Has no expiry, but is cleared by age along with cookies. + * This is needed by mediaDevices.enumerateDevices() to produce persistent + * deviceIds that wont work cross-origin. + */ + GetOriginKey(uint32_t aRequestId, nsCString aOrigin, bool aPrivateBrowsing); + + /** + * On clear cookies. Fire and forget. + */ + SanitizeOriginKeys(uint64_t aSinceWhen); + +child: + GetOriginKeyResponse(uint32_t aRequestId, nsCString key); + __delete__(); +}; + +} // namespace media +} // namespace mozilla diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build index b727dd477e..d8bcb24e43 100644 --- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -37,6 +37,22 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': ] ] +EXPORTS.mozilla.media += ['MediaChild.h', + 'MediaParent.h', + 'MediaUtils.h' +] +UNIFIED_SOURCES += ['MediaChild.cpp', + 'MediaParent.cpp', + 'MediaUtils.cpp' +] +IPDL_SOURCES += [ + 'PMedia.ipdl', +] +# /dom/base needed for nsGlobalWindow.h in MediaChild.cpp +LOCAL_INCLUDES += [ + '/dom/base', +] + include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' diff --git a/dom/media/webm/WebMReader.cpp b/dom/media/webm/WebMReader.cpp index 68a6ab43ed..322611a0bf 100644 --- a/dom/media/webm/WebMReader.cpp +++ b/dom/media/webm/WebMReader.cpp @@ -716,7 +716,7 @@ bool WebMReader::ShouldSkipVideoFrame(int64_t aTimeThreshold) bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) { if (!(aKeyframeSkip && ShouldSkipVideoFrame(aTimeThreshold))) { - LOG(PR_LOG_DEBUG, ("Reader [%p]: set the aKeyframeSkip to false.",this)); + LOG(PR_LOG_DEBUG+1, ("Reader [%p]: set the aKeyframeSkip to false.",this)); aKeyframeSkip = false; } return mVideoDecoder->DecodeVideoFrame(aKeyframeSkip, aTimeThreshold); diff --git a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp index 54ae8e54c0..211677b789 100644 --- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp @@ -191,13 +191,47 @@ MediaEngineCameraVideoSource::GetBestFitnessDistance( return candidateSet[0].mDistance; } +void +MediaEngineCameraVideoSource::LogConstraints( + const MediaTrackConstraintSet& aConstraints, bool aAdvanced) +{ +#ifdef PR_LOGGING + NormalizedConstraintSet c(aConstraints, aAdvanced); + LOG(((c.mWidth.mIdeal.WasPassed()? + "Constraints: width: { min: %d, max: %d, ideal: %d }" : + "Constraints: width: { min: %d, max: %d }"), + c.mWidth.mMin, c.mWidth.mMax, + c.mWidth.mIdeal.WasPassed()? c.mWidth.mIdeal.Value() : 0)); + LOG(((c.mHeight.mIdeal.WasPassed()? + " height: { min: %d, max: %d, ideal: %d }" : + " height: { min: %d, max: %d }"), + c.mHeight.mMin, c.mHeight.mMax, + c.mHeight.mIdeal.WasPassed()? c.mHeight.mIdeal.Value() : 0)); + LOG(((c.mFrameRate.mIdeal.WasPassed()? + " frameRate: { min: %f, max: %f, ideal: %f }" : + " frameRate: { min: %f, max: %f }"), + c.mFrameRate.mMin, c.mFrameRate.mMax, + c.mFrameRate.mIdeal.WasPassed()? c.mFrameRate.mIdeal.Value() : 0)); +#endif +} + bool MediaEngineCameraVideoSource::ChooseCapability( const dom::MediaTrackConstraints &aConstraints, const MediaEnginePrefs &aPrefs) { +#ifdef PR_LOGGING LOG(("ChooseCapability: prefs: %dx%d @%d-%dfps", - aPrefs.mWidth, aPrefs.mHeight, aPrefs.mFPS, aPrefs.mMinFPS)); + aPrefs.GetWidth(), aPrefs.GetHeight(), + aPrefs.mFPS, aPrefs.mMinFPS)); + LogConstraints(aConstraints, false); + if (aConstraints.mAdvanced.WasPassed()) { + LOG(("Advanced array[%u]:", aConstraints.mAdvanced.Value().Length())); + for (auto& advanced : aConstraints.mAdvanced.Value()) { + LogConstraints(advanced, true); + } + } +#endif size_t num = NumCapabilities(); diff --git a/dom/media/webrtc/MediaEngineCameraVideoSource.h b/dom/media/webrtc/MediaEngineCameraVideoSource.h index 58285856ad..06ec2506b2 100644 --- a/dom/media/webrtc/MediaEngineCameraVideoSource.h +++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h @@ -83,6 +83,8 @@ protected: static uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate, const dom::MediaTrackConstraintSet &aConstraints); static void TrimLessFitCandidates(CapabilitySet& set); + static void LogConstraints(const dom::MediaTrackConstraintSet& aConstraints, + bool aAdvanced); virtual size_t NumCapabilities(); virtual void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut); bool ChooseCapability(const dom::MediaTrackConstraints &aConstraints, diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp index aafb4a02df..ffed03d140 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.cpp +++ b/dom/media/webrtc/MediaEngineWebRTC.cpp @@ -31,7 +31,7 @@ GetUserMediaLog() #include "AndroidBridge.h" #endif -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) #include "ICameraControl.h" #include "MediaEngineGonkVideoSource.h" #endif @@ -62,7 +62,9 @@ MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs) compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID, &mHasTabVideoSource); } #else +#ifdef MOZ_WIDGET_GONK AsyncLatencyLogger::Get()->AddRef(); +#endif #endif // XXX gFarendObserver = new AudioOutputObserver(); @@ -78,7 +80,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource, // We spawn threads to handle gUM runnables, so we must protect the member vars MutexAutoLock lock(mMutex); -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) if (aMediaSource != dom::MediaSourceEnum::Camera) { // only supports camera sources return; diff --git a/dom/media/webrtc/MediaEngineWebRTC.h b/dom/media/webrtc/MediaEngineWebRTC.h index 1bffc9ff63..c66ce683f1 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.h +++ b/dom/media/webrtc/MediaEngineWebRTC.h @@ -255,7 +255,7 @@ public: private: ~MediaEngineWebRTC() { Shutdown(); -#ifdef MOZ_B2G_CAMERA +#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK) AsyncLatencyLogger::Get()->Release(); #endif gFarendObserver = nullptr; diff --git a/dom/media/webrtc/moz.build b/dom/media/webrtc/moz.build index ab66b3ceb8..9af1293db6 100644 --- a/dom/media/webrtc/moz.build +++ b/dom/media/webrtc/moz.build @@ -38,7 +38,7 @@ if CONFIG['MOZ_WEBRTC']: '/media/webrtc/trunk', ] # Gonk camera source. - if CONFIG['MOZ_B2G_CAMERA']: + if CONFIG['MOZ_B2G_CAMERA'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': EXPORTS += [ 'GonkCameraImage.h', 'MediaEngineGonkVideoSource.h', diff --git a/dom/plugins/base/moz.build b/dom/plugins/base/moz.build index 1ea4cab200..9a07cbc956 100644 --- a/dom/plugins/base/moz.build +++ b/dom/plugins/base/moz.build @@ -4,8 +4,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': - DIRS += ['android'] XPIDL_SOURCES += [ 'nsIHTTPHeaderListener.idl', @@ -99,16 +97,10 @@ LOCAL_INCLUDES += [ '/layout/xul', '/netwerk/base', '/widget', - '/widget/android', '/widget/cocoa', '/xpcom/base', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': - LOCAL_INCLUDES += [ - '/dom/plugins/base/android', - ] - if CONFIG['OS_ARCH'] == 'WINNT': LOCAL_INCLUDES += [ '/xpcom/base', @@ -116,8 +108,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': include('/ipc/chromium/chromium-config.mozbuild') -DEFINES['SK_BUILD_FOR_ANDROID_NDK'] = True - FINAL_LIBRARY = 'xul' CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] diff --git a/dom/plugins/ipc/PluginAsyncSurrogate.cpp b/dom/plugins/ipc/PluginAsyncSurrogate.cpp index 71ff12d758..f1e18ab04f 100644 --- a/dom/plugins/ipc/PluginAsyncSurrogate.cpp +++ b/dom/plugins/ipc/PluginAsyncSurrogate.cpp @@ -436,7 +436,7 @@ PluginAsyncSurrogate::SetStreamType(NPStream* aStream, uint16_t aStreamType) void PluginAsyncSurrogate::OnInstanceCreated(PluginInstanceParent* aInstance) { - for (PRUint32 i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) { + for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) { PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i]; uint16_t streamType = NP_NORMAL; NPError curError = aInstance->NPP_NewStream( diff --git a/dom/plugins/test/mochitest/cocoa_focus.html b/dom/plugins/test/mochitest/cocoa_focus.html index f9ff1c444e..53deac6e20 100644 --- a/dom/plugins/test/mochitest/cocoa_focus.html +++ b/dom/plugins/test/mochitest/cocoa_focus.html @@ -73,7 +73,7 @@ is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount); // Focus the window. - window.focus(); + SpecialPowers.focus(window); is(plugin1.getFocusState(), true, "(3) Plugin should still have focus."); is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount); diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index 8e43d0e9e0..25435b5c92 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -58,8 +58,6 @@ #include "UsageInfo.h" #include "Utilities.h" -#define BAD_TLS_INDEX ((uint32_t) -1) - // The amount of time, in milliseconds, that our IO thread will stay alive // after the last event it processes. #define DEFAULT_THREAD_TIMEOUT_MS 30000 @@ -1260,8 +1258,7 @@ GetTemporaryStorageLimit(nsIFile* aDirectory, uint64_t aCurrentUsage, } // namespace QuotaManager::QuotaManager() -: mCurrentWindowIndex(BAD_TLS_INDEX), - mQuotaMutex("QuotaManager.mQuotaMutex"), +: mQuotaMutex("QuotaManager.mQuotaMutex"), mTemporaryStorageLimit(0), mTemporaryStorageUsage(0), mTemporaryStorageInitialized(false), @@ -1338,15 +1335,6 @@ QuotaManager::IsShuttingDown() nsresult QuotaManager::Init() { - // We need a thread-local to hold the current window. - NS_ASSERTION(mCurrentWindowIndex == BAD_TLS_INDEX, "Huh?"); - - if (PR_NewThreadPrivateIndex(&mCurrentWindowIndex, nullptr) != PR_SUCCESS) { - NS_ERROR("PR_NewThreadPrivateIndex failed, QuotaManager disabled"); - mCurrentWindowIndex = BAD_TLS_INDEX; - return NS_ERROR_FAILURE; - } - nsresult rv; if (IsMainProcess()) { nsCOMPtr baseDir; @@ -3003,24 +2991,6 @@ QuotaManager::Observe(nsISupports* aSubject, return NS_ERROR_UNEXPECTED; } -void -QuotaManager::SetCurrentWindowInternal(nsPIDOMWindow* aWindow) -{ - NS_ASSERTION(mCurrentWindowIndex != BAD_TLS_INDEX, - "Should have a valid TLS storage index!"); - - if (aWindow) { - NS_ASSERTION(!PR_GetThreadPrivate(mCurrentWindowIndex), - "Somebody forgot to clear the current window!"); - PR_SetThreadPrivate(mCurrentWindowIndex, aWindow); - } - else { - // We cannot assert PR_GetThreadPrivate(mCurrentWindowIndex) here because - // there are some cases where we did not already have a window. - PR_SetThreadPrivate(mCurrentWindowIndex, nullptr); - } -} - uint64_t QuotaManager::LockedCollectOriginsForEviction( uint64_t aMinSizeToBeFreed, diff --git a/dom/quota/QuotaManager.h b/dom/quota/QuotaManager.h index 34c9cd6b9a..86dc8ad259 100644 --- a/dom/quota/QuotaManager.h +++ b/dom/quota/QuotaManager.h @@ -155,17 +155,6 @@ public: const nsACString& aOrigin, const nsAString& aPath); - // Set the Window that the current thread is doing operations for. - // The caller is responsible for ensuring that aWindow is held alive. - static void - SetCurrentWindow(nsPIDOMWindow* aWindow) - { - QuotaManager* quotaManager = Get(); - NS_ASSERTION(quotaManager, "Must have a manager here!"); - - quotaManager->SetCurrentWindowInternal(aWindow); - } - // Called when a storage is created. bool RegisterStorage(nsIOfflineStorage* aStorage); @@ -333,9 +322,6 @@ private: nsresult Init(); - void - SetCurrentWindowInternal(nsPIDOMWindow* aWindow); - uint64_t LockedCollectOriginsForEviction(uint64_t aMinSizeToBeFreed, nsTArray& aOriginInfos); @@ -446,9 +432,6 @@ private: GroupInfoPair* aValue, void* aUserArg); - // TLS storage index for the current thread's window. - unsigned int mCurrentWindowIndex; - mozilla::Mutex mQuotaMutex; nsClassHashtable mGroupInfoPairs; @@ -488,20 +471,6 @@ private: bool mStorageAreaInitialized; }; -class AutoEnterWindow -{ -public: - explicit AutoEnterWindow(nsPIDOMWindow* aWindow) - { - QuotaManager::SetCurrentWindow(aWindow); - } - - ~AutoEnterWindow() - { - QuotaManager::SetCurrentWindow(nullptr); - } -}; - END_QUOTA_NAMESPACE #endif /* mozilla_dom_quota_quotamanager_h__ */ diff --git a/editor/libeditor/tests/test_bug417418.html b/editor/libeditor/tests/test_bug417418.html index 146de09202..24fa6935f1 100644 --- a/editor/libeditor/tests/test_bug417418.html +++ b/editor/libeditor/tests/test_bug417418.html @@ -25,6 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=417418 /** Test for Bug 417418 **/ SimpleTest.waitForExplicitFinish(); SimpleTest.waitForFocus(runTest); +SimpleTest.expectAssertions(0, 1); function resetSelection() { window.getSelection().collapse(document.getElementById("coin"), 0); diff --git a/embedding/browser/nsDocShellTreeOwner.cpp b/embedding/browser/nsDocShellTreeOwner.cpp index a65d236ad7..21a3d4e028 100644 --- a/embedding/browser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/nsDocShellTreeOwner.cpp @@ -910,7 +910,7 @@ nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent) nsIWebNavigation* webnav = static_cast(mWebBrowser); nsAutoString link, name; - if (webnav && NS_SUCCEEDED(handler->DropLink(dragEvent, link, false, name))) { + if (webnav && NS_SUCCEEDED(handler->DropLink(dragEvent, name, true, link))) { if (!link.IsEmpty()) { webnav->LoadURI(link.get(), 0, nullptr, nullptr, nullptr); } diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index c87deff603..6807dbfde2 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -628,6 +628,9 @@ APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget, uint64_t aInputBlockId, const nsRefPtr& aCallback) { + if (!aWidget || !aDocument) { + return; + } if (nsIPresShell* shell = aDocument->GetShell()) { if (nsIFrame* rootFrame = shell->GetRootFrame()) { bool waitForRefresh = false; diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 90be379478..9c02bcced2 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -631,7 +631,7 @@ bool ImageBridgeChild::StartUpOnThread(Thread* aThread) } sImageBridgeChildSingleton = new ImageBridgeChild(); sImageBridgeParentSingleton = new ImageBridgeParent( - CompositorParent::CompositorLoop(), nullptr, ipc::kCurrentProcessId); + CompositorParent::CompositorLoop(), nullptr, base::GetCurrentProcId()); sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton); return true; } else { @@ -959,7 +959,7 @@ void ImageBridgeChild::RemoveTexture(TextureClient* aTexture) bool ImageBridgeChild::IsSameProcess() const { - return OtherPid() == ipc::kCurrentProcessId; + return OtherPid() == base::GetCurrentProcId(); } void ImageBridgeChild::SendPendingAsyncMessges() diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp index 67e38eff29..2648ce5a0e 100644 --- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -340,7 +340,7 @@ ImageBridgeParent::CloneToplevel(const InfallibleTArray& aFds bool ImageBridgeParent::IsSameProcess() const { - return OtherPid() == ipc::kCurrentProcessId; + return OtherPid() == base::GetCurrentProcId(); } void diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index 4931b9c02f..3547263607 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -971,7 +971,7 @@ LayerTransactionParent::ActorDestroy(ActorDestroyReason why) bool LayerTransactionParent::IsSameProcess() const { - return OtherPid() == ipc::kCurrentProcessId; + return OtherPid() == base::GetCurrentProcId(); } void diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 0e055b09eb..5acce0a7ad 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -753,7 +753,7 @@ ShadowLayerForwarder::IsSameProcess() const if (!HasShadowManager() || !mShadowManager->IPCOpen()) { return false; } - return mShadowManager->OtherPid() == kCurrentProcessId; + return mShadowManager->OtherPid() == base::GetCurrentProcId(); } /** diff --git a/hal/Hal.cpp b/hal/Hal.cpp index b663087303..cf3ae82fac 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -861,16 +861,11 @@ SetAlarm(int32_t aSeconds, int32_t aNanoseconds) } void -SetProcessPriority(int aPid, - ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU) +SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) { // n.b. The sandboxed implementation crashes; SetProcessPriority works only // from the main process. - MOZ_ASSERT(aBackgroundLRU == 0 || aPriority == PROCESS_PRIORITY_BACKGROUND); - PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aCPUPriority, - aBackgroundLRU)); + PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aLRU)); } void @@ -920,89 +915,6 @@ ThreadPriorityToString(ThreadPriority aPriority) } } -// From HalTypes.h. -const char* -ProcessPriorityToString(ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority) -{ - // Sorry this is ugly. At least it's all in one place. - // - // We intentionally fall through if aCPUPriority is invalid; we won't hit any - // of the if statements further down, so it's OK. - - switch (aPriority) { - case PROCESS_PRIORITY_MASTER: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "MASTER:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "MASTER:CPU_LOW"; - } - case PROCESS_PRIORITY_PREALLOC: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "PREALLOC:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "PREALLOC:CPU_LOW"; - } - case PROCESS_PRIORITY_FOREGROUND_HIGH: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "FOREGROUND_HIGH:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "FOREGROUND_HIGH:CPU_LOW"; - } - case PROCESS_PRIORITY_FOREGROUND: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "FOREGROUND:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "FOREGROUND:CPU_LOW"; - } - case PROCESS_PRIORITY_FOREGROUND_KEYBOARD: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "FOREGROUND_KEYBOARD:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "FOREGROUND_KEYBOARD:CPU_LOW"; - } - case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "BACKGROUND_PERCEIVABLE:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "BACKGROUND_PERCEIVABLE:CPU_LOW"; - } - case PROCESS_PRIORITY_BACKGROUND_HOMESCREEN: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "BACKGROUND_HOMESCREEN:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "BACKGROUND_HOMESCREEN:CPU_LOW"; - } - case PROCESS_PRIORITY_BACKGROUND: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "BACKGROUND:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "BACKGROUND:CPU_LOW"; - } - case PROCESS_PRIORITY_UNKNOWN: - if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) { - return "UNKNOWN:CPU_NORMAL"; - } - if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) { - return "UNKNOWN:CPU_LOW"; - } - default: - // Fall through. (|default| is here to silence warnings.) - break; - } - - MOZ_ASSERT(false); - return "???"; -} - static StaticAutoPtr > sFMRadioObservers; static StaticAutoPtr > sFMRadioRDSObservers; diff --git a/hal/Hal.h b/hal/Hal.h index 4d4d8745fc..ba256c3fe9 100644 --- a/hal/Hal.h +++ b/hal/Hal.h @@ -468,13 +468,7 @@ void NotifyAlarmFired(); bool SetAlarm(int32_t aSeconds, int32_t aNanoseconds); /** - * Set the priority of the given process. A process's priority is a two-tuple - * consisting of a hal::ProcessPriority value and a hal::ProcessCPUPriority - * value. - * - * Two processes with the same ProcessCPUPriority value don't necessarily have - * the same CPU priority; the CPU priority we assign to a process is a function - * of its ProcessPriority and ProcessCPUPriority. + * Set the priority of the given process. * * Exactly what this does will vary between platforms. On *nix we might give * background processes higher nice values. On other platforms, we might @@ -482,7 +476,6 @@ bool SetAlarm(int32_t aSeconds, int32_t aNanoseconds); */ void SetProcessPriority(int aPid, hal::ProcessPriority aPriority, - hal::ProcessCPUPriority aCPUPriority, uint32_t aLRU = 0); diff --git a/hal/HalTypes.h b/hal/HalTypes.h index 394b0d750d..63e99a34ee 100644 --- a/hal/HalTypes.h +++ b/hal/HalTypes.h @@ -73,12 +73,6 @@ enum ProcessPriority { NUM_PROCESS_PRIORITY }; -enum ProcessCPUPriority { - PROCESS_CPU_PRIORITY_LOW, - PROCESS_CPU_PRIORITY_NORMAL, - NUM_PROCESS_CPU_PRIORITY -}; - /** * Values that can be passed to hal::SetCurrentThreadPriority(). These should be * functional in nature, such as COMPOSITOR, instead of levels, like LOW/HIGH. @@ -92,9 +86,8 @@ enum ThreadPriority { }; /** - * Convert a ProcessPriority enum value (with an optional ProcessCPUPriority) - * to a string. The strings returned by this function are statically - * allocated; do not attempt to free one! + * Convert a ProcessPriority enum value to a string. The strings returned by + * this function are statically allocated; do not attempt to free one! * * If you pass an unknown process priority, we fatally assert in debug * builds and otherwise return "???". @@ -102,10 +95,6 @@ enum ThreadPriority { const char* ProcessPriorityToString(ProcessPriority aPriority); -const char* -ProcessPriorityToString(ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority); - /** * Convert a ThreadPriority enum value to a string. The strings returned by * this function are statically allocated; do not attempt to free one! diff --git a/hal/fallback/FallbackProcessPriority.cpp b/hal/fallback/FallbackProcessPriority.cpp index 6cf416cde3..b03b1542e1 100644 --- a/hal/fallback/FallbackProcessPriority.cpp +++ b/hal/fallback/FallbackProcessPriority.cpp @@ -11,14 +11,10 @@ namespace mozilla { namespace hal_impl { void -SetProcessPriority(int aPid, - ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU) +SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) { HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s, %u)\n", - aPid, ProcessPriorityToString(aPriority, aCPUPriority), - aBackgroundLRU); + aPid, ProcessPriorityToString(aPriority), aLRU); } } // namespace hal_impl diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index 155c628a4d..0bac6daee5 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -1149,12 +1149,12 @@ OomAdjOfOomScoreAdj(int aOomScoreAdj) } static void -RoundOomScoreAdjUpWithBackroundLRU(int& aOomScoreAdj, uint32_t aBackgroundLRU) +RoundOomScoreAdjUpWithLRU(int& aOomScoreAdj, uint32_t aLRU) { // We want to add minimum value to round OomScoreAdj up according to - // the steps by aBackgroundLRU. + // the steps by aLRU. aOomScoreAdj += - ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aBackgroundLRU); + ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aLRU); } #define OOM_LOG(level, args...) __android_log_print(level, "OomLogger", ##args) @@ -1736,13 +1736,10 @@ EnsureKernelLowMemKillerParamsSet() } void -SetProcessPriority(int aPid, - ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU) +SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) { - HAL_LOG("SetProcessPriority(pid=%d, priority=%d, cpuPriority=%d, LRU=%u)", - aPid, aPriority, aCPUPriority, aBackgroundLRU); + HAL_LOG("SetProcessPriority(pid=%d, priority=%d, LRU=%u)", + aPid, aPriority, aLRU); // If this is the first time SetProcessPriority was called, set the kernel's // OOM parameters according to our prefs. @@ -1757,7 +1754,7 @@ SetProcessPriority(int aPid, int oomScoreAdj = pc->OomScoreAdj(); - RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU); + RoundOomScoreAdjUpWithLRU(oomScoreAdj, aLRU); // We try the newer interface first, and fall back to the older interface // on failure. diff --git a/hal/sandbox/SandboxHal.cpp b/hal/sandbox/SandboxHal.cpp index 05bff9b509..d863d5334c 100644 --- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -355,10 +355,7 @@ SetAlarm(int32_t aSeconds, int32_t aNanoseconds) } void -SetProcessPriority(int aPid, - ProcessPriority aPriority, - ProcessCPUPriority aCPUPriority, - uint32_t aBackgroundLRU) +SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) { NS_RUNTIMEABORT("Only the main process may set processes' priorities."); } diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index cafff2464a..b360f14571 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -7,6 +7,7 @@ #include "ActorsChild.h" // IndexedDB #include "BroadcastChannelChild.h" #include "FileDescriptorSetChild.h" +#include "mozilla/media/MediaChild.h" #include "mozilla/Assertions.h" #include "mozilla/dom/PBlobChild.h" #include "mozilla/dom/cache/ActorUtils.h" @@ -282,6 +283,18 @@ BackgroundChildImpl::DeallocPCacheStreamControlChild(PCacheStreamControlChild* a return true; } +media::PMediaChild* +BackgroundChildImpl::AllocPMediaChild() +{ + return media::AllocPMediaChild(); +} + +bool +BackgroundChildImpl::DeallocPMediaChild(media::PMediaChild *aActor) +{ + return media::DeallocPMediaChild(aActor); +} + } // namespace ipc } // namespace mozilla diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index 0d4023eff6..b28e238ea4 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -71,6 +71,12 @@ protected: virtual bool DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) override; + virtual PMediaChild* + AllocPMediaChild() override; + + virtual bool + DeallocPMediaChild(PMediaChild* aActor) override; + virtual PVsyncChild* AllocPVsyncChild() override; diff --git a/ipc/glue/BackgroundImpl.cpp b/ipc/glue/BackgroundImpl.cpp index a7274d2241..eca898f599 100644 --- a/ipc/glue/BackgroundImpl.cpp +++ b/ipc/glue/BackgroundImpl.cpp @@ -1957,7 +1957,7 @@ ChildImpl::OpenMainProcessActorRunnable::Run() } // Make sure the parent knows it is same process. - parentActor->SetOtherProcessId(kCurrentProcessId); + parentActor->SetOtherProcessId(base::GetCurrentProcId()); // Now that Open() has succeeded transfer the ownership of the actors to IPDL. unused << parentActor.forget(); diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 6db147a42a..2725418de1 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -6,6 +6,7 @@ #include "BroadcastChannelParent.h" #include "FileDescriptorSetParent.h" +#include "mozilla/media/MediaParent.h" #include "mozilla/AppProcessChecker.h" #include "mozilla/Assertions.h" #include "mozilla/dom/ContentParent.h" @@ -362,6 +363,18 @@ BackgroundParentImpl::DeallocPBroadcastChannelParent( return true; } +media::PMediaParent* +BackgroundParentImpl::AllocPMediaParent() +{ + return media::AllocPMediaParent(); +} + +bool +BackgroundParentImpl::DeallocPMediaParent(media::PMediaParent *aActor) +{ + return media::DeallocPMediaParent(aActor); +} + namespace { class RegisterServiceWorkerCallback final : public nsRunnable diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index a51758857d..3fa61c7ae8 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -86,6 +86,12 @@ protected: virtual bool DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override; + virtual PMediaParent* + AllocPMediaParent() override; + + virtual bool + DeallocPMediaParent(PMediaParent* aActor) override; + virtual bool RecvRegisterServiceWorker(const ServiceWorkerRegistrationData& aData) override; diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index eacd454e42..db28baa490 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -11,6 +11,7 @@ include protocol PCacheStorage; include protocol PCacheStreamControl; include protocol PFileDescriptorSet; include protocol PVsync; +include protocol PMedia; include DOMTypes; include PBackgroundSharedTypes; @@ -34,6 +35,7 @@ sync protocol PBackground manages PCacheStreamControl; manages PFileDescriptorSet; manages PVsync; + manages PMedia; parent: // Only called at startup during mochitests to check the basic infrastructure. @@ -42,6 +44,7 @@ parent: PBackgroundIDBFactory(LoggingInfo loggingInfo); PVsync(); + PMedia(); PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel, bool privateBrowsing); diff --git a/ipc/glue/ProtocolUtils.cpp b/ipc/glue/ProtocolUtils.cpp index b3cba6e19c..e5022fc2a2 100644 --- a/ipc/glue/ProtocolUtils.cpp +++ b/ipc/glue/ProtocolUtils.cpp @@ -193,7 +193,7 @@ bool DuplicateHandle(HANDLE aSourceHandle, DWORD aDesiredAccess, DWORD aOptions) { // If our process is the target just duplicate the handle. - if (aTargetProcessId == kCurrentProcessId) { + if (aTargetProcessId == base::GetCurrentProcId()) { return !!::DuplicateHandle(::GetCurrentProcess(), aSourceHandle, ::GetCurrentProcess(), aTargetHandle, aDesiredAccess, false, aOptions); @@ -246,7 +246,7 @@ FatalError(const char* aProtocolName, const char* aMsg, formattedMessage.AppendLiteral("\". Killing child side as a result."); NS_ERROR(formattedMessage.get()); - if (aOtherPid != kInvalidProcessId && aOtherPid != kCurrentProcessId) { + if (aOtherPid != kInvalidProcessId && aOtherPid != base::GetCurrentProcId()) { ScopedProcessHandle otherProcessHandle; if (base::OpenProcessHandle(aOtherPid, &otherProcessHandle.rwget())) { if (!base::KillProcess(otherProcessHandle, diff --git a/ipc/glue/ProtocolUtils.h b/ipc/glue/ProtocolUtils.h index 72211d96f8..14c8fdae54 100644 --- a/ipc/glue/ProtocolUtils.h +++ b/ipc/glue/ProtocolUtils.h @@ -72,7 +72,6 @@ const base::ProcessId kInvalidProcessId = kuint32max; const base::ProcessHandle kInvalidProcessHandle = -1; const base::ProcessId kInvalidProcessId = -1; #endif -const base::ProcessId kCurrentProcessId = base::GetCurrentProcId(); // Scoped base::ProcessHandle to ensure base::CloseProcessHandle is called. struct ScopedProcessHandleTraits diff --git a/ipc/ipdl/ipdl/cxx/cgen.py b/ipc/ipdl/ipdl/cxx/cgen.py index 6b50a4cb1b..60ae90005f 100644 --- a/ipc/ipdl/ipdl/cxx/cgen.py +++ b/ipc/ipdl/ipdl/cxx/cgen.py @@ -187,7 +187,7 @@ class CxxCodeGen(CodePrinter, Visitor): self.write('MOZ_WARN_UNUSED_RESULT ') if md.inline: self.write('inline ') - if md.inline: + if md.never_inline: self.write('MOZ_NEVER_INLINE ') if md.static: self.write('static ') diff --git a/ipc/ipdl/ipdl/lower.py b/ipc/ipdl/ipdl/lower.py index 9744565304..485d2312e8 100644 --- a/ipc/ipdl/ipdl/lower.py +++ b/ipc/ipdl/ipdl/lower.py @@ -4,6 +4,7 @@ import os, re, sys from copy import deepcopy +from collections import OrderedDict import ipdl.ast import ipdl.builtin @@ -2780,7 +2781,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): bridgeActorsCreated = ProcessGraph.bridgeEndpointsOf(ptype, self.side) opensActorsCreated = ProcessGraph.opensEndpointsOf(ptype, self.side) - channelOpenedActors = bridgeActorsCreated + opensActorsCreated + channelOpenedActors = OrderedDict.fromkeys(bridgeActorsCreated + opensActorsCreated, None) friends = _FindFriends().findFriends(ptype) if ptype.isManaged(): @@ -3004,7 +3005,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): ret=Type.BOOL)) openmeth.addstmts([ - StmtExpr(ExprAssn(p.otherPidVar(), ExprVar('ipc::kCurrentProcessId'))), + StmtExpr(ExprAssn(p.otherPidVar(), ExprCall(ExprVar('base::GetCurrentProcId')))), StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'), [ aChannel, aMessageLoop, sidevar ])) ]) diff --git a/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl b/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl index 93e905dd4d..77b9024bf1 100644 --- a/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl +++ b/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl @@ -7,6 +7,7 @@ namespace _ipdltest { protocol PTestBridgeMain { child spawns PTestBridgeSub; + child opens PTestBridgeMainSub; child: Start(); diff --git a/ipc/ipdl/test/cxx/TestBridgeMain.h b/ipc/ipdl/test/cxx/TestBridgeMain.h index b88b60a5d4..df63167fea 100644 --- a/ipc/ipdl/test/cxx/TestBridgeMain.h +++ b/ipc/ipdl/test/cxx/TestBridgeMain.h @@ -72,6 +72,16 @@ public: protected: virtual bool RecvStart() override; + virtual PTestBridgeMainSubChild* + AllocPTestBridgeMainSubChild(Transport* transport, + ProcessId otherProcess) MOZ_OVERRIDE + { + // This shouldn't be called. It's just a byproduct of testing that + // the right code is generated for a bridged protocol that's also + // opened, but we only test bridging here. + MOZ_CRASH(); + } + virtual void ActorDestroy(ActorDestroyReason why) override; IPDLUnitTestSubprocess* mSubprocess; diff --git a/ipc/ipdl/test/cxx/TestDataStructures.cpp b/ipc/ipdl/test/cxx/TestDataStructures.cpp index 22f66437bb..1280e4d196 100644 --- a/ipc/ipdl/test/cxx/TestDataStructures.cpp +++ b/ipc/ipdl/test/cxx/TestDataStructures.cpp @@ -494,7 +494,7 @@ TestDataStructuresChild::RecvStart() Test15(); Test16(); Test17(); - if (OtherPid() != ipc::kCurrentProcessId) { + if (OtherPid() != base::GetCurrentProcId()) { //FIXME/bug 703317 allocation of nsIntRegion uses a global //region pool which breaks threads Test18(); diff --git a/ipc/ipdl/test/cxx/TestFailedCtor.cpp b/ipc/ipdl/test/cxx/TestFailedCtor.cpp index 01b778f4c9..12ea8fdc11 100644 --- a/ipc/ipdl/test/cxx/TestFailedCtor.cpp +++ b/ipc/ipdl/test/cxx/TestFailedCtor.cpp @@ -110,7 +110,7 @@ TestFailedCtorChild::DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* act void TestFailedCtorChild::ProcessingError(Result aCode, const char* aReason) { - if (OtherPid() != ipc::kCurrentProcessId) // thread-mode + if (OtherPid() != base::GetCurrentProcId()) // thread-mode _exit(0); } diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index 002f3f35cc..39df06e5dd 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -894,6 +894,8 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin JS::CompartmentOptions compartmentOptions; if (options.sameZoneAs) compartmentOptions.setSameZoneAs(js::UncheckedUnwrap(options.sameZoneAs)); + else if (options.freshZone) + compartmentOptions.setZone(JS::FreshZone); else compartmentOptions.setZone(JS::SystemZone); @@ -1369,18 +1371,28 @@ SandboxOptions::ParseGlobalProperties() bool SandboxOptions::Parse() { - return ParseObject("sandboxPrototype", &proto) && - ParseBoolean("wantXrays", &wantXrays) && - ParseBoolean("wantComponents", &wantComponents) && - ParseBoolean("wantExportHelpers", &wantExportHelpers) && - ParseString("sandboxName", sandboxName) && - ParseObject("sameZoneAs", &sameZoneAs) && - ParseBoolean("invisibleToDebugger", &invisibleToDebugger) && - ParseBoolean("discardSource", &discardSource) && - ParseJSString("addonId", &addonId) && - ParseBoolean("writeToGlobalPrototype", &writeToGlobalPrototype) && - ParseGlobalProperties() && - ParseValue("metadata", &metadata); + bool ok = ParseObject("sandboxPrototype", &proto) && + ParseBoolean("wantXrays", &wantXrays) && + ParseBoolean("wantComponents", &wantComponents) && + ParseBoolean("wantExportHelpers", &wantExportHelpers) && + ParseString("sandboxName", sandboxName) && + ParseObject("sameZoneAs", &sameZoneAs) && + ParseBoolean("freshZone", &freshZone) && + ParseBoolean("invisibleToDebugger", &invisibleToDebugger) && + ParseBoolean("discardSource", &discardSource) && + ParseJSString("addonId", &addonId) && + ParseBoolean("writeToGlobalPrototype", &writeToGlobalPrototype) && + ParseGlobalProperties() && + ParseValue("metadata", &metadata); + if (!ok) + return false; + + if (freshZone && sameZoneAs) { + JS_ReportError(mCx, "Cannot use both sameZoneAs and freshZone"); + return false; + } + + return true; } static nsresult diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index b57a309e97..5b740c2e3c 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3447,6 +3447,7 @@ public: , addonId(cx) , writeToGlobalPrototype(false) , sameZoneAs(cx) + , freshZone(false) , invisibleToDebugger(false) , discardSource(false) , metadata(cx) @@ -3462,6 +3463,7 @@ public: JS::RootedString addonId; bool writeToGlobalPrototype; JS::RootedObject sameZoneAs; + bool freshZone; bool invisibleToDebugger; bool discardSource; GlobalProperties globalProperties; diff --git a/layout/xul/nsImageBoxFrame.cpp b/layout/xul/nsImageBoxFrame.cpp index 9a99dbff38..b5ff1f4cde 100644 --- a/layout/xul/nsImageBoxFrame.cpp +++ b/layout/xul/nsImageBoxFrame.cpp @@ -192,11 +192,9 @@ nsImageBoxFrame::Init(nsIContent* aContent, nsIFrame* aPrevInFlow) { if (!mListener) { - nsImageBoxListener *listener = new nsImageBoxListener(); - NS_ADDREF(listener); + nsRefPtr listener = new nsImageBoxListener(); listener->SetFrame(this); - listener->QueryInterface(NS_GET_IID(imgINotificationObserver), getter_AddRefs(mListener)); - NS_RELEASE(listener); + mListener = listener.forget(); } mSuppressStyleCheck = true; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h index 2f9ca74e08..81be30fc5d 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h @@ -10,7 +10,7 @@ #include "mozilla/Attributes.h" #include "StaticPtr.h" #include "PeerConnectionImpl.h" -#include "mozIGoannaMediaPluginService.h" +#include "mozIGeckoMediaPluginService.h" #include "nsIRunnable.h" namespace mozilla { @@ -87,12 +87,12 @@ public: private: #endif - // We cannot form offers/answers properly until the Goanna Media Plugin stuff + // We cannot form offers/answers properly until the Gecko Media Plugin stuff // has been initted, which is a complicated mess of thread dispatches, // including sync dispatches to main. So, we need to be able to queue up // offer creation (or SetRemote, when we're the answerer) until all of this is // ready to go, since blocking on this init is just begging for deadlock. - nsCOMPtr mGMPService; + nsCOMPtr mGMPService; bool mGMPReady; nsTArray> mQueuedJSEPOperations; diff --git a/parser/html/javasrc/Tokenizer.java b/parser/html/javasrc/Tokenizer.java index 79dc67a4e4..997a58f8f5 100644 --- a/parser/html/javasrc/Tokenizer.java +++ b/parser/html/javasrc/Tokenizer.java @@ -3593,7 +3593,7 @@ public class Tokenizer implements Locator { */ flushChars(buf, pos); clearStrBufAndAppend(c); - additional = '\u0000'; + setAdditionalAndRememberAmpersandLocation('\u0000'); returnState = state; state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos); continue stateloop; diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 6f157d8b1a..d40c3a4220 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -1919,7 +1919,7 @@ nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos, char16_t* bu case '&': { flushChars(buf, pos); clearStrBufAndAppend(c); - additional = '\0'; + setAdditionalAndRememberAmpersandLocation('\0'); returnState = state; state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos); NS_HTML5_CONTINUE(stateloop); diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index e3772dc621..6053bfad4b 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -169,7 +169,7 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssLoadingComponent, nsNSSComponent, Init) using namespace mozilla::psm; - + namespace { // Use the special factory constructor for everything this module implements, @@ -199,9 +199,9 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsPkcs11) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCertPicker) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsNTLMAuthModule, InitTest) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureChromeOrContent, nsCryptoHash) -NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCryptoHMAC) -NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObject) -NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObjectFactory) +NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureChromeOrContent, nsCryptoHMAC) +NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureChromeOrContent, nsKeyObject) +NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureChromeOrContent, nsKeyObjectFactory) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsDataSignatureVerifier) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsRandomGenerator) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus) diff --git a/toolkit/content/tests/browser/browser.ini b/toolkit/content/tests/browser/browser.ini index df78d6da92..19f9069704 100644 --- a/toolkit/content/tests/browser/browser.ini +++ b/toolkit/content/tests/browser/browser.ini @@ -3,7 +3,7 @@ support-files = head.js [browser_autoscroll_disabled.js] skip-if = e10s # Bug ?????? - test touches content (getElementById on the content document) [browser_browserDrop.js] -skip-if = buildapp == 'mulet' +skip-if = buildapp == 'mulet' || e10s # Relies on drop to be handled in the parent process [browser_bug295977_autoscroll_overflow.js] skip-if = e10s # Bug 921935 - focusmanager issues with e10s [browser_bug594509.js] diff --git a/toolkit/content/widgets/browser.xml b/toolkit/content/widgets/browser.xml index 43413de8d9..0d02053977 100644 --- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -1233,7 +1233,9 @@ { throw new Error("Exception thrown while Encrypted Media Extensions: " + ex); diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index a7be571098..be623d0e62 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -195,7 +195,7 @@ if CONFIG['MOZ_B2G_BT_BLUEZ'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'dbus', ] -if CONFIG['MOZ_B2G_CAMERA']: +if CONFIG['MOZ_B2G_CAMERA'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': OS_LIBS += [ 'stagefright', 'stagefright_omx', diff --git a/toolkit/mozapps/extensions/internal/GMPProvider.jsm b/toolkit/mozapps/extensions/internal/GMPProvider.jsm index 1c9468992c..665c1df249 100644 --- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm +++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm @@ -62,7 +62,7 @@ const GMP_PLUGINS = [ XPCOMUtils.defineLazyGetter(this, "pluginsBundle", () => Services.strings.createBundle("chrome://global/locale/plugins.properties")); XPCOMUtils.defineLazyGetter(this, "gmpService", - () => Cc["@mozilla.org/goanna-media-plugin-service;1"].getService(Ci.mozIGoannaMediaPluginService)); + () => Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(Ci.mozIGeckoMediaPluginChromeService)); let messageManager = Cc["@mozilla.org/globalmessagemanager;1"] .getService(Ci.nsIMessageListenerManager); diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h index 3dcf9dc507..ad1f5b3e2a 100644 --- a/widget/MouseEvents.h +++ b/widget/MouseEvents.h @@ -306,6 +306,13 @@ public: class WidgetDragEvent : public WidgetMouseEvent { +private: + friend class mozilla::dom::PBrowserParent; + friend class mozilla::dom::PBrowserChild; +protected: + WidgetDragEvent() + { + } public: virtual WidgetDragEvent* AsDragEvent() override { return this; } diff --git a/widget/PuppetBidiKeyboard.cpp b/widget/PuppetBidiKeyboard.cpp new file mode 100644 index 0000000000..54d7c93972 --- /dev/null +++ b/widget/PuppetBidiKeyboard.cpp @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "PuppetBidiKeyboard.h" + +using namespace mozilla::widget; + +NS_IMPL_ISUPPORTS(PuppetBidiKeyboard, nsIBidiKeyboard) + +PuppetBidiKeyboard::PuppetBidiKeyboard() : nsIBidiKeyboard() +{ +} + +PuppetBidiKeyboard::~PuppetBidiKeyboard() +{ +} + +NS_IMETHODIMP +PuppetBidiKeyboard::Reset() +{ + return NS_OK; +} + +NS_IMETHODIMP +PuppetBidiKeyboard::IsLangRTL(bool* aIsRTL) +{ + *aIsRTL = mIsLangRTL; + return NS_OK; +} + +void +PuppetBidiKeyboard::SetIsLangRTL(bool aIsLangRTL) +{ + mIsLangRTL = aIsLangRTL; +} + +NS_IMETHODIMP +PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult) +{ + // not implemented yet + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/widget/PuppetBidiKeyboard.h b/widget/PuppetBidiKeyboard.h new file mode 100644 index 0000000000..54c68582aa --- /dev/null +++ b/widget/PuppetBidiKeyboard.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_widget_PuppetBidiKeyboard_h_ +#define mozilla_widget_PuppetBidiKeyboard_h_ + +#include "nsIBidiKeyboard.h" + +namespace mozilla { +namespace widget { + +class PuppetBidiKeyboard final : public nsIBidiKeyboard +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIBIDIKEYBOARD + + PuppetBidiKeyboard(); + + void SetIsLangRTL(bool aIsLangRTL); + +private: + ~PuppetBidiKeyboard(); + + bool mIsLangRTL; +}; + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_PuppetBidiKeyboard_h_ diff --git a/widget/android/APZCCallbackHandler.cpp b/widget/android/APZCCallbackHandler.cpp deleted file mode 100644 index b4bb446fad..0000000000 --- a/widget/android/APZCCallbackHandler.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "APZCCallbackHandler.h" -#include "mozilla/layers/APZCCallbackHelper.h" -#include "mozilla/layers/APZCTreeManager.h" -#include "nsAppShell.h" -#include "nsLayoutUtils.h" -#include "nsPrintfCString.h" -#include "nsThreadUtils.h" -#include "base/message_loop.h" -#include "nsWindow.h" -#include "nsIInterfaceRequestorUtils.h" -#include "AndroidBridge.h" -#include "nsIContent.h" - -using mozilla::layers::APZCCallbackHelper; -using mozilla::layers::APZCTreeManager; -using mozilla::layers::FrameMetrics; -using mozilla::layers::ScrollableLayerGuid; - -namespace mozilla { -namespace widget { -namespace android { - -StaticRefPtr APZCCallbackHandler::sInstance; - -NativePanZoomController::LocalRef -APZCCallbackHandler::SetNativePanZoomController(NativePanZoomController::Param obj) -{ - NativePanZoomController::LocalRef old = mNativePanZoomController; - mNativePanZoomController = obj; - return old; -} - -void -APZCCallbackHandler::NotifyDefaultPrevented(uint64_t aInputBlockId, - bool aDefaultPrevented) -{ - if (!AndroidBridge::IsJavaUiThread()) { - // The notification must reach the APZ on the Java UI thread (aka the - // APZ "controller" thread) but we get it from the Goanna thread, so we - // have to throw it onto the other thread. - AndroidBridge::Bridge()->PostTaskToUiThread(NewRunnableMethod( - this, &APZCCallbackHandler::NotifyDefaultPrevented, - aInputBlockId, aDefaultPrevented), 0); - return; - } - - MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); - APZCTreeManager* controller = nsWindow::GetAPZCTreeManager(); - if (controller) { - controller->ContentReceivedInputBlock(aInputBlockId, aDefaultPrevented); - } -} - -nsIDOMWindowUtils* -APZCCallbackHandler::GetDOMWindowUtils() -{ - nsIAndroidBrowserApp* browserApp = nullptr; - if (!nsAppShell::gAppShell) { - return nullptr; - } - nsAppShell::gAppShell->GetBrowserApp(&browserApp); - if (!browserApp) { - return nullptr; - } - nsIBrowserTab* tab = nullptr; - if (browserApp->GetSelectedTab(&tab) != NS_OK) { - return nullptr; - } - nsIDOMWindow* window = nullptr; - if (tab->GetWindow(&window) != NS_OK) { - return nullptr; - } - nsCOMPtr utils = do_GetInterface(window); - return utils.get(); -} - -void -APZCCallbackHandler::RequestContentRepaint(const FrameMetrics& aFrameMetrics) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID); - - if (aFrameMetrics.GetIsRoot()) { - nsIDOMWindowUtils* utils = GetDOMWindowUtils(); - if (utils && APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) { - FrameMetrics metrics = aFrameMetrics; - APZCCallbackHelper::UpdateRootFrame(utils, metrics); - } - } else { - // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe. - // This requires special handling. - nsCOMPtr content = nsLayoutUtils::FindContentFor(aFrameMetrics.GetScrollId()); - if (content) { - FrameMetrics newSubFrameMetrics(aFrameMetrics); - APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics); - } - } -} - -void -APZCCallbackHandler::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, - const mozilla::CSSPoint& aDestination) -{ - APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination); -} - -void -APZCCallbackHandler::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, - const uint32_t& aScrollGeneration) -{ - APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration); -} - -void -APZCCallbackHandler::HandleDoubleTap(const CSSPoint& aPoint, - Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) -{ - CSSIntPoint point = RoundedToInt(aPoint); - nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y); - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeBroadcastEvent( - NS_LITERAL_CSTRING("Gesture:DoubleTap"), data)); -} - -void -APZCCallbackHandler::HandleSingleTap(const CSSPoint& aPoint, - Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) -{ - // FIXME Send the modifier data to Goanna for use in mouse events. - CSSIntPoint point = RoundedToInt(aPoint); - nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y); - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeBroadcastEvent( - NS_LITERAL_CSTRING("Gesture:SingleTap"), data)); -} - -void -APZCCallbackHandler::HandleLongTap(const CSSPoint& aPoint, - Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId) -{ - // TODO send content response back to APZC - CSSIntPoint point = RoundedToInt(aPoint); - nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y); - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeBroadcastEvent( - NS_LITERAL_CSTRING("Gesture:LongPress"), data)); -} - -void -APZCCallbackHandler::HandleLongTapUp(const CSSPoint& aPoint, - Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) -{ - HandleSingleTap(aPoint, aModifiers, aGuid); -} - -void -APZCCallbackHandler::SendAsyncScrollDOMEvent(bool aIsRoot, - const CSSRect& aContentRect, - const CSSSize& aScrollableSize) -{ - // no-op, we don't want to support this event on fennec, and we - // want to get rid of this entirely. See bug 898075. -} - -void -APZCCallbackHandler::PostDelayedTask(Task* aTask, int aDelayMs) -{ - AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs); -} - -} // namespace android -} // namespace widget -} // namespace mozilla diff --git a/widget/android/APZCCallbackHandler.h b/widget/android/APZCCallbackHandler.h deleted file mode 100644 index 0189ecb743..0000000000 --- a/widget/android/APZCCallbackHandler.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef APZCCallbackHandler_h__ -#define APZCCallbackHandler_h__ - -#include "mozilla/layers/GeckoContentController.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/TimeStamp.h" -#include "GeneratedJNIWrappers.h" -#include "nsIDOMWindowUtils.h" -#include "nsTArray.h" - -namespace mozilla { -namespace widget { -namespace android { - -class APZCCallbackHandler final : public mozilla::layers::GeckoContentController -{ -private: - static StaticRefPtr sInstance; - NativePanZoomController::GlobalRef mNativePanZoomController; - -private: - APZCCallbackHandler() - : mNativePanZoomController(nullptr) - {} - - nsIDOMWindowUtils* GetDOMWindowUtils(); - -public: - static APZCCallbackHandler* GetInstance() { - if (sInstance.get() == nullptr) { - sInstance = new APZCCallbackHandler(); - } - return sInstance.get(); - } - - NativePanZoomController::LocalRef SetNativePanZoomController(NativePanZoomController::Param obj); - void NotifyDefaultPrevented(uint64_t aInputBlockId, bool aDefaultPrevented); - -public: // GeckoContentController methods - void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics) override; - void RequestFlingSnap(const mozilla::layers::FrameMetrics::ViewID& aScrollId, - const mozilla::CSSPoint& aDestination) override; - void AcknowledgeScrollUpdate(const mozilla::layers::FrameMetrics::ViewID& aScrollId, - const uint32_t& aScrollGeneration) override; - void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) override; - void HandleSingleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) override; - void HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId) override; - void HandleLongTapUp(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) override; - void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect& aContentRect, - const mozilla::CSSSize& aScrollableSize) override; - void PostDelayedTask(Task* aTask, int aDelayMs) override; -}; - -} // namespace android -} // namespace widget -} // namespace mozilla - -#endif diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp deleted file mode 100644 index 15a19c61ce..0000000000 --- a/widget/android/AndroidBridge.cpp +++ /dev/null @@ -1,2089 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/layers/CompositorChild.h" -#include "mozilla/layers/CompositorParent.h" - -#include -#include -#include - -#include "mozilla/Hal.h" -#include "nsXULAppAPI.h" -#include -#include "nsXPCOMStrings.h" -#include "AndroidBridge.h" -#include "AndroidJNIWrapper.h" -#include "AndroidBridgeUtilities.h" -#include "nsAppShell.h" -#include "nsOSHelperAppService.h" -#include "nsWindow.h" -#include "mozilla/Preferences.h" -#include "nsThreadUtils.h" -#include "nsIThreadManager.h" -#include "mozilla/dom/mobilemessage/PSms.h" -#include "gfxPlatform.h" -#include "gfxContext.h" -#include "mozilla/gfx/2D.h" -#include "gfxUtils.h" -#include "nsPresContext.h" -#include "nsIDocShell.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/ScreenOrientation.h" -#include "nsIDOMWindowUtils.h" -#include "nsIDOMClientRect.h" -#include "StrongPointer.h" -#include "mozilla/ClearOnShutdown.h" -#include "nsPrintfCString.h" -#include "NativeJSContainer.h" -#include "nsContentUtils.h" -#include "nsIScriptError.h" -#include "nsIHttpChannel.h" - -#include "MediaCodec.h" -#include "SurfaceTexture.h" - -using namespace mozilla; -using namespace mozilla::gfx; -using namespace mozilla::jni; -using namespace mozilla::widget; - -AndroidBridge* AndroidBridge::sBridge; -pthread_t AndroidBridge::sJavaUiThread = -1; -static unsigned sJavaEnvThreadIndex = 0; -static jobject sGlobalContext = nullptr; -static void JavaThreadDetachFunc(void *arg); - -// This is a dummy class that can be used in the template for android::sp -class AndroidRefable { - void incStrong(void* thing) { } - void decStrong(void* thing) { } -}; - -// This isn't in AndroidBridge.h because including StrongPointer.h there is gross -static android::sp (*android_SurfaceTexture_getNativeWindow)(JNIEnv* env, jobject surfaceTexture) = nullptr; - -jclass AndroidBridge::GetClassGlobalRef(JNIEnv* env, const char* className) -{ - // First try the default class loader. - auto classRef = ClassObject::LocalRef::Adopt( - env, env->FindClass(className)); - - if (!classRef && sBridge && sBridge->mClassLoader) { - // If the default class loader failed but we have an app class loader, try that. - // Clear the pending exception from failed FindClass call above. - env->ExceptionClear(); - classRef = ClassObject::LocalRef::Adopt(env, - env->CallObjectMethod(sBridge->mClassLoader.Get(), - sBridge->mClassLoaderLoadClass, - Param::Type(className, env).Get())); - } - - if (!classRef) { - ALOG(">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. " - "Did ProGuard optimize away something it shouldn't have?", - className); - env->ExceptionDescribe(); - MOZ_CRASH(); - } - - return ClassObject::GlobalRef(env, classRef).Forget(); -} - -jmethodID AndroidBridge::GetMethodID(JNIEnv* env, jclass jClass, - const char* methodName, const char* methodType) -{ - jmethodID methodID = env->GetMethodID(jClass, methodName, methodType); - if (!methodID) { - ALOG(">>> FATAL JNI ERROR! GetMethodID(methodName=\"%s\", " - "methodType=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?", - methodName, methodType); - env->ExceptionDescribe(); - MOZ_CRASH(); - } - return methodID; -} - -jmethodID AndroidBridge::GetStaticMethodID(JNIEnv* env, jclass jClass, - const char* methodName, const char* methodType) -{ - jmethodID methodID = env->GetStaticMethodID(jClass, methodName, methodType); - if (!methodID) { - ALOG(">>> FATAL JNI ERROR! GetStaticMethodID(methodName=\"%s\", " - "methodType=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?", - methodName, methodType); - env->ExceptionDescribe(); - MOZ_CRASH(); - } - return methodID; -} - -jfieldID AndroidBridge::GetFieldID(JNIEnv* env, jclass jClass, - const char* fieldName, const char* fieldType) -{ - jfieldID fieldID = env->GetFieldID(jClass, fieldName, fieldType); - if (!fieldID) { - ALOG(">>> FATAL JNI ERROR! GetFieldID(fieldName=\"%s\", " - "fieldType=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?", - fieldName, fieldType); - env->ExceptionDescribe(); - MOZ_CRASH(); - } - return fieldID; -} - -jfieldID AndroidBridge::GetStaticFieldID(JNIEnv* env, jclass jClass, - const char* fieldName, const char* fieldType) -{ - jfieldID fieldID = env->GetStaticFieldID(jClass, fieldName, fieldType); - if (!fieldID) { - ALOG(">>> FATAL JNI ERROR! GetStaticFieldID(fieldName=\"%s\", " - "fieldType=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?", - fieldName, fieldType); - env->ExceptionDescribe(); - MOZ_CRASH(); - } - return fieldID; -} - -void -AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader) -{ - /* NSS hack -- bionic doesn't handle recursive unloads correctly, - * because library finalizer functions are called with the dynamic - * linker lock still held. This results in a deadlock when trying - * to call dlclose() while we're already inside dlclose(). - * Conveniently, NSS has an env var that can prevent it from unloading. - */ - putenv("NSS_DISABLE_UNLOAD=1"); - - PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc); - - AndroidBridge *bridge = new AndroidBridge(); - if (!bridge->Init(jEnv, clsLoader)) { - delete bridge; - } - sBridge = bridge; -} - -bool -AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader) -{ - ALOG_BRIDGE("AndroidBridge::Init"); - jEnv->GetJavaVM(&mJavaVM); - if (!mJavaVM) { - MOZ_CRASH(); // Nothing we can do here - } - - AutoLocalJNIFrame jniFrame(jEnv); - - mClassLoader = Object::GlobalRef(jEnv, clsLoader); - mClassLoaderLoadClass = GetMethodID( - jEnv, jEnv->GetObjectClass(clsLoader.Get()), - "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - - mJNIEnv = nullptr; - mThread = -1; - mGLControllerObj = nullptr; - mOpenedGraphicsLibraries = false; - mHasNativeBitmapAccess = false; - mHasNativeWindowAccess = false; - mHasNativeWindowFallback = false; - -#ifdef MOZ_WEBSMS_BACKEND - AutoJNIClass smsMessage(jEnv, "android/telephony/SmsMessage"); - mAndroidSmsMessageClass = smsMessage.getGlobalRef(); - jCalculateLength = smsMessage.getStaticMethod("calculateLength", "(Ljava/lang/CharSequence;Z)[I"); -#endif - - AutoJNIClass string(jEnv, "java/lang/String"); - jStringClass = string.getGlobalRef(); - - if (!GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &mAPIVersion, jEnv)) { - ALOG_BRIDGE("Failed to find API version"); - } - - AutoJNIClass surface(jEnv, "android/view/Surface"); - jSurfaceClass = surface.getGlobalRef(); - if (mAPIVersion <= 8 /* Froyo */) { - jSurfacePointerField = surface.getField("mSurface", "I"); - } else if (mAPIVersion > 8 && mAPIVersion < 19 /* KitKat */) { - jSurfacePointerField = surface.getField("mNativeSurface", "I"); - } else { - // We don't know how to get this, just set it to 0 - jSurfacePointerField = 0; - } - - AutoJNIClass egl(jEnv, "com/google/android/gles_jni/EGLSurfaceImpl"); - jclass eglClass = egl.getGlobalRef(); - if (eglClass) { - // The pointer type moved to a 'long' in Android L, API version 20 - const char* jniType = mAPIVersion >= 20 ? "J" : "I"; - jEGLSurfacePointerField = egl.getField("mEGLSurface", jniType); - } else { - jEGLSurfacePointerField = 0; - } - - AutoJNIClass channels(jEnv, "java/nio/channels/Channels"); - jChannels = channels.getGlobalRef(); - jChannelCreate = channels.getStaticMethod("newChannel", "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;"); - - AutoJNIClass readableByteChannel(jEnv, "java/nio/channels/ReadableByteChannel"); - jReadableByteChannel = readableByteChannel.getGlobalRef(); - jByteBufferRead = readableByteChannel.getMethod("read", "(Ljava/nio/ByteBuffer;)I"); - - AutoJNIClass inputStream(jEnv, "java/io/InputStream"); - jInputStream = inputStream.getGlobalRef(); - jClose = inputStream.getMethod("close", "()V"); - jAvailable = inputStream.getMethod("available", "()I"); - - InitAndroidJavaWrappers(jEnv); - - // jEnv should NOT be cached here by anything -- the jEnv here - // is not valid for the real goanna main thread, which is set - // at SetMainThread time. - - return true; -} - -bool -AndroidBridge::SetMainThread(pthread_t thr) -{ - ALOG_BRIDGE("AndroidBridge::SetMainThread"); - if (thr) { - mThread = thr; - mJavaVM->GetEnv((void**) &mJNIEnv, JNI_VERSION_1_2); - return (bool) mJNIEnv; - } - - mJNIEnv = nullptr; - mThread = -1; - return true; -} - -// Raw JNIEnv variants. -jstring AndroidBridge::NewJavaString(JNIEnv* env, const char16_t* string, uint32_t len) { - jstring ret = env->NewString(reinterpret_cast(string), len); - if (env->ExceptionCheck()) { - ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); - env->ExceptionDescribe(); - env->ExceptionClear(); - return nullptr; - } - return ret; -} - -jstring AndroidBridge::NewJavaString(JNIEnv* env, const nsAString& string) { - return NewJavaString(env, string.BeginReading(), string.Length()); -} - -jstring AndroidBridge::NewJavaString(JNIEnv* env, const char* string) { - return NewJavaString(env, NS_ConvertUTF8toUTF16(string)); -} - -jstring AndroidBridge::NewJavaString(JNIEnv* env, const nsACString& string) { - return NewJavaString(env, NS_ConvertUTF8toUTF16(string)); -} - -// AutoLocalJNIFrame variants.. -jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const char16_t* string, uint32_t len) { - return NewJavaString(frame->GetEnv(), string, len); -} - -jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsAString& string) { - return NewJavaString(frame, string.BeginReading(), string.Length()); -} - -jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const char* string) { - return NewJavaString(frame, NS_ConvertUTF8toUTF16(string)); -} - -jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string) { - return NewJavaString(frame, NS_ConvertUTF8toUTF16(string)); -} - -extern "C" { - __attribute__ ((visibility("default"))) - JNIEnv * GetJNIForThread() - { - JNIEnv *jEnv = static_cast(PR_GetThreadPrivate(sJavaEnvThreadIndex)); - if (jEnv) { - return jEnv; - } - JavaVM *jVm = mozilla::AndroidBridge::GetVM(); - if (!jVm->GetEnv(reinterpret_cast(&jEnv), JNI_VERSION_1_2)) { - MOZ_ASSERT(jEnv); - return jEnv; - } - if (!jVm->AttachCurrentThread(&jEnv, nullptr)) { - MOZ_ASSERT(jEnv); - PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv); - return jEnv; - } - MOZ_CRASH(); - return nullptr; // unreachable - } -} - -void AutoGlobalWrappedJavaObject::Dispose() { - if (isNull()) { - return; - } - - GetJNIForThread()->DeleteGlobalRef(wrapped_obj); - wrapped_obj = nullptr; -} - -AutoGlobalWrappedJavaObject::~AutoGlobalWrappedJavaObject() { - Dispose(); -} - -// Decides if we should store thumbnails for a given docshell based on the presence -// of a Cache-Control: no-store header and the "browser.cache.disk_cache_ssl" pref. -static bool ShouldStoreThumbnail(nsIDocShell* docshell) { - if (!docshell) { - return false; - } - - nsresult rv; - nsCOMPtr channel; - - docshell->GetCurrentDocumentChannel(getter_AddRefs(channel)); - if (!channel) { - return false; - } - - nsCOMPtr httpChannel; - rv = channel->QueryInterface(NS_GET_IID(nsIHttpChannel), getter_AddRefs(httpChannel)); - if (!NS_SUCCEEDED(rv)) { - return false; - } - - // Don't store thumbnails for sites that didn't load - uint32_t responseStatus; - rv = httpChannel->GetResponseStatus(&responseStatus); - if (!NS_SUCCEEDED(rv) || floor((double) (responseStatus / 100)) != 2) { - return false; - } - - // Cache-Control: no-store. - bool isNoStoreResponse = false; - httpChannel->IsNoStoreResponse(&isNoStoreResponse); - if (isNoStoreResponse) { - return false; - } - - // Deny storage if we're viewing a HTTPS page with a - // 'Cache-Control' header having a value that is not 'public'. - nsCOMPtr uri; - rv = channel->GetURI(getter_AddRefs(uri)); - if (!NS_SUCCEEDED(rv)) { - return false; - } - - // Don't capture HTTPS pages unless the user enabled it - // or the page has a Cache-Control:public header. - bool isHttps = false; - uri->SchemeIs("https", &isHttps); - if (isHttps && !Preferences::GetBool("browser.cache.disk_cache_ssl", false)) { - nsAutoCString cacheControl; - rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"), cacheControl); - if (!NS_SUCCEEDED(rv)) { - return false; - } - - if (!cacheControl.IsEmpty() && !cacheControl.LowerCaseEqualsLiteral("public")) { - return false; - } - } - - return true; -} - -static void -getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen, - nsIMutableArray *aHandlersArray, - nsIHandlerApp **aDefaultApp, - const nsAString& aAction = EmptyString(), - const nsACString& aMimeType = EmptyCString()) -{ - nsString empty = EmptyString(); - for (jsize i = 0; i < aLen; i+=4) { - - AutoLocalJNIFrame jniFrame(aJNIEnv, 4); - nsJNIString name( - static_cast(aJNIEnv->GetObjectArrayElement(jArr, i)), aJNIEnv); - nsJNIString isDefault( - static_cast(aJNIEnv->GetObjectArrayElement(jArr, i + 1)), aJNIEnv); - nsJNIString packageName( - static_cast(aJNIEnv->GetObjectArrayElement(jArr, i + 2)), aJNIEnv); - nsJNIString className( - static_cast(aJNIEnv->GetObjectArrayElement(jArr, i + 3)), aJNIEnv); - nsIHandlerApp* app = nsOSHelperAppService:: - CreateAndroidHandlerApp(name, className, packageName, - className, aMimeType, aAction); - - aHandlersArray->AppendElement(app, false); - if (aDefaultApp && isDefault.Length() > 0) - *aDefaultApp = app; - } -} - -bool -AndroidBridge::GetHandlersForMimeType(const nsAString& aMimeType, - nsIMutableArray *aHandlersArray, - nsIHandlerApp **aDefaultApp, - const nsAString& aAction) -{ - ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType"); - - auto arr = GoannaAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction); - if (!arr) - return false; - - JNIEnv* const env = arr.Env(); - jsize len = env->GetArrayLength(arr.Get()); - - if (!aHandlersArray) - return len > 0; - - getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray, - aDefaultApp, aAction, - NS_ConvertUTF16toUTF8(aMimeType)); - return true; -} - -bool -AndroidBridge::GetHandlersForURL(const nsAString& aURL, - nsIMutableArray* aHandlersArray, - nsIHandlerApp **aDefaultApp, - const nsAString& aAction) -{ - ALOG_BRIDGE("AndroidBridge::GetHandlersForURL"); - - auto arr = GoannaAppShell::GetHandlersForURLWrapper(aURL, aAction); - if (!arr) - return false; - - JNIEnv* const env = arr.Env(); - jsize len = env->GetArrayLength(arr.Get()); - - if (!aHandlersArray) - return len > 0; - - getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray, - aDefaultApp, aAction); - return true; -} - -void -AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType) -{ - ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions"); - - auto jstrType = GoannaAppShell::GetMimeTypeFromExtensionsWrapper(aFileExt); - - if (jstrType) { - aMimeType = jstrType; - } -} - -void -AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt) -{ - ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType"); - - auto jstrExt = GoannaAppShell::GetExtensionFromMimeTypeWrapper(aMimeType); - - if (jstrExt) { - aFileExt = nsCString(jstrExt); - } -} - -bool -AndroidBridge::GetClipboardText(nsAString& aText) -{ - ALOG_BRIDGE("AndroidBridge::GetClipboardText"); - - auto text = Clipboard::GetClipboardTextWrapper(); - - if (text) { - aText = nsString(text); - } - return !!text; -} - -void -AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl, - const nsAString& aAlertTitle, - const nsAString& aAlertText, - const nsAString& aAlertCookie, - nsIObserver *aAlertListener, - const nsAString& aAlertName) -{ - if (nsAppShell::gAppShell && aAlertListener) { - // This will remove any observers already registered for this id - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeAddObserver(aAlertName, aAlertListener)); - } - - GoannaAppShell::ShowAlertNotificationWrapper - (aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName); -} - -int -AndroidBridge::GetDPI() -{ - static int sDPI = 0; - if (sDPI) - return sDPI; - - const int DEFAULT_DPI = 160; - - sDPI = GoannaAppShell::GetDpiWrapper(); - if (!sDPI) { - return DEFAULT_DPI; - } - - return sDPI; -} - -int -AndroidBridge::GetScreenDepth() -{ - ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); - - static int sDepth = 0; - if (sDepth) - return sDepth; - - const int DEFAULT_DEPTH = 16; - - if (HasEnv()) { - sDepth = GoannaAppShell::GetScreenDepthWrapper(); - } - if (!sDepth) - return DEFAULT_DEPTH; - - return sDepth; -} -void -AndroidBridge::Vibrate(const nsTArray& aPattern) -{ - ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); - - uint32_t len = aPattern.Length(); - if (!len) { - ALOG_BRIDGE(" invalid 0-length array"); - return; - } - - // It's clear if this worth special-casing, but it creates less - // java junk, so dodges the GC. - if (len == 1) { - jlong d = aPattern[0]; - if (d < 0) { - ALOG_BRIDGE(" invalid vibration duration < 0"); - return; - } - GoannaAppShell::Vibrate1(d); - return; - } - - // First element of the array vibrate() expects is how long to wait - // *before* vibrating. For us, this is always 0. - - JNIEnv *env = GetJNIEnv(); - AutoLocalJNIFrame jniFrame(env, 1); - - jlongArray array = env->NewLongArray(len + 1); - if (!array) { - ALOG_BRIDGE(" failed to allocate array"); - return; - } - - jlong* elts = env->GetLongArrayElements(array, nullptr); - elts[0] = 0; - for (uint32_t i = 0; i < aPattern.Length(); ++i) { - jlong d = aPattern[i]; - if (d < 0) { - ALOG_BRIDGE(" invalid vibration duration < 0"); - env->ReleaseLongArrayElements(array, elts, JNI_ABORT); - return; - } - elts[i + 1] = d; - } - env->ReleaseLongArrayElements(array, elts, 0); - - GoannaAppShell::VibrateA(LongArray::Ref::From(array), -1 /* don't repeat */); -} - -void -AndroidBridge::GetSystemColors(AndroidSystemColors *aColors) -{ - - NS_ASSERTION(aColors != nullptr, "AndroidBridge::GetSystemColors: aColors is null!"); - if (!aColors) - return; - - auto arr = GoannaAppShell::GetSystemColoursWrapper(); - if (!arr) - return; - - JNIEnv* const env = arr.Env(); - uint32_t len = static_cast(env->GetArrayLength(arr.Get())); - jint *elements = env->GetIntArrayElements(arr.Get(), 0); - - uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor); - if (len < colorsCount) - colorsCount = len; - - // Convert Android colors to nscolor by switching R and B in the ARGB 32 bit value - nscolor *colors = (nscolor*)aColors; - - for (uint32_t i = 0; i < colorsCount; i++) { - uint32_t androidColor = static_cast(elements[i]); - uint8_t r = (androidColor & 0x00ff0000) >> 16; - uint8_t b = (androidColor & 0x000000ff); - colors[i] = (androidColor & 0xff00ff00) | (b << 16) | r; - } - - env->ReleaseIntArrayElements(arr.Get(), elements, 0); -} - -void -AndroidBridge::GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf) -{ - ALOG_BRIDGE("AndroidBridge::GetIconForExtension"); - NS_ASSERTION(aBuf != nullptr, "AndroidBridge::GetIconForExtension: aBuf is null!"); - if (!aBuf) - return; - - auto arr = GoannaAppShell::GetIconForExtensionWrapper - (NS_ConvertUTF8toUTF16(aFileExt), aIconSize); - - NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!"); - if (!arr) - return; - - JNIEnv* const env = arr.Env(); - uint32_t len = static_cast(env->GetArrayLength(arr.Get())); - jbyte *elements = env->GetByteArrayElements(arr.Get(), 0); - - uint32_t bufSize = aIconSize * aIconSize * 4; - NS_ASSERTION(len == bufSize, "AndroidBridge::GetIconForExtension: Pixels array is incomplete!"); - if (len == bufSize) - memcpy(aBuf, elements, bufSize); - - env->ReleaseByteArrayElements(arr.Get(), elements, 0); -} - -void -AndroidBridge::SetLayerClient(GoannaLayerClient::Param jobj) -{ - // if resetting is true, that means Android destroyed our GoannaApp activity - // and we had to recreate it, but all the Goanna-side things were not destroyed. - // We therefore need to link up the new java objects to Goanna, and that's what - // we do here. - bool resetting = (mLayerClient != nullptr); - - mLayerClient = jobj; - - if (resetting) { - // since we are re-linking the new java objects to Goanna, we need to get - // the viewport from the compositor (since the Java copy was thrown away) - // and we do that by setting the first-paint flag. - nsWindow::ForceIsFirstPaint(); - } -} - -void -AndroidBridge::RegisterCompositor(JNIEnv *env) -{ - if (mGLControllerObj != nullptr) { - // we already have this set up, no need to do it again - return; - } - - mGLControllerObj = GLController::LocalRef( - LayerView::RegisterCompositorWrapper()); -} - -EGLSurface -AndroidBridge::CreateEGLSurfaceForCompositor() -{ - if (!jEGLSurfacePointerField) { - return nullptr; - } - MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref"); - - auto eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper(); - if (!eglSurface) { - return nullptr; - } - - JNIEnv* const env = GetJNIForThread(); // called on the compositor thread - return reinterpret_cast( - env->GetIntField(eglSurface.Get(), jEGLSurfacePointerField)); -} - -bool -AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, int32_t* aInt, JNIEnv* jEnv /* = nullptr */) -{ - ALOG_BRIDGE("AndroidBridge::GetStaticIntField %s", fieldName); - - if (!jEnv) { - if (!HasEnv()) { - return false; - } - jEnv = GetJNIEnv(); - } - - AutoJNIClass cls(jEnv, className); - jfieldID field = cls.getStaticField(fieldName, "I"); - - if (!field) { - return false; - } - - *aInt = static_cast(jEnv->GetStaticIntField(cls.getRawRef(), field)); - return true; -} - -bool -AndroidBridge::GetStaticStringField(const char *className, const char *fieldName, nsAString &result, JNIEnv* jEnv /* = nullptr */) -{ - ALOG_BRIDGE("AndroidBridge::GetStaticStringField %s", fieldName); - - if (!jEnv) { - if (!HasEnv()) { - return false; - } - jEnv = GetJNIEnv(); - } - - AutoLocalJNIFrame jniFrame(jEnv, 1); - AutoJNIClass cls(jEnv, className); - jfieldID field = cls.getStaticField(fieldName, "Ljava/lang/String;"); - - if (!field) { - return false; - } - - jstring jstr = (jstring) jEnv->GetStaticObjectField(cls.getRawRef(), field); - if (!jstr) - return false; - - result.Assign(nsJNIString(jstr, jEnv)); - return true; -} - -// Available for places elsewhere in the code to link to. -bool -mozilla_AndroidBridge_SetMainThread(pthread_t thr) -{ - return AndroidBridge::Bridge()->SetMainThread(thr); -} - -void* -AndroidBridge::GetNativeSurface(JNIEnv* env, jobject surface) { - if (!env || !mHasNativeWindowFallback || !jSurfacePointerField) - return nullptr; - - return (void*)env->GetIntField(surface, jSurfacePointerField); -} - -void -AndroidBridge::OpenGraphicsLibraries() -{ - if (!mOpenedGraphicsLibraries) { - // Try to dlopen libjnigraphics.so for direct bitmap access on - // Android 2.2+ (API level 8) - mOpenedGraphicsLibraries = true; - mHasNativeWindowAccess = false; - mHasNativeWindowFallback = false; - mHasNativeBitmapAccess = false; - - void *handle = dlopen("libjnigraphics.so", RTLD_LAZY | RTLD_LOCAL); - if (handle) { - AndroidBitmap_getInfo = (int (*)(JNIEnv *, jobject, void *))dlsym(handle, "AndroidBitmap_getInfo"); - AndroidBitmap_lockPixels = (int (*)(JNIEnv *, jobject, void **))dlsym(handle, "AndroidBitmap_lockPixels"); - AndroidBitmap_unlockPixels = (int (*)(JNIEnv *, jobject))dlsym(handle, "AndroidBitmap_unlockPixels"); - - mHasNativeBitmapAccess = AndroidBitmap_getInfo && AndroidBitmap_lockPixels && AndroidBitmap_unlockPixels; - - ALOG_BRIDGE("Successfully opened libjnigraphics.so, have native bitmap access? %d", mHasNativeBitmapAccess); - } - - // Try to dlopen libandroid.so for and native window access on - // Android 2.3+ (API level 9) - handle = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL); - if (handle) { - ANativeWindow_fromSurface = (void* (*)(JNIEnv*, jobject))dlsym(handle, "ANativeWindow_fromSurface"); - ANativeWindow_release = (void (*)(void*))dlsym(handle, "ANativeWindow_release"); - ANativeWindow_setBuffersGeometry = (int (*)(void*, int, int, int)) dlsym(handle, "ANativeWindow_setBuffersGeometry"); - ANativeWindow_lock = (int (*)(void*, void*, void*)) dlsym(handle, "ANativeWindow_lock"); - ANativeWindow_unlockAndPost = (int (*)(void*))dlsym(handle, "ANativeWindow_unlockAndPost"); - - // This is only available in Honeycomb and ICS. It was removed in Jelly Bean - ANativeWindow_fromSurfaceTexture = (void* (*)(JNIEnv*, jobject))dlsym(handle, "ANativeWindow_fromSurfaceTexture"); - - mHasNativeWindowAccess = ANativeWindow_fromSurface && ANativeWindow_release && ANativeWindow_lock && ANativeWindow_unlockAndPost; - - ALOG_BRIDGE("Successfully opened libandroid.so, have native window access? %d", mHasNativeWindowAccess); - } - - // We need one symbol from here on Jelly Bean - handle = dlopen("libandroid_runtime.so", RTLD_LAZY | RTLD_LOCAL); - if (handle) { - android_SurfaceTexture_getNativeWindow = (android::sp (*)(JNIEnv*, jobject))dlsym(handle, "_ZN7android38android_SurfaceTexture_getNativeWindowEP7_JNIEnvP8_jobject"); - } - - if (mHasNativeWindowAccess) - return; - - // Look up Surface functions, used for native window (surface) fallback - handle = dlopen("libsurfaceflinger_client.so", RTLD_LAZY); - if (handle) { - Surface_lock = (int (*)(void*, void*, void*, bool))dlsym(handle, "_ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionEb"); - Surface_unlockAndPost = (int (*)(void*))dlsym(handle, "_ZN7android7Surface13unlockAndPostEv"); - - handle = dlopen("libui.so", RTLD_LAZY); - if (handle) { - Region_constructor = (void (*)(void*))dlsym(handle, "_ZN7android6RegionC1Ev"); - Region_set = (void (*)(void*, void*))dlsym(handle, "_ZN7android6Region3setERKNS_4RectE"); - - mHasNativeWindowFallback = Surface_lock && Surface_unlockAndPost && Region_constructor && Region_set; - } - } - } -} - -namespace mozilla { - class TracerRunnable : public nsRunnable{ - public: - TracerRunnable() { - mTracerLock = new Mutex("TracerRunnable"); - mTracerCondVar = new CondVar(*mTracerLock, "TracerRunnable"); - mMainThread = do_GetMainThread(); - - } - ~TracerRunnable() { - delete mTracerCondVar; - delete mTracerLock; - mTracerLock = nullptr; - mTracerCondVar = nullptr; - } - - virtual nsresult Run() { - MutexAutoLock lock(*mTracerLock); - if (!AndroidBridge::Bridge()) - return NS_OK; - - mHasRun = true; - mTracerCondVar->Notify(); - return NS_OK; - } - - bool Fire() { - if (!mTracerLock || !mTracerCondVar) - return false; - MutexAutoLock lock(*mTracerLock); - mHasRun = false; - mMainThread->Dispatch(this, NS_DISPATCH_NORMAL); - while (!mHasRun) - mTracerCondVar->Wait(); - return true; - } - - void Signal() { - MutexAutoLock lock(*mTracerLock); - mHasRun = true; - mTracerCondVar->Notify(); - } - private: - Mutex* mTracerLock; - CondVar* mTracerCondVar; - bool mHasRun; - nsCOMPtr mMainThread; - - }; - StaticRefPtr sTracerRunnable; - - bool InitWidgetTracing() { - if (!sTracerRunnable) - sTracerRunnable = new TracerRunnable(); - return true; - } - - void CleanUpWidgetTracing() { - sTracerRunnable = nullptr; - } - - bool FireAndWaitForTracerEvent() { - if (sTracerRunnable) - return sTracerRunnable->Fire(); - return false; - } - - void SignalTracerThread() - { - if (sTracerRunnable) - return sTracerRunnable->Signal(); - } - -} -bool -AndroidBridge::HasNativeBitmapAccess() -{ - OpenGraphicsLibraries(); - - return mHasNativeBitmapAccess; -} - -bool -AndroidBridge::ValidateBitmap(jobject bitmap, int width, int height) -{ - // This structure is defined in Android API level 8's - // Because we can't depend on this, we get the function pointers via dlsym - // and define this struct ourselves. - struct BitmapInfo { - uint32_t width; - uint32_t height; - uint32_t stride; - uint32_t format; - uint32_t flags; - }; - - int err; - struct BitmapInfo info = { 0, }; - - JNIEnv *env = GetJNIEnv(); - - if ((err = AndroidBitmap_getInfo(env, bitmap, &info)) != 0) { - ALOG_BRIDGE("AndroidBitmap_getInfo failed! (error %d)", err); - return false; - } - - if ((int)info.width != width || (int)info.height != height) - return false; - - return true; -} - -bool -AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps) -{ - auto arr = GoannaAppShell::InitCameraWrapper - (NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) *width, (int32_t) *height); - - if (!arr) - return false; - - JNIEnv* const env = arr.Env(); - jint *elements = env->GetIntArrayElements(arr.Get(), 0); - - *width = elements[1]; - *height = elements[2]; - *fps = elements[3]; - - bool res = elements[0] == 1; - - env->ReleaseIntArrayElements(arr.Get(), elements, 0); - - return res; -} - -void -AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo) -{ - ALOG_BRIDGE("AndroidBridge::GetCurrentBatteryInformation"); - - // To prevent calling too many methods through JNI, the Java method returns - // an array of double even if we actually want a double and a boolean. - auto arr = GoannaAppShell::GetCurrentBatteryInformationWrapper(); - - JNIEnv* const env = arr.Env(); - if (!arr || env->GetArrayLength(arr.Get()) != 3) { - return; - } - - jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0); - - aBatteryInfo->level() = info[0]; - aBatteryInfo->charging() = info[1] == 1.0f; - aBatteryInfo->remainingTime() = info[2]; - - env->ReleaseDoubleArrayElements(arr.Get(), info, 0); -} - -void -AndroidBridge::HandleGoannaMessage(JSContext* cx, JS::HandleObject object) -{ - ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); - - JNIEnv* const env = GetJNIEnv(); - auto message = Object::LocalRef::Adopt(env, - mozilla::widget::CreateNativeJSContainer(env, cx, object)); - GoannaAppShell::HandleGoannaMessageWrapper(message); -} - -nsresult -AndroidBridge::GetSegmentInfoForText(const nsAString& aText, - nsIMobileMessageCallback* aRequest) -{ -#ifndef MOZ_WEBSMS_BACKEND - return NS_ERROR_FAILURE; -#else - ALOG_BRIDGE("AndroidBridge::GetSegmentInfoForText"); - - int32_t segments, charsPerSegment, charsAvailableInLastSegment; - - JNIEnv *env = GetJNIEnv(); - - AutoLocalJNIFrame jniFrame(env, 2); - jstring jText = NewJavaString(&jniFrame, aText); - jobject obj = env->CallStaticObjectMethod(mAndroidSmsMessageClass, - jCalculateLength, jText, JNI_FALSE); - if (jniFrame.CheckForException()) - return NS_ERROR_FAILURE; - - jintArray arr = static_cast(obj); - if (!arr || env->GetArrayLength(arr) != 4) - return NS_ERROR_FAILURE; - - jint* info = env->GetIntArrayElements(arr, JNI_FALSE); - - segments = info[0]; // msgCount - charsPerSegment = info[2]; // codeUnitsRemaining - // segmentChars = (codeUnitCount + codeUnitsRemaining) / msgCount - charsAvailableInLastSegment = (info[1] + info[2]) / info[0]; - - env->ReleaseIntArrayElements(arr, info, JNI_ABORT); - - // TODO Bug 908598 - Should properly use |QueueSmsRequest(...)| to queue up - // the nsIMobileMessageCallback just like other functions. - return aRequest->NotifySegmentInfoForTextGot(segments, - charsPerSegment, - charsAvailableInLastSegment); -#endif -} - -void -AndroidBridge::SendMessage(const nsAString& aNumber, - const nsAString& aMessage, - nsIMobileMessageCallback* aRequest) -{ - ALOG_BRIDGE("AndroidBridge::SendMessage"); - - uint32_t requestId; - if (!QueueSmsRequest(aRequest, &requestId)) - return; - - GoannaAppShell::SendMessageWrapper(aNumber, aMessage, requestId); -} - -void -AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest) -{ - ALOG_BRIDGE("AndroidBridge::GetMessage"); - - uint32_t requestId; - if (!QueueSmsRequest(aRequest, &requestId)) - return; - - GoannaAppShell::GetMessageWrapper(aMessageId, requestId); -} - -void -AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest) -{ - ALOG_BRIDGE("AndroidBridge::DeleteMessage"); - - uint32_t requestId; - if (!QueueSmsRequest(aRequest, &requestId)) - return; - - GoannaAppShell::DeleteMessageWrapper(aMessageId, requestId); -} - -void -AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, bool aReverse, - nsIMobileMessageCallback* aRequest) -{ - ALOG_BRIDGE("AndroidBridge::CreateMessageList"); - - JNIEnv *env = GetJNIEnv(); - - uint32_t requestId; - if (!QueueSmsRequest(aRequest, &requestId)) - return; - - AutoLocalJNIFrame jniFrame(env, 2); - - jobjectArray numbers = - (jobjectArray)env->NewObjectArray(aFilter.numbers().Length(), - jStringClass, - NewJavaString(&jniFrame, EmptyString())); - - for (uint32_t i = 0; i < aFilter.numbers().Length(); ++i) { - jstring elem = NewJavaString(&jniFrame, aFilter.numbers()[i]); - env->SetObjectArrayElement(numbers, i, elem); - env->DeleteLocalRef(elem); - } - - int64_t startDate = aFilter.hasStartDate() ? aFilter.startDate() : -1; - int64_t endDate = aFilter.hasEndDate() ? aFilter.endDate() : -1; - GoannaAppShell::CreateMessageListWrapper(startDate, endDate, - ObjectArray::Ref::From(numbers), - aFilter.numbers().Length(), - aFilter.delivery(), - aFilter.hasRead(), aFilter.read(), - aFilter.threadId(), - aReverse, requestId); -} - -void -AndroidBridge::GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* aRequest) -{ - ALOG_BRIDGE("AndroidBridge::GetNextMessageInList"); - - uint32_t requestId; - if (!QueueSmsRequest(aRequest, &requestId)) - return; - - GoannaAppShell::GetNextMessageInListWrapper(aListId, requestId); -} - -bool -AndroidBridge::QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut) -{ - MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); - MOZ_ASSERT(aRequest && aRequestIdOut); - - const uint32_t length = mSmsRequests.Length(); - for (uint32_t i = 0; i < length; i++) { - if (!(mSmsRequests)[i]) { - (mSmsRequests)[i] = aRequest; - *aRequestIdOut = i; - return true; - } - } - - mSmsRequests.AppendElement(aRequest); - - // After AppendElement(), previous `length` points to the new tail element. - *aRequestIdOut = length; - return true; -} - -already_AddRefed -AndroidBridge::DequeueSmsRequest(uint32_t aRequestId) -{ - MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); - - MOZ_ASSERT(aRequestId < mSmsRequests.Length()); - if (aRequestId >= mSmsRequests.Length()) { - return nullptr; - } - - return mSmsRequests[aRequestId].forget(); -} - -void -AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo) -{ - ALOG_BRIDGE("AndroidBridge::GetCurrentNetworkInformation"); - - // To prevent calling too many methods through JNI, the Java method returns - // an array of double even if we actually want an integer, a boolean, and an integer. - - auto arr = GoannaAppShell::GetCurrentNetworkInformationWrapper(); - - JNIEnv* const env = arr.Env(); - if (!arr || env->GetArrayLength(arr.Get()) != 3) { - return; - } - - jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0); - - aNetworkInfo->type() = info[0]; - aNetworkInfo->isWifi() = info[1] == 1.0f; - aNetworkInfo->dhcpGateway() = info[2]; - - env->ReleaseDoubleArrayElements(arr.Get(), info, 0); -} - -void * -AndroidBridge::LockBitmap(jobject bitmap) -{ - JNIEnv *env = GetJNIEnv(); - - int err; - void *buf; - - if ((err = AndroidBitmap_lockPixels(env, bitmap, &buf)) != 0) { - ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err); - buf = nullptr; - } - - return buf; -} - -void -AndroidBridge::UnlockBitmap(jobject bitmap) -{ - JNIEnv *env = GetJNIEnv(); - - int err; - - if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0) - ALOG_BRIDGE("AndroidBitmap_unlockPixels failed! (error %d)", err); -} - - -bool -AndroidBridge::HasNativeWindowAccess() -{ - OpenGraphicsLibraries(); - - // We have a fallback hack in place, so return true if that will work as well - return mHasNativeWindowAccess || mHasNativeWindowFallback; -} - -void* -AndroidBridge::AcquireNativeWindow(JNIEnv* aEnv, jobject aSurface) -{ - OpenGraphicsLibraries(); - - if (mHasNativeWindowAccess) - return ANativeWindow_fromSurface(aEnv, aSurface); - - if (mHasNativeWindowFallback) - return GetNativeSurface(aEnv, aSurface); - - return nullptr; -} - -void -AndroidBridge::ReleaseNativeWindow(void *window) -{ - if (!window) - return; - - if (mHasNativeWindowAccess) - ANativeWindow_release(window); - - // XXX: we don't ref the pointer we get from the fallback (GetNativeSurface), so we - // have nothing to do here. We should probably ref it. -} - -void* -AndroidBridge::AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurfaceTexture) -{ - OpenGraphicsLibraries(); - - if (mHasNativeWindowAccess && ANativeWindow_fromSurfaceTexture) - return ANativeWindow_fromSurfaceTexture(aEnv, aSurfaceTexture); - - if (mHasNativeWindowAccess && android_SurfaceTexture_getNativeWindow) { - android::sp window = android_SurfaceTexture_getNativeWindow(aEnv, aSurfaceTexture); - return window.get(); - } - - return nullptr; -} - -void -AndroidBridge::ReleaseNativeWindowForSurfaceTexture(void *window) -{ - if (!window) - return; - - // FIXME: we don't ref the pointer we get, so nothing to do currently. We should ref it. -} - -bool -AndroidBridge::LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride) -{ - /* Copied from native_window.h in Android NDK (platform-9) */ - typedef struct ANativeWindow_Buffer { - // The number of pixels that are show horizontally. - int32_t width; - - // The number of pixels that are shown vertically. - int32_t height; - - // The number of *pixels* that a line in the buffer takes in - // memory. This may be >= width. - int32_t stride; - - // The format of the buffer. One of WINDOW_FORMAT_* - int32_t format; - - // The actual bits. - void* bits; - - // Do not touch. - uint32_t reserved[6]; - } ANativeWindow_Buffer; - - // Very similar to the above, but the 'usage' field is included. We use this - // in the fallback case when NDK support is not available - struct SurfaceInfo { - uint32_t w; - uint32_t h; - uint32_t s; - uint32_t usage; - uint32_t format; - unsigned char* bits; - uint32_t reserved[2]; - }; - - int err; - *bits = nullptr; - *width = *height = *format = 0; - - if (mHasNativeWindowAccess) { - ANativeWindow_Buffer buffer; - - if ((err = ANativeWindow_lock(window, (void*)&buffer, nullptr)) != 0) { - ALOG_BRIDGE("ANativeWindow_lock failed! (error %d)", err); - return false; - } - - *bits = (unsigned char*)buffer.bits; - *width = buffer.width; - *height = buffer.height; - *format = buffer.format; - *stride = buffer.stride; - } else if (mHasNativeWindowFallback) { - SurfaceInfo info; - - if ((err = Surface_lock(window, &info, nullptr, true)) != 0) { - ALOG_BRIDGE("Surface_lock failed! (error %d)", err); - return false; - } - - *bits = info.bits; - *width = info.w; - *height = info.h; - *format = info.format; - *stride = info.s; - } else return false; - - return true; -} - -jobject -AndroidBridge::GetGlobalContextRef() { - if (sGlobalContext) { - return sGlobalContext; - } - - JNIEnv* const env = GetJNIForThread(); - AutoLocalJNIFrame jniFrame(env, 4); - - auto context = GoannaAppShell::GetContext(); - if (!context) { - ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__); - return 0; - } - jclass contextClass = env->FindClass("android/content/Context"); - if (!contextClass) { - ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__); - return 0; - } - jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext", - "()Landroid/content/Context;"); - if (!mid) { - ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__); - return 0; - } - jobject appContext = env->CallObjectMethod(context.Get(), mid); - if (!appContext) { - ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__); - return 0; - } - - sGlobalContext = env->NewGlobalRef(appContext); - MOZ_ASSERT(sGlobalContext); - return sGlobalContext; -} - -bool -AndroidBridge::UnlockWindow(void* window) -{ - int err; - - if (!HasNativeWindowAccess()) - return false; - - if (mHasNativeWindowAccess && (err = ANativeWindow_unlockAndPost(window)) != 0) { - ALOG_BRIDGE("ANativeWindow_unlockAndPost failed! (error %d)", err); - return false; - } else if (mHasNativeWindowFallback && (err = Surface_unlockAndPost(window)) != 0) { - ALOG_BRIDGE("Surface_unlockAndPost failed! (error %d)", err); - return false; - } - - return true; -} - -void -AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect) -{ - if (!mLayerClient) { - return; - } - - mLayerClient->SetFirstPaintViewport(float(aOffset.x), float(aOffset.y), aZoom.scale, - aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); -} - -void -AndroidBridge::SetPageRect(const CSSRect& aCssPageRect) -{ - if (!mLayerClient) { - return; - } - - mLayerClient->SetPageRect(aCssPageRect.x, aCssPageRect.y, - aCssPageRect.XMost(), aCssPageRect.YMost()); -} - -void -AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, - LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) -{ - if (!mLayerClient) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return; - } - - ViewTransform::LocalRef viewTransform = mLayerClient->SyncViewportInfo( - aDisplayPort.x, aDisplayPort.y, - aDisplayPort.width, aDisplayPort.height, - aDisplayResolution.scale, aLayersUpdated); - - MOZ_ASSERT(viewTransform, "No view transform object!"); - - aScrollOffset = ParentLayerPoint(viewTransform->X(), viewTransform->Y()); - aScale.scale = viewTransform->Scale(); - aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop(); - aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight(); - aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom(); - aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft(); - aOffset.x = viewTransform->OffsetX(); - aOffset.y = viewTransform->OffsetY(); -} - -void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) -{ - if (!mLayerClient) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return; - } - - // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels - LayerRect dpUnrounded = aDisplayPort * aDisplayResolution; - dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint()); - LayerIntRect dp = gfx::RoundedToInt(dpUnrounded); - - ViewTransform::LocalRef viewTransform = mLayerClient->SyncFrameMetrics( - aScrollOffset.x, aScrollOffset.y, aZoom, - aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(), - aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale, - aIsFirstPaint); - - MOZ_ASSERT(viewTransform, "No view transform object!"); - - aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop(); - aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight(); - aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom(); - aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft(); - - aOffset.x = viewTransform->OffsetX(); - aOffset.y = viewTransform->OffsetY(); -} - -AndroidBridge::AndroidBridge() - : mLayerClient(nullptr) -{ -} - -AndroidBridge::~AndroidBridge() -{ -} - -/* Implementation file */ -NS_IMPL_ISUPPORTS(nsAndroidBridge, nsIAndroidBridge) - -nsAndroidBridge::nsAndroidBridge() -{ -} - -nsAndroidBridge::~nsAndroidBridge() -{ -} - -/* void handleGoannaEvent (in AString message); */ -NS_IMETHODIMP nsAndroidBridge::HandleGoannaMessage(JS::HandleValue val, - JSContext *cx) -{ - if (val.isObject()) { - JS::RootedObject object(cx, &val.toObject()); - AndroidBridge::Bridge()->HandleGoannaMessage(cx, object); - return NS_OK; - } - - // Now handle legacy JSON messages. - if (!val.isString()) { - return NS_ERROR_INVALID_ARG; - } - JS::RootedString jsonStr(cx, val.toString()); - - JS::RootedValue jsonVal(cx); - if (!JS_ParseJSON(cx, jsonStr, &jsonVal) || !jsonVal.isObject()) { - return NS_ERROR_INVALID_ARG; - } - - // Spit out a warning before sending the message. - nsContentUtils::ReportToConsoleNonLocalized( - NS_LITERAL_STRING("Use of JSON is deprecated. " - "Please pass Javascript objects directly to handleGoannaMessage."), - nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("nsIAndroidBridge"), - nullptr); - - JS::RootedObject object(cx, &jsonVal.toObject()); - AndroidBridge::Bridge()->HandleGoannaMessage(cx, object); - return NS_OK; -} - -/* nsIAndroidDisplayport getDisplayPort(in boolean aPageSizeUpdate, in boolean isBrowserContentDisplayed, in int32_t tabId, in nsIAndroidViewport metrics); */ -NS_IMETHODIMP nsAndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort) -{ - AndroidBridge::Bridge()->GetDisplayPort(aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort); - return NS_OK; -} - -/* void displayedDocumentChanged(); */ -NS_IMETHODIMP nsAndroidBridge::ContentDocumentChanged() -{ - AndroidBridge::Bridge()->ContentDocumentChanged(); - return NS_OK; -} - -/* boolean isContentDocumentDisplayed(); */ -NS_IMETHODIMP nsAndroidBridge::IsContentDocumentDisplayed(bool *aRet) -{ - *aRet = AndroidBridge::Bridge()->IsContentDocumentDisplayed(); - return NS_OK; -} - -// DO NOT USE THIS unless you need to access JNI from -// non-main threads. This is probably not what you want. -// Questions, ask blassey or dougt. - -static void -JavaThreadDetachFunc(void *arg) -{ - JNIEnv *env = (JNIEnv*) arg; - MOZ_ASSERT(env, "No JNIEnv on Goanna thread"); - if (!env) { - return; - } - JavaVM *vm = nullptr; - env->GetJavaVM(&vm); - MOZ_ASSERT(vm, "No JavaVM on Goanna thread"); - if (!vm) { - return; - } - vm->DetachCurrentThread(); -} - -uint32_t -AndroidBridge::GetScreenOrientation() -{ - ALOG_BRIDGE("AndroidBridge::GetScreenOrientation"); - - int16_t orientation = GoannaAppShell::GetScreenOrientationWrapper(); - - if (!orientation) - return dom::eScreenOrientation_None; - - return static_cast(orientation); -} - -void -AndroidBridge::ScheduleComposite() -{ - nsWindow::ScheduleComposite(); -} - -nsresult -AndroidBridge::GetProxyForURI(const nsACString & aSpec, - const nsACString & aScheme, - const nsACString & aHost, - const int32_t aPort, - nsACString & aResult) -{ - if (!HasEnv()) { - return NS_ERROR_FAILURE; - } - - auto jstrRet = GoannaAppShell::GetProxyForURIWrapper(aSpec, aScheme, aHost, aPort); - - if (!jstrRet) - return NS_ERROR_FAILURE; - - aResult = nsCString(jstrRet); - return NS_OK; -} - - -/* attribute nsIAndroidBrowserApp browserApp; */ -NS_IMETHODIMP nsAndroidBridge::GetBrowserApp(nsIAndroidBrowserApp * *aBrowserApp) -{ - if (nsAppShell::gAppShell) - nsAppShell::gAppShell->GetBrowserApp(aBrowserApp); - return NS_OK; -} - -NS_IMETHODIMP nsAndroidBridge::SetBrowserApp(nsIAndroidBrowserApp *aBrowserApp) -{ - if (nsAppShell::gAppShell) - nsAppShell::gAppShell->SetBrowserApp(aBrowserApp); - return NS_OK; -} - -void -AndroidBridge::AddPluginView(jobject view, const LayoutDeviceRect& rect, bool isFullScreen) { - nsWindow* win = nsWindow::TopWindow(); - if (!win) - return; - - CSSRect cssRect = rect / win->GetDefaultScale(); - GoannaAppShell::AddPluginViewWrapper(Object::Ref::From(view), cssRect.x, cssRect.y, - cssRect.width, cssRect.height, isFullScreen); -} - -extern "C" -__attribute__ ((visibility("default"))) -jobject JNICALL -Java_org_mozilla_goanna_GoannaAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size); - -bool -AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult) -{ - auto jstrThreadName = GoannaJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId); - - if (!jstrThreadName) - return false; - - aResult = nsCString(jstrThreadName); - return true; -} - -bool -AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId, - uint32_t aFrameId, nsCString & aResult) -{ - auto jstrSampleName = GoannaJavaSampler::GetFrameNameJavaProfilingWrapper - (aThreadId, aSampleId, aFrameId); - - if (!jstrSampleName) - return false; - - aResult = nsCString(jstrSampleName); - return true; -} - -static float -GetScaleFactor(nsPresContext* aPresContext) { - nsIPresShell* presShell = aPresContext->PresShell(); - LayoutDeviceToLayerScale cumulativeResolution(presShell->GetCumulativeResolution()); - return cumulativeResolution.scale; -} - -nsresult -AndroidBridge::CaptureZoomedView(nsIDOMWindow *window, nsIntRect zoomedViewRect, Object::Param buffer, - float zoomFactor) { - nsresult rv; - - if (!buffer) - return NS_ERROR_FAILURE; - - nsCOMPtr utils = do_GetInterface(window); - if (!utils) - return NS_ERROR_FAILURE; - - JNIEnv* env = GetJNIEnv(); - - AutoLocalJNIFrame jniFrame(env, 0); - - nsCOMPtr win = do_QueryInterface(window); - if (!win) { - return NS_ERROR_FAILURE; - } - nsRefPtr presContext; - - nsIDocShell* docshell = win->GetDocShell(); - - if (docshell) { - docshell->GetPresContext(getter_AddRefs(presContext)); - } - - if (!presContext) { - return NS_ERROR_FAILURE; - } - nsCOMPtr presShell = presContext->PresShell(); - - float scaleFactor = GetScaleFactor(presContext) ; - - nscolor bgColor = NS_RGB(255, 255, 255); - uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING | nsIPresShell::RENDER_DOCUMENT_RELATIVE); - nsRect r(presContext->DevPixelsToAppUnits(zoomedViewRect.x / scaleFactor), - presContext->DevPixelsToAppUnits(zoomedViewRect.y / scaleFactor ), - presContext->DevPixelsToAppUnits(zoomedViewRect.width / scaleFactor ), - presContext->DevPixelsToAppUnits(zoomedViewRect.height / scaleFactor )); - - bool is24bit = (GetScreenDepth() == 24); - SurfaceFormat format = is24bit ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::R5G6B5; - gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format); - uint32_t stride = gfxASurface::FormatStrideForWidth(iFormat, zoomedViewRect.width); - - uint8_t* data = static_cast (env->GetDirectBufferAddress(buffer.Get())); - if (!data) { - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO), - "Need BackendType::CAIRO support"); - RefPtr < DrawTarget > dt = Factory::CreateDrawTargetForData( - BackendType::CAIRO, data, IntSize(zoomedViewRect.width, zoomedViewRect.height), stride, - format); - if (!dt) { - ALOG_BRIDGE("Error creating DrawTarget"); - return NS_ERROR_FAILURE; - } - nsRefPtr context = new gfxContext(dt); - context->SetMatrix(context->CurrentMatrix().Scale(zoomFactor, zoomFactor)); - - rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context); - - if (is24bit) { - gfxUtils::ConvertBGRAtoRGBA(data, stride * zoomedViewRect.height); - } - - LayerView::updateZoomedView(buffer); - - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, Object::Param buffer, bool &shouldStore) -{ - nsresult rv; - float scale = 1.0; - - if (!buffer) - return NS_ERROR_FAILURE; - - // take a screenshot, as wide as possible, proportional to the destination size - nsCOMPtr utils = do_GetInterface(window); - if (!utils) - return NS_ERROR_FAILURE; - - nsCOMPtr rect; - rv = utils->GetRootBounds(getter_AddRefs(rect)); - NS_ENSURE_SUCCESS(rv, rv); - if (!rect) - return NS_ERROR_FAILURE; - - float left, top, width, height; - rect->GetLeft(&left); - rect->GetTop(&top); - rect->GetWidth(&width); - rect->GetHeight(&height); - - if (width == 0 || height == 0) - return NS_ERROR_FAILURE; - - int32_t srcX = left; - int32_t srcY = top; - int32_t srcW; - int32_t srcH; - - float aspectRatio = ((float) bufW) / bufH; - if (width / aspectRatio < height) { - srcW = width; - srcH = width / aspectRatio; - } else { - srcW = height * aspectRatio; - srcH = height; - } - - JNIEnv* env = GetJNIEnv(); - - AutoLocalJNIFrame jniFrame(env, 0); - - nsCOMPtr win = do_QueryInterface(window); - if (!win) - return NS_ERROR_FAILURE; - nsRefPtr presContext; - - nsIDocShell* docshell = win->GetDocShell(); - - // Decide if callers should store this thumbnail for later use. - shouldStore = ShouldStoreThumbnail(docshell); - - if (docshell) { - docshell->GetPresContext(getter_AddRefs(presContext)); - } - - if (!presContext) - return NS_ERROR_FAILURE; - nscolor bgColor = NS_RGB(255, 255, 255); - nsCOMPtr presShell = presContext->PresShell(); - uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING | - nsIPresShell::RENDER_DOCUMENT_RELATIVE); - nsRect r(nsPresContext::CSSPixelsToAppUnits(srcX / scale), - nsPresContext::CSSPixelsToAppUnits(srcY / scale), - nsPresContext::CSSPixelsToAppUnits(srcW / scale), - nsPresContext::CSSPixelsToAppUnits(srcH / scale)); - - bool is24bit = (GetScreenDepth() == 24); - uint32_t stride = bufW * (is24bit ? 4 : 2); - - uint8_t* data = static_cast(env->GetDirectBufferAddress(buffer.Get())); - if (!data) - return NS_ERROR_FAILURE; - - MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO), - "Need BackendType::CAIRO support"); - RefPtr dt = - Factory::CreateDrawTargetForData(BackendType::CAIRO, - data, - IntSize(bufW, bufH), - stride, - is24bit ? SurfaceFormat::B8G8R8X8 : - SurfaceFormat::R5G6B5); - if (!dt) { - ALOG_BRIDGE("Error creating DrawTarget"); - return NS_ERROR_FAILURE; - } - nsRefPtr context = new gfxContext(dt); - context->SetMatrix( - context->CurrentMatrix().Scale(scale * bufW / srcW, - scale * bufH / srcH)); - rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context); - if (is24bit) { - gfxUtils::ConvertBGRAtoRGBA(data, stride * bufH); - } - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; -} - -void -AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort) -{ - - ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__); - if (!mLayerClient) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return; - } - - JNIEnv* const env = GetJNIEnv(); - AutoLocalJNIFrame jniFrame(env, 1); - - float x, y, width, height, - pageLeft, pageTop, pageRight, pageBottom, - cssPageLeft, cssPageTop, cssPageRight, cssPageBottom, - zoom; - metrics->GetX(&x); - metrics->GetY(&y); - metrics->GetWidth(&width); - metrics->GetHeight(&height); - metrics->GetPageLeft(&pageLeft); - metrics->GetPageTop(&pageTop); - metrics->GetPageRight(&pageRight); - metrics->GetPageBottom(&pageBottom); - metrics->GetCssPageLeft(&cssPageLeft); - metrics->GetCssPageTop(&cssPageTop); - metrics->GetCssPageRight(&cssPageRight); - metrics->GetCssPageBottom(&cssPageBottom); - metrics->GetZoom(&zoom); - - auto jmetrics = ImmutableViewportMetrics::New( - pageLeft, pageTop, pageRight, pageBottom, - cssPageLeft, cssPageTop, cssPageRight, cssPageBottom, - x, y, x + width, y + height, - zoom); - - DisplayPortMetrics::LocalRef displayPortMetrics = mLayerClient->GetDisplayPort( - aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics); - - if (!displayPortMetrics) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return; - } - - AndroidRectF rect(env, displayPortMetrics->MPosition().Get()); - float resolution = displayPortMetrics->Resolution(); - - *displayPort = new nsAndroidDisplayport(rect, resolution); - (*displayPort)->AddRef(); - - ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__); -} - -void -AndroidBridge::ContentDocumentChanged() -{ - if (!mLayerClient) { - return; - } - mLayerClient->ContentDocumentChanged(); -} - -bool -AndroidBridge::IsContentDocumentDisplayed() -{ - if (!mLayerClient) - return false; - - return mLayerClient->IsContentDocumentDisplayed(); -} - -bool -AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, - const LayerRect& aDisplayPort, float aDisplayResolution, - bool aDrawingCritical, ParentLayerPoint& aScrollOffset, - CSSToParentLayerScale& aZoom) -{ - if (!mLayerClient) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return false; - } - - ProgressiveUpdateData::LocalRef progressiveUpdateData = - mLayerClient->ProgressiveUpdateCallback(aHasPendingNewThebesContent, - (float)aDisplayPort.x, - (float)aDisplayPort.y, - (float)aDisplayPort.width, - (float)aDisplayPort.height, - aDisplayResolution, - !aDrawingCritical); - - aScrollOffset.x = progressiveUpdateData->X(); - aScrollOffset.y = progressiveUpdateData->Y(); - aZoom.scale = progressiveUpdateData->Scale(); - - return progressiveUpdateData->Abort(); -} - -void -AndroidBridge::PostTaskToUiThread(Task* aTask, int aDelayMs) -{ - // add the new task into the mDelayedTaskQueue, sorted with - // the earliest task first in the queue - DelayedTask* newTask = new DelayedTask(aTask, aDelayMs); - uint32_t i = 0; - while (i < mDelayedTaskQueue.Length()) { - if (newTask->IsEarlierThan(mDelayedTaskQueue[i])) { - mDelayedTaskQueue.InsertElementAt(i, newTask); - break; - } - i++; - } - if (i == mDelayedTaskQueue.Length()) { - // this new task will run after all the existing tasks in the queue - mDelayedTaskQueue.AppendElement(newTask); - } - if (i == 0) { - // if we're inserting it at the head of the queue, notify Java because - // we need to get a callback at an earlier time than the last scheduled - // callback - GoannaAppShell::RequestUiThreadCallback((int64_t)aDelayMs); - } -} - -int64_t -AndroidBridge::RunDelayedUiThreadTasks() -{ - while (mDelayedTaskQueue.Length() > 0) { - DelayedTask* nextTask = mDelayedTaskQueue[0]; - int64_t timeLeft = nextTask->MillisecondsToRunTime(); - if (timeLeft > 0) { - // this task (and therefore all remaining tasks) - // have not yet reached their runtime. return the - // time left until we should be called again - return timeLeft; - } - - // we have a delayed task to run. extract it from - // the wrapper and free the wrapper - - mDelayedTaskQueue.RemoveElementAt(0); - Task* task = nextTask->GetTask(); - delete nextTask; - - task->Run(); - } - return -1; -} - -Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) { - JNIEnv* const env = GetJNIForThread(); - auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod( - sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream.Get())); - HandleUncaughtException(env); - return rv; -} - -void AndroidBridge::InputStreamClose(Object::Param obj) { - JNIEnv* const env = GetJNIForThread(); - env->CallVoidMethod(obj.Get(), sBridge->jClose); - HandleUncaughtException(env); -} - -uint32_t AndroidBridge::InputStreamAvailable(Object::Param obj) { - JNIEnv* const env = GetJNIForThread(); - auto rv = env->CallIntMethod(obj.Get(), sBridge->jAvailable); - HandleUncaughtException(env); - return rv; -} - -nsresult AndroidBridge::InputStreamRead(Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead) { - JNIEnv* const env = GetJNIForThread(); - auto arr = Object::LocalRef::Adopt(env, env->NewDirectByteBuffer(aBuf, aCount)); - jint read = env->CallIntMethod(obj.Get(), sBridge->jByteBufferRead, arr.Get()); - - if (env->ExceptionCheck()) { - env->ExceptionClear(); - return NS_ERROR_FAILURE; - } - - if (read <= 0) { - *aRead = 0; - return NS_OK; - } - *aRead = read; - return NS_OK; -} - -nsresult AndroidBridge::GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath) { - auto path = GoannaAppShell::GetExternalPublicDirectory(aType); - if (!path) { - return NS_ERROR_NOT_AVAILABLE; - } - aPath = nsString(path); - return NS_OK; -} diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h deleted file mode 100644 index 5d0033c40b..0000000000 --- a/widget/android/AndroidBridge.h +++ /dev/null @@ -1,610 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef AndroidBridge_h__ -#define AndroidBridge_h__ - -#include -#include -#include -#include - -#include "nsCOMPtr.h" -#include "nsCOMArray.h" - -#include "GeneratedJNIWrappers.h" -#include "AndroidJavaWrappers.h" - -#include "nsIMutableArray.h" -#include "nsIMIMEInfo.h" -#include "nsColor.h" -#include "gfxRect.h" - -#include "nsIAndroidBridge.h" -#include "nsIMobileMessageCallback.h" - -#include "mozilla/Likely.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/TimeStamp.h" -#include "mozilla/Types.h" -#include "mozilla/jni/Utils.h" - -// Some debug #defines -// #define DEBUG_ANDROID_EVENTS -// #define DEBUG_ANDROID_WIDGET - -class nsWindow; -class nsIDOMMozSmsMessage; -class nsIObserver; -class Task; - -extern bool mozilla_AndroidBridge_SetMainThread(pthread_t); - -namespace base { -class Thread; -} // end namespace base - -typedef void* EGLSurface; - -namespace mozilla { - -namespace hal { -class BatteryInformation; -class NetworkInformation; -} // namespace hal - -namespace dom { -namespace mobilemessage { -struct SmsFilterData; -} // namespace mobilemessage -} // namespace dom - -namespace layers { -class CompositorParent; -} // namespace layers - -// The order and number of the members in this structure must correspond -// to the attrsAppearance array in GoannaAppShell.getSystemColors() -typedef struct AndroidSystemColors { - nscolor textColorPrimary; - nscolor textColorPrimaryInverse; - nscolor textColorSecondary; - nscolor textColorSecondaryInverse; - nscolor textColorTertiary; - nscolor textColorTertiaryInverse; - nscolor textColorHighlight; - nscolor colorForeground; - nscolor colorBackground; - nscolor panelColorForeground; - nscolor panelColorBackground; -} AndroidSystemColors; - -class nsFilePickerCallback : nsISupports { -public: - NS_DECL_THREADSAFE_ISUPPORTS - virtual void handleResult(nsAString& filePath) = 0; - nsFilePickerCallback() {} -protected: - virtual ~nsFilePickerCallback() {} -}; - -class DelayedTask { -public: - DelayedTask(Task* aTask, int aDelayMs) { - mTask = aTask; - mRunTime = mozilla::TimeStamp::Now() + mozilla::TimeDuration::FromMilliseconds(aDelayMs); - } - - bool IsEarlierThan(DelayedTask *aOther) { - return mRunTime < aOther->mRunTime; - } - - int64_t MillisecondsToRunTime() { - mozilla::TimeDuration timeLeft = mRunTime - mozilla::TimeStamp::Now(); - return (int64_t)timeLeft.ToMilliseconds(); - } - - Task* GetTask() { - return mTask; - } - -private: - Task* mTask; - mozilla::TimeStamp mRunTime; -}; - -class AndroidBridge final -{ -public: - enum { - // Values for NotifyIME, in addition to values from the Goanna - // IMEMessage enum; use negative values here to prevent conflict - NOTIFY_IME_OPEN_VKB = -2, - NOTIFY_IME_REPLY_EVENT = -1, - }; - - enum { - LAYER_CLIENT_TYPE_NONE = 0, - LAYER_CLIENT_TYPE_GL = 2 // AndroidGoannaGLLayerClient - }; - - static void RegisterJavaUiThread() { - sJavaUiThread = pthread_self(); - } - - static bool IsJavaUiThread() { - return pthread_equal(pthread_self(), sJavaUiThread); - } - - static void ConstructBridge(JNIEnv *jEnv, jni::Object::Param clsLoader); - - static AndroidBridge *Bridge() { - return sBridge; - } - - static JavaVM *GetVM() { - MOZ_ASSERT(sBridge); - return sBridge->mJavaVM; - } - - - static JNIEnv *GetJNIEnv() { - MOZ_ASSERT(sBridge); - if (MOZ_UNLIKELY(!pthread_equal(pthread_self(), sBridge->mThread))) { - MOZ_CRASH(); - } - MOZ_ASSERT(sBridge->mJNIEnv); - return sBridge->mJNIEnv; - } - - static bool HasEnv() { - return sBridge && sBridge->mJNIEnv; - } - - static bool ThrowException(JNIEnv *aEnv, const char *aClass, - const char *aMessage) { - - return jni::ThrowException(aEnv, aClass, aMessage); - } - - static bool ThrowException(JNIEnv *aEnv, const char *aMessage) { - return jni::ThrowException(aEnv, aMessage); - } - - static void HandleUncaughtException(JNIEnv *aEnv) { - jni::HandleUncaughtException(aEnv); - } - - // The bridge needs to be constructed via ConstructBridge first, - // and then once the Goanna main thread is spun up (Goanna side), - // SetMainThread should be called which will create the JNIEnv for - // us to use. toolkit/xre/nsAndroidStartup.cpp calls - // SetMainThread. - bool SetMainThread(pthread_t thr); - - /* These are all implemented in Java */ - bool GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult); - bool GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId, uint32_t aFrameId, nsCString & aResult); - - nsresult CaptureZoomedView(nsIDOMWindow *window, nsIntRect zoomedViewRect, jni::Object::Param buffer, float zoomFactor); - nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jni::Object::Param buffer, bool &shouldStore); - void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort); - void ContentDocumentChanged(); - bool IsContentDocumentDisplayed(); - - bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, - mozilla::ParentLayerPoint& aScrollOffset, mozilla::CSSToParentLayerScale& aZoom); - - void SetLayerClient(widget::GoannaLayerClient::Param jobj); - const widget::GoannaLayerClient::Ref& GetLayerClient() { return mLayerClient; } - - bool GetHandlersForURL(const nsAString& aURL, - nsIMutableArray* handlersArray = nullptr, - nsIHandlerApp **aDefaultApp = nullptr, - const nsAString& aAction = EmptyString()); - - bool GetHandlersForMimeType(const nsAString& aMimeType, - nsIMutableArray* handlersArray = nullptr, - nsIHandlerApp **aDefaultApp = nullptr, - const nsAString& aAction = EmptyString()); - - void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType); - void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt); - - bool GetClipboardText(nsAString& aText); - - void ShowAlertNotification(const nsAString& aImageUrl, - const nsAString& aAlertTitle, - const nsAString& aAlertText, - const nsAString& aAlertData, - nsIObserver *aAlertListener, - const nsAString& aAlertName); - - int GetDPI(); - int GetScreenDepth(); - - void Vibrate(const nsTArray& aPattern); - - void GetSystemColors(AndroidSystemColors *aColors); - - void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf); - - // Switch Java to composite with the Goanna Compositor thread - void RegisterCompositor(JNIEnv* env = nullptr); - EGLSurface CreateEGLSurfaceForCompositor(); - - bool GetStaticStringField(const char *classID, const char *field, nsAString &result, JNIEnv* env = nullptr); - - bool GetStaticIntField(const char *className, const char *fieldName, int32_t* aInt, JNIEnv* env = nullptr); - - // These next four functions are for native Bitmap access in Android 2.2+ - bool HasNativeBitmapAccess(); - - bool ValidateBitmap(jobject bitmap, int width, int height); - - void *LockBitmap(jobject bitmap); - - // Returns a global reference to the Context for Fennec's Activity. The - // caller is responsible for ensuring this doesn't leak by calling - // DeleteGlobalRef() when the context is no longer needed. - jobject GetGlobalContextRef(void); - - void UnlockBitmap(jobject bitmap); - - /* Copied from Android's native_window.h in newer (platform 9) NDK */ - enum { - WINDOW_FORMAT_RGBA_8888 = 1, - WINDOW_FORMAT_RGBX_8888 = 2, - WINDOW_FORMAT_RGB_565 = 4 - }; - - bool HasNativeWindowAccess(); - - void *AcquireNativeWindow(JNIEnv* aEnv, jobject aSurface); - void ReleaseNativeWindow(void *window); - - void *AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurface); - void ReleaseNativeWindowForSurfaceTexture(void *window); - - bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride); - bool UnlockWindow(void *window); - - void HandleGoannaMessage(JSContext* cx, JS::HandleObject message); - - bool InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps); - - void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo); - - nsresult GetSegmentInfoForText(const nsAString& aText, - nsIMobileMessageCallback* aRequest); - void SendMessage(const nsAString& aNumber, const nsAString& aText, - nsIMobileMessageCallback* aRequest); - void GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest); - void DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest); - void CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, - bool aReverse, nsIMobileMessageCallback* aRequest); - void GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* aRequest); - already_AddRefed DequeueSmsRequest(uint32_t aRequestId); - - void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo); - - void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); - void SetPageRect(const CSSRect& aCssPageRect); - void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, - LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - - void AddPluginView(jobject view, const LayoutDeviceRect& rect, bool isFullScreen); - - // These methods don't use a ScreenOrientation because it's an - // enum and that would require including the header which requires - // include IPC headers which requires including basictypes.h which - // requires a lot of changes... - uint32_t GetScreenOrientation(); - - int GetAPIVersion() { return mAPIVersion; } - bool IsHoneycomb() { return mAPIVersion >= 11 && mAPIVersion <= 13; } - - void ScheduleComposite(); - - nsresult GetProxyForURI(const nsACString & aSpec, - const nsACString & aScheme, - const nsACString & aHost, - const int32_t aPort, - nsACString & aResult); - - // Utility methods. - static jstring NewJavaString(JNIEnv* env, const char16_t* string, uint32_t len); - static jstring NewJavaString(JNIEnv* env, const nsAString& string); - static jstring NewJavaString(JNIEnv* env, const char* string); - static jstring NewJavaString(JNIEnv* env, const nsACString& string); - - static jstring NewJavaString(AutoLocalJNIFrame* frame, const char16_t* string, uint32_t len); - static jstring NewJavaString(AutoLocalJNIFrame* frame, const nsAString& string); - static jstring NewJavaString(AutoLocalJNIFrame* frame, const char* string); - static jstring NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string); - - static jclass GetClassGlobalRef(JNIEnv* env, const char* className); - static jfieldID GetFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType); - static jfieldID GetStaticFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType); - static jmethodID GetMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType); - static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType); - - static jni::Object::LocalRef ChannelCreate(jni::Object::Param); - - static void InputStreamClose(jni::Object::Param obj); - static uint32_t InputStreamAvailable(jni::Object::Param obj); - static nsresult InputStreamRead(jni::Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead); - - static nsresult GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath); - -protected: - static pthread_t sJavaUiThread; - static AndroidBridge* sBridge; - nsTArray > mSmsRequests; - - // the global JavaVM - JavaVM *mJavaVM; - - // the JNIEnv for the main thread - JNIEnv *mJNIEnv; - pthread_t mThread; - - widget::GoannaLayerClient::GlobalRef mLayerClient; - - // the android.telephony.SmsMessage class - jclass mAndroidSmsMessageClass; - - AndroidBridge(); - ~AndroidBridge(); - - void InitStubs(JNIEnv *jEnv); - bool Init(JNIEnv *jEnv, jni::Object::Param clsLoader); - - bool mOpenedGraphicsLibraries; - void OpenGraphicsLibraries(); - void* GetNativeSurface(JNIEnv* env, jobject surface); - - bool mHasNativeBitmapAccess; - bool mHasNativeWindowAccess; - bool mHasNativeWindowFallback; - - int mAPIVersion; - - bool QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut); - - // intput stream - jclass jReadableByteChannel; - jclass jChannels; - jmethodID jChannelCreate; - jmethodID jByteBufferRead; - - jclass jInputStream; - jmethodID jClose; - jmethodID jAvailable; - - // other things - jmethodID jNotifyAppShellReady; - jmethodID jGetOutstandingDrawEvents; - jmethodID jPostToJavaThread; - jmethodID jCreateSurface; - jmethodID jShowSurface; - jmethodID jHideSurface; - jmethodID jDestroySurface; - - jmethodID jCalculateLength; - - // For native surface stuff - jclass jSurfaceClass; - jfieldID jSurfacePointerField; - - jclass jLayerView; - - jfieldID jEGLSurfacePointerField; - widget::GLController::GlobalRef mGLControllerObj; - - // some convinient types to have around - jclass jStringClass; - - jni::Object::GlobalRef mClassLoader; - jmethodID mClassLoaderLoadClass; - - // calls we've dlopened from libjnigraphics.so - int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info); - int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer); - int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap); - - void* (*ANativeWindow_fromSurface)(JNIEnv *env, jobject surface); - void* (*ANativeWindow_fromSurfaceTexture)(JNIEnv *env, jobject surfaceTexture); - void (*ANativeWindow_release)(void *window); - int (*ANativeWindow_setBuffersGeometry)(void *window, int width, int height, int format); - - int (* ANativeWindow_lock)(void *window, void *outBuffer, void *inOutDirtyBounds); - int (* ANativeWindow_unlockAndPost)(void *window); - - int (* Surface_lock)(void* surface, void* surfaceInfo, void* region, bool block); - int (* Surface_unlockAndPost)(void* surface); - void (* Region_constructor)(void* region); - void (* Region_set)(void* region, void* rect); - -private: - // This will always be accessed from one thread (the Java UI thread), - // so we don't need to do locking to touch it. - nsTArray mDelayedTaskQueue; -public: - void PostTaskToUiThread(Task* aTask, int aDelayMs); - int64_t RunDelayedUiThreadTasks(); -}; - -class AutoJNIClass { -private: - JNIEnv* const mEnv; - const jclass mClass; - -public: - AutoJNIClass(JNIEnv* jEnv, const char* name) - : mEnv(jEnv) - , mClass(AndroidBridge::GetClassGlobalRef(jEnv, name)) - {} - - ~AutoJNIClass() { - mEnv->DeleteGlobalRef(mClass); - } - - jclass getRawRef() const { - return mClass; - } - - jclass getGlobalRef() const { - return static_cast(mEnv->NewGlobalRef(mClass)); - } - - jfieldID getField(const char* name, const char* type) const { - return AndroidBridge::GetFieldID(mEnv, mClass, name, type); - } - - jfieldID getStaticField(const char* name, const char* type) const { - return AndroidBridge::GetStaticFieldID(mEnv, mClass, name, type); - } - - jmethodID getMethod(const char* name, const char* type) const { - return AndroidBridge::GetMethodID(mEnv, mClass, name, type); - } - - jmethodID getStaticMethod(const char* name, const char* type) const { - return AndroidBridge::GetStaticMethodID(mEnv, mClass, name, type); - } -}; - -class AutoJObject { -public: - AutoJObject(JNIEnv* aJNIEnv = nullptr) : mObject(nullptr) - { - mJNIEnv = aJNIEnv ? aJNIEnv : AndroidBridge::GetJNIEnv(); - } - - AutoJObject(JNIEnv* aJNIEnv, jobject aObject) - { - mJNIEnv = aJNIEnv ? aJNIEnv : AndroidBridge::GetJNIEnv(); - mObject = aObject; - } - - ~AutoJObject() { - if (mObject) - mJNIEnv->DeleteLocalRef(mObject); - } - - jobject operator=(jobject aObject) - { - if (mObject) { - mJNIEnv->DeleteLocalRef(mObject); - } - return mObject = aObject; - } - - operator jobject() { - return mObject; - } -private: - JNIEnv* mJNIEnv; - jobject mObject; -}; - -class AutoLocalJNIFrame { -public: - AutoLocalJNIFrame(int nEntries = 15) - : mEntries(nEntries) - , mJNIEnv(AndroidBridge::GetJNIEnv()) - , mHasFrameBeenPushed(false) - { - MOZ_ASSERT(mJNIEnv); - Push(); - } - - AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 15) - : mEntries(nEntries) - , mJNIEnv(aJNIEnv ? aJNIEnv : AndroidBridge::GetJNIEnv()) - , mHasFrameBeenPushed(false) - { - MOZ_ASSERT(mJNIEnv); - Push(); - } - - ~AutoLocalJNIFrame() { - if (mHasFrameBeenPushed) { - Pop(); - } - } - - JNIEnv* GetEnv() { - return mJNIEnv; - } - - bool CheckForException() { - if (mJNIEnv->ExceptionCheck()) { - jni::HandleUncaughtException(mJNIEnv); - return true; - } - return false; - } - - // Note! Calling Purge makes all previous local refs created in - // the AutoLocalJNIFrame's scope INVALID; be sure that you locked down - // any local refs that you need to keep around in global refs! - void Purge() { - Pop(); - Push(); - } - - template - ReturnType Pop(ReturnType aResult = nullptr) { - MOZ_ASSERT(mHasFrameBeenPushed); - mHasFrameBeenPushed = false; - return static_cast( - mJNIEnv->PopLocalFrame(static_cast(aResult))); - } - -private: - void Push() { - MOZ_ASSERT(!mHasFrameBeenPushed); - // Make sure there is enough space to store a local ref to the - // exception. I am not completely sure this is needed, but does - // not hurt. - if (mJNIEnv->PushLocalFrame(mEntries + 1) != 0) { - CheckForException(); - return; - } - mHasFrameBeenPushed = true; - } - - const int mEntries; - JNIEnv* const mJNIEnv; - bool mHasFrameBeenPushed; -}; - -} - -#define NS_ANDROIDBRIDGE_CID \ -{ 0x0FE2321D, 0xEBD9, 0x467D, \ - { 0xA7, 0x43, 0x03, 0xA6, 0x8D, 0x40, 0x59, 0x9E } } - -class nsAndroidBridge final : public nsIAndroidBridge -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIANDROIDBRIDGE - - nsAndroidBridge(); - -private: - ~nsAndroidBridge(); - -protected: -}; - -#endif /* AndroidBridge_h__ */ diff --git a/widget/android/AndroidBridgeUtilities.h b/widget/android/AndroidBridgeUtilities.h deleted file mode 100644 index a14cf32ddb..0000000000 --- a/widget/android/AndroidBridgeUtilities.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ALOG -#if defined(DEBUG) || defined(FORCE_ALOG) -#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Goanna" , ## args) -#else -#define ALOG(args...) ((void)0) -#endif -#endif - -#ifdef DEBUG -#define ALOG_BRIDGE(args...) ALOG(args) -#else -#define ALOG_BRIDGE(args...) ((void)0) -#endif diff --git a/widget/android/AndroidDirectTexture.cpp b/widget/android/AndroidDirectTexture.cpp deleted file mode 100644 index 24afaec19a..0000000000 --- a/widget/android/AndroidDirectTexture.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include -#include "AndroidDirectTexture.h" -#include "nsRect.h" - -namespace mozilla { - -AndroidDirectTexture::AndroidDirectTexture(uint32_t width, uint32_t height, uint32_t usage, - gfxImageFormat format) : - mLock("AndroidDirectTexture.mLock") - , mNeedFlip(false) - , mWidth(width) - , mHeight(height) - , mFormat(format) - , mPendingReallocBuffer(nullptr) -{ - mFrontBuffer = new AndroidGraphicBuffer(width, height, usage, format); - mBackBuffer = new AndroidGraphicBuffer(width, height, usage, format); -} - -AndroidDirectTexture::~AndroidDirectTexture() -{ - if (mFrontBuffer) { - delete mFrontBuffer; - mFrontBuffer = nullptr; - } - - if (mBackBuffer) { - delete mBackBuffer; - mBackBuffer = nullptr; - } -} - -void -AndroidDirectTexture::ReallocPendingBuffer() -{ - // We may have reallocated while the current back buffer was being - // used as the front buffer. If we have such a reallocation pending - // and the current back buffer is the target buffer, do it now. - // - // It is assumed that mLock is already acquired - if (mPendingReallocBuffer == mBackBuffer) { - mBackBuffer->Reallocate(mWidth, mHeight, mFormat); - mPendingReallocBuffer = nullptr; - } -} - -bool -AndroidDirectTexture::Lock(uint32_t aUsage, unsigned char **bits) -{ - nsIntRect rect(0, 0, mWidth, mHeight); - return Lock(aUsage, rect, bits); -} - -bool -AndroidDirectTexture::Lock(uint32_t aUsage, const nsIntRect& aRect, unsigned char **bits) -{ - mLock.Lock(); - ReallocPendingBuffer(); - - int result; - while ((result = mBackBuffer->Lock(aUsage, aRect, bits)) == -EBUSY) { - usleep(1000); // 1ms - } - - return result == 0; -} - -bool -AndroidDirectTexture::Unlock(bool aFlip) -{ - if (aFlip) { - mNeedFlip = true; - } - - bool result = mBackBuffer->Unlock(); - mLock.Unlock(); - - return result; -} - -bool -AndroidDirectTexture::Reallocate(uint32_t aWidth, uint32_t aHeight) { - return Reallocate(aWidth, aHeight, mFormat); -} - -bool -AndroidDirectTexture::Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat) -{ - MutexAutoLock lock(mLock); - - // We only reallocate the current back buffer. The front buffer is likely - // in use, so we'll reallocate it on the first Lock() after it is rotated - // to the back. - bool result = mBackBuffer->Reallocate(aWidth, aHeight, aFormat); - if (result) { - mPendingReallocBuffer = mFrontBuffer; - - mWidth = aWidth; - mHeight = aHeight; - } - - return result; -} - -bool -AndroidDirectTexture::Bind() -{ - MutexAutoLock lock(mLock); - - if (mNeedFlip) { - AndroidGraphicBuffer* tmp = mBackBuffer; - mBackBuffer = mFrontBuffer; - mFrontBuffer = tmp; - mNeedFlip = false; - } - - return mFrontBuffer->Bind(); -} - -} /* mozilla */ diff --git a/widget/android/AndroidDirectTexture.h b/widget/android/AndroidDirectTexture.h deleted file mode 100644 index bf7a603b98..0000000000 --- a/widget/android/AndroidDirectTexture.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef AndroidDirectTexture_h_ -#define AndroidDirectTexture_h_ - -#include "gfxTypes.h" -#include "mozilla/Mutex.h" -#include "AndroidGraphicBuffer.h" - -struct nsIntRect; - -namespace mozilla { - -/** - * This is a thread safe wrapper around AndroidGraphicBuffer that handles - * double buffering. Each call to Bind() flips the buffer when necessary. - * - * You need to be careful when destroying an instance of this class. If either - * buffer is locked by the application of the driver/hardware, bad things will - * happen. Be sure that the OpenGL texture is no longer on the screen. - */ -class AndroidDirectTexture -{ -public: - AndroidDirectTexture(uint32_t width, uint32_t height, uint32_t usage, gfxImageFormat format); - virtual ~AndroidDirectTexture(); - - bool Lock(uint32_t usage, unsigned char **bits); - bool Lock(uint32_t usage, const nsIntRect& rect, unsigned char **bits); - bool Unlock(bool aFlip = true); - - bool Reallocate(uint32_t aWidth, uint32_t aHeight); - bool Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat); - - uint32_t Width() { return mWidth; } - uint32_t Height() { return mHeight; } - - bool Bind(); - -private: - mozilla::Mutex mLock; - bool mNeedFlip; - - uint32_t mWidth; - uint32_t mHeight; - gfxImageFormat mFormat; - - AndroidGraphicBuffer* mFrontBuffer; - AndroidGraphicBuffer* mBackBuffer; - - AndroidGraphicBuffer* mPendingReallocBuffer; - void ReallocPendingBuffer(); -}; - -} /* mozilla */ -#endif /* AndroidDirectTexture_h_ */ diff --git a/widget/android/AndroidGraphicBuffer.cpp b/widget/android/AndroidGraphicBuffer.cpp deleted file mode 100644 index ab0f1a3a91..0000000000 --- a/widget/android/AndroidGraphicBuffer.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include -#include -#include -#include "AndroidGraphicBuffer.h" -#include "AndroidBridge.h" -#include "mozilla/Preferences.h" - -#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidGraphicBuffer" , ## args) - -#define EGL_NATIVE_BUFFER_ANDROID 0x3140 -#define EGL_IMAGE_PRESERVED_KHR 0x30D2 - -typedef void *EGLContext; -typedef void *EGLDisplay; -typedef uint32_t EGLenum; -typedef int32_t EGLint; -typedef uint32_t EGLBoolean; - -#define EGL_TRUE 1 -#define EGL_FALSE 0 -#define EGL_NONE 0x3038 -#define EGL_NO_CONTEXT (EGLContext)0 -#define EGL_DEFAULT_DISPLAY (void*)0 - -#define ANDROID_LIBUI_PATH "libui.so" -#define ANDROID_GLES_PATH "libGLESv2.so" -#define ANDROID_EGL_PATH "libEGL.so" - -// Really I have no idea, but this should be big enough -#define GRAPHIC_BUFFER_SIZE 1024 - -enum { - /* buffer is never read in software */ - GRALLOC_USAGE_SW_READ_NEVER = 0x00000000, - /* buffer is rarely read in software */ - GRALLOC_USAGE_SW_READ_RARELY = 0x00000002, - /* buffer is often read in software */ - GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003, - /* mask for the software read values */ - GRALLOC_USAGE_SW_READ_MASK = 0x0000000F, - - /* buffer is never written in software */ - GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000, - /* buffer is never written in software */ - GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020, - /* buffer is never written in software */ - GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030, - /* mask for the software write values */ - GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0, - - /* buffer will be used as an OpenGL ES texture */ - GRALLOC_USAGE_HW_TEXTURE = 0x00000100, - /* buffer will be used as an OpenGL ES render target */ - GRALLOC_USAGE_HW_RENDER = 0x00000200, - /* buffer will be used by the 2D hardware blitter */ - GRALLOC_USAGE_HW_2D = 0x00000400, - /* buffer will be used with the framebuffer device */ - GRALLOC_USAGE_HW_FB = 0x00001000, - /* mask for the software usage bit-mask */ - GRALLOC_USAGE_HW_MASK = 0x00001F00, -}; - -enum { - HAL_PIXEL_FORMAT_RGBA_8888 = 1, - HAL_PIXEL_FORMAT_RGBX_8888 = 2, - HAL_PIXEL_FORMAT_RGB_888 = 3, - HAL_PIXEL_FORMAT_RGB_565 = 4, - HAL_PIXEL_FORMAT_BGRA_8888 = 5, - HAL_PIXEL_FORMAT_RGBA_5551 = 6, - HAL_PIXEL_FORMAT_RGBA_4444 = 7, -}; - -typedef struct ARect { - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; -} ARect; - -static bool gTryRealloc = true; - -static class GLFunctions -{ -public: - MOZ_CONSTEXPR GLFunctions() : fGetDisplay(nullptr), - fEGLGetError(nullptr), - fCreateImageKHR(nullptr), - fDestroyImageKHR(nullptr), - fImageTargetTexture2DOES(nullptr), - fBindTexture(nullptr), - fGLGetError(nullptr), - fGraphicBufferCtor(nullptr), - fGraphicBufferDtor(nullptr), - fGraphicBufferLock(nullptr), - fGraphicBufferLockRect(nullptr), - fGraphicBufferUnlock(nullptr), - fGraphicBufferGetNativeBuffer(nullptr), - fGraphicBufferReallocate(nullptr), - mInitialized(false) - { - } - - typedef EGLDisplay (* pfnGetDisplay)(void *display_id); - pfnGetDisplay fGetDisplay; - typedef EGLint (* pfnEGLGetError)(void); - pfnEGLGetError fEGLGetError; - - typedef EGLImageKHR (* pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); - pfnCreateImageKHR fCreateImageKHR; - typedef EGLBoolean (* pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image); - pfnDestroyImageKHR fDestroyImageKHR; - - typedef void (* pfnImageTargetTexture2DOES)(GLenum target, EGLImageKHR image); - pfnImageTargetTexture2DOES fImageTargetTexture2DOES; - - typedef void (* pfnBindTexture)(GLenum target, GLuint texture); - pfnBindTexture fBindTexture; - - typedef GLenum (* pfnGLGetError)(); - pfnGLGetError fGLGetError; - - typedef void (*pfnGraphicBufferCtor)(void*, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); - pfnGraphicBufferCtor fGraphicBufferCtor; - - typedef void (*pfnGraphicBufferDtor)(void*); - pfnGraphicBufferDtor fGraphicBufferDtor; - - typedef int (*pfnGraphicBufferLock)(void*, uint32_t usage, unsigned char **addr); - pfnGraphicBufferLock fGraphicBufferLock; - - typedef int (*pfnGraphicBufferLockRect)(void*, uint32_t usage, const ARect&, unsigned char **addr); - pfnGraphicBufferLockRect fGraphicBufferLockRect; - - typedef int (*pfnGraphicBufferUnlock)(void*); - pfnGraphicBufferUnlock fGraphicBufferUnlock; - - typedef void* (*pfnGraphicBufferGetNativeBuffer)(void*); - pfnGraphicBufferGetNativeBuffer fGraphicBufferGetNativeBuffer; - - typedef int (*pfnGraphicBufferReallocate)(void*, uint32_t w, uint32_t h, uint32_t format); - pfnGraphicBufferReallocate fGraphicBufferReallocate; - - bool EnsureInitialized() - { - if (mInitialized) { - return true; - } - - void *handle = dlopen(ANDROID_EGL_PATH, RTLD_LAZY); - if (!handle) { - LOG("Couldn't load EGL library"); - return false; - } - - fGetDisplay = (pfnGetDisplay)dlsym(handle, "eglGetDisplay"); - fEGLGetError = (pfnEGLGetError)dlsym(handle, "eglGetError"); - fCreateImageKHR = (pfnCreateImageKHR)dlsym(handle, "eglCreateImageKHR"); - fDestroyImageKHR = (pfnDestroyImageKHR)dlsym(handle, "eglDestroyImageKHR"); - - if (!fGetDisplay || !fEGLGetError || !fCreateImageKHR || !fDestroyImageKHR) { - LOG("Failed to find some EGL functions"); - return false; - } - - handle = dlopen(ANDROID_GLES_PATH, RTLD_LAZY); - if (!handle) { - LOG("Couldn't load GL library"); - return false; - } - - fImageTargetTexture2DOES = (pfnImageTargetTexture2DOES)dlsym(handle, "glEGLImageTargetTexture2DOES"); - fBindTexture = (pfnBindTexture)dlsym(handle, "glBindTexture"); - fGLGetError = (pfnGLGetError)dlsym(handle, "glGetError"); - - if (!fImageTargetTexture2DOES || !fBindTexture || !fGLGetError) { - LOG("Failed to find some GL functions"); - return false; - } - - handle = dlopen(ANDROID_LIBUI_PATH, RTLD_LAZY); - if (!handle) { - LOG("Couldn't load libui.so"); - return false; - } - - fGraphicBufferCtor = (pfnGraphicBufferCtor)dlsym(handle, "_ZN7android13GraphicBufferC1Ejjij"); - fGraphicBufferDtor = (pfnGraphicBufferDtor)dlsym(handle, "_ZN7android13GraphicBufferD1Ev"); - fGraphicBufferLock = (pfnGraphicBufferLock)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjPPv"); - fGraphicBufferLockRect = (pfnGraphicBufferLockRect)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjRKNS_4RectEPPv"); - fGraphicBufferUnlock = (pfnGraphicBufferUnlock)dlsym(handle, "_ZN7android13GraphicBuffer6unlockEv"); - fGraphicBufferGetNativeBuffer = (pfnGraphicBufferGetNativeBuffer)dlsym(handle, "_ZNK7android13GraphicBuffer15getNativeBufferEv"); - fGraphicBufferReallocate = (pfnGraphicBufferReallocate)dlsym(handle, "_ZN7android13GraphicBuffer10reallocateEjjij"); - - if (!fGraphicBufferCtor || !fGraphicBufferDtor || !fGraphicBufferLock || - !fGraphicBufferUnlock || !fGraphicBufferGetNativeBuffer) { - LOG("Failed to lookup some GraphicBuffer functions"); - return false; - } - - mInitialized = true; - return true; - } - -private: - bool mInitialized; - -} sGLFunctions; - -namespace mozilla { - -static void clearGLError() -{ - while (glGetError() != GL_NO_ERROR); -} - -static bool ensureNoGLError(const char* name) -{ - bool result = true; - GLuint error; - - while ((error = glGetError()) != GL_NO_ERROR) { - LOG("GL error [%s]: %40x\n", name, error); - result = false; - } - - return result; -} - -AndroidGraphicBuffer::AndroidGraphicBuffer(uint32_t width, uint32_t height, uint32_t usage, - gfxImageFormat format) : - mWidth(width) - , mHeight(height) - , mUsage(usage) - , mFormat(format) - , mHandle(0) - , mEGLImage(0) -{ -} - -AndroidGraphicBuffer::~AndroidGraphicBuffer() -{ - DestroyBuffer(); -} - -void -AndroidGraphicBuffer::DestroyBuffer() -{ - /** - * XXX: eglDestroyImageKHR crashes sometimes due to refcount badness (I think) - * - * If you look at egl.cpp (https://github.com/android/platform_frameworks_base/blob/master/opengl/libagl/egl.cpp#L2002) - * you can see that eglCreateImageKHR just refs the native buffer, and eglDestroyImageKHR - * just unrefs it. Somehow the ref count gets messed up and things are already destroyed - * by the time eglDestroyImageKHR gets called. For now, at least, just not calling - * eglDestroyImageKHR should be fine since we do free the GraphicBuffer below. - * - * Bug 712716 - */ -#if 0 - if (mEGLImage) { - if (sGLFunctions.EnsureInitialized()) { - sGLFunctions.fDestroyImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), mEGLImage); - mEGLImage = nullptr; - } - } -#endif - mEGLImage = nullptr; - - if (mHandle) { - if (sGLFunctions.EnsureInitialized()) { - sGLFunctions.fGraphicBufferDtor(mHandle); - } - free(mHandle); - mHandle = nullptr; - } - -} - -bool -AndroidGraphicBuffer::EnsureBufferCreated() -{ - if (!mHandle) { - mHandle = malloc(GRAPHIC_BUFFER_SIZE); - sGLFunctions.fGraphicBufferCtor(mHandle, mWidth, mHeight, GetAndroidFormat(mFormat), GetAndroidUsage(mUsage)); - } - - return true; -} - -bool -AndroidGraphicBuffer::EnsureInitialized() -{ - if (!sGLFunctions.EnsureInitialized()) { - return false; - } - - EnsureBufferCreated(); - return true; -} - -int -AndroidGraphicBuffer::Lock(uint32_t aUsage, unsigned char **bits) -{ - if (!EnsureInitialized()) - return true; - - return sGLFunctions.fGraphicBufferLock(mHandle, GetAndroidUsage(aUsage), bits); -} - -int -AndroidGraphicBuffer::Lock(uint32_t aUsage, const nsIntRect& aRect, unsigned char **bits) -{ - if (!EnsureInitialized()) - return false; - - ARect rect; - rect.left = aRect.x; - rect.top = aRect.y; - rect.right = aRect.x + aRect.width; - rect.bottom = aRect.y + aRect.height; - - return sGLFunctions.fGraphicBufferLockRect(mHandle, GetAndroidUsage(aUsage), rect, bits); -} - -int -AndroidGraphicBuffer::Unlock() -{ - if (!EnsureInitialized()) - return false; - - return sGLFunctions.fGraphicBufferUnlock(mHandle); -} - -bool -AndroidGraphicBuffer::Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat) -{ - if (!EnsureInitialized()) - return false; - - mWidth = aWidth; - mHeight = aHeight; - mFormat = aFormat; - - // Sometimes GraphicBuffer::reallocate just doesn't work. In those cases we'll just allocate a brand - // new buffer. If reallocate fails once, never try it again. - if (!gTryRealloc || sGLFunctions.fGraphicBufferReallocate(mHandle, aWidth, aHeight, GetAndroidFormat(aFormat)) != 0) { - DestroyBuffer(); - EnsureBufferCreated(); - - gTryRealloc = false; - } - - return true; -} - -uint32_t -AndroidGraphicBuffer::GetAndroidUsage(uint32_t aUsage) -{ - uint32_t flags = 0; - - if (aUsage & UsageSoftwareRead) { - flags |= GRALLOC_USAGE_SW_READ_OFTEN; - } - - if (aUsage & UsageSoftwareWrite) { - flags |= GRALLOC_USAGE_SW_WRITE_OFTEN; - } - - if (aUsage & UsageTexture) { - flags |= GRALLOC_USAGE_HW_TEXTURE; - } - - if (aUsage & UsageTarget) { - flags |= GRALLOC_USAGE_HW_RENDER; - } - - if (aUsage & Usage2D) { - flags |= GRALLOC_USAGE_HW_2D; - } - - return flags; -} - -uint32_t -AndroidGraphicBuffer::GetAndroidFormat(gfxImageFormat aFormat) -{ - switch (aFormat) { - case gfxImageFormat::RGB24: - return HAL_PIXEL_FORMAT_RGBX_8888; - case gfxImageFormat::RGB16_565: - return HAL_PIXEL_FORMAT_RGB_565; - default: - return 0; - } -} - -bool -AndroidGraphicBuffer::EnsureEGLImage() -{ - if (mEGLImage) - return true; - - - if (!EnsureInitialized()) - return false; - - EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; - void* nativeBuffer = sGLFunctions.fGraphicBufferGetNativeBuffer(mHandle); - - mEGLImage = sGLFunctions.fCreateImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)nativeBuffer, eglImgAttrs); - return mEGLImage != nullptr; -} - -bool -AndroidGraphicBuffer::Bind() -{ - if (!EnsureInitialized()) - return false; - - if (!EnsureEGLImage()) { - LOG("No valid EGLImage!"); - return false; - } - - clearGLError(); - sGLFunctions.fImageTargetTexture2DOES(GL_TEXTURE_2D, mEGLImage); - return ensureNoGLError("glEGLImageTargetTexture2DOES"); -} - -// Build whitelist to check for board type. -static void InitWhiteList(nsTArray& list) -{ - nsString ele; - ele.AssignASCII("droid2"); // Motorola Droid 2 - list.AppendElement(ele); - ele.AssignASCII("GT-I9100"); // Samsung Galaxy SII - list.AppendElement(ele); - ele.AssignASCII("herring"); // Samsung Nexus S - list.AppendElement(ele); - ele.AssignASCII("omap4sdp"); // Amazon Kindle Fire - list.AppendElement(ele); - ele.AssignASCII("SGH-I897"); // Samsung Galaxy S - list.AppendElement(ele); - ele.AssignASCII("sgh-i997"); // Samsung Infuse 4G - list.AppendElement(ele); - ele.AssignASCII("sgh-t839"); // Samsung Sidekick 4G - list.AppendElement(ele); - ele.AssignASCII("shadow"); // Motorola Droid X - list.AppendElement(ele); - ele.AssignASCII("spyder"); // Motorola Razr - list.AppendElement(ele); - ele.AssignASCII("targa"); // Motorola Droid Bionic - list.AppendElement(ele); - ele.AssignASCII("tuna"); // Galaxy Nexus - list.AppendElement(ele); - ele.AssignASCII("venus2"); // Motorla Droid Pro - list.AppendElement(ele); -} - -bool -AndroidGraphicBuffer::IsBlacklisted() -{ - nsAutoString board; - if (!AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "BOARD", board)) - return true; - - NS_ConvertUTF16toUTF8 boardUtf8(board); - - if (Preferences::GetBool("direct-texture.force.enabled", false)) { - LOG("allowing board '%s' due to prefs override", boardUtf8.get()); - return false; - } - - if (Preferences::GetBool("direct-texture.force.disabled", false)) { - LOG("disallowing board '%s' due to prefs override", boardUtf8.get()); - return true; - } - - static nsTArray sListAllowed; - if (sListAllowed.Length() == 0) { - InitWhiteList(sListAllowed); - } - - int i = -1; - if ((i = sListAllowed.BinaryIndexOf(board)) >= 0) { - nsString name = sListAllowed.ElementAt(i); - LOG("allowing board '%s' based on '%s'\n", boardUtf8.get(), NS_ConvertUTF16toUTF8(name).get()); - return false; - } - - LOG("disallowing board: %s\n", boardUtf8.get()); - return true; -} - -} /* mozilla */ diff --git a/widget/android/AndroidGraphicBuffer.h b/widget/android/AndroidGraphicBuffer.h deleted file mode 100644 index a7af87bf84..0000000000 --- a/widget/android/AndroidGraphicBuffer.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef AndroidGraphicBuffer_h_ -#define AndroidGraphicBuffer_h_ - -#include "gfxTypes.h" - -typedef void* EGLImageKHR; -typedef void* EGLClientBuffer; - -struct nsIntRect; - -namespace mozilla { - -/** - * This class allows access to Android's direct texturing mechanism. Locking - * the buffer gives you a pointer you can read/write to directly. It is fully - * threadsafe, but you probably really want to use the AndroidDirectTexture - * class which will handle double buffering. - * - * In order to use the buffer in OpenGL, just call Bind() and it will attach - * to whatever texture is bound to GL_TEXTURE_2D. - */ -class AndroidGraphicBuffer -{ -public: - enum { - UsageSoftwareRead = 1, - UsageSoftwareWrite = 1 << 1, - UsageTexture = 1 << 2, - UsageTarget = 1 << 3, - Usage2D = 1 << 4 - }; - - AndroidGraphicBuffer(uint32_t width, uint32_t height, uint32_t usage, gfxImageFormat format); - virtual ~AndroidGraphicBuffer(); - - int Lock(uint32_t usage, unsigned char **bits); - int Lock(uint32_t usage, const nsIntRect& rect, unsigned char **bits); - int Unlock(); - bool Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat); - - uint32_t Width() { return mWidth; } - uint32_t Height() { return mHeight; } - - bool Bind(); - - static bool IsBlacklisted(); - -private: - uint32_t mWidth; - uint32_t mHeight; - uint32_t mUsage; - gfxImageFormat mFormat; - - bool EnsureInitialized(); - bool EnsureEGLImage(); - - void DestroyBuffer(); - bool EnsureBufferCreated(); - - uint32_t GetAndroidUsage(uint32_t aUsage); - uint32_t GetAndroidFormat(gfxImageFormat aFormat); - - void *mHandle; - void *mEGLImage; -}; - -} /* mozilla */ -#endif /* AndroidGraphicBuffer_h_ */ diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp deleted file mode 100644 index 3bb5e75827..0000000000 --- a/widget/android/AndroidJNI.cpp +++ /dev/null @@ -1,1037 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/Hal.h" -#include "nsIFile.h" -#include "nsString.h" - -#include "AndroidBridge.h" -#include "AndroidGraphicBuffer.h" -#include "APZCCallbackHandler.h" - -#include -#include -#include -#include -#include - -#include "nsAppShell.h" -#include "nsWindow.h" -#include -#include "nsIObserverService.h" -#include "mozilla/Services.h" -#include "nsThreadUtils.h" - -#include "mozilla/unused.h" -#include "mozilla/UniquePtr.h" - -#include "mozilla/dom/SmsMessage.h" -#include "mozilla/dom/mobilemessage/Constants.h" -#include "mozilla/dom/mobilemessage/Types.h" -#include "mozilla/dom/mobilemessage/PSms.h" -#include "mozilla/dom/mobilemessage/SmsParent.h" -#include "mozilla/layers/APZCTreeManager.h" -#include "nsIMobileMessageDatabaseService.h" -#include "nsPluginInstanceOwner.h" -#include "AndroidSurfaceTexture.h" -#include "GeckoProfiler.h" -#include "nsMemoryPressure.h" - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::dom::mobilemessage; -using namespace mozilla::layers; -using namespace mozilla::widget; -using namespace mozilla::widget::android; - -/* Forward declare all the JNI methods as extern "C" */ - -extern "C" { -/* - * Incoming JNI methods - */ - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_registerJavaUiThread(JNIEnv *jenv, jclass jc) -{ - AndroidBridge::RegisterJavaUiThread(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_nativeInit(JNIEnv *jenv, jclass, jobject clsLoader) -{ - AndroidBridge::ConstructBridge(jenv, jni::Object::Ref::From(clsLoader)); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_notifyGoannaOfEvent(JNIEnv *jenv, jclass jc, jobject event) -{ - // poke the appshell - if (nsAppShell::gAppShell) - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeFromJavaObject(jenv, event)); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_notifyGoannaObservers(JNIEnv *aEnv, jclass, - jstring aTopic, jstring aData) -{ - if (!NS_IsMainThread()) { - AndroidBridge::ThrowException(aEnv, - "java/lang/IllegalThreadStateException", "Not on Goanna main thread"); - return; - } - - nsCOMPtr obsServ = - mozilla::services::GetObserverService(); - if (!obsServ) { - AndroidBridge::ThrowException(aEnv, - "java/lang/IllegalStateException", "No observer service"); - return; - } - - const nsJNICString topic(aTopic, aEnv); - const nsJNIString data(aData, aEnv); - obsServ->NotifyObservers(nullptr, topic.get(), data.get()); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_processNextNativeEvent(JNIEnv *jenv, jclass, jboolean mayWait) -{ - // poke the appshell - if (nsAppShell::gAppShell) - nsAppShell::gAppShell->ProcessNextNativeEvent(mayWait != JNI_FALSE); -} - -NS_EXPORT jlong JNICALL -Java_org_mozilla_goanna_GoannaAppShell_runUiThreadCallback(JNIEnv* env, jclass) -{ - if (!AndroidBridge::Bridge()) { - return -1; - } - - return AndroidBridge::Bridge()->RunDelayedUiThreadTasks(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_onResume(JNIEnv *jenv, jclass jc) -{ - if (nsAppShell::gAppShell) - nsAppShell::gAppShell->OnResume(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_reportJavaCrash(JNIEnv *jenv, jclass, jstring jStackTrace) -{ - MOZ_CRASH("Uncaught Java exception"); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, - jdouble aLevel, - jboolean aCharging, - jdouble aRemainingTime) -{ - class NotifyBatteryChangeRunnable : public nsRunnable { - public: - NotifyBatteryChangeRunnable(double aLevel, bool aCharging, double aRemainingTime) - : mLevel(aLevel) - , mCharging(aCharging) - , mRemainingTime(aRemainingTime) - {} - - NS_IMETHODIMP Run() { - hal::NotifyBatteryChange(hal::BatteryInformation(mLevel, mCharging, mRemainingTime)); - return NS_OK; - } - - private: - double mLevel; - bool mCharging; - double mRemainingTime; - }; - - nsCOMPtr runnable = new NotifyBatteryChangeRunnable(aLevel, aCharging, aRemainingTime); - NS_DispatchToMainThread(runnable); -} - -#ifdef MOZ_WEBSMS_BACKEND - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsReceived(JNIEnv* jenv, jclass, - jstring aSender, - jstring aBody, - jint aMessageClass, - jlong aTimestamp) -{ - class NotifySmsReceivedRunnable : public nsRunnable { - public: - NotifySmsReceivedRunnable(const SmsMessageData& aMessageData) - : mMessageData(aMessageData) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr obs = services::GetObserverService(); - if (!obs) { - return NS_OK; - } - - nsCOMPtr message = new SmsMessage(mMessageData); - obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr); - return NS_OK; - } - - private: - SmsMessageData mMessageData; - }; - - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(0, 0, eDeliveryState_Received, eDeliveryStatus_Success, - nsJNIString(aSender, jenv), EmptyString(), - nsJNIString(aBody, jenv), - static_cast(aMessageClass), - aTimestamp, false); - - nsCOMPtr runnable = new NotifySmsReceivedRunnable(message); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsSent(JNIEnv* jenv, jclass, - jint aId, - jstring aReceiver, - jstring aBody, - jlong aTimestamp, - jint aRequestId) -{ - class NotifySmsSentRunnable : public nsRunnable { - public: - NotifySmsSentRunnable(const SmsMessageData& aMessageData, - int32_t aRequestId) - : mMessageData(aMessageData) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - /* - * First, we are going to notify all SmsManager that a message has - * been sent. Then, we will notify the SmsRequest object about it. - */ - nsCOMPtr obs = services::GetObserverService(); - if (!obs) { - return NS_OK; - } - - nsCOMPtr message = new SmsMessage(mMessageData); - obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr); - - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifyMessageSent(message); - return NS_OK; - } - - private: - SmsMessageData mMessageData; - int32_t mRequestId; - }; - - // TODO Need to add the message `messageClass` parameter value. Bug 804476 - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(aId, 0, eDeliveryState_Sent, eDeliveryStatus_Pending, - EmptyString(), nsJNIString(aReceiver, jenv), - nsJNIString(aBody, jenv), eMessageClass_Normal, - aTimestamp, true); - - nsCOMPtr runnable = new NotifySmsSentRunnable(message, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsDelivery(JNIEnv* jenv, jclass, - jint aId, - jint aDeliveryStatus, - jstring aReceiver, - jstring aBody, - jlong aTimestamp) -{ - class NotifySmsDeliveredRunnable : public nsRunnable { - public: - NotifySmsDeliveredRunnable(const SmsMessageData& aMessageData) - : mMessageData(aMessageData) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr obs = services::GetObserverService(); - if (!obs) { - return NS_OK; - } - - nsCOMPtr message = new SmsMessage(mMessageData); - const char* topic = (mMessageData.deliveryStatus() == eDeliveryStatus_Success) - ? kSmsDeliverySuccessObserverTopic - : kSmsDeliveryErrorObserverTopic; - obs->NotifyObservers(message, topic, nullptr); - - return NS_OK; - } - - private: - SmsMessageData mMessageData; - }; - - // TODO Need to add the message `messageClass` parameter value. Bug 804476 - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(aId, 0, eDeliveryState_Sent, - static_cast(aDeliveryStatus), - EmptyString(), nsJNIString(aReceiver, jenv), - nsJNIString(aBody, jenv), eMessageClass_Normal, - aTimestamp, true); - - nsCOMPtr runnable = new NotifySmsDeliveredRunnable(message); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsSendFailed(JNIEnv* jenv, jclass, - jint aError, - jint aRequestId) -{ - class NotifySmsSendFailedRunnable : public nsRunnable { - public: - NotifySmsSendFailedRunnable(int32_t aError, - int32_t aRequestId) - : mError(aError) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifySendMessageFailed(mError); - return NS_OK; - } - - private: - int32_t mError; - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifySmsSendFailedRunnable(aError, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyGetSms(JNIEnv* jenv, jclass, - jint aId, - jint aDeliveryStatus, - jstring aReceiver, - jstring aSender, - jstring aBody, - jlong aTimestamp, - jint aRequestId) -{ - class NotifyGetSmsRunnable : public nsRunnable { - public: - NotifyGetSmsRunnable(const SmsMessageData& aMessageData, - int32_t aRequestId) - : mMessageData(aMessageData) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - nsCOMPtr message = new SmsMessage(mMessageData); - request->NotifyMessageGot(message); - return NS_OK; - } - - private: - SmsMessageData mMessageData; - int32_t mRequestId; - }; - - nsJNIString receiver = nsJNIString(aReceiver, jenv); - DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received - : eDeliveryState_Sent; - - // TODO Need to add the message `read` parameter value. Bug 748391 - // TODO Need to add the message `messageClass` parameter value. Bug 804476 - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(aId, 0, state, - static_cast(aDeliveryStatus), - nsJNIString(aSender, jenv), receiver, - nsJNIString(aBody, jenv), eMessageClass_Normal, - aTimestamp, true); - - nsCOMPtr runnable = new NotifyGetSmsRunnable(message, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyGetSmsFailed(JNIEnv* jenv, jclass, - jint aError, - jint aRequestId) -{ - class NotifyGetSmsFailedRunnable : public nsRunnable { - public: - NotifyGetSmsFailedRunnable(int32_t aError, - int32_t aRequestId) - : mError(aError) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifyGetMessageFailed(mError); - return NS_OK; - } - - private: - int32_t mError; - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifyGetSmsFailedRunnable(aError, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsDeleted(JNIEnv* jenv, jclass, - jboolean aDeleted, - jint aRequestId) -{ - class NotifySmsDeletedRunnable : public nsRunnable { - public: - NotifySmsDeletedRunnable(bool aDeleted, int32_t aRequestId) - : mDeleted(aDeleted) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - // For android, we support only single SMS deletion. - request->NotifyMessageDeleted(&mDeleted, 1); - return NS_OK; - } - - private: - bool mDeleted; - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifySmsDeletedRunnable(aDeleted, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifySmsDeleteFailed(JNIEnv* jenv, jclass, - jint aError, - jint aRequestId) -{ - class NotifySmsDeleteFailedRunnable : public nsRunnable { - public: - NotifySmsDeleteFailedRunnable(int32_t aError, - int32_t aRequestId) - : mError(aError) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifyDeleteMessageFailed(mError); - return NS_OK; - } - - private: - int32_t mError; - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifySmsDeleteFailedRunnable(aError, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyNoMessageInList(JNIEnv* jenv, jclass, - jint aRequestId) -{ - class NotifyNoMessageInListRunnable : public nsRunnable { - public: - NotifyNoMessageInListRunnable(int32_t aRequestId) - : mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifyNoMessageInList(); - return NS_OK; - } - - private: - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifyNoMessageInListRunnable(aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyListCreated(JNIEnv* jenv, jclass, - jint aListId, - jint aMessageId, - jint aDeliveryStatus, - jstring aReceiver, - jstring aSender, - jstring aBody, - jlong aTimestamp, - jint aRequestId) -{ - class NotifyCreateMessageListRunnable : public nsRunnable { - public: - NotifyCreateMessageListRunnable(int32_t aListId, - const SmsMessageData& aMessageData, - int32_t aRequestId) - : mListId(aListId) - , mMessageData(aMessageData) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - nsCOMPtr message = new SmsMessage(mMessageData); - request->NotifyMessageListCreated(mListId, message); - return NS_OK; - } - - private: - int32_t mListId; - SmsMessageData mMessageData; - int32_t mRequestId; - }; - - - nsJNIString receiver = nsJNIString(aReceiver, jenv); - DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received - : eDeliveryState_Sent; - - // TODO Need to add the message `read` parameter value. Bug 748391 - // TODO Need to add the message `messageClass` parameter value. Bug 804476 - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(aMessageId, 0, state, - static_cast(aDeliveryStatus), - nsJNIString(aSender, jenv), receiver, - nsJNIString(aBody, jenv), eMessageClass_Normal, - aTimestamp, true); - - nsCOMPtr runnable = - new NotifyCreateMessageListRunnable(aListId, message, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyGotNextMessage(JNIEnv* jenv, jclass, - jint aMessageId, - jint aDeliveryStatus, - jstring aReceiver, - jstring aSender, - jstring aBody, - jlong aTimestamp, - jint aRequestId) -{ - class NotifyGotNextMessageRunnable : public nsRunnable { - public: - NotifyGotNextMessageRunnable(const SmsMessageData& aMessageData, - int32_t aRequestId) - : mMessageData(aMessageData) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - nsCOMPtr message = new SmsMessage(mMessageData); - request->NotifyNextMessageInListGot(message); - return NS_OK; - } - - private: - SmsMessageData mMessageData; - int32_t mRequestId; - }; - - - nsJNIString receiver = nsJNIString(aReceiver, jenv); - DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received - : eDeliveryState_Sent; - - // TODO Need to add the message `read` parameter value. Bug 748391 - // TODO Need to add the message `messageClass` parameter value. Bug 804476 - // TODO Need to correct the message `threadId` parameter value. Bug 859098 - SmsMessageData message(aMessageId, 0, state, - static_cast(aDeliveryStatus), - nsJNIString(aSender, jenv), receiver, - nsJNIString(aBody, jenv), eMessageClass_Normal, - aTimestamp, true); - - nsCOMPtr runnable = - new NotifyGotNextMessageRunnable(message, aRequestId); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaSmsManager_notifyReadingMessageListFailed(JNIEnv* jenv, jclass, - jint aError, - jint aRequestId) -{ - class NotifyReadListFailedRunnable : public nsRunnable { - public: - NotifyReadListFailedRunnable(int32_t aError, - int32_t aRequestId) - : mError(aError) - , mRequestId(aRequestId) - {} - - NS_IMETHODIMP Run() { - nsCOMPtr request = - AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId); - NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); - - request->NotifyReadMessageListFailed(mError); - return NS_OK; - } - - private: - int32_t mError; - int32_t mRequestId; - }; - - - nsCOMPtr runnable = - new NotifyReadListFailedRunnable(aError, aRequestId); - NS_DispatchToMainThread(runnable); -} - -#endif // MOZ_WEBSMS_BACKEND - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_scheduleComposite(JNIEnv*, jclass) -{ - nsWindow::ScheduleComposite(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_scheduleResumeComposition(JNIEnv*, jclass, jint width, jint height) -{ - nsWindow::ScheduleResumeComposition(width, height); -} - -NS_EXPORT float JNICALL -Java_org_mozilla_goanna_GoannaAppShell_computeRenderIntegrity(JNIEnv*, jclass) -{ - return nsWindow::ComputeRenderIntegrity(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass, jstring filePath, jlong callback) -{ - class NotifyFilePickerResultRunnable : public nsRunnable { - public: - NotifyFilePickerResultRunnable(nsString& fileDir, long callback) : - mFileDir(fileDir), mCallback(callback) {} - - NS_IMETHODIMP Run() { - nsFilePickerCallback* handler = (nsFilePickerCallback*)mCallback; - handler->handleResult(mFileDir); - handler->Release(); - return NS_OK; - } - private: - nsString mFileDir; - long mCallback; - }; - nsString path = nsJNIString(filePath, jenv); - - nsCOMPtr runnable = - new NotifyFilePickerResultRunnable(path, (long)callback); - NS_DispatchToMainThread(runnable); -} - -static int -NextPowerOfTwo(int value) { - // code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html - if (0 == value--) { - return 1; - } - value = (value >> 1) | value; - value = (value >> 2) | value; - value = (value >> 4) | value; - value = (value >> 8) | value; - value = (value >> 16) | value; - return value + 1; -} - -#define MAX_LOCK_ATTEMPTS 10 - -static bool LockWindowWithRetry(void* window, unsigned char** bits, int* width, int* height, int* format, int* stride) -{ - int count = 0; - - while (count < MAX_LOCK_ATTEMPTS) { - if (AndroidBridge::Bridge()->LockWindow(window, bits, width, height, format, stride)) - return true; - - count++; - usleep(500); - } - - return false; -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_GoannaAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobject surface) -{ - static jclass jSurfaceBitsClass = nullptr; - static jmethodID jSurfaceBitsCtor = 0; - static jfieldID jSurfaceBitsWidth, jSurfaceBitsHeight, jSurfaceBitsFormat, jSurfaceBitsBuffer; - - jobject surfaceBits = nullptr; - unsigned char* bitsCopy = nullptr; - int dstWidth, dstHeight, dstSize; - - void* window = AndroidBridge::Bridge()->AcquireNativeWindow(jenv, surface); - if (!window) - return nullptr; - - unsigned char* bits; - int srcWidth, srcHeight, format, srcStride; - - // So we lock/unlock once here in order to get whatever is currently the front buffer. It sucks. - if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) - return nullptr; - - AndroidBridge::Bridge()->UnlockWindow(window); - - // This is lock will result in the front buffer, since the last unlock rotated it to the back. Probably. - if (!LockWindowWithRetry(window, &bits, &srcWidth, &srcHeight, &format, &srcStride)) - return nullptr; - - // These are from android.graphics.PixelFormat - int bpp; - switch (format) { - case 1: // RGBA_8888 - bpp = 4; - break; - case 4: // RGB_565 - bpp = 2; - break; - default: - goto cleanup; - } - - dstWidth = NextPowerOfTwo(srcWidth); - dstHeight = NextPowerOfTwo(srcHeight); - dstSize = dstWidth * dstHeight * bpp; - - bitsCopy = (unsigned char*)malloc(dstSize); - bzero(bitsCopy, dstSize); - for (int i = 0; i < srcHeight; i++) { - memcpy(bitsCopy + ((dstHeight - i - 1) * dstWidth * bpp), bits + (i * srcStride * bpp), srcStride * bpp); - } - - if (!jSurfaceBitsClass) { - jSurfaceBitsClass = (jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/goanna/SurfaceBits")); - jSurfaceBitsCtor = jenv->GetMethodID(jSurfaceBitsClass, "", "()V"); - - jSurfaceBitsWidth = jenv->GetFieldID(jSurfaceBitsClass, "width", "I"); - jSurfaceBitsHeight = jenv->GetFieldID(jSurfaceBitsClass, "height", "I"); - jSurfaceBitsFormat = jenv->GetFieldID(jSurfaceBitsClass, "format", "I"); - jSurfaceBitsBuffer = jenv->GetFieldID(jSurfaceBitsClass, "buffer", "Ljava/nio/ByteBuffer;"); - } - - surfaceBits = jenv->NewObject(jSurfaceBitsClass, jSurfaceBitsCtor); - jenv->SetIntField(surfaceBits, jSurfaceBitsWidth, dstWidth); - jenv->SetIntField(surfaceBits, jSurfaceBitsHeight, dstHeight); - jenv->SetIntField(surfaceBits, jSurfaceBitsFormat, format); - jenv->SetObjectField(surfaceBits, jSurfaceBitsBuffer, jenv->NewDirectByteBuffer(bitsCopy, dstSize)); - -cleanup: - AndroidBridge::Bridge()->UnlockWindow(window); - AndroidBridge::Bridge()->ReleaseNativeWindow(window); - - return surfaceBits; -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_onFullScreenPluginHidden(JNIEnv* jenv, jclass, jobject view) -{ - class ExitFullScreenRunnable : public nsRunnable { - public: - ExitFullScreenRunnable(jobject view) : mView(view) {} - - NS_IMETHODIMP Run() { - JNIEnv* env = AndroidBridge::GetJNIEnv(); - nsPluginInstanceOwner::ExitFullScreen(mView); - env->DeleteGlobalRef(mView); - return NS_OK; - } - - private: - jobject mView; - }; - - nsCOMPtr runnable = new ExitFullScreenRunnable(jenv->NewGlobalRef(view)); - NS_DispatchToMainThread(runnable); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_GoannaAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue) -{ - static jclass jMessageQueueCls = nullptr; - static jfieldID jMessagesField; - static jmethodID jNextMethod; - if (!jMessageQueueCls) { - jMessageQueueCls = (jclass) jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue")); - jNextMethod = jenv->GetMethodID(jMessageQueueCls, "next", "()Landroid/os/Message;"); - jMessagesField = jenv->GetFieldID(jMessageQueueCls, "mMessages", "Landroid/os/Message;"); - } - - if (!jMessageQueueCls || !jNextMethod) - return nullptr; - - if (jMessagesField) { - jobject msg = jenv->GetObjectField(queue, jMessagesField); - // if queue.mMessages is null, queue.next() will block, which we don't want - // It turns out to be an order of magnitude more performant to do this extra check here and - // block less vs. one fewer checks here and more blocking. - if (!msg) { - return nullptr; - } - } - return jenv->CallObjectMethod(queue, jNextMethod); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_onSurfaceTextureFrameAvailable(JNIEnv* jenv, jclass, jobject surfaceTexture, jint id) -{ - mozilla::gl::AndroidSurfaceTexture* st = mozilla::gl::AndroidSurfaceTexture::Find(id); - if (!st) { - __android_log_print(ANDROID_LOG_ERROR, "GoannaJNI", "Failed to find AndroidSurfaceTexture with id %d", id); - return; - } - - st->NotifyFrameAvailable(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_GoannaAppShell_dispatchMemoryPressure(JNIEnv* jenv, jclass) -{ - NS_DispatchMemoryPressure(MemPressure_New); -} - -NS_EXPORT jdouble JNICALL -Java_org_mozilla_goanna_GoannaJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) -{ - return profiler_time(); -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance) -{ - APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); - if (controller) { - // TODO: Pass in correct values for presShellId and viewId. - controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0)); - } -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_init(JNIEnv* env, jobject instance) -{ - if (!AndroidBridge::Bridge()) { - return; - } - - const auto& newRef = NativePanZoomController::Ref::From(instance); - NativePanZoomController::LocalRef oldRef = - APZCCallbackHandler::GetInstance()->SetNativePanZoomController(newRef); - - MOZ_ASSERT(!oldRef, "Registering a new NPZC when we already have one"); -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event) -{ - APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); - if (!controller) { - return false; - } - - AndroidGoannaEvent* wrapper = AndroidGoannaEvent::MakeFromJavaObject(env, event); - MultiTouchInput input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow()); - delete wrapper; - - if (input.mType < 0 || !nsAppShell::gAppShell) { - return false; - } - - ScrollableLayerGuid guid; - uint64_t blockId; - nsEventStatus status = controller->ReceiveInputEvent(input, &guid, &blockId); - if (status != nsEventStatus_eConsumeNoDefault) { - nsAppShell::gAppShell->PostEvent(AndroidGoannaEvent::MakeApzInputEvent(input, guid, blockId)); - } - return true; -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_handleMotionEvent(JNIEnv* env, jobject instance, jobject event) -{ - // FIXME implement this -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance) -{ - if (!AndroidBridge::Bridge()) { - return; - } - - NativePanZoomController::LocalRef oldRef = - APZCCallbackHandler::GetInstance()->SetNativePanZoomController(nullptr); - - MOZ_ASSERT(oldRef, "Clearing a non-existent NPZC"); -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_getRedrawHint(JNIEnv* env, jobject instance) -{ - // FIXME implement this - return true; -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_setOverScrollMode(JNIEnv* env, jobject instance, jint overscrollMode) -{ - // FIXME implement this -} - -NS_EXPORT jint JNICALL -Java_org_mozilla_goanna_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env, jobject instance) -{ - // FIXME implement this - return 0; -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_ANRReporter_requestNativeStack(JNIEnv*, jclass, jboolean aUnwind) -{ - if (profiler_is_active()) { - // Don't proceed if profiler is already running - return JNI_FALSE; - } - // WARNING: we are on the ANR reporter thread at this point and it is - // generally unsafe to use the profiler from off the main thread. However, - // the risk here is limited because for most users, the profiler is not run - // elsewhere. See the discussion in Bug 863777, comment 13 - const char *NATIVE_STACK_FEATURES[] = - {"leaf", "threads", "privacy"}; - const char *NATIVE_STACK_UNWIND_FEATURES[] = - {"leaf", "threads", "privacy", "stackwalk"}; - - const char **features = NATIVE_STACK_FEATURES; - size_t features_size = sizeof(NATIVE_STACK_FEATURES); - if (aUnwind) { - features = NATIVE_STACK_UNWIND_FEATURES; - features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES); - // We want the new unwinder if the unwind mode has not been set yet - putenv("MOZ_PROFILER_NEW=1"); - } - - const char *NATIVE_STACK_THREADS[] = - {"GoannaMain", "Compositor"}; - // Buffer one sample and let the profiler wait a long time - profiler_start(100, 10000, features, features_size / sizeof(char*), - NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*)); - return JNI_TRUE; -} - -NS_EXPORT jstring JNICALL -Java_org_mozilla_goanna_ANRReporter_getNativeStack(JNIEnv* jenv, jclass) -{ - if (!profiler_is_active()) { - // Maybe profiler support is disabled? - return nullptr; - } - - // Timeout if we don't get a profiler sample after 5 seconds. - const PRIntervalTime timeout = PR_SecondsToInterval(5); - const PRIntervalTime startTime = PR_IntervalNow(); - - typedef struct { void operator()(void* p) { free(p); } } ProfilePtrPolicy; - // Pointer to a profile JSON string - typedef mozilla::UniquePtr ProfilePtr; - - ProfilePtr profile(profiler_get_profile()); - - while (profile && !strstr(profile.get(), "\"samples\":[{")) { - // no sample yet? - if (PR_IntervalNow() - startTime >= timeout) { - return nullptr; - } - usleep(100000ul); // Sleep for 100ms - profile = ProfilePtr(profiler_get_profile()); - } - - if (profile) { - return jenv->NewStringUTF(profile.get()); - } - return nullptr; -} - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_ANRReporter_releaseNativeStack(JNIEnv* jenv, jclass) -{ - if (!profiler_is_active()) { - // Maybe profiler support is disabled? - return; - } - mozilla_sampler_stop(); -} - -} diff --git a/widget/android/AndroidJNIWrapper.cpp b/widget/android/AndroidJNIWrapper.cpp deleted file mode 100644 index e4bdd36dcb..0000000000 --- a/widget/android/AndroidJNIWrapper.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include -#include - -#include "mozilla/DebugOnly.h" -#include "mozilla/Assertions.h" -#include "nsThreadUtils.h" -#include "AndroidBridge.h" - -extern "C" { - jclass __jsjni_GetGlobalClassRef(const char *className); -} - -class GetGlobalClassRefRunnable : public nsRunnable { - public: - GetGlobalClassRefRunnable(const char *className, jclass *foundClass) : - mClassName(className), mResult(foundClass) {} - NS_IMETHOD Run() { - *mResult = __jsjni_GetGlobalClassRef(mClassName); - return NS_OK; - } - private: - const char *mClassName; - jclass *mResult; -}; - -extern "C" { - __attribute__ ((visibility("default"))) - jclass - jsjni_FindClass(const char *className) { - // FindClass outside the main thread will run into problems due - // to missing the classpath - MOZ_ASSERT(NS_IsMainThread()); - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - return env->FindClass(className); - } - - jclass - __jsjni_GetGlobalClassRef(const char *className) { - // root class globally - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - jclass globalRef = static_cast(env->NewGlobalRef(env->FindClass(className))); - if (!globalRef) - return nullptr; - - // return the newly create global reference - return globalRef; - } - - __attribute__ ((visibility("default"))) - jclass - jsjni_GetGlobalClassRef(const char *className) { - nsCOMPtr mainThread; - mozilla::DebugOnly rv = NS_GetMainThread(getter_AddRefs(mainThread)); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - - jclass foundClass; - nsCOMPtr runnable_ref(new GetGlobalClassRefRunnable(className, - &foundClass)); - mainThread->Dispatch(runnable_ref, NS_DISPATCH_SYNC); - if (!foundClass) - return nullptr; - - return foundClass; - } - - __attribute__ ((visibility("default"))) - jmethodID - jsjni_GetStaticMethodID(jclass methodClass, - const char *methodName, - const char *signature) { - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - return env->GetStaticMethodID(methodClass, methodName, signature); - } - - __attribute__ ((visibility("default"))) - bool - jsjni_ExceptionCheck() { - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - return env->ExceptionCheck(); - } - - __attribute__ ((visibility("default"))) - void - jsjni_CallStaticVoidMethodA(jclass cls, - jmethodID method, - jvalue *values) { - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - - mozilla::AutoLocalJNIFrame jniFrame(env); - env->CallStaticVoidMethodA(cls, method, values); - } - - __attribute__ ((visibility("default"))) - int - jsjni_CallStaticIntMethodA(jclass cls, - jmethodID method, - jvalue *values) { - JNIEnv *env = mozilla::AndroidBridge::GetJNIEnv(); - - mozilla::AutoLocalJNIFrame jniFrame(env); - return env->CallStaticIntMethodA(cls, method, values); - } - - __attribute__ ((visibility("default"))) - jobject jsjni_GetGlobalContextRef() { - return mozilla::AndroidBridge::Bridge()->GetGlobalContextRef(); - } - - __attribute__ ((visibility("default"))) - JavaVM* jsjni_GetVM() { - return mozilla::AndroidBridge::GetVM(); - } - - __attribute__ ((visibility("default"))) - JNIEnv* jsjni_GetJNIForThread() { - return GetJNIForThread(); - } -} diff --git a/widget/android/AndroidJNIWrapper.h b/widget/android/AndroidJNIWrapper.h deleted file mode 100644 index 90bca26939..0000000000 --- a/widget/android/AndroidJNIWrapper.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef AndroidJNIWrapper_h__ -#define AndroidJNIWrapper_h__ - -#include "mozilla/Types.h" -#include -#include - -extern "C" MOZ_EXPORT jclass jsjni_FindClass(const char *className); - -/** - * JNIEnv::FindClass alternative. - * Callable from any thread, including code - * invoked via the JNI that doesn't have MOZILLA_INTERNAL_API defined. - * The caller is responsible for ensuring that the class is not leaked by - * calling DeleteGlobalRef at an appropriate time. - */ -extern "C" MOZ_EXPORT jclass jsjni_GetGlobalClassRef(const char *className); - -extern "C" MOZ_EXPORT jmethodID jsjni_GetStaticMethodID(jclass methodClass, - const char *methodName, - const char *signature); -extern "C" MOZ_EXPORT bool jsjni_ExceptionCheck(); -extern "C" MOZ_EXPORT void jsjni_CallStaticVoidMethodA(jclass cls, jmethodID method, jvalue *values); -extern "C" MOZ_EXPORT int jsjni_CallStaticIntMethodA(jclass cls, jmethodID method, jvalue *values); -extern "C" MOZ_EXPORT jobject jsjni_GetGlobalContextRef(); -extern "C" MOZ_EXPORT JavaVM* jsjni_GetVM(); -extern "C" MOZ_EXPORT JNIEnv* jsjni_GetJNIForThread(); - -#endif /* AndroidJNIWrapper_h__ */ diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp deleted file mode 100644 index 6cc47e64b8..0000000000 --- a/widget/android/AndroidJavaWrappers.cpp +++ /dev/null @@ -1,1073 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "AndroidJavaWrappers.h" -#include "AndroidBridge.h" -#include "AndroidBridgeUtilities.h" -#include "nsIDOMKeyEvent.h" -#include "nsIWidget.h" -#include "mozilla/BasicEvents.h" -#include "mozilla/TimeStamp.h" -#include "mozilla/TouchEvents.h" - -using namespace mozilla; -using namespace mozilla::dom; - -jclass AndroidGoannaEvent::jGoannaEventClass = 0; -jfieldID AndroidGoannaEvent::jActionField = 0; -jfieldID AndroidGoannaEvent::jTypeField = 0; -jfieldID AndroidGoannaEvent::jAckNeededField = 0; -jfieldID AndroidGoannaEvent::jTimeField = 0; -jfieldID AndroidGoannaEvent::jPoints = 0; -jfieldID AndroidGoannaEvent::jPointIndicies = 0; -jfieldID AndroidGoannaEvent::jPressures = 0; -jfieldID AndroidGoannaEvent::jToolTypes = 0; -jfieldID AndroidGoannaEvent::jPointRadii = 0; -jfieldID AndroidGoannaEvent::jOrientations = 0; -jfieldID AndroidGoannaEvent::jXField = 0; -jfieldID AndroidGoannaEvent::jYField = 0; -jfieldID AndroidGoannaEvent::jZField = 0; -jfieldID AndroidGoannaEvent::jDistanceField = 0; -jfieldID AndroidGoannaEvent::jRectField = 0; -jfieldID AndroidGoannaEvent::jNativeWindowField = 0; - -jfieldID AndroidGoannaEvent::jCharactersField = 0; -jfieldID AndroidGoannaEvent::jCharactersExtraField = 0; -jfieldID AndroidGoannaEvent::jDataField = 0; -jfieldID AndroidGoannaEvent::jDOMPrintableKeyValueField = 0; -jfieldID AndroidGoannaEvent::jKeyCodeField = 0; -jfieldID AndroidGoannaEvent::jScanCodeField = 0; -jfieldID AndroidGoannaEvent::jMetaStateField = 0; -jfieldID AndroidGoannaEvent::jFlagsField = 0; -jfieldID AndroidGoannaEvent::jUnicodeCharField = 0; -jfieldID AndroidGoannaEvent::jBaseUnicodeCharField = 0; -jfieldID AndroidGoannaEvent::jRepeatCountField = 0; -jfieldID AndroidGoannaEvent::jCountField = 0; -jfieldID AndroidGoannaEvent::jStartField = 0; -jfieldID AndroidGoannaEvent::jEndField = 0; -jfieldID AndroidGoannaEvent::jPointerIndexField = 0; -jfieldID AndroidGoannaEvent::jRangeTypeField = 0; -jfieldID AndroidGoannaEvent::jRangeStylesField = 0; -jfieldID AndroidGoannaEvent::jRangeLineStyleField = 0; -jfieldID AndroidGoannaEvent::jRangeBoldLineField = 0; -jfieldID AndroidGoannaEvent::jRangeForeColorField = 0; -jfieldID AndroidGoannaEvent::jRangeBackColorField = 0; -jfieldID AndroidGoannaEvent::jRangeLineColorField = 0; -jfieldID AndroidGoannaEvent::jLocationField = 0; -jfieldID AndroidGoannaEvent::jConnectionTypeField = 0; -jfieldID AndroidGoannaEvent::jIsWifiField = 0; -jfieldID AndroidGoannaEvent::jDHCPGatewayField = 0; -jfieldID AndroidGoannaEvent::jScreenOrientationField = 0; -jfieldID AndroidGoannaEvent::jByteBufferField = 0; -jfieldID AndroidGoannaEvent::jWidthField = 0; -jfieldID AndroidGoannaEvent::jHeightField = 0; -jfieldID AndroidGoannaEvent::jIDField = 0; -jfieldID AndroidGoannaEvent::jGamepadButtonField = 0; -jfieldID AndroidGoannaEvent::jGamepadButtonPressedField = 0; -jfieldID AndroidGoannaEvent::jGamepadButtonValueField = 0; -jfieldID AndroidGoannaEvent::jGamepadValuesField = 0; -jfieldID AndroidGoannaEvent::jPrefNamesField = 0; -jfieldID AndroidGoannaEvent::jObjectField = 0; - -jclass AndroidPoint::jPointClass = 0; -jfieldID AndroidPoint::jXField = 0; -jfieldID AndroidPoint::jYField = 0; - -jclass AndroidRect::jRectClass = 0; -jfieldID AndroidRect::jBottomField = 0; -jfieldID AndroidRect::jLeftField = 0; -jfieldID AndroidRect::jRightField = 0; -jfieldID AndroidRect::jTopField = 0; - -jclass AndroidRectF::jRectClass = 0; -jfieldID AndroidRectF::jBottomField = 0; -jfieldID AndroidRectF::jLeftField = 0; -jfieldID AndroidRectF::jRightField = 0; -jfieldID AndroidRectF::jTopField = 0; - -jclass AndroidLocation::jLocationClass = 0; -jmethodID AndroidLocation::jGetLatitudeMethod = 0; -jmethodID AndroidLocation::jGetLongitudeMethod = 0; -jmethodID AndroidLocation::jGetAltitudeMethod = 0; -jmethodID AndroidLocation::jGetAccuracyMethod = 0; -jmethodID AndroidLocation::jGetBearingMethod = 0; -jmethodID AndroidLocation::jGetSpeedMethod = 0; -jmethodID AndroidLocation::jGetTimeMethod = 0; - -jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0; -jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0; -jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0; -jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0; -jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0; - -RefCountedJavaObject::~RefCountedJavaObject() { - if (mObject) - GetJNIForThread()->DeleteGlobalRef(mObject); - mObject = nullptr; -} - -void -mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) -{ - AndroidGoannaEvent::InitGoannaEventClass(jEnv); - AndroidPoint::InitPointClass(jEnv); - AndroidLocation::InitLocationClass(jEnv); - AndroidRect::InitRectClass(jEnv); - AndroidRectF::InitRectFClass(jEnv); - AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv); -} - -void -AndroidGoannaEvent::InitGoannaEventClass(JNIEnv *jEnv) -{ - AutoJNIClass goannaEvent(jEnv, "org/mozilla/goanna/GoannaEvent"); - jGoannaEventClass = goannaEvent.getGlobalRef(); - - jActionField = goannaEvent.getField("mAction", "I"); - jTypeField = goannaEvent.getField("mType", "I"); - jAckNeededField = goannaEvent.getField("mAckNeeded", "Z"); - jTimeField = goannaEvent.getField("mTime", "J"); - jPoints = goannaEvent.getField("mPoints", "[Landroid/graphics/Point;"); - jPointIndicies = goannaEvent.getField("mPointIndicies", "[I"); - jOrientations = goannaEvent.getField("mOrientations", "[F"); - jPressures = goannaEvent.getField("mPressures", "[F"); - jToolTypes = goannaEvent.getField("mToolTypes", "[I"); - jPointRadii = goannaEvent.getField("mPointRadii", "[Landroid/graphics/Point;"); - jXField = goannaEvent.getField("mX", "D"); - jYField = goannaEvent.getField("mY", "D"); - jZField = goannaEvent.getField("mZ", "D"); - jRectField = goannaEvent.getField("mRect", "Landroid/graphics/Rect;"); - - jCharactersField = goannaEvent.getField("mCharacters", "Ljava/lang/String;"); - jCharactersExtraField = goannaEvent.getField("mCharactersExtra", "Ljava/lang/String;"); - jDataField = goannaEvent.getField("mData", "Ljava/lang/String;"); - jKeyCodeField = goannaEvent.getField("mKeyCode", "I"); - jScanCodeField = goannaEvent.getField("mScanCode", "I"); - jMetaStateField = goannaEvent.getField("mMetaState", "I"); - jFlagsField = goannaEvent.getField("mFlags", "I"); - jUnicodeCharField = goannaEvent.getField("mUnicodeChar", "I"); - jBaseUnicodeCharField = goannaEvent.getField("mBaseUnicodeChar", "I"); - jDOMPrintableKeyValueField = goannaEvent.getField("mDOMPrintableKeyValue", "I"); - jRepeatCountField = goannaEvent.getField("mRepeatCount", "I"); - jCountField = goannaEvent.getField("mCount", "I"); - jStartField = goannaEvent.getField("mStart", "I"); - jEndField = goannaEvent.getField("mEnd", "I"); - jPointerIndexField = goannaEvent.getField("mPointerIndex", "I"); - jRangeTypeField = goannaEvent.getField("mRangeType", "I"); - jRangeStylesField = goannaEvent.getField("mRangeStyles", "I"); - jRangeLineStyleField = goannaEvent.getField("mRangeLineStyle", "I"); - jRangeBoldLineField = goannaEvent.getField("mRangeBoldLine", "Z"); - jRangeForeColorField = goannaEvent.getField("mRangeForeColor", "I"); - jRangeBackColorField = goannaEvent.getField("mRangeBackColor", "I"); - jRangeLineColorField = goannaEvent.getField("mRangeLineColor", "I"); - jLocationField = goannaEvent.getField("mLocation", "Landroid/location/Location;"); - jConnectionTypeField = goannaEvent.getField("mConnectionType", "I"); - jIsWifiField = goannaEvent.getField("mIsWifi", "Z"); - jDHCPGatewayField = goannaEvent.getField("mDHCPGateway", "I"); - jScreenOrientationField = goannaEvent.getField("mScreenOrientation", "S"); - jByteBufferField = goannaEvent.getField("mBuffer", "Ljava/nio/ByteBuffer;"); - jWidthField = goannaEvent.getField("mWidth", "I"); - jHeightField = goannaEvent.getField("mHeight", "I"); - jIDField = goannaEvent.getField("mID", "I"); - jGamepadButtonField = goannaEvent.getField("mGamepadButton", "I"); - jGamepadButtonPressedField = goannaEvent.getField("mGamepadButtonPressed", "Z"); - jGamepadButtonValueField = goannaEvent.getField("mGamepadButtonValue", "F"); - jGamepadValuesField = goannaEvent.getField("mGamepadValues", "[F"); - jPrefNamesField = goannaEvent.getField("mPrefNames", "[Ljava/lang/String;"); - jObjectField = goannaEvent.getField("mObject", "Ljava/lang/Object;"); -} - -void -AndroidLocation::InitLocationClass(JNIEnv *jEnv) -{ - AutoJNIClass location(jEnv, "android/location/Location"); - jLocationClass = location.getGlobalRef(); - jGetLatitudeMethod = location.getMethod("getLatitude", "()D"); - jGetLongitudeMethod = location.getMethod("getLongitude", "()D"); - jGetAltitudeMethod = location.getMethod("getAltitude", "()D"); - jGetAccuracyMethod = location.getMethod("getAccuracy", "()F"); - jGetBearingMethod = location.getMethod("getBearing", "()F"); - jGetSpeedMethod = location.getMethod("getSpeed", "()F"); - jGetTimeMethod = location.getMethod("getTime", "()J"); -} - -nsGeoPosition* -AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) -{ - AutoLocalJNIFrame jniFrame(jenv); - - double latitude = jenv->CallDoubleMethod(jobj, jGetLatitudeMethod); - if (jniFrame.CheckForException()) return nullptr; - double longitude = jenv->CallDoubleMethod(jobj, jGetLongitudeMethod); - if (jniFrame.CheckForException()) return nullptr; - double altitude = jenv->CallDoubleMethod(jobj, jGetAltitudeMethod); - if (jniFrame.CheckForException()) return nullptr; - float accuracy = jenv->CallFloatMethod (jobj, jGetAccuracyMethod); - if (jniFrame.CheckForException()) return nullptr; - float bearing = jenv->CallFloatMethod (jobj, jGetBearingMethod); - if (jniFrame.CheckForException()) return nullptr; - float speed = jenv->CallFloatMethod (jobj, jGetSpeedMethod); - if (jniFrame.CheckForException()) return nullptr; - long long time = jenv->CallLongMethod (jobj, jGetTimeMethod); - if (jniFrame.CheckForException()) return nullptr; - - return new nsGeoPosition(latitude, longitude, - altitude, accuracy, - accuracy, bearing, - speed, time); -} - -void -AndroidPoint::InitPointClass(JNIEnv *jEnv) -{ - AutoJNIClass point(jEnv, "android/graphics/Point"); - jPointClass = point.getGlobalRef(); - - jXField = point.getField("x", "I"); - jYField = point.getField("y", "I"); -} - -void -AndroidRect::InitRectClass(JNIEnv *jEnv) -{ - AutoJNIClass rect(jEnv, "android/graphics/Rect"); - jRectClass = rect.getGlobalRef(); - - jBottomField = rect.getField("bottom", "I"); - jLeftField = rect.getField("left", "I"); - jTopField = rect.getField("top", "I"); - jRightField = rect.getField("right", "I"); -} - -void -AndroidRectF::InitRectFClass(JNIEnv *jEnv) -{ - AutoJNIClass rect(jEnv, "android/graphics/RectF"); - jRectClass = rect.getGlobalRef(); - - jBottomField = rect.getField("bottom", "F"); - jLeftField = rect.getField("left", "F"); - jTopField = rect.getField("top", "F"); - jRightField = rect.getField("right", "F"); -} - -void -AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv) -{ - AutoJNIClass layerRendererFrame(jEnv, "org/mozilla/goanna/gfx/LayerRenderer$Frame"); - jLayerRendererFrameClass = layerRendererFrame.getGlobalRef(); - - jBeginDrawingMethod = layerRendererFrame.getMethod("beginDrawing", "()V"); - jDrawBackgroundMethod = layerRendererFrame.getMethod("drawBackground", "()V"); - jDrawForegroundMethod = layerRendererFrame.getMethod("drawForeground", "()V"); - jEndDrawingMethod = layerRendererFrame.getMethod("endDrawing", "()V"); -} - -void -AndroidGoannaEvent::ReadPointArray(nsTArray &points, - JNIEnv *jenv, - jfieldID field, - int32_t count) -{ - jobjectArray jObjArray = (jobjectArray)jenv->GetObjectField(wrapped_obj, field); - for (int32_t i = 0; i < count; i++) { - jobject jObj = jenv->GetObjectArrayElement(jObjArray, i); - AndroidPoint jpoint(jenv, jObj); - - nsIntPoint p(jpoint.X(), jpoint.Y()); - points.AppendElement(p); - } -} - -void -AndroidGoannaEvent::ReadIntArray(nsTArray &aVals, - JNIEnv *jenv, - jfieldID field, - int32_t count) -{ - jintArray jIntArray = (jintArray)jenv->GetObjectField(wrapped_obj, field); - jint *vals = jenv->GetIntArrayElements(jIntArray, nullptr); - for (int32_t i = 0; i < count; i++) { - aVals.AppendElement(vals[i]); - } - jenv->ReleaseIntArrayElements(jIntArray, vals, JNI_ABORT); -} - -void -AndroidGoannaEvent::ReadFloatArray(nsTArray &aVals, - JNIEnv *jenv, - jfieldID field, - int32_t count) -{ - jfloatArray jFloatArray = (jfloatArray)jenv->GetObjectField(wrapped_obj, field); - jfloat *vals = jenv->GetFloatArrayElements(jFloatArray, nullptr); - for (int32_t i = 0; i < count; i++) { - aVals.AppendElement(vals[i]); - } - jenv->ReleaseFloatArrayElements(jFloatArray, vals, JNI_ABORT); -} - -void -AndroidGoannaEvent::ReadStringArray(nsTArray &array, - JNIEnv *jenv, - jfieldID field) -{ - jarray jArray = (jarray)jenv->GetObjectField(wrapped_obj, field); - jsize length = jenv->GetArrayLength(jArray); - jobjectArray jStringArray = (jobjectArray)jArray; - nsString *strings = array.AppendElements(length); - for (jsize i = 0; i < length; ++i) { - jstring javastring = (jstring) jenv->GetObjectArrayElement(jStringArray, i); - ReadStringFromJString(strings[i], jenv, javastring); - } -} - -void -AndroidGoannaEvent::ReadRectField(JNIEnv *jenv) -{ - AndroidRect r(jenv, jenv->GetObjectField(wrappedObject(), jRectField)); - if (!r.isNull()) { - mRect.SetRect(r.Left(), - r.Top(), - r.Width(), - r.Height()); - } else { - mRect.SetEmpty(); - } -} - -void -AndroidGoannaEvent::ReadStringFromJString(nsString &aString, JNIEnv *jenv, - jstring s) -{ - if (!s) { - aString.SetIsVoid(true); - return; - } - - int len = jenv->GetStringLength(s); - aString.SetLength(len); - jenv->GetStringRegion(s, 0, len, reinterpret_cast(aString.BeginWriting())); -} - -void -AndroidGoannaEvent::ReadCharactersField(JNIEnv *jenv) -{ - jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersField); - ReadStringFromJString(mCharacters, jenv, s); -} - -void -AndroidGoannaEvent::ReadCharactersExtraField(JNIEnv *jenv) -{ - jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField); - ReadStringFromJString(mCharactersExtra, jenv, s); -} - -void -AndroidGoannaEvent::ReadDataField(JNIEnv *jenv) -{ - jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jDataField); - ReadStringFromJString(mData, jenv, s); -} - -void -AndroidGoannaEvent::UnionRect(nsIntRect const& aRect) -{ - mRect = aRect.Union(mRect); -} - -void -AndroidGoannaEvent::Init(JNIEnv *jenv, jobject jobj) -{ - NS_ASSERTION(!wrapped_obj, "Init called on non-null wrapped_obj!"); - - wrapped_obj = jobj; - - if (!jobj) - return; - - mAction = jenv->GetIntField(jobj, jActionField); - mType = jenv->GetIntField(jobj, jTypeField); - mAckNeeded = jenv->GetBooleanField(jobj, jAckNeededField); - - switch (mType) { - case SIZE_CHANGED: - ReadPointArray(mPoints, jenv, jPoints, 2); - break; - - case KEY_EVENT: - case IME_KEY_EVENT: - mTime = jenv->GetLongField(jobj, jTimeField); - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - mFlags = jenv->GetIntField(jobj, jFlagsField); - mKeyCode = jenv->GetIntField(jobj, jKeyCodeField); - mScanCode = jenv->GetIntField(jobj, jScanCodeField); - mUnicodeChar = jenv->GetIntField(jobj, jUnicodeCharField); - mBaseUnicodeChar = jenv->GetIntField(jobj, jBaseUnicodeCharField); - mDOMPrintableKeyValue = - jenv->GetIntField(jobj, jDOMPrintableKeyValueField); - mRepeatCount = jenv->GetIntField(jobj, jRepeatCountField); - ReadCharactersField(jenv); - break; - - case NATIVE_GESTURE_EVENT: - mTime = jenv->GetLongField(jobj, jTimeField); - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - mCount = jenv->GetIntField(jobj, jCountField); - ReadPointArray(mPoints, jenv, jPoints, mCount); - mX = jenv->GetDoubleField(jobj, jXField); - - break; - - case MOTION_EVENT: - case LONG_PRESS: - mTime = jenv->GetLongField(jobj, jTimeField); - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - mCount = jenv->GetIntField(jobj, jCountField); - mPointerIndex = jenv->GetIntField(jobj, jPointerIndexField); - - ReadPointArray(mPointRadii, jenv, jPointRadii, mCount); - ReadFloatArray(mOrientations, jenv, jOrientations, mCount); - ReadFloatArray(mPressures, jenv, jPressures, mCount); - ReadIntArray(mToolTypes, jenv, jToolTypes, mCount); - ReadPointArray(mPoints, jenv, jPoints, mCount); - ReadIntArray(mPointIndicies, jenv, jPointIndicies, mCount); - - break; - - case IME_EVENT: - mStart = jenv->GetIntField(jobj, jStartField); - mEnd = jenv->GetIntField(jobj, jEndField); - - if (mAction == IME_REPLACE_TEXT || - mAction == IME_COMPOSE_TEXT) { - ReadCharactersField(jenv); - } else if (mAction == IME_UPDATE_COMPOSITION || - mAction == IME_ADD_COMPOSITION_RANGE) { - mRangeType = jenv->GetIntField(jobj, jRangeTypeField); - mRangeStyles = jenv->GetIntField(jobj, jRangeStylesField); - mRangeLineStyle = - jenv->GetIntField(jobj, jRangeLineStyleField); - mRangeBoldLine = - jenv->GetBooleanField(jobj, jRangeBoldLineField); - mRangeForeColor = - jenv->GetIntField(jobj, jRangeForeColorField); - mRangeBackColor = - jenv->GetIntField(jobj, jRangeBackColorField); - mRangeLineColor = - jenv->GetIntField(jobj, jRangeLineColorField); - } - break; - - case SENSOR_EVENT: - mX = jenv->GetDoubleField(jobj, jXField); - mY = jenv->GetDoubleField(jobj, jYField); - mZ = jenv->GetDoubleField(jobj, jZField); - mFlags = jenv->GetIntField(jobj, jFlagsField); - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - break; - - case PROCESS_OBJECT: { - const jobject obj = jenv->GetObjectField(jobj, jObjectField); - mObject.Init(obj, jenv); - jenv->DeleteLocalRef(obj); - break; - } - - case LOCATION_EVENT: { - jobject location = jenv->GetObjectField(jobj, jLocationField); - mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location); - break; - } - - case LOAD_URI: { - ReadCharactersField(jenv); - ReadCharactersExtraField(jenv); - break; - } - - case VIEWPORT: - case BROADCAST: { - ReadCharactersField(jenv); - ReadCharactersExtraField(jenv); - break; - } - - case NETWORK_CHANGED: { - mConnectionType = jenv->GetIntField(jobj, jConnectionTypeField); - mIsWifi = jenv->GetBooleanField(jobj, jIsWifiField); - mDHCPGateway = jenv->GetIntField(jobj, jDHCPGatewayField); - break; - } - - case VISITED: { - ReadCharactersField(jenv); - break; - } - - case THUMBNAIL: { - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - ReadPointArray(mPoints, jenv, jPoints, 1); - mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField)); - break; - } - - case ZOOMEDVIEW: { - mX = jenv->GetDoubleField(jobj, jXField); - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - ReadPointArray(mPoints, jenv, jPoints, 2); - mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField)); - break; - } - - case SCREENORIENTATION_CHANGED: { - mScreenOrientation = jenv->GetShortField(jobj, jScreenOrientationField); - break; - } - - case COMPOSITOR_CREATE: { - mWidth = jenv->GetIntField(jobj, jWidthField); - mHeight = jenv->GetIntField(jobj, jHeightField); - break; - } - - case CALL_OBSERVER: { - ReadCharactersField(jenv); - ReadCharactersExtraField(jenv); - ReadDataField(jenv); - break; - } - - case REMOVE_OBSERVER: { - ReadCharactersField(jenv); - break; - } - - case LOW_MEMORY: { - mMetaState = jenv->GetIntField(jobj, jMetaStateField); - break; - } - - case NETWORK_LINK_CHANGE: { - ReadCharactersField(jenv); - break; - } - - case TELEMETRY_HISTOGRAM_ADD: { - ReadCharactersField(jenv); - mCount = jenv->GetIntField(jobj, jCountField); - break; - } - - case TELEMETRY_UI_SESSION_START: { - ReadCharactersField(jenv); - mTime = jenv->GetLongField(jobj, jTimeField); - break; - } - - case TELEMETRY_UI_SESSION_STOP: { - ReadCharactersField(jenv); - ReadCharactersExtraField(jenv); - mTime = jenv->GetLongField(jobj, jTimeField); - break; - } - - case TELEMETRY_UI_EVENT: { - ReadCharactersField(jenv); - ReadCharactersExtraField(jenv); - ReadDataField(jenv); - mTime = jenv->GetLongField(jobj, jTimeField); - break; - } - - case GAMEPAD_ADDREMOVE: { - mID = jenv->GetIntField(jobj, jIDField); - break; - } - - case GAMEPAD_DATA: { - mID = jenv->GetIntField(jobj, jIDField); - if (mAction == ACTION_GAMEPAD_BUTTON) { - mGamepadButton = jenv->GetIntField(jobj, jGamepadButtonField); - mGamepadButtonPressed = jenv->GetBooleanField(jobj, jGamepadButtonPressedField); - mGamepadButtonValue = jenv->GetFloatField(jobj, jGamepadButtonValueField); - } else if (mAction == ACTION_GAMEPAD_AXES) { - // Flags is a bitfield of valid entries in gamepadvalues - mFlags = jenv->GetIntField(jobj, jFlagsField); - mCount = jenv->GetIntField(jobj, jCountField); - ReadFloatArray(mGamepadValues, jenv, jGamepadValuesField, mCount); - } - break; - } - - case PREFERENCES_OBSERVE: - case PREFERENCES_GET: { - ReadStringArray(mPrefNames, jenv, jPrefNamesField); - mCount = jenv->GetIntField(jobj, jCountField); - break; - } - - case PREFERENCES_REMOVE_OBSERVERS: { - mCount = jenv->GetIntField(jobj, jCountField); - break; - } - - default: - break; - } - -#ifdef DEBUG_ANDROID_EVENTS - ALOG("AndroidGoannaEvent: %p : %d", (void*)jobj, mType); -#endif -} - -void -AndroidGoannaEvent::Init(int aType) -{ - mType = aType; - mAckNeeded = false; -} - -void -AndroidGoannaEvent::Init(AndroidGoannaEvent *aResizeEvent) -{ - NS_ASSERTION(aResizeEvent->Type() == SIZE_CHANGED, "Init called on non-SIZE_CHANGED event"); - - mType = FORCED_RESIZE; - mAckNeeded = false; - mTime = aResizeEvent->mTime; - mPoints = aResizeEvent->mPoints; // x,y coordinates -} - -bool -AndroidGoannaEvent::CanCoalesceWith(AndroidGoannaEvent* ae) -{ - if (Type() == MOTION_EVENT && ae->Type() == MOTION_EVENT) { - return Action() == AndroidMotionEvent::ACTION_MOVE - && ae->Action() == AndroidMotionEvent::ACTION_MOVE; - } else if (Type() == APZ_INPUT_EVENT && ae->Type() == APZ_INPUT_EVENT) { - return mApzInput.mType == MultiTouchInput::MULTITOUCH_MOVE - && ae->mApzInput.mType == MultiTouchInput::MULTITOUCH_MOVE; - } - return false; -} - -mozilla::layers::ScrollableLayerGuid -AndroidGoannaEvent::ApzGuid() -{ - MOZ_ASSERT(Type() == APZ_INPUT_EVENT); - return mApzGuid; -} - -uint64_t -AndroidGoannaEvent::ApzInputBlockId() -{ - MOZ_ASSERT(Type() == APZ_INPUT_EVENT); - return mApzInputBlockId; -} - -WidgetTouchEvent -AndroidGoannaEvent::MakeTouchEvent(nsIWidget* widget) -{ - if (Type() == APZ_INPUT_EVENT) { - return mApzInput.ToWidgetTouchEvent(widget); - } - - int type = NS_EVENT_NULL; - int startIndex = 0; - int endIndex = Count(); - - switch (Action()) { - case AndroidMotionEvent::ACTION_HOVER_ENTER: { - if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) { - break; - } - } - case AndroidMotionEvent::ACTION_DOWN: - case AndroidMotionEvent::ACTION_POINTER_DOWN: { - type = NS_TOUCH_START; - break; - } - case AndroidMotionEvent::ACTION_HOVER_MOVE: { - if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) { - break; - } - } - case AndroidMotionEvent::ACTION_MOVE: { - type = NS_TOUCH_MOVE; - break; - } - case AndroidMotionEvent::ACTION_HOVER_EXIT: { - if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) { - break; - } - } - case AndroidMotionEvent::ACTION_UP: - case AndroidMotionEvent::ACTION_POINTER_UP: { - type = NS_TOUCH_END; - // for pointer-up events we only want the data from - // the one pointer that went up - startIndex = PointerIndex(); - endIndex = startIndex + 1; - break; - } - case AndroidMotionEvent::ACTION_OUTSIDE: - case AndroidMotionEvent::ACTION_CANCEL: { - type = NS_TOUCH_CANCEL; - break; - } - } - - WidgetTouchEvent event(true, type, widget); - if (type == NS_EVENT_NULL) { - // An event we don't know about - return event; - } - - event.modifiers = DOMModifiers(); - event.time = Time(); - - const LayoutDeviceIntPoint& offset = widget->WidgetToScreenOffset(); - event.touches.SetCapacity(endIndex - startIndex); - for (int i = startIndex; i < endIndex; i++) { - // In this code branch, we are dispatching this event directly - // into Goanna (as opposed to going through the AsyncPanZoomController), - // and the Points() array has points in CSS pixels, which we need - // to convert. - CSSToLayoutDeviceScale scale = widget->GetDefaultScale(); - LayoutDeviceIntPoint pt( - (Points()[i].x * scale.scale) - offset.x, - (Points()[i].y * scale.scale) - offset.y); - nsIntPoint radii( - PointRadii()[i].x * scale.scale, - PointRadii()[i].y * scale.scale); - nsRefPtr t = new Touch(PointIndicies()[i], - pt, - radii, - Orientations()[i], - Pressures()[i]); - event.touches.AppendElement(t); - } - - return event; -} - -MultiTouchInput -AndroidGoannaEvent::MakeMultiTouchInput(nsIWidget* widget) -{ - MultiTouchInput::MultiTouchType type = (MultiTouchInput::MultiTouchType)-1; - int startIndex = 0; - int endIndex = Count(); - - switch (Action()) { - case AndroidMotionEvent::ACTION_DOWN: - case AndroidMotionEvent::ACTION_POINTER_DOWN: { - type = MultiTouchInput::MULTITOUCH_START; - break; - } - case AndroidMotionEvent::ACTION_MOVE: { - type = MultiTouchInput::MULTITOUCH_MOVE; - break; - } - case AndroidMotionEvent::ACTION_UP: - case AndroidMotionEvent::ACTION_POINTER_UP: { - // for pointer-up events we only want the data from - // the one pointer that went up - startIndex = PointerIndex(); - endIndex = startIndex + 1; - type = MultiTouchInput::MULTITOUCH_END; - break; - } - case AndroidMotionEvent::ACTION_OUTSIDE: - case AndroidMotionEvent::ACTION_CANCEL: { - type = MultiTouchInput::MULTITOUCH_CANCEL; - break; - } - } - - MultiTouchInput event(type, Time(), TimeStamp(), 0); - event.modifiers = DOMModifiers(); - - if (type < 0) { - // An event we don't know about - return event; - } - - const nsIntPoint& offset = widget->WidgetToScreenOffsetUntyped(); - event.mTouches.SetCapacity(endIndex - startIndex); - for (int i = startIndex; i < endIndex; i++) { - nsIntPoint point = Points()[i] - offset; - nsIntPoint radius = PointRadii()[i]; - SingleTouchData data(PointIndicies()[i], - ScreenIntPoint::FromUnknownPoint( - gfx::IntPoint(point.x, point.y)), - ScreenSize::FromUnknownSize( - gfx::Size(radius.x, radius.y)), - Orientations()[i], - Pressures()[i]); - event.mTouches.AppendElement(data); - } - - return event; -} - -WidgetMouseEvent -AndroidGoannaEvent::MakeMouseEvent(nsIWidget* widget) -{ - uint32_t msg = NS_EVENT_NULL; - if (Points().Length() > 0) { - switch (Action()) { - case AndroidMotionEvent::ACTION_HOVER_MOVE: - msg = NS_MOUSE_MOVE; - break; - case AndroidMotionEvent::ACTION_HOVER_ENTER: - msg = NS_MOUSE_ENTER; - break; - case AndroidMotionEvent::ACTION_HOVER_EXIT: - msg = NS_MOUSE_EXIT; - break; - default: - break; - } - } - - WidgetMouseEvent event(true, msg, widget, - WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); - - if (msg == NS_EVENT_NULL) { - // unknown type, or no point data. abort - return event; - } - - // XXX can we synthesize different buttons? - event.button = WidgetMouseEvent::eLeftButton; - if (msg != NS_MOUSE_MOVE) { - event.clickCount = 1; - } - event.modifiers = DOMModifiers(); - event.time = Time(); - - // We are dispatching this event directly into Goanna (as opposed to going - // through the AsyncPanZoomController), and the Points() array has points - // in CSS pixels, which we need to convert to LayoutDevice pixels. - const LayoutDeviceIntPoint& offset = widget->WidgetToScreenOffset(); - CSSToLayoutDeviceScale scale = widget->GetDefaultScale(); - event.refPoint = LayoutDeviceIntPoint((Points()[0].x * scale.scale) - offset.x, - (Points()[0].y * scale.scale) - offset.y); - return event; -} - -Modifiers -AndroidGoannaEvent::DOMModifiers() const -{ - Modifiers result = 0; - if (mMetaState & AMETA_ALT_MASK) { - result |= MODIFIER_ALT; - } - if (mMetaState & AMETA_SHIFT_MASK) { - result |= MODIFIER_SHIFT; - } - if (mMetaState & AMETA_CTRL_MASK) { - result |= MODIFIER_CONTROL; - } - if (mMetaState & AMETA_META_MASK) { - result |= MODIFIER_META; - } - if (mMetaState & AMETA_FUNCTION_ON) { - result |= MODIFIER_FN; - } - if (mMetaState & AMETA_CAPS_LOCK_ON) { - result |= MODIFIER_CAPSLOCK; - } - if (mMetaState & AMETA_NUM_LOCK_ON) { - result |= MODIFIER_NUMLOCK; - } - if (mMetaState & AMETA_SCROLL_LOCK_ON) { - result |= MODIFIER_SCROLLLOCK; - } - return result; -} - -void -AndroidPoint::Init(JNIEnv *jenv, jobject jobj) -{ - if (jobj) { - mX = jenv->GetIntField(jobj, jXField); - mY = jenv->GetIntField(jobj, jYField); - } else { - mX = 0; - mY = 0; - } -} - -void -AndroidLayerRendererFrame::Init(JNIEnv *env, jobject jobj) -{ - if (!isNull()) { - Dispose(env); - } - - wrapped_obj = env->NewGlobalRef(jobj); -} - -void -AndroidLayerRendererFrame::Dispose(JNIEnv *env) -{ - if (isNull()) { - return; - } - - env->DeleteGlobalRef(wrapped_obj); - wrapped_obj = 0; -} - -NS_IMPL_ISUPPORTS(nsAndroidDisplayport, nsIAndroidDisplayport) - -bool -AndroidLayerRendererFrame::BeginDrawing(AutoLocalJNIFrame *jniFrame) -{ - if (!jniFrame || !jniFrame->GetEnv()) - return false; - - jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod); - if (jniFrame->CheckForException()) - return false; - - return true; -} - -bool -AndroidLayerRendererFrame::DrawBackground(AutoLocalJNIFrame *jniFrame) -{ - if (!jniFrame || !jniFrame->GetEnv()) - return false; - - jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod); - if (jniFrame->CheckForException()) - return false; - - return true; -} - -bool -AndroidLayerRendererFrame::DrawForeground(AutoLocalJNIFrame *jniFrame) -{ - if (!jniFrame || !jniFrame->GetEnv()) - return false; - - jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawForegroundMethod); - if (jniFrame->CheckForException()) - return false; - - return true; -} - -bool -AndroidLayerRendererFrame::EndDrawing(AutoLocalJNIFrame *jniFrame) -{ - if (!jniFrame || !jniFrame->GetEnv()) - return false; - - jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jEndDrawingMethod); - if (jniFrame->CheckForException()) - return false; - - return true; -} - -void -AndroidRect::Init(JNIEnv *jenv, jobject jobj) -{ - NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!"); - - wrapped_obj = jobj; - - if (jobj) { - mTop = jenv->GetIntField(jobj, jTopField); - mLeft = jenv->GetIntField(jobj, jLeftField); - mRight = jenv->GetIntField(jobj, jRightField); - mBottom = jenv->GetIntField(jobj, jBottomField); - } else { - mTop = 0; - mLeft = 0; - mRight = 0; - mBottom = 0; - } -} - -void -AndroidRectF::Init(JNIEnv *jenv, jobject jobj) -{ - NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!"); - - wrapped_obj = jobj; - - if (jobj) { - mTop = jenv->GetFloatField(jobj, jTopField); - mLeft = jenv->GetFloatField(jobj, jLeftField); - mRight = jenv->GetFloatField(jobj, jRightField); - mBottom = jenv->GetFloatField(jobj, jBottomField); - } else { - mTop = 0; - mLeft = 0; - mRight = 0; - mBottom = 0; - } -} - -nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv) -{ - if (!jstr) { - SetIsVoid(true); - return; - } - JNIEnv *jni = jenv; - if (!jni) { - jni = AndroidBridge::GetJNIEnv(); - } - const jchar* jCharPtr = jni->GetStringChars(jstr, nullptr); - - if (!jCharPtr) { - SetIsVoid(true); - return; - } - - jsize len = jni->GetStringLength(jstr); - - if (len <= 0) { - SetIsVoid(true); - } else { - Assign(reinterpret_cast(jCharPtr), len); - } - jni->ReleaseStringChars(jstr, jCharPtr); -} - -nsJNICString::nsJNICString(jstring jstr, JNIEnv *jenv) -{ - if (!jstr) { - SetIsVoid(true); - return; - } - JNIEnv *jni = jenv; - if (!jni) { - jni = AndroidBridge::GetJNIEnv(); - } - const char* jCharPtr = jni->GetStringUTFChars(jstr, nullptr); - - if (!jCharPtr) { - SetIsVoid(true); - return; - } - - jsize len = jni->GetStringUTFLength(jstr); - - if (len <= 0) { - SetIsVoid(true); - } else { - Assign(jCharPtr, len); - } - jni->ReleaseStringUTFChars(jstr, jCharPtr); -} diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h deleted file mode 100644 index 3e3cdfb16d..0000000000 --- a/widget/android/AndroidJavaWrappers.h +++ /dev/null @@ -1,799 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef AndroidJavaWrappers_h__ -#define AndroidJavaWrappers_h__ - -#include -#include -#include -#include - -#include "nsGeoPosition.h" -#include "nsRect.h" -#include "nsString.h" -#include "nsTArray.h" -#include "nsIObserver.h" -#include "nsIAndroidBridge.h" -#include "mozilla/gfx/Rect.h" -#include "mozilla/dom/Touch.h" -#include "mozilla/EventForwards.h" -#include "InputData.h" -#include "Units.h" -#include "FrameMetrics.h" - -//#define FORCE_ALOG 1 - -class nsIAndroidDisplayport; -class nsIAndroidViewport; -class nsIWidget; - -namespace mozilla { - -class AutoLocalJNIFrame; - -void InitAndroidJavaWrappers(JNIEnv *jEnv); - -class RefCountedJavaObject { -public: - RefCountedJavaObject(JNIEnv* env, jobject obj) : mRefCnt(0), mObject(env->NewGlobalRef(obj)) {} - - ~RefCountedJavaObject(); - - int32_t AddRef() { return ++mRefCnt; } - - int32_t Release() { - int32_t refcnt = --mRefCnt; - if (refcnt == 0) - delete this; - return refcnt; - } - - jobject GetObject() { return mObject; } -private: - int32_t mRefCnt; - jobject mObject; -}; - -/* - * Note: do not store global refs to any WrappedJavaObject; - * these are live only during a particular JNI method, as - * NewGlobalRef is -not- called on the jobject. - * - * If this is needed, WrappedJavaObject can be extended to - * handle it. - */ -class WrappedJavaObject { -public: - WrappedJavaObject() : - wrapped_obj(nullptr) - { } - - WrappedJavaObject(jobject jobj) : wrapped_obj(nullptr) { - Init(jobj); - } - - void Init(jobject jobj) { - wrapped_obj = jobj; - } - - bool isNull() const { - return wrapped_obj == nullptr; - } - - jobject wrappedObject() const { - return wrapped_obj; - } - -protected: - jobject wrapped_obj; -}; - -class AutoGlobalWrappedJavaObject : protected WrappedJavaObject{ -public: - AutoGlobalWrappedJavaObject() : - wrapped_obj(nullptr) - { } - - AutoGlobalWrappedJavaObject(jobject jobj, JNIEnv* env) : wrapped_obj(nullptr) { - Init(jobj, env); - } - - virtual ~AutoGlobalWrappedJavaObject(); - void Dispose(); - - void Init(jobject jobj, JNIEnv* env) { - if (!isNull()) { - env->DeleteGlobalRef(wrapped_obj); - } - wrapped_obj = env->NewGlobalRef(jobj); - } - - bool isNull() const { - return wrapped_obj == nullptr; - } - - jobject wrappedObject() const { - return wrapped_obj; - } - -protected: - jobject wrapped_obj; -}; - -class AndroidPoint : public WrappedJavaObject -{ -public: - static void InitPointClass(JNIEnv *jEnv); - - AndroidPoint() { } - AndroidPoint(JNIEnv *jenv, jobject jobj) { - Init(jenv, jobj); - } - - void Init(JNIEnv *jenv, jobject jobj); - - int X() { return mX; } - int Y() { return mY; } - -protected: - int mX; - int mY; - - static jclass jPointClass; - static jfieldID jXField; - static jfieldID jYField; -}; - -class AndroidRect : public WrappedJavaObject -{ -public: - static void InitRectClass(JNIEnv *jEnv); - - AndroidRect() { } - AndroidRect(JNIEnv *jenv, jobject jobj) { - Init(jenv, jobj); - } - - void Init(JNIEnv *jenv, jobject jobj); - - int Bottom() { return mBottom; } - int Left() { return mLeft; } - int Right() { return mRight; } - int Top() { return mTop; } - int Width() { return mRight - mLeft; } - int Height() { return mBottom - mTop; } - -protected: - int mBottom; - int mLeft; - int mRight; - int mTop; - - static jclass jRectClass; - static jfieldID jBottomField; - static jfieldID jLeftField; - static jfieldID jRightField; - static jfieldID jTopField; -}; - -class AndroidRectF : public WrappedJavaObject -{ -public: - static void InitRectFClass(JNIEnv *jEnv); - - AndroidRectF() { } - AndroidRectF(JNIEnv *jenv, jobject jobj) { - Init(jenv, jobj); - } - - void Init(JNIEnv *jenv, jobject jobj); - - float Bottom() { return mBottom; } - float Left() { return mLeft; } - float Right() { return mRight; } - float Top() { return mTop; } - float Width() { return mRight - mLeft; } - float Height() { return mBottom - mTop; } - -protected: - float mBottom; - float mLeft; - float mRight; - float mTop; - - static jclass jRectClass; - static jfieldID jBottomField; - static jfieldID jLeftField; - static jfieldID jRightField; - static jfieldID jTopField; -}; - -class AndroidLayerRendererFrame : public WrappedJavaObject { -public: - static void InitLayerRendererFrameClass(JNIEnv *jEnv); - - void Init(JNIEnv *env, jobject jobj); - void Dispose(JNIEnv *env); - - bool BeginDrawing(AutoLocalJNIFrame *jniFrame); - bool DrawBackground(AutoLocalJNIFrame *jniFrame); - bool DrawForeground(AutoLocalJNIFrame *jniFrame); - bool EndDrawing(AutoLocalJNIFrame *jniFrame); - -private: - static jclass jLayerRendererFrameClass; - static jmethodID jBeginDrawingMethod; - static jmethodID jDrawBackgroundMethod; - static jmethodID jDrawForegroundMethod; - static jmethodID jEndDrawingMethod; -}; - -enum { - // These keycode masks are not defined in android/keycodes.h: -#if __ANDROID_API__ < 13 - AKEYCODE_ESCAPE = 111, - AKEYCODE_FORWARD_DEL = 112, - AKEYCODE_CTRL_LEFT = 113, - AKEYCODE_CTRL_RIGHT = 114, - AKEYCODE_CAPS_LOCK = 115, - AKEYCODE_SCROLL_LOCK = 116, - AKEYCODE_META_LEFT = 117, - AKEYCODE_META_RIGHT = 118, - AKEYCODE_FUNCTION = 119, - AKEYCODE_SYSRQ = 120, - AKEYCODE_BREAK = 121, - AKEYCODE_MOVE_HOME = 122, - AKEYCODE_MOVE_END = 123, - AKEYCODE_INSERT = 124, - AKEYCODE_FORWARD = 125, - AKEYCODE_MEDIA_PLAY = 126, - AKEYCODE_MEDIA_PAUSE = 127, - AKEYCODE_MEDIA_CLOSE = 128, - AKEYCODE_MEDIA_EJECT = 129, - AKEYCODE_MEDIA_RECORD = 130, - AKEYCODE_F1 = 131, - AKEYCODE_F2 = 132, - AKEYCODE_F3 = 133, - AKEYCODE_F4 = 134, - AKEYCODE_F5 = 135, - AKEYCODE_F6 = 136, - AKEYCODE_F7 = 137, - AKEYCODE_F8 = 138, - AKEYCODE_F9 = 139, - AKEYCODE_F10 = 140, - AKEYCODE_F11 = 141, - AKEYCODE_F12 = 142, - AKEYCODE_NUM_LOCK = 143, - AKEYCODE_NUMPAD_0 = 144, - AKEYCODE_NUMPAD_1 = 145, - AKEYCODE_NUMPAD_2 = 146, - AKEYCODE_NUMPAD_3 = 147, - AKEYCODE_NUMPAD_4 = 148, - AKEYCODE_NUMPAD_5 = 149, - AKEYCODE_NUMPAD_6 = 150, - AKEYCODE_NUMPAD_7 = 151, - AKEYCODE_NUMPAD_8 = 152, - AKEYCODE_NUMPAD_9 = 153, - AKEYCODE_NUMPAD_DIVIDE = 154, - AKEYCODE_NUMPAD_MULTIPLY = 155, - AKEYCODE_NUMPAD_SUBTRACT = 156, - AKEYCODE_NUMPAD_ADD = 157, - AKEYCODE_NUMPAD_DOT = 158, - AKEYCODE_NUMPAD_COMMA = 159, - AKEYCODE_NUMPAD_ENTER = 160, - AKEYCODE_NUMPAD_EQUALS = 161, - AKEYCODE_NUMPAD_LEFT_PAREN = 162, - AKEYCODE_NUMPAD_RIGHT_PAREN = 163, - AKEYCODE_VOLUME_MUTE = 164, - AKEYCODE_INFO = 165, - AKEYCODE_CHANNEL_UP = 166, - AKEYCODE_CHANNEL_DOWN = 167, - AKEYCODE_ZOOM_IN = 168, - AKEYCODE_ZOOM_OUT = 169, - AKEYCODE_TV = 170, - AKEYCODE_WINDOW = 171, - AKEYCODE_GUIDE = 172, - AKEYCODE_DVR = 173, - AKEYCODE_BOOKMARK = 174, - AKEYCODE_CAPTIONS = 175, - AKEYCODE_SETTINGS = 176, - AKEYCODE_TV_POWER = 177, - AKEYCODE_TV_INPUT = 178, - AKEYCODE_STB_POWER = 179, - AKEYCODE_STB_INPUT = 180, - AKEYCODE_AVR_POWER = 181, - AKEYCODE_AVR_INPUT = 182, - AKEYCODE_PROG_RED = 183, - AKEYCODE_PROG_GREEN = 184, - AKEYCODE_PROG_YELLOW = 185, - AKEYCODE_PROG_BLUE = 186, - AKEYCODE_APP_SWITCH = 187, - AKEYCODE_BUTTON_1 = 188, - AKEYCODE_BUTTON_2 = 189, - AKEYCODE_BUTTON_3 = 190, - AKEYCODE_BUTTON_4 = 191, - AKEYCODE_BUTTON_5 = 192, - AKEYCODE_BUTTON_6 = 193, - AKEYCODE_BUTTON_7 = 194, - AKEYCODE_BUTTON_8 = 195, - AKEYCODE_BUTTON_9 = 196, - AKEYCODE_BUTTON_10 = 197, - AKEYCODE_BUTTON_11 = 198, - AKEYCODE_BUTTON_12 = 199, - AKEYCODE_BUTTON_13 = 200, - AKEYCODE_BUTTON_14 = 201, - AKEYCODE_BUTTON_15 = 202, - AKEYCODE_BUTTON_16 = 203, -#endif -#if __ANDROID_API__ < 14 - AKEYCODE_LANGUAGE_SWITCH = 204, - AKEYCODE_MANNER_MODE = 205, - AKEYCODE_3D_MODE = 206, -#endif -#if __ANDROID_API__ < 15 - AKEYCODE_CONTACTS = 207, - AKEYCODE_CALENDAR = 208, - AKEYCODE_MUSIC = 209, - AKEYCODE_CALCULATOR = 210, -#endif -#if __ANDROID_API__ < 16 - AKEYCODE_ZENKAKU_HANKAKU = 211, - AKEYCODE_EISU = 212, - AKEYCODE_MUHENKAN = 213, - AKEYCODE_HENKAN = 214, - AKEYCODE_KATAKANA_HIRAGANA = 215, - AKEYCODE_YEN = 216, - AKEYCODE_RO = 217, - AKEYCODE_KANA = 218, - AKEYCODE_ASSIST = 219, -#endif - - AMETA_FUNCTION_ON = 0x00000008, - AMETA_CTRL_ON = 0x00001000, - AMETA_CTRL_LEFT_ON = 0x00002000, - AMETA_CTRL_RIGHT_ON = 0x00004000, - AMETA_META_ON = 0x00010000, - AMETA_META_LEFT_ON = 0x00020000, - AMETA_META_RIGHT_ON = 0x00040000, - AMETA_CAPS_LOCK_ON = 0x00100000, - AMETA_NUM_LOCK_ON = 0x00200000, - AMETA_SCROLL_LOCK_ON = 0x00400000, - - AMETA_ALT_MASK = AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON | AMETA_ALT_ON, - AMETA_CTRL_MASK = AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON | AMETA_CTRL_ON, - AMETA_META_MASK = AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON | AMETA_META_ON, - AMETA_SHIFT_MASK = AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON | AMETA_SHIFT_ON, -}; - -class nsAndroidDisplayport final : public nsIAndroidDisplayport -{ -public: - NS_DECL_ISUPPORTS - virtual nsresult GetLeft(float *aLeft) { *aLeft = mLeft; return NS_OK; } - virtual nsresult GetTop(float *aTop) { *aTop = mTop; return NS_OK; } - virtual nsresult GetRight(float *aRight) { *aRight = mRight; return NS_OK; } - virtual nsresult GetBottom(float *aBottom) { *aBottom = mBottom; return NS_OK; } - virtual nsresult GetResolution(float *aResolution) { *aResolution = mResolution; return NS_OK; } - virtual nsresult SetLeft(float aLeft) { mLeft = aLeft; return NS_OK; } - virtual nsresult SetTop(float aTop) { mTop = aTop; return NS_OK; } - virtual nsresult SetRight(float aRight) { mRight = aRight; return NS_OK; } - virtual nsresult SetBottom(float aBottom) { mBottom = aBottom; return NS_OK; } - virtual nsresult SetResolution(float aResolution) { mResolution = aResolution; return NS_OK; } - - nsAndroidDisplayport(AndroidRectF aRect, float aResolution): - mLeft(aRect.Left()), mTop(aRect.Top()), mRight(aRect.Right()), mBottom(aRect.Bottom()), mResolution(aResolution) {} - -private: - ~nsAndroidDisplayport() {} - float mLeft, mTop, mRight, mBottom, mResolution; -}; - -class AndroidMotionEvent -{ -public: - enum { - ACTION_DOWN = 0, - ACTION_UP = 1, - ACTION_MOVE = 2, - ACTION_CANCEL = 3, - ACTION_OUTSIDE = 4, - ACTION_POINTER_DOWN = 5, - ACTION_POINTER_UP = 6, - ACTION_HOVER_MOVE = 7, - ACTION_HOVER_ENTER = 9, - ACTION_HOVER_EXIT = 10, - ACTION_MAGNIFY_START = 11, - ACTION_MAGNIFY = 12, - ACTION_MAGNIFY_END = 13, - EDGE_TOP = 0x00000001, - EDGE_BOTTOM = 0x00000002, - EDGE_LEFT = 0x00000004, - EDGE_RIGHT = 0x00000008, - SAMPLE_X = 0, - SAMPLE_Y = 1, - SAMPLE_PRESSURE = 2, - SAMPLE_SIZE = 3, - NUM_SAMPLE_DATA = 4, - TOOL_TYPE_UNKNOWN = 0, - TOOL_TYPE_FINGER = 1, - TOOL_TYPE_STYLUS = 2, - TOOL_TYPE_MOUSE = 3, - TOOL_TYPE_ERASER = 4, - dummy_java_enum_list_end - }; -}; - -class AndroidLocation : public WrappedJavaObject -{ -public: - static void InitLocationClass(JNIEnv *jEnv); - static nsGeoPosition* CreateGeoPosition(JNIEnv *jenv, jobject jobj); - static jclass jLocationClass; - static jmethodID jGetLatitudeMethod; - static jmethodID jGetLongitudeMethod; - static jmethodID jGetAltitudeMethod; - static jmethodID jGetAccuracyMethod; - static jmethodID jGetBearingMethod; - static jmethodID jGetSpeedMethod; - static jmethodID jGetTimeMethod; -}; - -class AndroidGoannaEvent : public WrappedJavaObject -{ -private: - AndroidGoannaEvent() { - } - - void Init(JNIEnv *jenv, jobject jobj); - void Init(int aType); - void Init(AndroidGoannaEvent *aResizeEvent); - -public: - static void InitGoannaEventClass(JNIEnv *jEnv); - - static AndroidGoannaEvent* MakeNativePoke() { - AndroidGoannaEvent *event = new AndroidGoannaEvent(); - event->Init(NATIVE_POKE); - return event; - } - - static AndroidGoannaEvent* MakeIMEEvent(int aAction) { - AndroidGoannaEvent *event = new AndroidGoannaEvent(); - event->Init(IME_EVENT); - event->mAction = aAction; - return event; - } - - static AndroidGoannaEvent* MakeFromJavaObject(JNIEnv *jenv, jobject jobj) { - AndroidGoannaEvent *event = new AndroidGoannaEvent(); - event->Init(jenv, jobj); - return event; - } - - static AndroidGoannaEvent* CopyResizeEvent(AndroidGoannaEvent *aResizeEvent) { - AndroidGoannaEvent *event = new AndroidGoannaEvent(); - event->Init(aResizeEvent); - return event; - } - - static AndroidGoannaEvent* MakeBroadcastEvent(const nsCString& topic, const nsCString& data) { - AndroidGoannaEvent* event = new AndroidGoannaEvent(); - event->Init(BROADCAST); - CopyUTF8toUTF16(topic, event->mCharacters); - CopyUTF8toUTF16(data, event->mCharactersExtra); - return event; - } - - static AndroidGoannaEvent* MakeAddObserver(const nsAString &key, nsIObserver *observer) { - AndroidGoannaEvent *event = new AndroidGoannaEvent(); - event->Init(ADD_OBSERVER); - event->mCharacters.Assign(key); - event->mObserver = observer; - return event; - } - - static AndroidGoannaEvent* MakeApzInputEvent(const MultiTouchInput& aInput, const mozilla::layers::ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { - AndroidGoannaEvent* event = new AndroidGoannaEvent(); - event->Init(APZ_INPUT_EVENT); - event->mApzInput = aInput; - event->mApzGuid = aGuid; - event->mApzInputBlockId = aInputBlockId; - return event; - } - - int Action() { return mAction; } - int Type() { return mType; } - bool AckNeeded() { return mAckNeeded; } - int64_t Time() { return mTime; } - const nsTArray& Points() { return mPoints; } - const nsTArray& PointIndicies() { return mPointIndicies; } - const nsTArray& Pressures() { return mPressures; } - const nsTArray& ToolTypes() { return mToolTypes; } - const nsTArray& Orientations() { return mOrientations; } - const nsTArray& PointRadii() { return mPointRadii; } - const nsTArray& PrefNames() { return mPrefNames; } - double X() { return mX; } - double Y() { return mY; } - double Z() { return mZ; } - const nsIntRect& Rect() { return mRect; } - nsAString& Characters() { return mCharacters; } - nsAString& CharactersExtra() { return mCharactersExtra; } - nsAString& Data() { return mData; } - int KeyCode() { return mKeyCode; } - int ScanCode() { return mScanCode; } - int MetaState() { return mMetaState; } - Modifiers DOMModifiers() const; - bool IsAltPressed() const { return (mMetaState & AMETA_ALT_MASK) != 0; } - bool IsShiftPressed() const { return (mMetaState & AMETA_SHIFT_MASK) != 0; } - bool IsCtrlPressed() const { return (mMetaState & AMETA_CTRL_MASK) != 0; } - bool IsMetaPressed() const { return (mMetaState & AMETA_META_MASK) != 0; } - int Flags() { return mFlags; } - int UnicodeChar() { return mUnicodeChar; } - int BaseUnicodeChar() { return mBaseUnicodeChar; } - int DOMPrintableKeyValue() { return mDOMPrintableKeyValue; } - int RepeatCount() const { return mRepeatCount; } - int Count() { return mCount; } - int Start() { return mStart; } - int End() { return mEnd; } - int PointerIndex() { return mPointerIndex; } - int RangeType() { return mRangeType; } - int RangeStyles() { return mRangeStyles; } - int RangeLineStyle() { return mRangeLineStyle; } - bool RangeBoldLine() { return mRangeBoldLine; } - int RangeForeColor() { return mRangeForeColor; } - int RangeBackColor() { return mRangeBackColor; } - int RangeLineColor() { return mRangeLineColor; } - nsGeoPosition* GeoPosition() { return mGeoPosition; } - int ConnectionType() { return mConnectionType; } - bool IsWifi() { return mIsWifi; } - int DHCPGateway() { return mDHCPGateway; } - short ScreenOrientation() { return mScreenOrientation; } - RefCountedJavaObject* ByteBuffer() { return mByteBuffer; } - int Width() { return mWidth; } - int Height() { return mHeight; } - int ID() { return mID; } - int GamepadButton() { return mGamepadButton; } - bool GamepadButtonPressed() { return mGamepadButtonPressed; } - float GamepadButtonValue() { return mGamepadButtonValue; } - const nsTArray& GamepadValues() { return mGamepadValues; } - int RequestId() { return mCount; } // for convenience - const AutoGlobalWrappedJavaObject& Object() { return mObject; } - bool CanCoalesceWith(AndroidGoannaEvent* ae); - WidgetTouchEvent MakeTouchEvent(nsIWidget* widget); - MultiTouchInput MakeMultiTouchInput(nsIWidget* widget); - WidgetMouseEvent MakeMouseEvent(nsIWidget* widget); - void UnionRect(nsIntRect const& aRect); - nsIObserver *Observer() { return mObserver; } - mozilla::layers::ScrollableLayerGuid ApzGuid(); - uint64_t ApzInputBlockId(); - -protected: - int mAction; - int mType; - bool mAckNeeded; - int64_t mTime; - nsTArray mPoints; - nsTArray mPointRadii; - nsTArray mPointIndicies; - nsTArray mOrientations; - nsTArray mPressures; - nsTArray mToolTypes; - nsIntRect mRect; - int mFlags, mMetaState; - int mKeyCode, mScanCode; - int mUnicodeChar, mBaseUnicodeChar, mDOMPrintableKeyValue; - int mRepeatCount; - int mCount; - int mStart, mEnd; - int mRangeType, mRangeStyles, mRangeLineStyle; - bool mRangeBoldLine; - int mRangeForeColor, mRangeBackColor, mRangeLineColor; - double mX, mY, mZ; - int mPointerIndex; - nsString mCharacters, mCharactersExtra, mData; - nsRefPtr mGeoPosition; - int mConnectionType; - bool mIsWifi; - int mDHCPGateway; - short mScreenOrientation; - nsRefPtr mByteBuffer; - int mWidth, mHeight; - int mID; - int mGamepadButton; - bool mGamepadButtonPressed; - float mGamepadButtonValue; - nsTArray mGamepadValues; - nsCOMPtr mObserver; - nsTArray mPrefNames; - MultiTouchInput mApzInput; - mozilla::layers::ScrollableLayerGuid mApzGuid; - uint64_t mApzInputBlockId; - AutoGlobalWrappedJavaObject mObject; - - void ReadIntArray(nsTArray &aVals, - JNIEnv *jenv, - jfieldID field, - int32_t count); - void ReadFloatArray(nsTArray &aVals, - JNIEnv *jenv, - jfieldID field, - int32_t count); - void ReadPointArray(nsTArray &mPoints, - JNIEnv *jenv, - jfieldID field, - int32_t count); - void ReadStringArray(nsTArray &aStrings, - JNIEnv *jenv, - jfieldID field); - void ReadRectField(JNIEnv *jenv); - void ReadCharactersField(JNIEnv *jenv); - void ReadCharactersExtraField(JNIEnv *jenv); - void ReadDataField(JNIEnv *jenv); - void ReadStringFromJString(nsString &aString, JNIEnv *jenv, jstring s); - - static jclass jGoannaEventClass; - static jfieldID jActionField; - static jfieldID jTypeField; - static jfieldID jAckNeededField; - static jfieldID jTimeField; - static jfieldID jPoints; - static jfieldID jPointIndicies; - static jfieldID jOrientations; - static jfieldID jPressures; - static jfieldID jToolTypes; - static jfieldID jPointRadii; - static jfieldID jXField; - static jfieldID jYField; - static jfieldID jZField; - static jfieldID jDistanceField; - static jfieldID jRectField; - static jfieldID jNativeWindowField; - - static jfieldID jCharactersField; - static jfieldID jCharactersExtraField; - static jfieldID jDataField; - static jfieldID jDOMPrintableKeyValueField; - static jfieldID jKeyCodeField; - static jfieldID jScanCodeField; - static jfieldID jMetaStateField; - static jfieldID jFlagsField; - static jfieldID jCountField; - static jfieldID jStartField; - static jfieldID jEndField; - static jfieldID jPointerIndexField; - static jfieldID jUnicodeCharField; - static jfieldID jBaseUnicodeCharField; - static jfieldID jRepeatCountField; - static jfieldID jRangeTypeField; - static jfieldID jRangeStylesField; - static jfieldID jRangeLineStyleField; - static jfieldID jRangeBoldLineField; - static jfieldID jRangeForeColorField; - static jfieldID jRangeBackColorField; - static jfieldID jRangeLineColorField; - static jfieldID jLocationField; - static jfieldID jPrefNamesField; - - static jfieldID jConnectionTypeField; - static jfieldID jIsWifiField; - static jfieldID jDHCPGatewayField; - - static jfieldID jScreenOrientationField; - static jfieldID jByteBufferField; - - static jfieldID jWidthField; - static jfieldID jHeightField; - - static jfieldID jIDField; - static jfieldID jGamepadButtonField; - static jfieldID jGamepadButtonPressedField; - static jfieldID jGamepadButtonValueField; - static jfieldID jGamepadValuesField; - - static jfieldID jObjectField; - -public: - enum { - NATIVE_POKE = 0, - KEY_EVENT = 1, - MOTION_EVENT = 2, - SENSOR_EVENT = 3, - PROCESS_OBJECT = 4, - LOCATION_EVENT = 5, - IME_EVENT = 6, - SIZE_CHANGED = 8, - APP_BACKGROUNDING = 9, - APP_FOREGROUNDING = 10, - LOAD_URI = 12, - NOOP = 15, - FORCED_RESIZE = 16, // used internally in nsAppShell/nsWindow - APZ_INPUT_EVENT = 17, // used internally in AndroidJNI/nsAppShell/nsWindow - BROADCAST = 19, - VIEWPORT = 20, - VISITED = 21, - NETWORK_CHANGED = 22, - THUMBNAIL = 25, - SCREENORIENTATION_CHANGED = 27, - COMPOSITOR_CREATE = 28, - COMPOSITOR_PAUSE = 29, - COMPOSITOR_RESUME = 30, - NATIVE_GESTURE_EVENT = 31, - IME_KEY_EVENT = 32, - CALL_OBSERVER = 33, - REMOVE_OBSERVER = 34, - LOW_MEMORY = 35, - NETWORK_LINK_CHANGE = 36, - TELEMETRY_HISTOGRAM_ADD = 37, - ADD_OBSERVER = 38, - PREFERENCES_OBSERVE = 39, - PREFERENCES_GET = 40, - PREFERENCES_REMOVE_OBSERVERS = 41, - TELEMETRY_UI_SESSION_START = 42, - TELEMETRY_UI_SESSION_STOP = 43, - TELEMETRY_UI_EVENT = 44, - GAMEPAD_ADDREMOVE = 45, - GAMEPAD_DATA = 46, - LONG_PRESS = 47, - ZOOMEDVIEW = 48, - dummy_java_enum_list_end - }; - - enum { - // Memory pressure levels. Keep these in sync with those in MemoryMonitor.java. - MEMORY_PRESSURE_NONE = 0, - MEMORY_PRESSURE_CLEANUP = 1, - MEMORY_PRESSURE_LOW = 2, - MEMORY_PRESSURE_MEDIUM = 3, - MEMORY_PRESSURE_HIGH = 4 - }; - - enum { - // Internal Goanna events - IME_FLUSH_CHANGES = -2, - IME_UPDATE_CONTEXT = -1, - // Events from Java to Goanna - IME_SYNCHRONIZE = 0, - IME_REPLACE_TEXT = 1, - IME_SET_SELECTION = 2, - IME_ADD_COMPOSITION_RANGE = 3, - IME_UPDATE_COMPOSITION = 4, - IME_REMOVE_COMPOSITION = 5, - IME_ACKNOWLEDGE_FOCUS = 6, - IME_COMPOSE_TEXT = 7, - dummy_ime_enum_list_end - }; - - enum { - ACTION_GAMEPAD_ADDED = 1, - ACTION_GAMEPAD_REMOVED = 2 - }; - - enum { - ACTION_GAMEPAD_BUTTON = 1, - ACTION_GAMEPAD_AXES = 2 - }; - - enum { - ACTION_OBJECT_LAYER_CLIENT = 1, - dummy_object_enum_list_end - }; -}; - -class nsJNIString : public nsString -{ -public: - nsJNIString(jstring jstr, JNIEnv *jenv); -}; - -class nsJNICString : public nsCString -{ -public: - nsJNICString(jstring jstr, JNIEnv *jenv); -}; - -} - -#endif diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp deleted file mode 100644 index c1c72e6a98..0000000000 --- a/widget/android/GeneratedJNIWrappers.cpp +++ /dev/null @@ -1,1312 +0,0 @@ -// GENERATED CODE -// Generated by the Java program at /build/annotationProcessors at compile time -// from annotations on Java methods. To update, change the annotations on the -// corresponding Javamethods and rerun the build. Manually updating this file -// will cause your build to fail. - -#include "GeneratedJNIWrappers.h" -#include "mozilla/jni/Accessors.h" - -namespace mozilla { -namespace widget { - -constexpr char DownloadsIntegration::name[]; - -constexpr char DownloadsIntegration::ScanMedia_t::name[]; -constexpr char DownloadsIntegration::ScanMedia_t::signature[]; - -void DownloadsIntegration::ScanMedia(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::name[]; - -constexpr char GoannaAppShell::AcknowledgeEvent_t::name[]; -constexpr char GoannaAppShell::AcknowledgeEvent_t::signature[]; - -void GoannaAppShell::AcknowledgeEvent() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::AddPluginViewWrapper_t::name[]; -constexpr char GoannaAppShell::AddPluginViewWrapper_t::signature[]; - -void GoannaAppShell::AddPluginViewWrapper(mozilla::jni::Object::Param a0, float a1, float a2, float a3, float a4, bool a5) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3, a4, a5); -} - -constexpr char GoannaAppShell::AlertsProgressListener_OnProgress_t::name[]; -constexpr char GoannaAppShell::AlertsProgressListener_OnProgress_t::signature[]; - -void GoannaAppShell::AlertsProgressListener_OnProgress(mozilla::jni::String::Param a0, int64_t a1, int64_t a2, mozilla::jni::String::Param a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaAppShell::CancelVibrate_t::name[]; -constexpr char GoannaAppShell::CancelVibrate_t::signature[]; - -void GoannaAppShell::CancelVibrate() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::CheckURIVisited_t::name[]; -constexpr char GoannaAppShell::CheckURIVisited_t::signature[]; - -void GoannaAppShell::CheckURIVisited(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::ClearMessageList_t::name[]; -constexpr char GoannaAppShell::ClearMessageList_t::signature[]; - -void GoannaAppShell::ClearMessageList(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::CloseCamera_t::name[]; -constexpr char GoannaAppShell::CloseCamera_t::signature[]; - -void GoannaAppShell::CloseCamera() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::CloseNotification_t::name[]; -constexpr char GoannaAppShell::CloseNotification_t::signature[]; - -void GoannaAppShell::CloseNotification(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::ConnectionGetMimeType_t::name[]; -constexpr char GoannaAppShell::ConnectionGetMimeType_t::signature[]; - -mozilla::jni::String::LocalRef GoannaAppShell::ConnectionGetMimeType(mozilla::jni::Object::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::CreateInputStream_t::name[]; -constexpr char GoannaAppShell::CreateInputStream_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaAppShell::CreateInputStream(mozilla::jni::Object::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::CreateMessageListWrapper_t::name[]; -constexpr char GoannaAppShell::CreateMessageListWrapper_t::signature[]; - -void GoannaAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, mozilla::jni::ObjectArray::Param a2, int32_t a3, mozilla::jni::String::Param a4, bool a5, bool a6, int64_t a7, bool a8, int32_t a9) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -constexpr char GoannaAppShell::CreateShortcut_t::name[]; -constexpr char GoannaAppShell::CreateShortcut_t::signature[]; - -void GoannaAppShell::CreateShortcut(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, mozilla::jni::String::Param a2) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2); -} - -constexpr char GoannaAppShell::DeleteMessageWrapper_t::name[]; -constexpr char GoannaAppShell::DeleteMessageWrapper_t::signature[]; - -void GoannaAppShell::DeleteMessageWrapper(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::DisableBatteryNotifications_t::name[]; -constexpr char GoannaAppShell::DisableBatteryNotifications_t::signature[]; - -void GoannaAppShell::DisableBatteryNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::DisableNetworkNotifications_t::name[]; -constexpr char GoannaAppShell::DisableNetworkNotifications_t::signature[]; - -void GoannaAppShell::DisableNetworkNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::DisableScreenOrientationNotifications_t::name[]; -constexpr char GoannaAppShell::DisableScreenOrientationNotifications_t::signature[]; - -void GoannaAppShell::DisableScreenOrientationNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::DisableSensor_t::name[]; -constexpr char GoannaAppShell::DisableSensor_t::signature[]; - -void GoannaAppShell::DisableSensor(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::EnableBatteryNotifications_t::name[]; -constexpr char GoannaAppShell::EnableBatteryNotifications_t::signature[]; - -void GoannaAppShell::EnableBatteryNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::EnableLocation_t::name[]; -constexpr char GoannaAppShell::EnableLocation_t::signature[]; - -void GoannaAppShell::EnableLocation(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::EnableLocationHighAccuracy_t::name[]; -constexpr char GoannaAppShell::EnableLocationHighAccuracy_t::signature[]; - -void GoannaAppShell::EnableLocationHighAccuracy(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::EnableNetworkNotifications_t::name[]; -constexpr char GoannaAppShell::EnableNetworkNotifications_t::signature[]; - -void GoannaAppShell::EnableNetworkNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::EnableScreenOrientationNotifications_t::name[]; -constexpr char GoannaAppShell::EnableScreenOrientationNotifications_t::signature[]; - -void GoannaAppShell::EnableScreenOrientationNotifications() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::EnableSensor_t::name[]; -constexpr char GoannaAppShell::EnableSensor_t::signature[]; - -void GoannaAppShell::EnableSensor(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::GamepadAdded_t::name[]; -constexpr char GoannaAppShell::GamepadAdded_t::signature[]; - -void GoannaAppShell::GamepadAdded(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetConnection_t::name[]; -constexpr char GoannaAppShell::GetConnection_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaAppShell::GetConnection(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::GetContext_t::name[]; -constexpr char GoannaAppShell::GetContext_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaAppShell::GetContext() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetCurrentBatteryInformationWrapper_t::name[]; -constexpr char GoannaAppShell::GetCurrentBatteryInformationWrapper_t::signature[]; - -mozilla::jni::DoubleArray::LocalRef GoannaAppShell::GetCurrentBatteryInformationWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetCurrentNetworkInformationWrapper_t::name[]; -constexpr char GoannaAppShell::GetCurrentNetworkInformationWrapper_t::signature[]; - -mozilla::jni::DoubleArray::LocalRef GoannaAppShell::GetCurrentNetworkInformationWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetDensity_t::name[]; -constexpr char GoannaAppShell::GetDensity_t::signature[]; - -float GoannaAppShell::GetDensity() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetDpiWrapper_t::name[]; -constexpr char GoannaAppShell::GetDpiWrapper_t::signature[]; - -int32_t GoannaAppShell::GetDpiWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetExtensionFromMimeTypeWrapper_t::name[]; -constexpr char GoannaAppShell::GetExtensionFromMimeTypeWrapper_t::signature[]; - -mozilla::jni::String::LocalRef GoannaAppShell::GetExtensionFromMimeTypeWrapper(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::GetExternalPublicDirectory_t::name[]; -constexpr char GoannaAppShell::GetExternalPublicDirectory_t::signature[]; - -mozilla::jni::String::LocalRef GoannaAppShell::GetExternalPublicDirectory(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::GetHandlersForMimeTypeWrapper_t::name[]; -constexpr char GoannaAppShell::GetHandlersForMimeTypeWrapper_t::signature[]; - -mozilla::jni::ObjectArray::LocalRef GoannaAppShell::GetHandlersForMimeTypeWrapper(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetHandlersForURLWrapper_t::name[]; -constexpr char GoannaAppShell::GetHandlersForURLWrapper_t::signature[]; - -mozilla::jni::ObjectArray::LocalRef GoannaAppShell::GetHandlersForURLWrapper(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetIconForExtensionWrapper_t::name[]; -constexpr char GoannaAppShell::GetIconForExtensionWrapper_t::signature[]; - -mozilla::jni::ByteArray::LocalRef GoannaAppShell::GetIconForExtensionWrapper(mozilla::jni::String::Param a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetMessageWrapper_t::name[]; -constexpr char GoannaAppShell::GetMessageWrapper_t::signature[]; - -void GoannaAppShell::GetMessageWrapper(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetMimeTypeFromExtensionsWrapper_t::name[]; -constexpr char GoannaAppShell::GetMimeTypeFromExtensionsWrapper_t::signature[]; - -mozilla::jni::String::LocalRef GoannaAppShell::GetMimeTypeFromExtensionsWrapper(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::GetNextMessageInListWrapper_t::name[]; -constexpr char GoannaAppShell::GetNextMessageInListWrapper_t::signature[]; - -void GoannaAppShell::GetNextMessageInListWrapper(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::GetProxyForURIWrapper_t::name[]; -constexpr char GoannaAppShell::GetProxyForURIWrapper_t::signature[]; - -mozilla::jni::String::LocalRef GoannaAppShell::GetProxyForURIWrapper(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, mozilla::jni::String::Param a2, int32_t a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaAppShell::GetScreenDepthWrapper_t::name[]; -constexpr char GoannaAppShell::GetScreenDepthWrapper_t::signature[]; - -int32_t GoannaAppShell::GetScreenDepthWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetScreenOrientationWrapper_t::name[]; -constexpr char GoannaAppShell::GetScreenOrientationWrapper_t::signature[]; - -int16_t GoannaAppShell::GetScreenOrientationWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetShowPasswordSetting_t::name[]; -constexpr char GoannaAppShell::GetShowPasswordSetting_t::signature[]; - -bool GoannaAppShell::GetShowPasswordSetting() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::GetSystemColoursWrapper_t::name[]; -constexpr char GoannaAppShell::GetSystemColoursWrapper_t::signature[]; - -mozilla::jni::IntArray::LocalRef GoannaAppShell::GetSystemColoursWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::HandleGoannaMessageWrapper_t::name[]; -constexpr char GoannaAppShell::HandleGoannaMessageWrapper_t::signature[]; - -void GoannaAppShell::HandleGoannaMessageWrapper(mozilla::jni::Object::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::HandleUncaughtException_t::name[]; -constexpr char GoannaAppShell::HandleUncaughtException_t::signature[]; - -void GoannaAppShell::HandleUncaughtException(mozilla::jni::Object::Param a0, mozilla::jni::Throwable::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::HideProgressDialog_t::name[]; -constexpr char GoannaAppShell::HideProgressDialog_t::signature[]; - -void GoannaAppShell::HideProgressDialog() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::InitCameraWrapper_t::name[]; -constexpr char GoannaAppShell::InitCameraWrapper_t::signature[]; - -mozilla::jni::IntArray::LocalRef GoannaAppShell::InitCameraWrapper(mozilla::jni::String::Param a0, int32_t a1, int32_t a2, int32_t a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaAppShell::IsNetworkLinkKnown_t::name[]; -constexpr char GoannaAppShell::IsNetworkLinkKnown_t::signature[]; - -bool GoannaAppShell::IsNetworkLinkKnown() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::IsNetworkLinkUp_t::name[]; -constexpr char GoannaAppShell::IsNetworkLinkUp_t::signature[]; - -bool GoannaAppShell::IsNetworkLinkUp() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::IsTablet_t::name[]; -constexpr char GoannaAppShell::IsTablet_t::signature[]; - -bool GoannaAppShell::IsTablet() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::KillAnyZombies_t::name[]; -constexpr char GoannaAppShell::KillAnyZombies_t::signature[]; - -void GoannaAppShell::KillAnyZombies() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::LoadPluginClass_t::name[]; -constexpr char GoannaAppShell::LoadPluginClass_t::signature[]; - -mozilla::jni::ClassObject::LocalRef GoannaAppShell::LoadPluginClass(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::LockScreenOrientation_t::name[]; -constexpr char GoannaAppShell::LockScreenOrientation_t::signature[]; - -void GoannaAppShell::LockScreenOrientation(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::MarkURIVisited_t::name[]; -constexpr char GoannaAppShell::MarkURIVisited_t::signature[]; - -void GoannaAppShell::MarkURIVisited(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::MoveTaskToBack_t::name[]; -constexpr char GoannaAppShell::MoveTaskToBack_t::signature[]; - -void GoannaAppShell::MoveTaskToBack() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::NetworkLinkType_t::name[]; -constexpr char GoannaAppShell::NetworkLinkType_t::signature[]; - -int32_t GoannaAppShell::NetworkLinkType() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::NotifyDefaultPrevented_t::name[]; -constexpr char GoannaAppShell::NotifyDefaultPrevented_t::signature[]; - -void GoannaAppShell::NotifyDefaultPrevented(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::NotifyIME_t::name[]; -constexpr char GoannaAppShell::NotifyIME_t::signature[]; - -void GoannaAppShell::NotifyIME(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::NotifyIMEChange_t::name[]; -constexpr char GoannaAppShell::NotifyIMEChange_t::signature[]; - -void GoannaAppShell::NotifyIMEChange(mozilla::jni::String::Param a0, int32_t a1, int32_t a2, int32_t a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaAppShell::NotifyIMEContext_t::name[]; -constexpr char GoannaAppShell::NotifyIMEContext_t::signature[]; - -void GoannaAppShell::NotifyIMEContext(int32_t a0, mozilla::jni::String::Param a1, mozilla::jni::String::Param a2, mozilla::jni::String::Param a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaAppShell::NotifyWakeLockChanged_t::name[]; -constexpr char GoannaAppShell::NotifyWakeLockChanged_t::signature[]; - -void GoannaAppShell::NotifyWakeLockChanged(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::NotifyXreExit_t::name[]; -constexpr char GoannaAppShell::NotifyXreExit_t::signature[]; - -void GoannaAppShell::NotifyXreExit() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::OpenUriExternal_t::name[]; -constexpr char GoannaAppShell::OpenUriExternal_t::signature[]; - -bool GoannaAppShell::OpenUriExternal(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, mozilla::jni::String::Param a2, mozilla::jni::String::Param a3, mozilla::jni::String::Param a4, mozilla::jni::String::Param a5) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3, a4, a5); -} - -constexpr char GoannaAppShell::PerformHapticFeedback_t::name[]; -constexpr char GoannaAppShell::PerformHapticFeedback_t::signature[]; - -void GoannaAppShell::PerformHapticFeedback(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::PumpMessageLoop_t::name[]; -constexpr char GoannaAppShell::PumpMessageLoop_t::signature[]; - -bool GoannaAppShell::PumpMessageLoop() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::RegisterSurfaceTextureFrameListener_t::name[]; -constexpr char GoannaAppShell::RegisterSurfaceTextureFrameListener_t::signature[]; - -void GoannaAppShell::RegisterSurfaceTextureFrameListener(mozilla::jni::Object::Param a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::RemovePluginView_t::name[]; -constexpr char GoannaAppShell::RemovePluginView_t::signature[]; - -void GoannaAppShell::RemovePluginView(mozilla::jni::Object::Param a0, bool a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::RequestUiThreadCallback_t::name[]; -constexpr char GoannaAppShell::RequestUiThreadCallback_t::signature[]; - -void GoannaAppShell::RequestUiThreadCallback(int64_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::ScheduleRestart_t::name[]; -constexpr char GoannaAppShell::ScheduleRestart_t::signature[]; - -void GoannaAppShell::ScheduleRestart() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::SendMessageWrapper_t::name[]; -constexpr char GoannaAppShell::SendMessageWrapper_t::signature[]; - -void GoannaAppShell::SendMessageWrapper(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, int32_t a2) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2); -} - -constexpr char GoannaAppShell::SetFullScreen_t::name[]; -constexpr char GoannaAppShell::SetFullScreen_t::signature[]; - -void GoannaAppShell::SetFullScreen(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::SetKeepScreenOn_t::name[]; -constexpr char GoannaAppShell::SetKeepScreenOn_t::signature[]; - -void GoannaAppShell::SetKeepScreenOn(bool a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::SetURITitle_t::name[]; -constexpr char GoannaAppShell::SetURITitle_t::signature[]; - -void GoannaAppShell::SetURITitle(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaAppShell::ShowAlertNotificationWrapper_t::name[]; -constexpr char GoannaAppShell::ShowAlertNotificationWrapper_t::signature[]; - -void GoannaAppShell::ShowAlertNotificationWrapper(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, mozilla::jni::String::Param a2, mozilla::jni::String::Param a3, mozilla::jni::String::Param a4) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3, a4); -} - -constexpr char GoannaAppShell::ShowInputMethodPicker_t::name[]; -constexpr char GoannaAppShell::ShowInputMethodPicker_t::signature[]; - -void GoannaAppShell::ShowInputMethodPicker() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::StartMonitoringGamepad_t::name[]; -constexpr char GoannaAppShell::StartMonitoringGamepad_t::signature[]; - -void GoannaAppShell::StartMonitoringGamepad() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::StopMonitoringGamepad_t::name[]; -constexpr char GoannaAppShell::StopMonitoringGamepad_t::signature[]; - -void GoannaAppShell::StopMonitoringGamepad() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::UnlockProfile_t::name[]; -constexpr char GoannaAppShell::UnlockProfile_t::signature[]; - -bool GoannaAppShell::UnlockProfile() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::UnlockScreenOrientation_t::name[]; -constexpr char GoannaAppShell::UnlockScreenOrientation_t::signature[]; - -void GoannaAppShell::UnlockScreenOrientation() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaAppShell::UnregisterSurfaceTextureFrameListener_t::name[]; -constexpr char GoannaAppShell::UnregisterSurfaceTextureFrameListener_t::signature[]; - -void GoannaAppShell::UnregisterSurfaceTextureFrameListener(mozilla::jni::Object::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::Vibrate1_t::name[]; -constexpr char GoannaAppShell::Vibrate1_t::signature[]; - -void GoannaAppShell::Vibrate1(int64_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaAppShell::VibrateA_t::name[]; -constexpr char GoannaAppShell::VibrateA_t::signature[]; - -void GoannaAppShell::VibrateA(mozilla::jni::LongArray::Param a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaJavaSampler::name[]; - -constexpr char GoannaJavaSampler::GetFrameNameJavaProfilingWrapper_t::name[]; -constexpr char GoannaJavaSampler::GetFrameNameJavaProfilingWrapper_t::signature[]; - -mozilla::jni::String::LocalRef GoannaJavaSampler::GetFrameNameJavaProfilingWrapper(int32_t a0, int32_t a1, int32_t a2) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2); -} - -constexpr char GoannaJavaSampler::GetSampleTimeJavaProfiling_t::name[]; -constexpr char GoannaJavaSampler::GetSampleTimeJavaProfiling_t::signature[]; - -double GoannaJavaSampler::GetSampleTimeJavaProfiling(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaJavaSampler::GetThreadNameJavaProfilingWrapper_t::name[]; -constexpr char GoannaJavaSampler::GetThreadNameJavaProfilingWrapper_t::signature[]; - -mozilla::jni::String::LocalRef GoannaJavaSampler::GetThreadNameJavaProfilingWrapper(int32_t a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char GoannaJavaSampler::PauseJavaProfiling_t::name[]; -constexpr char GoannaJavaSampler::PauseJavaProfiling_t::signature[]; - -void GoannaJavaSampler::PauseJavaProfiling() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaJavaSampler::StartJavaProfiling_t::name[]; -constexpr char GoannaJavaSampler::StartJavaProfiling_t::signature[]; - -void GoannaJavaSampler::StartJavaProfiling(int32_t a0, int32_t a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char GoannaJavaSampler::StopJavaProfiling_t::name[]; -constexpr char GoannaJavaSampler::StopJavaProfiling_t::signature[]; - -void GoannaJavaSampler::StopJavaProfiling() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char GoannaJavaSampler::UnpauseJavaProfiling_t::name[]; -constexpr char GoannaJavaSampler::UnpauseJavaProfiling_t::signature[]; - -void GoannaJavaSampler::UnpauseJavaProfiling() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char RestrictedProfiles::name[]; - -constexpr char RestrictedProfiles::GetUserRestrictions_t::name[]; -constexpr char RestrictedProfiles::GetUserRestrictions_t::signature[]; - -mozilla::jni::String::LocalRef RestrictedProfiles::GetUserRestrictions() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char RestrictedProfiles::IsAllowed_t::name[]; -constexpr char RestrictedProfiles::IsAllowed_t::signature[]; - -bool RestrictedProfiles::IsAllowed(int32_t a0, mozilla::jni::String::Param a1) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1); -} - -constexpr char RestrictedProfiles::IsUserRestricted_t::name[]; -constexpr char RestrictedProfiles::IsUserRestricted_t::signature[]; - -bool RestrictedProfiles::IsUserRestricted() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char SurfaceBits::name[]; - -constexpr char SurfaceBits::New_t::name[]; -constexpr char SurfaceBits::New_t::signature[]; - -SurfaceBits::LocalRef SurfaceBits::New() -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr); -} - -constexpr char SurfaceBits::Buffer_t::name[]; -constexpr char SurfaceBits::Buffer_t::signature[]; - -mozilla::jni::Object::LocalRef SurfaceBits::Buffer() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void SurfaceBits::Buffer(mozilla::jni::Object::Param a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char SurfaceBits::Format_t::name[]; -constexpr char SurfaceBits::Format_t::signature[]; - -int32_t SurfaceBits::Format() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void SurfaceBits::Format(int32_t a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char SurfaceBits::Height_t::name[]; -constexpr char SurfaceBits::Height_t::signature[]; - -int32_t SurfaceBits::Height() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void SurfaceBits::Height(int32_t a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char SurfaceBits::Width_t::name[]; -constexpr char SurfaceBits::Width_t::signature[]; - -int32_t SurfaceBits::Width() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void SurfaceBits::Width(int32_t a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ThumbnailHelper::name[]; - -constexpr char ThumbnailHelper::SendThumbnail_t::name[]; -constexpr char ThumbnailHelper::SendThumbnail_t::signature[]; - -void ThumbnailHelper::SendThumbnail(mozilla::jni::Object::Param a0, int32_t a1, bool a2, bool a3) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2, a3); -} - -constexpr char DisplayPortMetrics::name[]; - -constexpr char DisplayPortMetrics::New_t::name[]; -constexpr char DisplayPortMetrics::New_t::signature[]; - -DisplayPortMetrics::LocalRef DisplayPortMetrics::New(float a0, float a1, float a2, float a3, float a4) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0, a1, a2, a3, a4); -} - -constexpr char DisplayPortMetrics::MPosition_t::name[]; -constexpr char DisplayPortMetrics::MPosition_t::signature[]; - -mozilla::jni::Object::LocalRef DisplayPortMetrics::MPosition() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -constexpr char DisplayPortMetrics::Resolution_t::name[]; -constexpr char DisplayPortMetrics::Resolution_t::signature[]; - -float DisplayPortMetrics::Resolution() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -constexpr char GLController::name[]; - -constexpr char GLController::CreateEGLSurfaceForCompositorWrapper_t::name[]; -constexpr char GLController::CreateEGLSurfaceForCompositorWrapper_t::signature[]; - -mozilla::jni::Object::LocalRef GLController::CreateEGLSurfaceForCompositorWrapper() const -{ - return mozilla::jni::Method::Call(this, nullptr); -} - -constexpr char GoannaLayerClient::name[]; - -constexpr char GoannaLayerClient::ActivateProgram_t::name[]; -constexpr char GoannaLayerClient::ActivateProgram_t::signature[]; - -void GoannaLayerClient::ActivateProgram() const -{ - return mozilla::jni::Method::Call(this, nullptr); -} - -constexpr char GoannaLayerClient::ContentDocumentChanged_t::name[]; -constexpr char GoannaLayerClient::ContentDocumentChanged_t::signature[]; - -void GoannaLayerClient::ContentDocumentChanged() const -{ - return mozilla::jni::Method::Call(this, nullptr); -} - -constexpr char GoannaLayerClient::CreateFrame_t::name[]; -constexpr char GoannaLayerClient::CreateFrame_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaLayerClient::CreateFrame() const -{ - return mozilla::jni::Method::Call(this, nullptr); -} - -constexpr char GoannaLayerClient::DeactivateProgramAndRestoreState_t::name[]; -constexpr char GoannaLayerClient::DeactivateProgramAndRestoreState_t::signature[]; - -void GoannaLayerClient::DeactivateProgramAndRestoreState(bool a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4); -} - -constexpr char GoannaLayerClient::GetDisplayPort_t::name[]; -constexpr char GoannaLayerClient::GetDisplayPort_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaLayerClient::GetDisplayPort(bool a0, bool a1, int32_t a2, mozilla::jni::Object::Param a3) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaLayerClient::IsContentDocumentDisplayed_t::name[]; -constexpr char GoannaLayerClient::IsContentDocumentDisplayed_t::signature[]; - -bool GoannaLayerClient::IsContentDocumentDisplayed() const -{ - return mozilla::jni::Method::Call(this, nullptr); -} - -constexpr char GoannaLayerClient::ProgressiveUpdateCallback_t::name[]; -constexpr char GoannaLayerClient::ProgressiveUpdateCallback_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaLayerClient::ProgressiveUpdateCallback(bool a0, float a1, float a2, float a3, float a4, float a5, bool a6) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4, a5, a6); -} - -constexpr char GoannaLayerClient::SetFirstPaintViewport_t::name[]; -constexpr char GoannaLayerClient::SetFirstPaintViewport_t::signature[]; - -void GoannaLayerClient::SetFirstPaintViewport(float a0, float a1, float a2, float a3, float a4, float a5, float a6) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4, a5, a6); -} - -constexpr char GoannaLayerClient::SetPageRect_t::name[]; -constexpr char GoannaLayerClient::SetPageRect_t::signature[]; - -void GoannaLayerClient::SetPageRect(float a0, float a1, float a2, float a3) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3); -} - -constexpr char GoannaLayerClient::SyncFrameMetrics_t::name[]; -constexpr char GoannaLayerClient::SyncFrameMetrics_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaLayerClient::SyncFrameMetrics(float a0, float a1, float a2, float a3, float a4, float a5, float a6, bool a7, int32_t a8, int32_t a9, int32_t a10, int32_t a11, float a12, bool a13) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -constexpr char GoannaLayerClient::SyncViewportInfo_t::name[]; -constexpr char GoannaLayerClient::SyncViewportInfo_t::signature[]; - -mozilla::jni::Object::LocalRef GoannaLayerClient::SyncViewportInfo(int32_t a0, int32_t a1, int32_t a2, int32_t a3, float a4, bool a5) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4, a5); -} - -constexpr char ImmutableViewportMetrics::name[]; - -constexpr char ImmutableViewportMetrics::New_t::name[]; -constexpr char ImmutableViewportMetrics::New_t::signature[]; - -ImmutableViewportMetrics::LocalRef ImmutableViewportMetrics::New(float a0, float a1, float a2, float a3, float a4, float a5, float a6, float a7, float a8, float a9, float a10, float a11, float a12) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -constexpr char LayerView::name[]; - -constexpr char LayerView::RegisterCompositorWrapper_t::name[]; -constexpr char LayerView::RegisterCompositorWrapper_t::signature[]; - -mozilla::jni::Object::LocalRef LayerView::RegisterCompositorWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char LayerView::updateZoomedView_t::name[]; -constexpr char LayerView::updateZoomedView_t::signature[]; - -void LayerView::updateZoomedView(mozilla::jni::Object::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - -constexpr char NativePanZoomController::name[]; - -constexpr char NativePanZoomController::RequestContentRepaintWrapper_t::name[]; -constexpr char NativePanZoomController::RequestContentRepaintWrapper_t::signature[]; - -void NativePanZoomController::RequestContentRepaintWrapper(float a0, float a1, float a2, float a3, float a4) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1, a2, a3, a4); -} - -constexpr char ProgressiveUpdateData::name[]; - -constexpr char ProgressiveUpdateData::New_t::name[]; -constexpr char ProgressiveUpdateData::New_t::signature[]; - -ProgressiveUpdateData::LocalRef ProgressiveUpdateData::New() -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr); -} - -constexpr char ProgressiveUpdateData::SetViewport_t::name[]; -constexpr char ProgressiveUpdateData::SetViewport_t::signature[]; - -void ProgressiveUpdateData::SetViewport(mozilla::jni::Object::Param a0) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0); -} - -constexpr char ProgressiveUpdateData::Abort_t::name[]; -constexpr char ProgressiveUpdateData::Abort_t::signature[]; - -bool ProgressiveUpdateData::Abort() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ProgressiveUpdateData::Abort(bool a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ProgressiveUpdateData::Scale_t::name[]; -constexpr char ProgressiveUpdateData::Scale_t::signature[]; - -float ProgressiveUpdateData::Scale() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ProgressiveUpdateData::Scale(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ProgressiveUpdateData::X_t::name[]; -constexpr char ProgressiveUpdateData::X_t::signature[]; - -float ProgressiveUpdateData::X() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ProgressiveUpdateData::X(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ProgressiveUpdateData::Y_t::name[]; -constexpr char ProgressiveUpdateData::Y_t::signature[]; - -float ProgressiveUpdateData::Y() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ProgressiveUpdateData::Y(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::name[]; - -constexpr char ViewTransform::New_t::name[]; -constexpr char ViewTransform::New_t::signature[]; - -ViewTransform::LocalRef ViewTransform::New(float a0, float a1, float a2) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0, a1, a2); -} - -constexpr char ViewTransform::FixedLayerMarginBottom_t::name[]; -constexpr char ViewTransform::FixedLayerMarginBottom_t::signature[]; - -float ViewTransform::FixedLayerMarginBottom() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::FixedLayerMarginBottom(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::FixedLayerMarginLeft_t::name[]; -constexpr char ViewTransform::FixedLayerMarginLeft_t::signature[]; - -float ViewTransform::FixedLayerMarginLeft() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::FixedLayerMarginLeft(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::FixedLayerMarginRight_t::name[]; -constexpr char ViewTransform::FixedLayerMarginRight_t::signature[]; - -float ViewTransform::FixedLayerMarginRight() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::FixedLayerMarginRight(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::FixedLayerMarginTop_t::name[]; -constexpr char ViewTransform::FixedLayerMarginTop_t::signature[]; - -float ViewTransform::FixedLayerMarginTop() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::FixedLayerMarginTop(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::OffsetX_t::name[]; -constexpr char ViewTransform::OffsetX_t::signature[]; - -float ViewTransform::OffsetX() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::OffsetX(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::OffsetY_t::name[]; -constexpr char ViewTransform::OffsetY_t::signature[]; - -float ViewTransform::OffsetY() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::OffsetY(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::Scale_t::name[]; -constexpr char ViewTransform::Scale_t::signature[]; - -float ViewTransform::Scale() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::Scale(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::X_t::name[]; -constexpr char ViewTransform::X_t::signature[]; - -float ViewTransform::X() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::X(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char ViewTransform::Y_t::name[]; -constexpr char ViewTransform::Y_t::signature[]; - -float ViewTransform::Y() const -{ - return mozilla::jni::Field::Get(this, nullptr); -} - -void ViewTransform::Y(float a0) const -{ - return mozilla::jni::Field::Set(this, nullptr, a0); -} - -constexpr char NativeZip::name[]; - -constexpr char NativeZip::CreateInputStream_t::name[]; -constexpr char NativeZip::CreateInputStream_t::signature[]; - -mozilla::jni::Object::LocalRef NativeZip::CreateInputStream(mozilla::jni::Object::Param a0, int32_t a1) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1); -} - -constexpr char MatrixBlobCursor::name[]; - -constexpr char MatrixBlobCursor::New_t::name[]; -constexpr char MatrixBlobCursor::New_t::signature[]; - -MatrixBlobCursor::LocalRef MatrixBlobCursor::New(mozilla::jni::ObjectArray::Param a0) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0); -} - -constexpr char MatrixBlobCursor::New2_t::name[]; -constexpr char MatrixBlobCursor::New2_t::signature[]; - -MatrixBlobCursor::LocalRef MatrixBlobCursor::New(mozilla::jni::ObjectArray::Param a0, int32_t a1) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0, a1); -} - -constexpr char MatrixBlobCursor::AddRow_t::name[]; -constexpr char MatrixBlobCursor::AddRow_t::signature[]; - -void MatrixBlobCursor::AddRow(mozilla::jni::Object::Param a0) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0); -} - -constexpr char MatrixBlobCursor::AddRow2_t::name[]; -constexpr char MatrixBlobCursor::AddRow2_t::signature[]; - -void MatrixBlobCursor::AddRow(mozilla::jni::Object::Param a0, int32_t a1) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0, a1); -} - -constexpr char MatrixBlobCursor::AddRow3_t::name[]; -constexpr char MatrixBlobCursor::AddRow3_t::signature[]; - -void MatrixBlobCursor::AddRow(mozilla::jni::ObjectArray::Param a0) const -{ - return mozilla::jni::Method::Call(this, nullptr, a0); -} - -constexpr char SQLiteBridgeException::name[]; - -constexpr char SQLiteBridgeException::New_t::name[]; -constexpr char SQLiteBridgeException::New_t::signature[]; - -SQLiteBridgeException::LocalRef SQLiteBridgeException::New() -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr); -} - -constexpr char SQLiteBridgeException::New2_t::name[]; -constexpr char SQLiteBridgeException::New2_t::signature[]; - -SQLiteBridgeException::LocalRef SQLiteBridgeException::New(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Constructor::Call(nullptr, nullptr, a0); -} - -constexpr char SQLiteBridgeException::SerialVersionUID_t::name[]; -constexpr char SQLiteBridgeException::SerialVersionUID_t::signature[]; - -int64_t SQLiteBridgeException::SerialVersionUID() -{ - return mozilla::jni::Field::Get(nullptr, nullptr); -} - -constexpr char Clipboard::name[]; - -constexpr char Clipboard::ClearText_t::name[]; -constexpr char Clipboard::ClearText_t::signature[]; - -void Clipboard::ClearText() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char Clipboard::GetClipboardTextWrapper_t::name[]; -constexpr char Clipboard::GetClipboardTextWrapper_t::signature[]; - -mozilla::jni::String::LocalRef Clipboard::GetClipboardTextWrapper() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char Clipboard::HasText_t::name[]; -constexpr char Clipboard::HasText_t::signature[]; - -bool Clipboard::HasText() -{ - return mozilla::jni::Method::Call(nullptr, nullptr); -} - -constexpr char Clipboard::SetClipboardText_t::name[]; -constexpr char Clipboard::SetClipboardText_t::signature[]; - -void Clipboard::SetClipboardText(mozilla::jni::String::Param a0) -{ - return mozilla::jni::Method::Call(nullptr, nullptr, a0); -} - - -} /* widget */ -} /* mozilla */ diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h deleted file mode 100644 index 29c4b085f0..0000000000 --- a/widget/android/GeneratedJNIWrappers.h +++ /dev/null @@ -1,2545 +0,0 @@ -// GENERATED CODE -// Generated by the Java program at /build/annotationProcessors at compile time -// from annotations on Java methods. To update, change the annotations on the -// corresponding Javamethods and rerun the build. Manually updating this file -// will cause your build to fail. - -#ifndef GeneratedJNIWrappers_h__ -#define GeneratedJNIWrappers_h__ - -#include "mozilla/jni/Refs.h" - -namespace mozilla { -namespace widget { - -class DownloadsIntegration : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/DownloadsIntegration"; - -protected: - DownloadsIntegration(jobject instance) : Class(instance) {} - -public: - struct ScanMedia_t { - typedef DownloadsIntegration Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "scanMedia"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ScanMedia(mozilla::jni::String::Param, mozilla::jni::String::Param); - -}; - -class GoannaAppShell : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/GoannaAppShell"; - -protected: - GoannaAppShell(jobject instance) : Class(instance) {} - -public: - struct AcknowledgeEvent_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "acknowledgeEvent"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void AcknowledgeEvent(); - -public: - struct AddPluginViewWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "addPluginView"; - static constexpr char signature[] = - "(Landroid/view/View;FFFFZ)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void AddPluginViewWrapper(mozilla::jni::Object::Param, float, float, float, float, bool); - -public: - struct AlertsProgressListener_OnProgress_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "alertsProgressListener_OnProgress"; - static constexpr char signature[] = - "(Ljava/lang/String;JJLjava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void AlertsProgressListener_OnProgress(mozilla::jni::String::Param, int64_t, int64_t, mozilla::jni::String::Param); - -public: - struct CancelVibrate_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "cancelVibrate"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CancelVibrate(); - -public: - struct CheckURIVisited_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "checkUriVisited"; - static constexpr char signature[] = - "(Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CheckURIVisited(mozilla::jni::String::Param); - -public: - struct ClearMessageList_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "clearMessageList"; - static constexpr char signature[] = - "(I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ClearMessageList(int32_t); - -public: - struct CloseCamera_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "closeCamera"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CloseCamera(); - -public: - struct CloseNotification_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "closeNotification"; - static constexpr char signature[] = - "(Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CloseNotification(mozilla::jni::String::Param); - -public: - struct ConnectionGetMimeType_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "connectionGetMimeType"; - static constexpr char signature[] = - "(Ljava/net/URLConnection;)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef ConnectionGetMimeType(mozilla::jni::Object::Param); - -public: - struct CreateInputStream_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "createInputStream"; - static constexpr char signature[] = - "(Ljava/net/URLConnection;)Ljava/io/InputStream;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::Object::LocalRef CreateInputStream(mozilla::jni::Object::Param); - -public: - struct CreateMessageListWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "createMessageList"; - static constexpr char signature[] = - "(JJ[Ljava/lang/String;ILjava/lang/String;ZZJZI)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CreateMessageListWrapper(int64_t, int64_t, mozilla::jni::ObjectArray::Param, int32_t, mozilla::jni::String::Param, bool, bool, int64_t, bool, int32_t); - -public: - struct CreateShortcut_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "createShortcut"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void CreateShortcut(mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct DeleteMessageWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "deleteMessage"; - static constexpr char signature[] = - "(II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void DeleteMessageWrapper(int32_t, int32_t); - -public: - struct DisableBatteryNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "disableBatteryNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void DisableBatteryNotifications(); - -public: - struct DisableNetworkNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "disableNetworkNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void DisableNetworkNotifications(); - -public: - struct DisableScreenOrientationNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "disableScreenOrientationNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void DisableScreenOrientationNotifications(); - -public: - struct DisableSensor_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "disableSensor"; - static constexpr char signature[] = - "(I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void DisableSensor(int32_t); - -public: - struct EnableBatteryNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableBatteryNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableBatteryNotifications(); - -public: - struct EnableLocation_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableLocation"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableLocation(bool); - -public: - struct EnableLocationHighAccuracy_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableLocationHighAccuracy"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableLocationHighAccuracy(bool); - -public: - struct EnableNetworkNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableNetworkNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableNetworkNotifications(); - -public: - struct EnableScreenOrientationNotifications_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableScreenOrientationNotifications"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableScreenOrientationNotifications(); - -public: - struct EnableSensor_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "enableSensor"; - static constexpr char signature[] = - "(I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void EnableSensor(int32_t); - -public: - struct GamepadAdded_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "gamepadAdded"; - static constexpr char signature[] = - "(II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void GamepadAdded(int32_t, int32_t); - -public: - struct GetConnection_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "getConnection"; - static constexpr char signature[] = - "(Ljava/lang/String;)Ljava/net/URLConnection;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::Object::LocalRef GetConnection(mozilla::jni::String::Param); - -public: - struct GetContext_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "getContext"; - static constexpr char signature[] = - "()Landroid/content/Context;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::Object::LocalRef GetContext(); - -public: - struct GetCurrentBatteryInformationWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::DoubleArray::LocalRef ReturnType; - typedef mozilla::jni::DoubleArray::Param SetterType; - static constexpr char name[] = "getCurrentBatteryInformation"; - static constexpr char signature[] = - "()[D"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::DoubleArray::LocalRef GetCurrentBatteryInformationWrapper(); - -public: - struct GetCurrentNetworkInformationWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::DoubleArray::LocalRef ReturnType; - typedef mozilla::jni::DoubleArray::Param SetterType; - static constexpr char name[] = "getCurrentNetworkInformation"; - static constexpr char signature[] = - "()[D"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::DoubleArray::LocalRef GetCurrentNetworkInformationWrapper(); - -public: - struct GetDensity_t { - typedef GoannaAppShell Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "getDensity"; - static constexpr char signature[] = - "()F"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static float GetDensity(); - -public: - struct GetDpiWrapper_t { - typedef GoannaAppShell Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "getDpi"; - static constexpr char signature[] = - "()I"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static int32_t GetDpiWrapper(); - -public: - struct GetExtensionFromMimeTypeWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getExtensionFromMimeType"; - static constexpr char signature[] = - "(Ljava/lang/String;)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetExtensionFromMimeTypeWrapper(mozilla::jni::String::Param); - -public: - struct GetExternalPublicDirectory_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getExternalPublicDirectory"; - static constexpr char signature[] = - "(Ljava/lang/String;)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetExternalPublicDirectory(mozilla::jni::String::Param); - -public: - struct GetHandlersForMimeTypeWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::ObjectArray::LocalRef ReturnType; - typedef mozilla::jni::ObjectArray::Param SetterType; - static constexpr char name[] = "getHandlersForMimeType"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::ObjectArray::LocalRef GetHandlersForMimeTypeWrapper(mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct GetHandlersForURLWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::ObjectArray::LocalRef ReturnType; - typedef mozilla::jni::ObjectArray::Param SetterType; - static constexpr char name[] = "getHandlersForURL"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::ObjectArray::LocalRef GetHandlersForURLWrapper(mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct GetIconForExtensionWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::ByteArray::LocalRef ReturnType; - typedef mozilla::jni::ByteArray::Param SetterType; - static constexpr char name[] = "getIconForExtension"; - static constexpr char signature[] = - "(Ljava/lang/String;I)[B"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::ByteArray::LocalRef GetIconForExtensionWrapper(mozilla::jni::String::Param, int32_t); - -public: - struct GetMessageWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "getMessage"; - static constexpr char signature[] = - "(II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void GetMessageWrapper(int32_t, int32_t); - -public: - struct GetMimeTypeFromExtensionsWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getMimeTypeFromExtensions"; - static constexpr char signature[] = - "(Ljava/lang/String;)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetMimeTypeFromExtensionsWrapper(mozilla::jni::String::Param); - -public: - struct GetNextMessageInListWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "getNextMessageInList"; - static constexpr char signature[] = - "(II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void GetNextMessageInListWrapper(int32_t, int32_t); - -public: - struct GetProxyForURIWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getProxyForURI"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetProxyForURIWrapper(mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, int32_t); - -public: - struct GetScreenDepthWrapper_t { - typedef GoannaAppShell Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "getScreenDepth"; - static constexpr char signature[] = - "()I"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static int32_t GetScreenDepthWrapper(); - -public: - struct GetScreenOrientationWrapper_t { - typedef GoannaAppShell Owner; - typedef int16_t ReturnType; - typedef int16_t SetterType; - static constexpr char name[] = "getScreenOrientation"; - static constexpr char signature[] = - "()S"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static int16_t GetScreenOrientationWrapper(); - -public: - struct GetShowPasswordSetting_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "getShowPasswordSetting"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool GetShowPasswordSetting(); - -public: - struct GetSystemColoursWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::IntArray::LocalRef ReturnType; - typedef mozilla::jni::IntArray::Param SetterType; - static constexpr char name[] = "getSystemColors"; - static constexpr char signature[] = - "()[I"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::IntArray::LocalRef GetSystemColoursWrapper(); - -public: - struct HandleGoannaMessageWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "handleGoannaMessage"; - static constexpr char signature[] = - "(Lorg/mozilla/goanna/util/NativeJSContainer;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void HandleGoannaMessageWrapper(mozilla::jni::Object::Param); - -public: - struct HandleUncaughtException_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "handleUncaughtException"; - static constexpr char signature[] = - "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::IGNORE; - }; - - static void HandleUncaughtException(mozilla::jni::Object::Param, mozilla::jni::Throwable::Param); - -public: - struct HideProgressDialog_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "hideProgressDialog"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void HideProgressDialog(); - -public: - struct InitCameraWrapper_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::IntArray::LocalRef ReturnType; - typedef mozilla::jni::IntArray::Param SetterType; - static constexpr char name[] = "initCamera"; - static constexpr char signature[] = - "(Ljava/lang/String;III)[I"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::IntArray::LocalRef InitCameraWrapper(mozilla::jni::String::Param, int32_t, int32_t, int32_t); - -public: - struct IsNetworkLinkKnown_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isNetworkLinkKnown"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool IsNetworkLinkKnown(); - -public: - struct IsNetworkLinkUp_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isNetworkLinkUp"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool IsNetworkLinkUp(); - -public: - struct IsTablet_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isTablet"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool IsTablet(); - -public: - struct KillAnyZombies_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "killAnyZombies"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void KillAnyZombies(); - -public: - struct LoadPluginClass_t { - typedef GoannaAppShell Owner; - typedef mozilla::jni::ClassObject::LocalRef ReturnType; - typedef mozilla::jni::ClassObject::Param SetterType; - static constexpr char name[] = "loadPluginClass"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::ClassObject::LocalRef LoadPluginClass(mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct LockScreenOrientation_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "lockScreenOrientation"; - static constexpr char signature[] = - "(I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void LockScreenOrientation(int32_t); - -public: - struct MarkURIVisited_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "markUriVisited"; - static constexpr char signature[] = - "(Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void MarkURIVisited(mozilla::jni::String::Param); - -public: - struct MoveTaskToBack_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "moveTaskToBack"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void MoveTaskToBack(); - -public: - struct NetworkLinkType_t { - typedef GoannaAppShell Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "networkLinkType"; - static constexpr char signature[] = - "()I"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static int32_t NetworkLinkType(); - -public: - struct NotifyDefaultPrevented_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyDefaultPrevented"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyDefaultPrevented(bool); - -public: - struct NotifyIME_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyIME"; - static constexpr char signature[] = - "(I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyIME(int32_t); - -public: - struct NotifyIMEChange_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyIMEChange"; - static constexpr char signature[] = - "(Ljava/lang/String;III)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyIMEChange(mozilla::jni::String::Param, int32_t, int32_t, int32_t); - -public: - struct NotifyIMEContext_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyIMEContext"; - static constexpr char signature[] = - "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyIMEContext(int32_t, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct NotifyWakeLockChanged_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyWakeLockChanged"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyWakeLockChanged(mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct NotifyXreExit_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "onXreExit"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void NotifyXreExit(); - -public: - struct OpenUriExternal_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "openUriExternal"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool OpenUriExternal(mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct PerformHapticFeedback_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "performHapticFeedback"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void PerformHapticFeedback(bool); - -public: - struct PumpMessageLoop_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "pumpMessageLoop"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool PumpMessageLoop(); - -public: - struct RegisterSurfaceTextureFrameListener_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "registerSurfaceTextureFrameListener"; - static constexpr char signature[] = - "(Ljava/lang/Object;I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void RegisterSurfaceTextureFrameListener(mozilla::jni::Object::Param, int32_t); - -public: - struct RemovePluginView_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "removePluginView"; - static constexpr char signature[] = - "(Landroid/view/View;Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void RemovePluginView(mozilla::jni::Object::Param, bool); - -public: - struct RequestUiThreadCallback_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "requestUiThreadCallback"; - static constexpr char signature[] = - "(J)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void RequestUiThreadCallback(int64_t); - -public: - struct ScheduleRestart_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "scheduleRestart"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ScheduleRestart(); - -public: - struct SendMessageWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "sendMessage"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;I)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SendMessageWrapper(mozilla::jni::String::Param, mozilla::jni::String::Param, int32_t); - -public: - struct SetFullScreen_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setFullScreen"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SetFullScreen(bool); - -public: - struct SetKeepScreenOn_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setKeepScreenOn"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SetKeepScreenOn(bool); - -public: - struct SetURITitle_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setUriTitle"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SetURITitle(mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct ShowAlertNotificationWrapper_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "showAlertNotification"; - static constexpr char signature[] = - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ShowAlertNotificationWrapper(mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param, mozilla::jni::String::Param); - -public: - struct ShowInputMethodPicker_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "showInputMethodPicker"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ShowInputMethodPicker(); - -public: - struct StartMonitoringGamepad_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "startMonitoringGamepad"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void StartMonitoringGamepad(); - -public: - struct StopMonitoringGamepad_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "stopMonitoringGamepad"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void StopMonitoringGamepad(); - -public: - struct UnlockProfile_t { - typedef GoannaAppShell Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "unlockProfile"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool UnlockProfile(); - -public: - struct UnlockScreenOrientation_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "unlockScreenOrientation"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void UnlockScreenOrientation(); - -public: - struct UnregisterSurfaceTextureFrameListener_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "unregisterSurfaceTextureFrameListener"; - static constexpr char signature[] = - "(Ljava/lang/Object;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void UnregisterSurfaceTextureFrameListener(mozilla::jni::Object::Param); - -public: - struct Vibrate1_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "vibrate"; - static constexpr char signature[] = - "(J)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void Vibrate1(int64_t); - -public: - struct VibrateA_t { - typedef GoannaAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "vibrate"; - static constexpr char signature[] = - "([JI)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void VibrateA(mozilla::jni::LongArray::Param, int32_t); - -}; - -class GoannaJavaSampler : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/GoannaJavaSampler"; - -protected: - GoannaJavaSampler(jobject instance) : Class(instance) {} - -public: - struct GetFrameNameJavaProfilingWrapper_t { - typedef GoannaJavaSampler Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getFrameName"; - static constexpr char signature[] = - "(III)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetFrameNameJavaProfilingWrapper(int32_t, int32_t, int32_t); - -public: - struct GetSampleTimeJavaProfiling_t { - typedef GoannaJavaSampler Owner; - typedef double ReturnType; - typedef double SetterType; - static constexpr char name[] = "getSampleTime"; - static constexpr char signature[] = - "(II)D"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static double GetSampleTimeJavaProfiling(int32_t, int32_t); - -public: - struct GetThreadNameJavaProfilingWrapper_t { - typedef GoannaJavaSampler Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getThreadName"; - static constexpr char signature[] = - "(I)Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetThreadNameJavaProfilingWrapper(int32_t); - -public: - struct PauseJavaProfiling_t { - typedef GoannaJavaSampler Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "pause"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void PauseJavaProfiling(); - -public: - struct StartJavaProfiling_t { - typedef GoannaJavaSampler Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "start"; - static constexpr char signature[] = - "(II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void StartJavaProfiling(int32_t, int32_t); - -public: - struct StopJavaProfiling_t { - typedef GoannaJavaSampler Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "stop"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void StopJavaProfiling(); - -public: - struct UnpauseJavaProfiling_t { - typedef GoannaJavaSampler Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "unpause"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void UnpauseJavaProfiling(); - -}; - -class RestrictedProfiles : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/RestrictedProfiles"; - -protected: - RestrictedProfiles(jobject instance) : Class(instance) {} - -public: - struct GetUserRestrictions_t { - typedef RestrictedProfiles Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getUserRestrictions"; - static constexpr char signature[] = - "()Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetUserRestrictions(); - -public: - struct IsAllowed_t { - typedef RestrictedProfiles Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isAllowed"; - static constexpr char signature[] = - "(ILjava/lang/String;)Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool IsAllowed(int32_t, mozilla::jni::String::Param); - -public: - struct IsUserRestricted_t { - typedef RestrictedProfiles Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isUserRestricted"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool IsUserRestricted(); - -}; - -class SurfaceBits : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/SurfaceBits"; - -protected: - SurfaceBits(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef SurfaceBits Owner; - typedef SurfaceBits::LocalRef ReturnType; - typedef SurfaceBits::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "()V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static SurfaceBits::LocalRef New(); - -public: - struct Buffer_t { - typedef SurfaceBits Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "buffer"; - static constexpr char signature[] = - "Ljava/nio/ByteBuffer;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef Buffer() const; - - void Buffer(mozilla::jni::Object::Param) const; - -public: - struct Format_t { - typedef SurfaceBits Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "format"; - static constexpr char signature[] = - "I"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - int32_t Format() const; - - void Format(int32_t) const; - -public: - struct Height_t { - typedef SurfaceBits Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "height"; - static constexpr char signature[] = - "I"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - int32_t Height() const; - - void Height(int32_t) const; - -public: - struct Width_t { - typedef SurfaceBits Owner; - typedef int32_t ReturnType; - typedef int32_t SetterType; - static constexpr char name[] = "width"; - static constexpr char signature[] = - "I"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - int32_t Width() const; - - void Width(int32_t) const; - -}; - -class ThumbnailHelper : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/ThumbnailHelper"; - -protected: - ThumbnailHelper(jobject instance) : Class(instance) {} - -public: - struct SendThumbnail_t { - typedef ThumbnailHelper Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "notifyThumbnail"; - static constexpr char signature[] = - "(Ljava/nio/ByteBuffer;IZZ)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SendThumbnail(mozilla::jni::Object::Param, int32_t, bool, bool); - -}; - -class DisplayPortMetrics : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/DisplayPortMetrics"; - -protected: - DisplayPortMetrics(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef DisplayPortMetrics Owner; - typedef DisplayPortMetrics::LocalRef ReturnType; - typedef DisplayPortMetrics::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "(FFFFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static DisplayPortMetrics::LocalRef New(float, float, float, float, float); - -public: - struct MPosition_t { - typedef DisplayPortMetrics Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "mPosition"; - static constexpr char signature[] = - "Landroid/graphics/RectF;"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef MPosition() const; - -public: - struct Resolution_t { - typedef DisplayPortMetrics Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "resolution"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float Resolution() const; - -}; - -class GLController : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/GLController"; - -protected: - GLController(jobject instance) : Class(instance) {} - -public: - struct CreateEGLSurfaceForCompositorWrapper_t { - typedef GLController Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "createEGLSurfaceForCompositor"; - static constexpr char signature[] = - "()Ljavax/microedition/khronos/egl/EGLSurface;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef CreateEGLSurfaceForCompositorWrapper() const; - -}; - -class GoannaLayerClient : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/GoannaLayerClient"; - -protected: - GoannaLayerClient(jobject instance) : Class(instance) {} - -public: - struct ActivateProgram_t { - typedef GoannaLayerClient Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "activateProgram"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void ActivateProgram() const; - -public: - struct ContentDocumentChanged_t { - typedef GoannaLayerClient Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "contentDocumentChanged"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void ContentDocumentChanged() const; - -public: - struct CreateFrame_t { - typedef GoannaLayerClient Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "createFrame"; - static constexpr char signature[] = - "()Lorg/mozilla/goanna/gfx/LayerRenderer$Frame;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef CreateFrame() const; - -public: - struct DeactivateProgramAndRestoreState_t { - typedef GoannaLayerClient Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "deactivateProgramAndRestoreState"; - static constexpr char signature[] = - "(ZIIII)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void DeactivateProgramAndRestoreState(bool, int32_t, int32_t, int32_t, int32_t) const; - -public: - struct GetDisplayPort_t { - typedef GoannaLayerClient Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "getDisplayPort"; - static constexpr char signature[] = - "(ZZILorg/mozilla/goanna/gfx/ImmutableViewportMetrics;)Lorg/mozilla/goanna/gfx/DisplayPortMetrics;"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef GetDisplayPort(bool, bool, int32_t, mozilla::jni::Object::Param) const; - -public: - struct IsContentDocumentDisplayed_t { - typedef GoannaLayerClient Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "isContentDocumentDisplayed"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - bool IsContentDocumentDisplayed() const; - -public: - struct ProgressiveUpdateCallback_t { - typedef GoannaLayerClient Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "progressiveUpdateCallback"; - static constexpr char signature[] = - "(ZFFFFFZ)Lorg/mozilla/goanna/gfx/ProgressiveUpdateData;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef ProgressiveUpdateCallback(bool, float, float, float, float, float, bool) const; - -public: - struct SetFirstPaintViewport_t { - typedef GoannaLayerClient Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setFirstPaintViewport"; - static constexpr char signature[] = - "(FFFFFFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void SetFirstPaintViewport(float, float, float, float, float, float, float) const; - -public: - struct SetPageRect_t { - typedef GoannaLayerClient Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setPageRect"; - static constexpr char signature[] = - "(FFFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void SetPageRect(float, float, float, float) const; - -public: - struct SyncFrameMetrics_t { - typedef GoannaLayerClient Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "syncFrameMetrics"; - static constexpr char signature[] = - "(FFFFFFFZIIIIFZ)Lorg/mozilla/goanna/gfx/ViewTransform;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef SyncFrameMetrics(float, float, float, float, float, float, float, bool, int32_t, int32_t, int32_t, int32_t, float, bool) const; - -public: - struct SyncViewportInfo_t { - typedef GoannaLayerClient Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "syncViewportInfo"; - static constexpr char signature[] = - "(IIIIFZ)Lorg/mozilla/goanna/gfx/ViewTransform;"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef SyncViewportInfo(int32_t, int32_t, int32_t, int32_t, float, bool) const; - -}; - -class ImmutableViewportMetrics : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/ImmutableViewportMetrics"; - -protected: - ImmutableViewportMetrics(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef ImmutableViewportMetrics Owner; - typedef ImmutableViewportMetrics::LocalRef ReturnType; - typedef ImmutableViewportMetrics::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "(FFFFFFFFFFFFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static ImmutableViewportMetrics::LocalRef New(float, float, float, float, float, float, float, float, float, float, float, float, float); - -}; - -class LayerView : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/LayerView"; - -protected: - LayerView(jobject instance) : Class(instance) {} - -public: - struct RegisterCompositorWrapper_t { - typedef LayerView Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "registerCxxCompositor"; - static constexpr char signature[] = - "()Lorg/mozilla/goanna/gfx/GLController;"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::Object::LocalRef RegisterCompositorWrapper(); - -public: - struct updateZoomedView_t { - typedef LayerView Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "updateZoomedView"; - static constexpr char signature[] = - "(Ljava/nio/ByteBuffer;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void updateZoomedView(mozilla::jni::Object::Param); - -}; - -class NativePanZoomController : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/NativePanZoomController"; - -protected: - NativePanZoomController(jobject instance) : Class(instance) {} - -public: - struct RequestContentRepaintWrapper_t { - typedef NativePanZoomController Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "requestContentRepaint"; - static constexpr char signature[] = - "(FFFFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void RequestContentRepaintWrapper(float, float, float, float, float) const; - -}; - -class ProgressiveUpdateData : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/ProgressiveUpdateData"; - -protected: - ProgressiveUpdateData(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef ProgressiveUpdateData Owner; - typedef ProgressiveUpdateData::LocalRef ReturnType; - typedef ProgressiveUpdateData::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "()V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static ProgressiveUpdateData::LocalRef New(); - -public: - struct SetViewport_t { - typedef ProgressiveUpdateData Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setViewport"; - static constexpr char signature[] = - "(Lorg/mozilla/goanna/gfx/ImmutableViewportMetrics;)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void SetViewport(mozilla::jni::Object::Param) const; - -public: - struct Abort_t { - typedef ProgressiveUpdateData Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "abort"; - static constexpr char signature[] = - "Z"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - bool Abort() const; - - void Abort(bool) const; - -public: - struct Scale_t { - typedef ProgressiveUpdateData Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "scale"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float Scale() const; - - void Scale(float) const; - -public: - struct X_t { - typedef ProgressiveUpdateData Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "x"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float X() const; - - void X(float) const; - -public: - struct Y_t { - typedef ProgressiveUpdateData Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "y"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float Y() const; - - void Y(float) const; - -}; - -class ViewTransform : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/gfx/ViewTransform"; - -protected: - ViewTransform(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef ViewTransform Owner; - typedef ViewTransform::LocalRef ReturnType; - typedef ViewTransform::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "(FFF)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static ViewTransform::LocalRef New(float, float, float); - -public: - struct FixedLayerMarginBottom_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "fixedLayerMarginBottom"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float FixedLayerMarginBottom() const; - - void FixedLayerMarginBottom(float) const; - -public: - struct FixedLayerMarginLeft_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "fixedLayerMarginLeft"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float FixedLayerMarginLeft() const; - - void FixedLayerMarginLeft(float) const; - -public: - struct FixedLayerMarginRight_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "fixedLayerMarginRight"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float FixedLayerMarginRight() const; - - void FixedLayerMarginRight(float) const; - -public: - struct FixedLayerMarginTop_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "fixedLayerMarginTop"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float FixedLayerMarginTop() const; - - void FixedLayerMarginTop(float) const; - -public: - struct OffsetX_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "offsetX"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float OffsetX() const; - - void OffsetX(float) const; - -public: - struct OffsetY_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "offsetY"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float OffsetY() const; - - void OffsetY(float) const; - -public: - struct Scale_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "scale"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float Scale() const; - - void Scale(float) const; - -public: - struct X_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "x"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float X() const; - - void X(float) const; - -public: - struct Y_t { - typedef ViewTransform Owner; - typedef float ReturnType; - typedef float SetterType; - static constexpr char name[] = "y"; - static constexpr char signature[] = - "F"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - float Y() const; - - void Y(float) const; - -}; - -class NativeZip : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/mozglue/NativeZip"; - -protected: - NativeZip(jobject instance) : Class(instance) {} - -public: - struct CreateInputStream_t { - typedef NativeZip Owner; - typedef mozilla::jni::Object::LocalRef ReturnType; - typedef mozilla::jni::Object::Param SetterType; - static constexpr char name[] = "createInputStream"; - static constexpr char signature[] = - "(Ljava/nio/ByteBuffer;I)Ljava/io/InputStream;"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - mozilla::jni::Object::LocalRef CreateInputStream(mozilla::jni::Object::Param, int32_t) const; - -}; - -class MatrixBlobCursor : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/sqlite/MatrixBlobCursor"; - -protected: - MatrixBlobCursor(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef MatrixBlobCursor Owner; - typedef MatrixBlobCursor::LocalRef ReturnType; - typedef MatrixBlobCursor::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "([Ljava/lang/String;)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static MatrixBlobCursor::LocalRef New(mozilla::jni::ObjectArray::Param); - -public: - struct New2_t { - typedef MatrixBlobCursor Owner; - typedef MatrixBlobCursor::LocalRef ReturnType; - typedef MatrixBlobCursor::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "([Ljava/lang/String;I)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static MatrixBlobCursor::LocalRef New(mozilla::jni::ObjectArray::Param, int32_t); - -public: - struct AddRow_t { - typedef MatrixBlobCursor Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "addRow"; - static constexpr char signature[] = - "(Ljava/lang/Iterable;)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void AddRow(mozilla::jni::Object::Param) const; - -public: - struct AddRow2_t { - typedef MatrixBlobCursor Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "addRow"; - static constexpr char signature[] = - "(Ljava/util/ArrayList;I)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void AddRow(mozilla::jni::Object::Param, int32_t) const; - -public: - struct AddRow3_t { - typedef MatrixBlobCursor Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "addRow"; - static constexpr char signature[] = - "([Ljava/lang/Object;)V"; - static const bool isStatic = false; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - void AddRow(mozilla::jni::ObjectArray::Param) const; - -}; - -class SQLiteBridgeException : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/sqlite/SQLiteBridgeException"; - -protected: - SQLiteBridgeException(jobject instance) : Class(instance) {} - -public: - struct New_t { - typedef SQLiteBridgeException Owner; - typedef SQLiteBridgeException::LocalRef ReturnType; - typedef SQLiteBridgeException::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "()V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static SQLiteBridgeException::LocalRef New(); - -public: - struct New2_t { - typedef SQLiteBridgeException Owner; - typedef SQLiteBridgeException::LocalRef ReturnType; - typedef SQLiteBridgeException::Param SetterType; - static constexpr char name[] = ""; - static constexpr char signature[] = - "(Ljava/lang/String;)V"; - static const bool isStatic = false; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static SQLiteBridgeException::LocalRef New(mozilla::jni::String::Param); - -public: - struct SerialVersionUID_t { - typedef SQLiteBridgeException Owner; - typedef int64_t ReturnType; - typedef int64_t SetterType; - static constexpr char name[] = "serialVersionUID"; - static constexpr char signature[] = - "J"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static int64_t SerialVersionUID(); - -}; - -class Clipboard : public mozilla::jni::Class { - -public: - typedef mozilla::jni::Ref Ref; - typedef mozilla::jni::LocalRef LocalRef; - typedef mozilla::jni::GlobalRef GlobalRef; - typedef const typename mozilla::jni::Param::Type& Param; - - static constexpr char name[] = - "org/mozilla/goanna/util/Clipboard"; - -protected: - Clipboard(jobject instance) : Class(instance) {} - -public: - struct ClearText_t { - typedef Clipboard Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "clearText"; - static constexpr char signature[] = - "()V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void ClearText(); - -public: - struct GetClipboardTextWrapper_t { - typedef Clipboard Owner; - typedef mozilla::jni::String::LocalRef ReturnType; - typedef mozilla::jni::String::Param SetterType; - static constexpr char name[] = "getText"; - static constexpr char signature[] = - "()Ljava/lang/String;"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static mozilla::jni::String::LocalRef GetClipboardTextWrapper(); - -public: - struct HasText_t { - typedef Clipboard Owner; - typedef bool ReturnType; - typedef bool SetterType; - static constexpr char name[] = "hasText"; - static constexpr char signature[] = - "()Z"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static bool HasText(); - -public: - struct SetClipboardText_t { - typedef Clipboard Owner; - typedef void ReturnType; - typedef void SetterType; - static constexpr char name[] = "setText"; - static constexpr char signature[] = - "(Ljava/lang/CharSequence;)V"; - static const bool isStatic = true; - static const bool isMultithreaded = false; - static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT; - }; - - static void SetClipboardText(mozilla::jni::String::Param); - -}; - - -} /* widget */ -} /* mozilla */ -#endif // GeneratedJNIWrappers_h__ diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp deleted file mode 100644 index 184005a3b4..0000000000 --- a/widget/android/GfxInfo.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "GfxInfo.h" -#include "GLContext.h" -#include "GLContextProvider.h" -#include "nsUnicharUtils.h" -#include "prenv.h" -#include "prprf.h" -#include "nsHashKeys.h" -#include "nsVersionComparator.h" -#include "AndroidBridge.h" -#include "nsIWindowWatcher.h" -#include "nsServiceManagerUtils.h" - -namespace mozilla { -namespace widget { - -class GfxInfo::GLStrings -{ - nsCString mVendor; - nsCString mRenderer; - nsCString mVersion; - bool mReady; - -public: - GLStrings() - : mReady(false) - {} - - const nsCString& Vendor() { - EnsureInitialized(); - return mVendor; - } - - void SpoofVendor(const nsCString& s) { - EnsureInitialized(); - mVendor = s; - } - - const nsCString& Renderer() { - EnsureInitialized(); - return mRenderer; - } - - void SpoofRenderer(const nsCString& s) { - EnsureInitialized(); - mRenderer = s; - } - - const nsCString& Version() { - EnsureInitialized(); - return mVersion; - } - - void SpoofVersion(const nsCString& s) { - EnsureInitialized(); - mVersion = s; - } - - void EnsureInitialized() { - if (mReady) { - return; - } - - nsRefPtr gl; - bool requireCompatProfile = true; - gl = gl::GLContextProvider::CreateHeadless(requireCompatProfile); - - if (!gl) { - // Setting mReady to true here means that we won't retry. Everything will - // remain blacklisted forever. Ideally, we would like to update that once - // any GLContext is successfully created, like the compositor's GLContext. - mReady = true; - return; - } - - gl->MakeCurrent(); - - const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR"); - if (spoofedVendor) - mVendor.Assign(spoofedVendor); - else - mVendor.Assign((const char*)gl->fGetString(LOCAL_GL_VENDOR)); - const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER"); - if (spoofedRenderer) - mRenderer.Assign(spoofedRenderer); - else - mRenderer.Assign((const char*)gl->fGetString(LOCAL_GL_RENDERER)); - const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION"); - if (spoofedVersion) - mVersion.Assign(spoofedVersion); - else - mVersion.Assign((const char*)gl->fGetString(LOCAL_GL_VERSION)); - - mReady = true; - } -}; - -#ifdef DEBUG -NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) -#endif - -GfxInfo::GfxInfo() - : mInitialized(false) - , mGLStrings(new GLStrings) -{ -} - -GfxInfo::~GfxInfo() -{ -} - -/* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization - * has occurred because they depend on it for information. (See bug 591561) */ -nsresult -GfxInfo::GetD2DEnabled(bool *aEnabled) -{ - return NS_ERROR_FAILURE; -} - -nsresult -GfxInfo::GetDWriteEnabled(bool *aEnabled) -{ - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString DWriteVersion; */ -NS_IMETHODIMP -GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) -{ - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString cleartypeParameters; */ -NS_IMETHODIMP -GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams) -{ - return NS_ERROR_FAILURE; -} - -void -GfxInfo::EnsureInitialized() -{ - if (mInitialized) - return; - - mGLStrings->EnsureInitialized(); - - MOZ_ASSERT(mozilla::AndroidBridge::Bridge()); - - if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", mModel)) { - mAdapterDescription.AppendPrintf("Model: %s", NS_LossyConvertUTF16toASCII(mModel).get()); - } - - if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "PRODUCT", mProduct)) { - mAdapterDescription.AppendPrintf(", Product: %s", NS_LossyConvertUTF16toASCII(mProduct).get()); - } - - if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MANUFACTURER", mManufacturer)) { - mAdapterDescription.AppendPrintf(", Manufacturer: %s", NS_LossyConvertUTF16toASCII(mManufacturer).get()); - } - - int32_t sdkVersion; - if (!mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &sdkVersion)) - sdkVersion = 0; - - // the HARDWARE field isn't available on Android SDK < 8 - if (sdkVersion >= 8 && mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", mHardware)) { - mAdapterDescription.AppendPrintf(", Hardware: %s", NS_LossyConvertUTF16toASCII(mHardware).get()); - } - - nsString release; - mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", release); - mOSVersion = NS_LossyConvertUTF16toASCII(release); - - mOSVersionInteger = 0; - char a[5], b[5], c[5], d[5]; - SplitDriverVersion(mOSVersion.get(), a, b, c, d); - uint8_t na = atoi(a); - uint8_t nb = atoi(b); - uint8_t nc = atoi(c); - uint8_t nd = atoi(d); - - mOSVersionInteger = (uint32_t(na) << 24) | - (uint32_t(nb) << 16) | - (uint32_t(nc) << 8) | - uint32_t(nd); - - mAdapterDescription.AppendPrintf(", OpenGL: %s -- %s -- %s", - mGLStrings->Vendor().get(), - mGLStrings->Renderer().get(), - mGLStrings->Version().get()); - - mInitialized = true; -} - -/* readonly attribute DOMString adapterDescription; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription) -{ - EnsureInitialized(); - aAdapterDescription = NS_ConvertASCIItoUTF16(mAdapterDescription); - return NS_OK; -} - -/* readonly attribute DOMString adapterDescription2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterRAM; */ -NS_IMETHODIMP -GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM) -{ - EnsureInitialized(); - aAdapterRAM.Truncate(); - return NS_OK; -} - -/* readonly attribute DOMString adapterRAM2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterDriver; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver) -{ - EnsureInitialized(); - aAdapterDriver.Truncate(); - return NS_OK; -} - -/* readonly attribute DOMString adapterDriver2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterDriverVersion; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) -{ - EnsureInitialized(); - aAdapterDriverVersion = NS_ConvertASCIItoUTF16(mGLStrings->Version()); - return NS_OK; -} - -/* readonly attribute DOMString adapterDriverVersion2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterDriverDate; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate) -{ - EnsureInitialized(); - aAdapterDriverDate.Truncate(); - return NS_OK; -} - -/* readonly attribute DOMString adapterDriverDate2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterVendorID; */ -NS_IMETHODIMP -GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID) -{ - EnsureInitialized(); - aAdapterVendorID = NS_ConvertASCIItoUTF16(mGLStrings->Vendor()); - return NS_OK; -} - -/* readonly attribute DOMString adapterVendorID2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterDeviceID; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID) -{ - EnsureInitialized(); - aAdapterDeviceID = NS_ConvertASCIItoUTF16(mGLStrings->Renderer()); - return NS_OK; -} - -/* readonly attribute DOMString adapterDeviceID2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterSubsysID; */ -NS_IMETHODIMP -GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute DOMString adapterSubsysID2; */ -NS_IMETHODIMP -GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -/* readonly attribute boolean isGPU2Active; */ -NS_IMETHODIMP -GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) -{ - EnsureInitialized(); - return NS_ERROR_FAILURE; -} - -const nsTArray& -GfxInfo::GetGfxDriverInfo() -{ - if (mDriverInfo->IsEmpty()) { - APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAll), GfxDriverInfo::allDevices, - nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK, - DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions ); - } - - return *mDriverInfo; -} - -nsresult -GfxInfo::GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS /* = nullptr */) -{ - NS_ENSURE_ARG_POINTER(aStatus); - aSuggestedDriverVersion.SetIsVoid(true); - *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; - OperatingSystem os = mOS; - if (aOS) - *aOS = os; - - // OpenGL layers are never blacklisted on Android. - // This early return is so we avoid potentially slow - // GLStrings initialization on startup when we initialize GL layers. - if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS) { - *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; - return NS_OK; - } - - EnsureInitialized(); - - if (mGLStrings->Vendor().IsEmpty() || mGLStrings->Renderer().IsEmpty()) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - - // Don't evaluate special cases when evaluating the downloaded blocklist. - if (aDriverInfo.IsEmpty()) { - if (aFeature == FEATURE_WEBGL_OPENGL) { - if (mGLStrings->Renderer().Find("Adreno 200") != -1 || - mGLStrings->Renderer().Find("Adreno 205") != -1) - { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - - if (mHardware.EqualsLiteral("ville")) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - - if (aFeature == FEATURE_STAGEFRIGHT) { - NS_LossyConvertUTF16toASCII cManufacturer(mManufacturer); - NS_LossyConvertUTF16toASCII cModel(mModel); - NS_LossyConvertUTF16toASCII cHardware(mHardware); - - if (cHardware.EqualsLiteral("antares") || - cHardware.EqualsLiteral("harmony") || - cHardware.EqualsLiteral("picasso") || - cHardware.EqualsLiteral("picasso_e") || - cHardware.EqualsLiteral("ventana") || - cHardware.EqualsLiteral("rk30board")) - { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - - if (CompareVersions(mOSVersion.get(), "2.2.0") >= 0 && - CompareVersions(mOSVersion.get(), "2.3.0") < 0) - { - // Froyo LG devices are whitelisted. - // All other Froyo - bool isWhitelisted = - cManufacturer.Equals("lge", nsCaseInsensitiveCStringComparator()); - - if (!isWhitelisted) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - else if (CompareVersions(mOSVersion.get(), "2.3.0") >= 0 && - CompareVersions(mOSVersion.get(), "2.4.0") < 0) - { - // Gingerbread HTC devices are whitelisted. - // Gingerbread Samsung devices are whitelisted except for: - // Samsung devices identified in Bug 847837 - // Gingerbread Sony devices are whitelisted. - // All other Gingerbread devices are blacklisted. - bool isWhitelisted = - cManufacturer.Equals("htc", nsCaseInsensitiveCStringComparator()) || - (cManufacturer.Find("sony", true) != -1) || - cManufacturer.Equals("samsung", nsCaseInsensitiveCStringComparator()); - - if (cModel.Equals("GT-I8160", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-I8160L", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-I8530", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-I9070", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-I9070P", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-I8160P", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-S7500", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-S7500T", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-S7500L", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("GT-S6500T", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("smdkc110", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("smdkc210", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("herring", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("shw-m110s", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("shw-m180s", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("n1", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("latona", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("aalto", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("atlas", nsCaseInsensitiveCStringComparator()) || - cHardware.Equals("qcom", nsCaseInsensitiveCStringComparator())) - { - isWhitelisted = false; - } - - if (!isWhitelisted) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - else if (CompareVersions(mOSVersion.get(), "3.0.0") >= 0 && - CompareVersions(mOSVersion.get(), "4.0.0") < 0) - { - // Honeycomb Samsung devices are whitelisted. - // All other Honeycomb devices are blacklisted. - bool isWhitelisted = - cManufacturer.Equals("samsung", nsCaseInsensitiveCStringComparator()); - - if (!isWhitelisted) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - else if (CompareVersions(mOSVersion.get(), "4.0.0") < 0) - { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION; - return NS_OK; - } - else if (CompareVersions(mOSVersion.get(), "4.1.0") < 0) - { - // Whitelist: - // All Samsung ICS devices, except for: - // Samsung SGH-I717 (Bug 845729) - // Samsung SGH-I727 (Bug 845729) - // Samsung SGH-I757 (Bug 845729) - // All Galaxy nexus ICS devices - // Sony Xperia Ion (LT28) ICS devices - bool isWhitelisted = - cModel.Equals("LT28h", nsCaseInsensitiveCStringComparator()) || - cManufacturer.Equals("samsung", nsCaseInsensitiveCStringComparator()) || - cModel.Equals("galaxy nexus", nsCaseInsensitiveCStringComparator()); // some Galaxy Nexus have manufacturer=amazon - - if (cModel.Find("SGH-I717", true) != -1 || - cModel.Find("SGH-I727", true) != -1 || - cModel.Find("SGH-I757", true) != -1) - { - isWhitelisted = false; - } - - if (!isWhitelisted) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - else if (CompareVersions(mOSVersion.get(), "4.2.0") < 0) - { - // Whitelist: - // All JB phones except for those in blocklist below - // Blocklist: - // Samsung devices from bug 812881 and 853522. - // Motorola XT890 from bug 882342. - bool isBlocklisted = - cModel.Find("GT-P3100", true) != -1 || - cModel.Find("GT-P3110", true) != -1 || - cModel.Find("GT-P3113", true) != -1 || - cModel.Find("GT-P5100", true) != -1 || - cModel.Find("GT-P5110", true) != -1 || - cModel.Find("GT-P5113", true) != -1 || - cModel.Find("XT890", true) != -1; - - if (isBlocklisted) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - else if (CompareVersions(mOSVersion.get(), "4.3.0") < 0) - { - // Blocklist all Sony devices - if (cManufacturer.Find("Sony", true) != -1) { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - } - - if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION) { - NS_LossyConvertUTF16toASCII cManufacturer(mManufacturer); - NS_LossyConvertUTF16toASCII cModel(mModel); - NS_LossyConvertUTF16toASCII cHardware(mHardware); - - if (cHardware.EqualsLiteral("hammerhead") && - CompareVersions(mOSVersion.get(), "4.4.2") >= 0 && - cManufacturer.Equals("lge", nsCaseInsensitiveCStringComparator()) && - cModel.Equals("nexus 5", nsCaseInsensitiveCStringComparator())) { - *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; - return NS_OK; - } else { - // Blocklist all other devices except Nexus 5 which VP8 hardware acceleration is supported - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - return NS_OK; - } - } - } - - return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os); -} - -#ifdef DEBUG - -// Implement nsIGfxInfoDebug - -/* void spoofVendorID (in DOMString aVendorID); */ -NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) -{ - EnsureInitialized(); - mGLStrings->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID)); - return NS_OK; -} - -/* void spoofDeviceID (in unsigned long aDeviceID); */ -NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) -{ - EnsureInitialized(); - mGLStrings->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID)); - return NS_OK; -} - -/* void spoofDriverVersion (in DOMString aDriverVersion); */ -NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) -{ - EnsureInitialized(); - mGLStrings->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion)); - return NS_OK; -} - -/* void spoofOSVersion (in unsigned long aVersion); */ -NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) -{ - EnsureInitialized(); - mOSVersion = aVersion; - return NS_OK; -} - -#endif - -nsString GfxInfo::Model() -{ - EnsureInitialized(); - return mModel; -} - -nsString GfxInfo::Hardware() -{ - EnsureInitialized(); - return mHardware; -} - -nsString GfxInfo::Product() -{ - EnsureInitialized(); - return mProduct; -} - -nsString GfxInfo::Manufacturer() -{ - EnsureInitialized(); - return mManufacturer; -} - -uint32_t GfxInfo::OperatingSystemVersion() -{ - EnsureInitialized(); - return mOSVersionInteger; -} - -} -} diff --git a/widget/android/GfxInfo.h b/widget/android/GfxInfo.h deleted file mode 100644 index 2e7bc5d089..0000000000 --- a/widget/android/GfxInfo.h +++ /dev/null @@ -1,102 +0,0 @@ -/* vim: se cin sw=2 ts=2 et : */ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __mozilla_widget_GfxInfo_h__ -#define __mozilla_widget_GfxInfo_h__ - -#include "GfxInfoBase.h" -#include "GfxDriverInfo.h" - -#include "nsString.h" -#include "mozilla/UniquePtr.h" - -namespace mozilla { - -namespace gl { -class GLContext; -} - -namespace widget { - -class GfxInfo : public GfxInfoBase -{ -private: - ~GfxInfo(); - -public: - GfxInfo(); - - // We only declare the subset of nsIGfxInfo that we actually implement. The - // rest is brought forward from GfxInfoBase. - NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled); - NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled); - NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion); - NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams); - NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate); - NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate); - NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active); - using GfxInfoBase::GetFeatureStatus; - using GfxInfoBase::GetFeatureSuggestedDriverVersion; - using GfxInfoBase::GetWebGLParameter; - - void EnsureInitialized(); - - virtual nsString Model(); - virtual nsString Hardware(); - virtual nsString Product(); - virtual nsString Manufacturer(); - -#ifdef DEBUG - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIGFXINFODEBUG -#endif - - virtual uint32_t OperatingSystemVersion() override; - -protected: - - virtual nsresult GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS = nullptr); - virtual const nsTArray& GetGfxDriverInfo(); - -private: - - bool mInitialized; - - class GLStrings; - UniquePtr mGLStrings; - - nsCString mAdapterDescription; - - OperatingSystem mOS; - - nsString mModel, mHardware, mManufacturer, mProduct; - nsCString mOSVersion; - uint32_t mOSVersionInteger; -}; - -} // namespace widget -} // namespace mozilla - -#endif /* __mozilla_widget_GfxInfo_h__ */ diff --git a/widget/android/NativeJSContainer.cpp b/widget/android/NativeJSContainer.cpp deleted file mode 100644 index 0ad47e7784..0000000000 --- a/widget/android/NativeJSContainer.cpp +++ /dev/null @@ -1,1011 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "NativeJSContainer.h" -#include "AndroidBridge.h" -#include "js/StructuredClone.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/Vector.h" -#include "prthread.h" -#include "nsJSUtils.h" - -using namespace mozilla; -using namespace mozilla::widget; - -namespace mozilla { -namespace widget { - -class NativeJSContainer -{ -public: - static void InitJNI(JNIEnv* env) { - if (jNativeJSContainer) { - return; - } - jNativeJSContainer = AndroidBridge::GetClassGlobalRef( - env, "org/mozilla/goanna/util/NativeJSContainer"); - MOZ_ASSERT(jNativeJSContainer); - jContainerNativeObject = AndroidBridge::GetFieldID( - env, jNativeJSContainer, "mNativeObject", "J"); - MOZ_ASSERT(jContainerNativeObject); - jContainerConstructor = AndroidBridge::GetMethodID( - env, jNativeJSContainer, "", "(J)V"); - MOZ_ASSERT(jContainerConstructor); - - jNativeJSObject = AndroidBridge::GetClassGlobalRef( - env, "org/mozilla/goanna/util/NativeJSObject"); - MOZ_ASSERT(jNativeJSObject); - jObjectContainer = AndroidBridge::GetFieldID( - env, jNativeJSObject, "mContainer", - "Lorg/mozilla/goanna/util/NativeJSContainer;"); - MOZ_ASSERT(jObjectContainer); - jObjectIndex = AndroidBridge::GetFieldID( - env, jNativeJSObject, "mObjectIndex", "I"); - MOZ_ASSERT(jObjectIndex); - jObjectConstructor = AndroidBridge::GetMethodID( - env, jNativeJSObject, "", - "(Lorg/mozilla/goanna/util/NativeJSContainer;I)V"); - MOZ_ASSERT(jContainerConstructor); - - jBundle = AndroidBridge::GetClassGlobalRef( - env, "android/os/Bundle"); - MOZ_ASSERT(jBundle); - jBundleConstructor = AndroidBridge::GetMethodID( - env, jBundle, "", "(I)V"); - MOZ_ASSERT(jBundleConstructor); - jBundlePutBoolean = AndroidBridge::GetMethodID( - env, jBundle, "putBoolean", - "(Ljava/lang/String;Z)V"); - MOZ_ASSERT(jBundlePutBoolean); - jBundlePutBundle = AndroidBridge::GetMethodID( - env, jBundle, "putBundle", - "(Ljava/lang/String;Landroid/os/Bundle;)V"); - MOZ_ASSERT(jBundlePutBundle); - jBundlePutDouble = AndroidBridge::GetMethodID( - env, jBundle, "putDouble", - "(Ljava/lang/String;D)V"); - MOZ_ASSERT(jBundlePutDouble); - jBundlePutInt = AndroidBridge::GetMethodID( - env, jBundle, "putInt", - "(Ljava/lang/String;I)V"); - MOZ_ASSERT(jBundlePutInt); - jBundlePutString = AndroidBridge::GetMethodID( - env, jBundle, "putString", - "(Ljava/lang/String;Ljava/lang/String;)V"); - MOZ_ASSERT(jBundlePutString); - jBundlePutBooleanArray = AndroidBridge::GetMethodID( - env, jBundle, "putBooleanArray", - "(Ljava/lang/String;[Z)V"); - MOZ_ASSERT(jBundlePutBooleanArray); - jBundlePutDoubleArray = AndroidBridge::GetMethodID( - env, jBundle, "putDoubleArray", - "(Ljava/lang/String;[D)V"); - MOZ_ASSERT(jBundlePutDoubleArray); - jBundlePutIntArray = AndroidBridge::GetMethodID( - env, jBundle, "putIntArray", - "(Ljava/lang/String;[I)V"); - MOZ_ASSERT(jBundlePutIntArray); - jBundlePutStringArray = AndroidBridge::GetMethodID( - env, jBundle, "putStringArray", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - MOZ_ASSERT(jBundlePutStringArray); - - jObject = AndroidBridge::GetClassGlobalRef( - env, "java/lang/Object"); - MOZ_ASSERT(jObject); - jString = AndroidBridge::GetClassGlobalRef( - env, "java/lang/String"); - MOZ_ASSERT(jString); - } - - static jobject CreateInstance(JNIEnv* env, JSContext* cx, - JS::HandleObject object) { - return CreateInstance(env, new NativeJSContainer(cx, object)); - } - - static NativeJSContainer* FromInstance(JNIEnv* env, jobject instance) { - MOZ_ASSERT(instance); - - const jlong fieldValue = - env->GetLongField(instance, jContainerNativeObject); - NativeJSContainer* const nativeObject = - reinterpret_cast( - static_cast(fieldValue)); - if (!nativeObject) { - AndroidBridge::ThrowException(env, - "java/lang/NullPointerException", - "Uninitialized NativeJSContainer"); - } - return nativeObject; - } - - static void DisposeInstance(JNIEnv* env, jobject instance) { - NativeJSContainer* const container = FromInstance(env, instance); - if (container) { - env->SetLongField(instance, jContainerNativeObject, - static_cast(reinterpret_cast(nullptr))); - delete container; - } - } - - static jobject CloneInstance(JNIEnv* env, jobject instance) { - NativeJSContainer* const container = FromInstance(env, instance); - if (!container || !container->EnsureObject(env)) { - return nullptr; - } - JSContext* const cx = container->mThreadContext; - JS::RootedObject object(cx, *container->mJSObject); - MOZ_ASSERT(object); - - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(cx, JS::RootedValue(cx, JS::ObjectValue(*object)))) { - AndroidBridge::ThrowException(env, - "java/lang/UnsupportedOperationException", - "Cannot serialize object"); - return nullptr; - } - return CreateInstance(env, new NativeJSContainer(cx, Move(buffer))); - } - - static jobject GetInstanceFromObject(JNIEnv* env, jobject object) { - MOZ_ASSERT(object); - - const jobject instance = env->GetObjectField(object, jObjectContainer); - MOZ_ASSERT(instance); - return instance; - } - - static JSContext* GetContextFromObject(JNIEnv* env, jobject object) { - MOZ_ASSERT(object); - AutoLocalJNIFrame frame(env, 1); - - NativeJSContainer* const container = - FromInstance(env, GetInstanceFromObject(env, object)); - if (!container) { - return nullptr; - } - return container->mThreadContext; - } - - static JSObject* GetObjectFromObject(JNIEnv* env, jobject object) { - MOZ_ASSERT(object); - AutoLocalJNIFrame frame(env, 1); - - NativeJSContainer* const container = - FromInstance(env, GetInstanceFromObject(env, object)); - if (!container || - !container->EnsureObject(env)) { // Do thread check - return nullptr; - } - const jint index = env->GetIntField(object, jObjectIndex); - if (index < 0) { - // -1 for index field means it's the root object of the container - return *container->mJSObject; - } - return *container->mRootedObjects[index]; - } - - static jobject CreateObjectInstance(JNIEnv* env, jobject object, - JSContext* cx, - JS::HandleObject jsObject) { - MOZ_ASSERT(object); - MOZ_ASSERT(jsObject); - AutoLocalJNIFrame frame(env, 2); - - jobject instance = GetInstanceFromObject(env, object); - NativeJSContainer* const container = FromInstance(env, instance); - if (!container) { - return nullptr; - } - size_t newIndex = container->mRootedObjects.length(); - PersistentObjectPtr rootedJSObject = - MakeUnique(cx, jsObject); - if (!container->mRootedObjects.append(Move(rootedJSObject))) { - AndroidBridge::ThrowException(env, - "java/lang/OutOfMemoryError", "Cannot allocate object"); - return nullptr; - } - const jobject newObject = - env->NewObject(jNativeJSObject, jObjectConstructor, - instance, newIndex); - MOZ_ASSERT(newObject); - return frame.Pop(newObject); - } - - // Make sure we have a JSObject and deserialize if necessary/possible - bool EnsureObject(JNIEnv* env) { - if (mJSObject) { - if (PR_GetCurrentThread() != mThread) { - AndroidBridge::ThrowException(env, - "java/lang/IllegalThreadStateException", - "Using NativeJSObject off its thread"); - return false; - } - return true; - } - if (!SwitchContextToCurrentThread()) { - AndroidBridge::ThrowException(env, - "java/lang/IllegalThreadStateException", - "Not available for this thread"); - return false; - } - - JS::RootedValue value(mThreadContext); - MOZ_ASSERT(mBuffer.data()); - MOZ_ALWAYS_TRUE(mBuffer.read(mThreadContext, &value)); - if (value.isObject()) { - mJSObject = MakeUnique(mThreadContext, &value.toObject()); - } - if (!mJSObject) { - AndroidBridge::ThrowException(env, - "java/lang/IllegalStateException", "Cannot deserialize data"); - return false; - } - mBuffer.clear(); - return true; - } - - static jclass jBundle; - static jclass jNativeJSContainer; - static jclass jNativeJSObject; - static jclass jObject; - static jclass jString; - - static jmethodID jBundleConstructor; - static jmethodID jBundlePutBoolean; - static jmethodID jBundlePutBundle; - static jmethodID jBundlePutDouble; - static jmethodID jBundlePutInt; - static jmethodID jBundlePutString; - static jmethodID jBundlePutBooleanArray; - static jmethodID jBundlePutDoubleArray; - static jmethodID jBundlePutIntArray; - static jmethodID jBundlePutStringArray; - -private: - static jfieldID jContainerNativeObject; - static jmethodID jContainerConstructor; - static jfieldID jObjectContainer; - static jfieldID jObjectIndex; - static jmethodID jObjectConstructor; - - static jobject CreateInstance(JNIEnv* env, - NativeJSContainer* nativeObject) { - InitJNI(env); - const jobject newObject = - env->NewObject(jNativeJSContainer, jContainerConstructor, - static_cast( - reinterpret_cast(nativeObject))); - AndroidBridge::HandleUncaughtException(env); - MOZ_ASSERT(newObject); - return newObject; - } - - typedef JS::PersistentRooted PersistentObject; - typedef UniquePtr PersistentObjectPtr; - - // Thread that the object is valid on - PRThread* mThread; - // Context that the object is valid in - JSContext* mThreadContext; - // Deserialized object, or nullptr if object is in serialized form - PersistentObjectPtr mJSObject; - // Serialized object, or empty if object is in deserialized form - JSAutoStructuredCloneBuffer mBuffer; - // Objects derived from mJSObject - Vector mRootedObjects; - - // Create a new container containing the given deserialized object - NativeJSContainer(JSContext* cx, JS::HandleObject object) - : mThread(PR_GetCurrentThread()) - , mThreadContext(cx) - , mJSObject(new PersistentObject(cx, object)) - { - } - - // Create a new container containing the given serialized object - NativeJSContainer(JSContext* cx, JSAutoStructuredCloneBuffer&& buffer) - : mThread(PR_GetCurrentThread()) - , mThreadContext(cx) - , mJSObject(nullptr) - , mBuffer(Forward(buffer)) - { - } - - bool SwitchContextToCurrentThread() { - PRThread* const currentThread = PR_GetCurrentThread(); - if (currentThread == mThread) { - return true; - } - return false; - } -}; - -jclass NativeJSContainer::jNativeJSContainer = 0; -jfieldID NativeJSContainer::jContainerNativeObject = 0; -jmethodID NativeJSContainer::jContainerConstructor = 0; -jclass NativeJSContainer::jNativeJSObject = 0; -jfieldID NativeJSContainer::jObjectContainer = 0; -jfieldID NativeJSContainer::jObjectIndex = 0; -jmethodID NativeJSContainer::jObjectConstructor = 0; -jclass NativeJSContainer::jBundle = 0; -jmethodID NativeJSContainer::jBundleConstructor = 0; -jmethodID NativeJSContainer::jBundlePutBoolean = 0; -jmethodID NativeJSContainer::jBundlePutBundle = 0; -jmethodID NativeJSContainer::jBundlePutDouble = 0; -jmethodID NativeJSContainer::jBundlePutInt = 0; -jmethodID NativeJSContainer::jBundlePutString = 0; -jmethodID NativeJSContainer::jBundlePutBooleanArray = 0; -jmethodID NativeJSContainer::jBundlePutDoubleArray = 0; -jmethodID NativeJSContainer::jBundlePutIntArray = 0; -jmethodID NativeJSContainer::jBundlePutStringArray = 0; -jclass NativeJSContainer::jString = 0; -jclass NativeJSContainer::jObject = 0; - -jobject -CreateNativeJSContainer(JNIEnv* env, JSContext* cx, JS::HandleObject object) -{ - return NativeJSContainer::CreateInstance(env, cx, object); -} - -} // namespace widget -} // namespace mozilla - -namespace { - -class JSJNIString -{ -public: - JSJNIString(JNIEnv* env, jstring str) - : mEnv(env) - , mJNIString(str) - , mJSString(!str ? nullptr : - reinterpret_cast(env->GetStringChars(str, nullptr))) - { - } - ~JSJNIString() { - if (mJNIString) { - mEnv->ReleaseStringChars(mJNIString, - reinterpret_cast(mJSString)); - } - } - operator const char16_t*() const { - return mJSString; - } - size_t Length() const { - return static_cast(mEnv->GetStringLength(mJNIString)); - } -private: - JNIEnv* const mEnv; - const jstring mJNIString; - const char16_t* const mJSString; -}; - -bool -CheckJSCall(JNIEnv* env, bool result) -{ - if (!result) { - AndroidBridge::ThrowException(env, - "java/lang/UnsupportedOperationException", "JSAPI call failed"); - } - return result; -} - -bool -CheckJNIArgument(JNIEnv* env, jobject arg) -{ - if (!arg) { - AndroidBridge::ThrowException(env, - "java/lang/IllegalArgumentException", "Null argument"); - return false; - } - return true; -} - -template bool -CheckProperty(JNIEnv* env, JSContext* cx, JS::HandleValue val) { - if (!(*InValue)(cx, val)) { - AndroidBridge::ThrowException(env, - "org/mozilla/goanna/util/NativeJSObject$InvalidPropertyException", - "Property type mismatch"); - return false; - } - return true; -} - -bool -AppendJSON(const char16_t* buf, uint32_t len, void* data) -{ - static_cast(data)->Append(buf, len); - return true; -} - -template -struct PrimitiveProperty -{ - typedef U Type; // JNI type - typedef UA ArrayType; // JNI array type - typedef V NativeType; // JSAPI type - - static bool InValue(JSContext* cx, JS::HandleValue val) { - return (static_cast(val).*IsMethod)(); - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, JS::HandleValue val) { - return static_cast( - (static_cast(val).*ToMethod)()); - } - - static ArrayType NewArray(JNIEnv* env, jobject instance, JSContext* cx, - JS::HandleObject array, size_t length) { - UniquePtr buffer = MakeUnique(length); - for (size_t i = 0; i < length; i++) { - JS::RootedValue elem(cx); - if (!CheckJSCall(env, JS_GetElement(cx, array, i, &elem)) || - !CheckProperty(env, cx, elem)) { - return nullptr; - } - buffer[i] = FromValue(env, instance, cx, elem); - } - AutoLocalJNIFrame frame(env, 1); - ArrayType jarray = (env->*NewArrayMethod)(length); - if (!jarray) { - return nullptr; - } - (env->*SetArrayRegionMethod)(jarray, 0, length, buffer.get()); - if (env->ExceptionCheck()) { - return nullptr; - } - return frame.Pop(jarray); - } -}; - -// Statically cast from bool to jboolean (unsigned char); it works -// since false and JNI_FALSE have the same value (0), and true and -// JNI_TRUE have the same value (1). -typedef PrimitiveProperty BooleanProperty; - -typedef PrimitiveProperty DoubleProperty; - -typedef PrimitiveProperty IntProperty; - -struct StringProperty -{ - typedef jstring Type; - - static jclass Class() { - return NativeJSContainer::jString; - } - - static bool InValue(JSContext* cx, JS::HandleValue val) { - return val.isString(); - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, JS::HandleValue val) { - const JS::RootedString str(cx, val.toString()); - return FromValue(env, instance, cx, str); - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, const JS::HandleString str) { - nsAutoJSString autoStr; - if (!CheckJSCall(env, autoStr.init(cx, str))) { - return nullptr; - } - jstring ret = env->NewString( - reinterpret_cast(autoStr.BeginReading()), - autoStr.Length()); - MOZ_ASSERT(ret); - return ret; - } -}; - -template -struct BaseObjectProperty -{ - typedef jobject Type; - - static jclass Class() { - return C; - } - - static bool InValue(JSContext* cx, JS::HandleValue val) { - return val.isObjectOrNull(); - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, JS::HandleValue val) { - if (val.isNull()) { - return nullptr; - } - JS::RootedObject object(cx, &val.toObject()); - return FactoryMethod(env, instance, cx, object); - } -}; - -jobject GetBundle(JNIEnv*, jobject, JSContext*, JS::HandleObject); - -// Returns a NativeJSObject from a JSObject -typedef BaseObjectProperty ObjectProperty; - -// Returns a Bundle from a JSObject -typedef BaseObjectProperty BundleProperty; - -template -struct ObjectArrayWrapper : public BaseProperty -{ - typedef jobjectArray ArrayType; - - static ArrayType NewArray(JNIEnv* env, jobject instance, JSContext* cx, - JS::HandleObject array, size_t length) { - AutoLocalJNIFrame frame(env, 2); - ArrayType jarray = env->NewObjectArray( - length, BaseProperty::Class(), nullptr); - if (!jarray) { - return nullptr; - } - for (size_t i = 0; i < length; i++) { - JS::RootedValue elem(cx); - if (!CheckJSCall(env, JS_GetElement(cx, array, i, &elem)) || - !CheckProperty(env, cx, elem)) { - return nullptr; - } - typename BaseProperty::Type jelem = - BaseProperty::FromValue(env, instance, cx, elem); - if (env->ExceptionCheck()) { - return nullptr; - } - env->SetObjectArrayElement(jarray, i, jelem); - env->DeleteLocalRef(jelem); - if (env->ExceptionCheck()) { - return nullptr; - } - } - return frame.Pop(jarray); - } -}; - -template -struct ArrayProperty -{ - typedef T Base; - typedef typename T::ArrayType Type; - - static bool InValue(JSContext* cx, JS::HandleValue val) { - if (!val.isObject()) { - return false; - } - JS::RootedObject obj(cx, &val.toObject()); - uint32_t length = 0; - if (!JS_IsArrayObject(cx, obj) || - !JS_GetArrayLength(cx, obj, &length)) { - return false; - } - if (!length) { - // Empty arrays are always okay. - return true; - } - // We only check to see the first element is the target type. If the - // array has mixed types, we'll throw an error during actual conversion. - JS::RootedValue element(cx); - return JS_GetElement(cx, obj, 0, &element) && - Base::InValue(cx, element); - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, JS::HandleValue val) { - JS::RootedObject obj(cx, &val.toObject()); - uint32_t length = 0; - if (!CheckJSCall(env, JS_GetArrayLength(cx, obj, &length))) { - return nullptr; - } - return Base::NewArray(env, instance, cx, obj, length); - } -}; - -typedef ArrayProperty BooleanArrayProperty; -typedef ArrayProperty DoubleArrayProperty; -typedef ArrayProperty IntArrayProperty; -typedef ArrayProperty> StringArrayProperty; -typedef ArrayProperty> ObjectArrayProperty; -typedef ArrayProperty> BundleArrayProperty; - -struct HasProperty -{ - typedef jboolean Type; - - static bool InValue(JSContext* cx, JS::HandleValue val) { - return true; - } - - static Type FromValue(JNIEnv* env, jobject instance, - JSContext* cx, JS::HandleValue val) { - return JNI_TRUE; - } -}; - -enum class FallbackOption { - THROW, - RETURN, -}; - -template -typename Property::Type -GetProperty(JNIEnv* env, jobject instance, jstring name, - FallbackOption option = FallbackOption::THROW, - typename Property::Type fallback = typename Property::Type()) -{ - MOZ_ASSERT(env); - MOZ_ASSERT(instance); - - JSContext* const cx = - NativeJSContainer::GetContextFromObject(env, instance); - if (!cx) { - return typename Property::Type(); - } - - const JS::RootedObject object(cx, - NativeJSContainer::GetObjectFromObject(env, instance)); - const JSJNIString strName(env, name); - JS::RootedValue val(cx); - - if (!object || - !CheckJNIArgument(env, name) || - !CheckJSCall(env, - JS_GetUCProperty(cx, object, strName, strName.Length(), &val))) { - return typename Property::Type(); - } - if (val.isUndefined() || val.isNull()) { - if (option == FallbackOption::THROW) { - AndroidBridge::ThrowException(env, - "org/mozilla/goanna/util/NativeJSObject$InvalidPropertyException", - "Property does not exist"); - } - return fallback; - } - if (!CheckProperty(env, cx, val)) { - return fallback; - } - return Property::FromValue(env, instance, cx, val); -} - -jobject -GetBundle(JNIEnv* env, jobject instance, JSContext* cx, JS::HandleObject obj) -{ - AutoLocalJNIFrame frame(env, 1); - - const JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj)); - if (!CheckJSCall(env, !!ids)) { - return nullptr; - } - - const size_t length = ids.length(); - const jobject newBundle = env->NewObject( - NativeJSContainer::jBundle, - NativeJSContainer::jBundleConstructor, - static_cast(length)); - if (!newBundle) { - return nullptr; - } - - for (size_t i = 0; i < ids.length(); i++) { - AutoLocalJNIFrame loopFrame(env, 2); - - const JS::RootedId id(cx, ids[i]); - JS::RootedValue idVal(cx); - if (!CheckJSCall(env, JS_IdToValue(cx, id, &idVal))) { - return nullptr; - } - - const JS::RootedString idStr(cx, JS::ToString(cx, idVal)); - if (!CheckJSCall(env, !!idStr)) { - return nullptr; - } - - const jstring name = - StringProperty::FromValue(env, instance, cx, idStr); - JS::RootedValue val(cx); - if (!name || - !CheckJSCall(env, JS_GetPropertyById(cx, obj, id, &val))) { - return nullptr; - } - -#define PUT_IN_BUNDLE_IF_TYPE_IS(TYPE) \ - if (TYPE##Property::InValue(cx, val)) { \ - const TYPE##Property::Type jval = \ - TYPE##Property::FromValue(env, instance, cx, val); \ - if (env->ExceptionCheck()) { \ - return nullptr; \ - } \ - env->CallVoidMethod(newBundle, \ - NativeJSContainer::jBundlePut##TYPE, name, jval); \ - if (env->ExceptionCheck()) { \ - return nullptr; \ - } \ - continue; \ - } \ - ((void) 0) // Accommodate trailing semicolon. - - // Scalar values are faster to check, so check them first. - PUT_IN_BUNDLE_IF_TYPE_IS(Boolean); - // Int can be casted to double, so check int first. - PUT_IN_BUNDLE_IF_TYPE_IS(Int); - PUT_IN_BUNDLE_IF_TYPE_IS(Double); - PUT_IN_BUNDLE_IF_TYPE_IS(String); - // There's no "putObject", so don't check ObjectProperty - - // Check for array types if scalar checks all failed. - PUT_IN_BUNDLE_IF_TYPE_IS(BooleanArray); - // XXX because we only check the first element of an array, - // a double array can potentially be seen as an int array. - PUT_IN_BUNDLE_IF_TYPE_IS(IntArray); - PUT_IN_BUNDLE_IF_TYPE_IS(DoubleArray); - PUT_IN_BUNDLE_IF_TYPE_IS(StringArray); - // There's no "putObjectArray", so don't check ObjectArrayProperty - // There's no "putBundleArray", so don't check BundleArrayProperty - - // Use Bundle as the default catch-all for objects - PUT_IN_BUNDLE_IF_TYPE_IS(Bundle); - -#undef PUT_IN_BUNDLE_IF_TYPE_IS - - // We tried all supported types; just bail. - AndroidBridge::ThrowException(env, - "java/lang/UnsupportedOperationException", - "Unsupported property type"); - return nullptr; - } - return frame.Pop(newBundle); -} - -} // namespace - -extern "C" { - -NS_EXPORT void JNICALL -Java_org_mozilla_goanna_util_NativeJSContainer_dispose(JNIEnv* env, jobject instance) -{ - MOZ_ASSERT(env); - NativeJSContainer::DisposeInstance(env, instance); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSContainer_clone(JNIEnv* env, jobject instance) -{ - MOZ_ASSERT(env); - return NativeJSContainer::CloneInstance(env, instance); -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getBoolean(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optBoolean(JNIEnv* env, jobject instance, - jstring name, jboolean fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jbooleanArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getBooleanArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jbooleanArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optBooleanArray( - JNIEnv* env, jobject instance, jstring name, jbooleanArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getBundle(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optBundle(JNIEnv* env, jobject instance, - jstring name, jobject fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getBundleArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optBundleArray( - JNIEnv* env, jobject instance, jstring name, jobjectArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jdouble JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getDouble(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jdouble JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optDouble(JNIEnv* env, jobject instance, - jstring name, jdouble fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jdoubleArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getDoubleArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jdoubleArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optDoubleArray( - JNIEnv* env, jobject instance, jstring name, jdoubleArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jint JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getInt(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jint JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optInt(JNIEnv* env, jobject instance, - jstring name, jint fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jintArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getIntArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jintArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optIntArray( - JNIEnv* env, jobject instance, jstring name, jintArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getObject(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optObject(JNIEnv* env, jobject instance, - jstring name, jobject fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getObjectArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optObjectArray( - JNIEnv* env, jobject instance, jstring name, jobjectArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jstring JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getString(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jstring JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optString(JNIEnv* env, jobject instance, - jstring name, jstring fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_getStringArray( - JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name); -} - -NS_EXPORT jobjectArray JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_optStringArray( - JNIEnv* env, jobject instance, jstring name, jobjectArray fallback) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, fallback); -} - -NS_EXPORT jboolean JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_has(JNIEnv* env, jobject instance, jstring name) -{ - return GetProperty(env, instance, name, FallbackOption::RETURN, JNI_FALSE); -} - -NS_EXPORT jobject JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_toBundle(JNIEnv* env, jobject instance) -{ - MOZ_ASSERT(env); - MOZ_ASSERT(instance); - - JSContext* const cx = NativeJSContainer::GetContextFromObject(env, instance); - if (!cx) { - return nullptr; - } - - const JS::RootedObject object(cx, NativeJSContainer::GetObjectFromObject(env, instance)); - if (!object) { - return nullptr; - } - return GetBundle(env, instance, cx, object); -} - -NS_EXPORT jstring JNICALL -Java_org_mozilla_goanna_util_NativeJSObject_toString(JNIEnv* env, jobject instance) -{ - MOZ_ASSERT(env); - MOZ_ASSERT(instance); - - JSContext* const cx = NativeJSContainer::GetContextFromObject(env, instance); - if (!cx) { - return nullptr; - } - - const JS::RootedObject object(cx, NativeJSContainer::GetObjectFromObject(env, instance)); - JS::RootedValue value(cx, JS::ObjectValue(*object)); - nsAutoString json; - - if (!object || - !CheckJSCall(env, - JS_Stringify(cx, &value, JS::NullPtr(), JS::NullHandleValue, AppendJSON, &json))) { - return nullptr; - } - jstring ret = env->NewString(reinterpret_cast(json.get()), json.Length()); - MOZ_ASSERT(ret); - return ret; -} - -} // extern "C" diff --git a/widget/android/NativeJSContainer.h b/widget/android/NativeJSContainer.h deleted file mode 100644 index b6ac86d1c4..0000000000 --- a/widget/android/NativeJSContainer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef NativeJSObject_h__ -#define NativeJSObject_h__ - -#include -#include "jsapi.h" - -namespace mozilla { -namespace widget { - -jobject CreateNativeJSContainer(JNIEnv* env, JSContext* cx, JS::HandleObject object); - -} // namespace widget -} // namespace mozilla - -#endif // NativeJSObject_h__ - diff --git a/widget/android/android/StrongPointer.h b/widget/android/android/StrongPointer.h deleted file mode 100644 index ca79fdfa4d..0000000000 --- a/widget/android/android/StrongPointer.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2005 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/************************************************************************* - * - * WARNING: EVERYTHING HERE IS NEUTERED - * - * The only reason we need this is to be able to call - * android_SurfaceTexture_getNativeWindow, which returns a - * android::sp. Therefore, we need the definition of - * android::sp (below) in order to get the pointer out. All of the actual - * ref management stuff is commented out by Mozilla. Do not try to use this - * for anything real. - */ - -#ifndef ANDROID_STRONG_POINTER_H -#define ANDROID_STRONG_POINTER_H - -#include -#include -#include - -// --------------------------------------------------------------------------- -namespace android { - -class TextOutput; -TextOutput& printStrongPointer(TextOutput& to, const void* val); - -template class wp; - -// --------------------------------------------------------------------------- - -#define COMPARE(_op_) \ -inline bool operator _op_ (const sp& o) const { \ - return m_ptr _op_ o.m_ptr; \ -} \ -inline bool operator _op_ (const T* o) const { \ - return m_ptr _op_ o; \ -} \ -template \ -inline bool operator _op_ (const sp& o) const { \ - return m_ptr _op_ o.m_ptr; \ -} \ -template \ -inline bool operator _op_ (const U* o) const { \ - return m_ptr _op_ o; \ -} \ -inline bool operator _op_ (const wp& o) const { \ - return m_ptr _op_ o.m_ptr; \ -} \ -template \ -inline bool operator _op_ (const wp& o) const { \ - return m_ptr _op_ o.m_ptr; \ -} - -// --------------------------------------------------------------------------- - -template -class sp -{ -public: - inline sp() : m_ptr(0) { } - - sp(T* other); - sp(const sp& other); - template sp(U* other); - template sp(const sp& other); - - ~sp(); - - // Assignment - - sp& operator = (T* other); - sp& operator = (const sp& other); - - template sp& operator = (const sp& other); - template sp& operator = (U* other); - - //! Special optimization for use by ProcessState (and nobody else). - void force_set(T* other); - - // Reset - - void clear(); - - // Accessors - - inline T& operator* () const { return *m_ptr; } - inline T* operator-> () const { return m_ptr; } - inline T* get() const { return m_ptr; } - - // Operators - - COMPARE(==) - COMPARE(!=) - COMPARE(>) - COMPARE(<) - COMPARE(<=) - COMPARE(>=) - -private: - template friend class sp; - template friend class wp; - void set_pointer(T* ptr); - T* m_ptr; -}; - -#undef COMPARE - -template -TextOutput& operator<<(TextOutput& to, const sp& val); - -// --------------------------------------------------------------------------- -// No user serviceable parts below here. - -template -sp::sp(T* other) -: m_ptr(other) - { - //if (other) other->incStrong(this); - } - -template -sp::sp(const sp& other) -: m_ptr(other.m_ptr) - { - //if (m_ptr) m_ptr->incStrong(this); - } - -template template -sp::sp(U* other) : m_ptr(other) -{ - //if (other) ((T*)other)->incStrong(this); -} - -template template -sp::sp(const sp& other) -: m_ptr(other.m_ptr) - { - //if (m_ptr) m_ptr->incStrong(this); - } - -template -sp::~sp() -{ - //if (m_ptr) m_ptr->decStrong(this); -} - -template -sp& sp::operator = (const sp& other) { - T* otherPtr(other.m_ptr); - /* - if (otherPtr) otherPtr->incStrong(this); - if (m_ptr) m_ptr->decStrong(this); - */ - m_ptr = otherPtr; - return *this; -} - -template -sp& sp::operator = (T* other) -{ - /* - if (other) other->incStrong(this); - if (m_ptr) m_ptr->decStrong(this); - */ - m_ptr = other; - return *this; -} - -template template -sp& sp::operator = (const sp& other) -{ - T* otherPtr(other.m_ptr); - /* - if (otherPtr) otherPtr->incStrong(this); - if (m_ptr) m_ptr->decStrong(this); - */ - m_ptr = otherPtr; - return *this; -} - -template template -sp& sp::operator = (U* other) -{ - /* - if (other) ((T*)other)->incStrong(this); - if (m_ptr) m_ptr->decStrong(this); - */ - m_ptr = other; - return *this; -} - -template -void sp::force_set(T* other) -{ - //other->forceIncStrong(this); - m_ptr = other; -} - -template -void sp::clear() -{ - if (m_ptr) { - m_ptr->decStrong(this); - m_ptr = 0; - } -} - -template -void sp::set_pointer(T* ptr) { - m_ptr = ptr; -} - -template -inline TextOutput& operator<<(TextOutput& to, const sp& val) -{ - return printStrongPointer(to, val.get()); -} - -}; // namespace android - -// --------------------------------------------------------------------------- - -#endif // ANDROID_STRONG_POINTER_H diff --git a/widget/android/bindings/Makefile.in b/widget/android/bindings/Makefile.in deleted file mode 100644 index 0fe53addf7..0000000000 --- a/widget/android/bindings/Makefile.in +++ /dev/null @@ -1,32 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# Bug 1099345 - The SDK's lint code (used by the code generator) does not enjoy -# concurrent access to a cache that it generates. -.NOTPARALLEL: - -annotation_processor_jar_files := $(DEPTH)/build/annotationProcessors/annotationProcessors.jar:$(ANDROID_TOOLS)/lib/lint.jar:$(ANDROID_TOOLS)/lib/lint-checks.jar - -sdk_processor := \ - $(JAVA) \ - -Dcom.android.tools.lint.bindir='$(ANDROID_TOOLS)' \ - -classpath $(annotation_processor_jar_files) \ - org.mozilla.goanna.annotationProcessors.SDKProcessor - -# For the benefit of readers: the following pattern rule says that, -# for example, MediaCodec.cpp and MediaCodec.h can be produced from -# MediaCodec-classes.txt. This formulation invokes the SDK processor -# at most once. - -%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt - $(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16 - -# We'd like these to be defined in a future GENERATED_EXPORTS list. -bindings_exports_FILES := \ - MediaCodec.h \ - SurfaceTexture.h \ - $(NULL) -bindings_exports_DEST = $(DIST)/include -bindings_exports_TARGET := export -INSTALL_TARGETS += bindings_exports diff --git a/widget/android/bindings/MediaCodec-classes.txt b/widget/android/bindings/MediaCodec-classes.txt deleted file mode 100644 index d8fb3420d3..0000000000 --- a/widget/android/bindings/MediaCodec-classes.txt +++ /dev/null @@ -1,3 +0,0 @@ -android.media.MediaCodec -android.media.MediaCodec$BufferInfo -android.media.MediaFormat diff --git a/widget/android/bindings/SurfaceTexture-classes.txt b/widget/android/bindings/SurfaceTexture-classes.txt deleted file mode 100644 index 5c7ca89688..0000000000 --- a/widget/android/bindings/SurfaceTexture-classes.txt +++ /dev/null @@ -1,2 +0,0 @@ -android.graphics.SurfaceTexture -android.view.Surface diff --git a/widget/android/bindings/moz.build b/widget/android/bindings/moz.build deleted file mode 100644 index 977aa2b4c7..0000000000 --- a/widget/android/bindings/moz.build +++ /dev/null @@ -1,35 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# List of stems to generate .cpp and .h files for. To add a stem, add it to -# this list and ensure that $(stem)-classes.txt exists in this directory. -generated = [ - 'MediaCodec', - 'SurfaceTexture', -] - -GENERATED_SOURCES += [stem + '.cpp' for stem in generated] - -# We'd like to add these to a future GENERATED_EXPORTS list, but for now we mark -# them as generated here and manually install them in Makefile.in. -GENERATED_FILES += [stem + '.h' for stem in generated] - -# There is an unfortunate race condition when using GENERATED_SOURCES and -# pattern rules (see Makefile.in) that manifests itself as a VPATH resolution -# conflict: MediaCodec.o looks for MediaCodec.cpp and $(CURDIR)/MediaCodec.cpp, -# and the pattern rule is matched but doesn't resolve both sources, causing a -# failure. Adding the GENERATED_SOURCES to GENERATED_FILES causes the sources -# to be built at export time, which is before MediaCodec.o needs them; and by -# the time MediaCodec.o is built, the source is in place and the VPATH -# resolution works as expected. -GENERATED_FILES += GENERATED_SOURCES - -FAIL_ON_WARNINGS = True -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/widget/android', -] diff --git a/widget/android/jni/Accessors.h b/widget/android/jni/Accessors.h deleted file mode 100644 index c38c47199f..0000000000 --- a/widget/android/jni/Accessors.h +++ /dev/null @@ -1,287 +0,0 @@ -#ifndef mozilla_jni_Accessors_h__ -#define mozilla_jni_Accessors_h__ - -#include - -#include "mozilla/Attributes.h" -#include "mozilla/jni/Refs.h" -#include "mozilla/jni/Types.h" -#include "AndroidBridge.h" - -namespace mozilla { -namespace jni{ - -namespace { - -// Helper class to convert an arbitrary type to a jvalue, e.g. Value(123).val. -struct Value -{ - Value(jboolean z) { val.z = z; } - Value(jbyte b) { val.b = b; } - Value(jchar c) { val.c = c; } - Value(jshort s) { val.s = s; } - Value(jint i) { val.i = i; } - Value(jlong j) { val.j = j; } - Value(jfloat f) { val.f = f; } - Value(jdouble d) { val.d = d; } - Value(jobject l) { val.l = l; } - - jvalue val; -}; - -} - -// Base class for Method<>, Field<>, and Constructor<>. -class Accessor { -private: - template - static void EnsureClassRef(JNIEnv* env) - { - if (!Cls::sClassRef) { - MOZ_ALWAYS_TRUE(Cls::sClassRef = - AndroidBridge::GetClassGlobalRef(env, Cls::name)); - } - } - - static void GetNsresult(JNIEnv* env, nsresult* rv) - { - if (env->ExceptionCheck()) { - env->ExceptionClear(); - *rv = NS_ERROR_FAILURE; - } else { - *rv = NS_OK; - } - } - -protected: - // Called before making a JNIEnv call. - template - static JNIEnv* BeginAccess() - { - JNIEnv* const env = Traits::isMultithreaded - ? GetJNIForThread() : AndroidBridge::GetJNIEnv(); - - EnsureClassRef(env); - return env; - } - - // Called after making a JNIEnv call. - template - static void EndAccess(JNIEnv* env, nsresult* rv) - { - if (Traits::exceptionMode == ExceptionMode::ABORT) { - return HandleUncaughtException(env); - - } else if (Traits::exceptionMode == ExceptionMode::NSRESULT) { - return GetNsresult(env, rv); - } - } -}; - - -// Member<> is used to call a JNI method given a traits class. -template -class Method : public Accessor -{ - typedef Accessor Base; - typedef class Traits::Owner Owner; - -protected: - static jmethodID sID; - - static JNIEnv* BeginAccess() - { - JNIEnv* const env = Base::BeginAccess(); - - if (sID) { - return env; - } - - if (Traits::isStatic) { - MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticMethodID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); - } else { - MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetMethodID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); - } - return env; - } - - static void EndAccess(JNIEnv* env, nsresult* rv) - { - return Base::EndAccess(env, rv); - } - -public: - template - static ReturnType Call(const Owner* cls, nsresult* rv, const Args&... args) - { - JNIEnv* const env = BeginAccess(); - - jvalue jargs[] = { - Value(TypeAdapter::FromNative(env, args)).val ... - }; - - auto result = TypeAdapter::ToNative(env, - Traits::isStatic ? - (env->*TypeAdapter::StaticCall)( - Owner::sClassRef, sID, jargs) : - (env->*TypeAdapter::Call)( - cls->mInstance, sID, jargs)); - - EndAccess(env, rv); - return result; - } -}; - -// Define sID member. -template jmethodID Method::sID; - - -// Specialize void because C++ forbids us from -// using a "void" temporary result variable. -template -class Method : public Method -{ - typedef Method Base; - typedef typename Traits::Owner Owner; - -public: - template - static void Call(const Owner* cls, nsresult* rv, - const Args&... args) override - { - JNIEnv* const env = Base::BeginAccess(); - - jvalue jargs[] = { - Value(TypeAdapter::FromNative(env, args)).val ... - }; - - if (Traits::isStatic) { - env->CallStaticVoidMethodA(Owner::sClassRef, Base::sID, jargs); - } else { - env->CallVoidMethodA(cls->mInstance, Base::sID, jargs); - } - - Base::EndAccess(env, rv); - } -}; - - -// Constructor<> is used to construct a JNI instance given a traits class. -template -class Constructor : protected Method { - typedef class Traits::Owner Owner; - typedef typename Traits::ReturnType ReturnType; - typedef Method Base; - -public: - template - static ReturnType Call(const Owner* cls, nsresult* rv, - const Args&... args) override - { - JNIEnv* const env = Base::BeginAccess(); - - jvalue jargs[] = { - Value(TypeAdapter::FromNative(env, args)).val ... - }; - - auto result = TypeAdapter::ToNative( - env, env->NewObjectA(Owner::sClassRef, Base::sID, jargs)); - - Base::EndAccess(env, rv); - return result; - } -}; - - -// Field<> is used to access a JNI field given a traits class. -template -class Field : public Accessor -{ - typedef Accessor Base; - typedef class Traits::Owner Owner; - typedef typename Traits::ReturnType GetterType; - typedef typename Traits::SetterType SetterType; - - template struct RemoveRef { typedef T Type; }; - template struct RemoveRef { typedef T Type; }; - - // Setter type without any const/& added - typedef typename RemoveRef::Type SetterBaseType; - -private: - - static jfieldID sID; - - static JNIEnv* BeginAccess() - { - JNIEnv* const env = Base::BeginAccess(); - - if (sID) { - return env; - } - - if (Traits::isStatic) { - MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticFieldID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); - } else { - MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetFieldID( - env, Traits::Owner::sClassRef, Traits::name, Traits::signature)); - } - return env; - } - - static void EndAccess(JNIEnv* env, nsresult* rv) - { - return Base::EndAccess(env, rv); - } - -public: - static GetterType Get(const Owner* cls, nsresult* rv) - { - JNIEnv* const env = BeginAccess(); - - auto result = TypeAdapter::ToNative( - env, Traits::isStatic ? - - (env->*TypeAdapter::StaticGet) - (Owner::sClassRef, sID) : - - (env->*TypeAdapter::Get) - (cls->mInstance, sID)); - - EndAccess(env, rv); - return result; - } - - static void Set(const Owner* cls, nsresult* rv, SetterType val) - { - JNIEnv* const env = BeginAccess(); - - if (Traits::isStatic) { - (env->*TypeAdapter::StaticSet)( - Owner::sClassRef, sID, - TypeAdapter::FromNative(env, val)); - } else { - (env->*TypeAdapter::Set)( - cls->mInstance, sID, - TypeAdapter::FromNative(env, val)); - } - - EndAccess(env, rv); - } -}; - -// Define sID member. -template jfieldID Field::sID; - - -// Define the sClassRef member declared in Refs.h and -// used by Method and Field above. -template jclass Class::sClassRef; - -} // namespace jni -} // namespace mozilla - -#endif // mozilla_jni_Accessors_h__ diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h deleted file mode 100644 index 6198f74308..0000000000 --- a/widget/android/jni/Refs.h +++ /dev/null @@ -1,644 +0,0 @@ -#ifndef mozilla_jni_Refs_h__ -#define mozilla_jni_Refs_h__ - -#include - -#include "mozilla/Move.h" -#include "mozilla/jni/Utils.h" - -#include "nsError.h" // for nsresult -#include "nsString.h" - -namespace mozilla { -namespace jni { - -class Accessor; -template class Constructor; -template class Field; -template class Method; - -// Wrapped object reference (e.g. jobject, jclass, etc...) -template class Ref; -// Wrapped local reference that inherits from Ref. -template class LocalRef; -// Wrapped global reference that inherits from Ref. -template class GlobalRef; - -// Type used for a reference parameter. Default is a wrapped object -// reference, but Param can be specialized to define custom behavior, -// e.g. a StringParam class that automatically converts nsAString& and -// nsACString& to a jstring. -template struct Param { typedef Ref Type; }; - - -// How exception during a JNI call should be treated. -enum class ExceptionMode -{ - // Abort on unhandled excepion (default). - ABORT, - // Ignore the exception and return to caller. - IGNORE, - // Catch any exception and return a nsresult. - NSRESULT, -}; - - -// Base class for all JNI binding classes. -// Templated so that we have one sClassRef for each class. -template -class Class -{ - friend class Accessor; - template friend class Constructor; - template friend class Field; - template friend class Method; - -private: - static jclass sClassRef; // global reference - -protected: - jobject mInstance; // local or global reference - - Class(jobject instance) : mInstance(instance) {} -}; - - -// Binding for a plain jobject. -class Object : public Class -{ -protected: - Object(jobject instance) : Class(instance) {} - -public: - typedef jni::Ref Ref; - typedef jni::LocalRef LocalRef; - typedef jni::GlobalRef GlobalRef; - typedef const typename jni::Param::Type& Param; -}; - - -// Binding for a built-in object reference other than jobject. -template -class TypedObject : public Object -{ - typedef TypedObject Self; - -protected: - TypedObject(jobject instance) : Object(instance) {} - -public: - typedef jni::Ref Ref; - typedef jni::LocalRef LocalRef; - typedef jni::GlobalRef GlobalRef; - typedef const typename jni::Param::Type& Param; -}; - -// Define bindings for built-in types. -typedef TypedObject String; -typedef TypedObject ClassObject; -typedef TypedObject Throwable; - -typedef TypedObject BooleanArray; -typedef TypedObject ByteArray; -typedef TypedObject CharArray; -typedef TypedObject ShortArray; -typedef TypedObject IntArray; -typedef TypedObject LongArray; -typedef TypedObject FloatArray; -typedef TypedObject DoubleArray; -typedef TypedObject ObjectArray; - -template<> struct Param { class Type; }; - - -// Base class for Ref and its specializations. -template -class RefBase : protected Cls -{ - typedef RefBase Self; - typedef void (Self::*bool_type)() const; - void non_null_reference() const {} - -protected: - RefBase(jobject instance) : Cls(instance) {} - -public: - // Construct a Ref form a raw JNI reference. - static Ref From(JNIType obj) - { - return Ref(static_cast(obj)); - } - - // Get the raw JNI reference. - JNIType Get() const - { - return static_cast(Cls::mInstance); - } - - bool operator==(const RefBase& other) const - { - // Treat two references of the same object as being the same. - return Cls::mInstance == other.mInstance && - GetJNIForThread()->IsSameObject( - Cls::mInstance, other.mInstance) != JNI_FALSE; - } - - bool operator!=(const RefBase& other) const - { - return !operator==(other); - } - - bool operator==(decltype(nullptr)) const - { - return !Cls::mInstance; - } - - bool operator!=(decltype(nullptr)) const - { - return !!Cls::mInstance; - } - - Cls* operator->() - { - MOZ_ASSERT(Cls::mInstance); - return this; - } - - const Cls* operator->() const - { - MOZ_ASSERT(Cls::mInstance); - return this; - } - - // Any ref can be cast to an object ref. - operator Ref() const; - - // Null checking (e.g. !!ref) using the safe-bool idiom. - operator bool_type() const - { - return Cls::mInstance ? &Self::non_null_reference : nullptr; - } - - // We don't allow implicit conversion to jobject because that can lead - // to easy mistakes such as assigning a temporary LocalRef to a jobject, - // and using the jobject after the LocalRef has been freed. - - // We don't allow explicit conversion, to make outside code use Ref::Get. - // Using Ref::Get makes it very easy to see which code is using raw JNI - // types to make future refactoring easier. - - // operator JNIType() const = delete; -}; - - -// Wrapped object reference (e.g. jobject, jclass, etc...) -template -class Ref : public RefBase -{ - template friend class RefBase; - friend class jni::LocalRef; - friend class jni::GlobalRef; - - typedef RefBase Base; - -protected: - // Protected jobject constructor because outside code should be using - // Ref::From. Using Ref::From makes it very easy to see which code is using - // raw JNI types for future refactoring. - Ref(jobject instance) : Base(instance) {} - - // Protected copy constructor so that there's no danger of assigning a - // temporary LocalRef/GlobalRef to a Ref, and potentially use the Ref - // after the source had been freed. - Ref(const Ref& ref) : Base(ref.mInstance) {} - -public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} -}; - - -template -RefBase::operator Ref() const -{ - return Ref(Cls::mInstance); -} - - -template -class Ref> - : public RefBase, T> -{ - friend class RefBase, T>; - friend class jni::LocalRef>; - friend class jni::GlobalRef>; - - typedef RefBase, T> Base; - -protected: - Ref(jobject instance) : Base(instance) {} - - Ref(const Ref& ref) : Base(ref.mInstance) {} - -public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} -}; - - -namespace { - -// See explanation in LocalRef. -template struct GenericObject { typedef Object Type; }; -template<> struct GenericObject { typedef struct {} Type; }; - -} // namespace - -template -class LocalRef : public Ref -{ - template friend class LocalRef; - -private: - // In order to be able to convert LocalRef to LocalRef, we - // need constructors and copy assignment operators that take in a - // LocalRef argument. However, if Cls *is* Object, we would have - // duplicated constructors and operators with LocalRef arguments. To - // avoid this conflict, we use GenericObject, which is defined as Object for - // LocalRef and defined as a dummy class for LocalRef. - typedef typename GenericObject::Type GenericObject; - - JNIEnv* const mEnv; - - LocalRef(JNIEnv* env, jobject instance) - : Ref(instance) - , mEnv(env) - {} - - LocalRef& swap(LocalRef& other) - { - auto instance = other.mInstance; - other.mInstance = Ref::mInstance; - Ref::mInstance = instance; - return *this; - } - -public: - // Construct a LocalRef from a raw JNI local reference. Unlike Ref::From, - // LocalRef::Adopt returns a LocalRef that will delete the local reference - // when going out of scope. - static LocalRef Adopt(jobject instance) - { - return LocalRef(GetJNIForThread(), instance); - } - - static LocalRef Adopt(JNIEnv* env, jobject instance) - { - return LocalRef(env, instance); - } - - // Copy constructor. - LocalRef(const LocalRef& ref) - : Ref(ref.mEnv->NewLocalRef(ref.mInstance)) - , mEnv(ref.mEnv) - {} - - // Move constructor. - LocalRef(LocalRef&& ref) - : Ref(ref.mInstance) - , mEnv(ref.mEnv) - { - ref.mInstance = nullptr; - } - - explicit LocalRef(JNIEnv* env = GetJNIForThread()) - : Ref(nullptr) - , mEnv(env) - {} - - // Construct a LocalRef from any Ref, - // which means creating a new local reference. - MOZ_IMPLICIT LocalRef(const Ref& ref) - : Ref(nullptr) - , mEnv(GetJNIForThread()) - { - Ref::mInstance = mEnv->NewLocalRef(ref.mInstance); - } - - // Move a LocalRef into a LocalRef without - // creating/deleting local references. - MOZ_IMPLICIT LocalRef(LocalRef&& ref) - : Ref(ref.mInstance) - , mEnv(ref.mEnv) - { - ref.mInstance = nullptr; - } - - // Implicitly converts nullptr to LocalRef. - MOZ_IMPLICIT LocalRef(decltype(nullptr)) - : Ref(nullptr) - , mEnv(GetJNIForThread()) - {} - - ~LocalRef() - { - if (Ref::mInstance) { - mEnv->DeleteLocalRef(Ref::mInstance); - Ref::mInstance = nullptr; - } - } - - // Get the JNIEnv* associated with this local reference. - JNIEnv* Env() const - { - return mEnv; - } - - // Get the raw JNI reference that can be used as a return value. - // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. - auto Forget() -> decltype(Ref(nullptr).Get()) - { - const auto obj = Ref::Get(); - Ref::mInstance = nullptr; - return obj; - } - - LocalRef& operator=(LocalRef ref) - { - return swap(ref); - } - - LocalRef& operator=(const Ref& ref) - { - LocalRef newRef(mEnv, ref.mInstance); - return swap(newRef); - } - - LocalRef& operator=(LocalRef&& ref) - { - LocalRef newRef(mozilla::Forward>(ref)); - return swap(newRef); - } - - LocalRef& operator=(decltype(nullptr)) - { - LocalRef newRef(mEnv, nullptr); - return swap(newRef); - } -}; - - -template -class GlobalRef : public Ref -{ -private: - static jobject NewGlobalRef(JNIEnv* env, jobject instance) - { - if (!instance) { - return nullptr; - } - if (!env) { - env = GetJNIForThread(); - } - return env->NewGlobalRef(instance); - } - - GlobalRef& swap(GlobalRef& other) - { - auto instance = other.mInstance; - other.mInstance = Ref::mInstance; - Ref::mInstance = instance; - return *this; - } - -public: - GlobalRef() - : Ref(nullptr) - {} - - // Copy constructor - GlobalRef(const GlobalRef& ref) - : Ref(ref.mInstance) - {} - - // Move constructor - GlobalRef(GlobalRef&& ref) - : Ref(ref.mInstance) - { - ref.mInstance = nullptr; - } - - MOZ_IMPLICIT GlobalRef(const Ref& ref) - : Ref(NewGlobalRef(nullptr, ref.mInstance)) - {} - - GlobalRef(JNIEnv* env, const Ref& ref) - : Ref(NewGlobalRef(env, ref.mInstance)) - {} - - // Implicitly converts nullptr to GlobalRef. - MOZ_IMPLICIT GlobalRef(decltype(nullptr)) - : Ref(nullptr) - {} - - ~GlobalRef() - { - if (Ref::mInstance) { - JNIEnv* const env = GetJNIForThread(); - env->DeleteGlobalRef(Ref::mInstance); - Ref::mInstance = nullptr; - } - } - - // Get the raw JNI reference that can be used as a return value. - // Returns the same JNI type (jobject, jstring, etc.) as the underlying Ref. - auto Forget() -> decltype(Ref(nullptr).Get()) - { - const auto obj = Ref::Get(); - Ref::mInstance = nullptr; - return obj; - } - - GlobalRef& operator=(GlobalRef ref) - { - return swap(ref); - } - - GlobalRef& operator=(const Ref& ref) - { - GlobalRef newRef(ref); - return swap(newRef); - } - - GlobalRef& operator=(decltype(nullptr)) - { - GlobalRef newRef(nullptr); - return swap(newRef); - } -}; - - -// Ref specialization for jstring. -template<> -class Ref : public RefBase -{ - friend class RefBase; - friend class jni::LocalRef; - friend class jni::GlobalRef; - - typedef RefBase, jstring> Base; - -protected: - Ref(jobject instance) : Base(instance) {} - - Ref(const Ref& ref) : Base(ref.mInstance) {} - -public: - MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} - - // Get the length of the jstring. - size_t Length() const - { - JNIEnv* const env = GetJNIForThread(); - return env->GetStringLength(Get()); - } - - // Convert jstring to a nsString. - operator nsString() const - { - MOZ_ASSERT(Object::mInstance); - - JNIEnv* const env = GetJNIForThread(); - const jchar* const str = env->GetStringChars(Get(), nullptr); - const jsize len = env->GetStringLength(Get()); - - nsString result(reinterpret_cast(str), len); - env->ReleaseStringChars(Get(), str); - return result; - } - - // Convert jstring to a nsCString. - operator nsCString() const - { - return NS_ConvertUTF16toUTF8(operator nsString()); - } -}; - - -// Define a custom parameter type for String, -// which accepts both String::Ref and nsAString/nsACString -class Param::Type : public Ref -{ -private: - // Not null if we should delete ref on destruction. - JNIEnv* const mEnv; - - static jstring GetString(JNIEnv* env, const nsAString& str) - { - const jstring result = env->NewString( - reinterpret_cast(str.BeginReading()), - str.Length()); - HandleUncaughtException(env); - return result; - } - -public: - MOZ_IMPLICIT Type(const String::Ref& ref) - : Ref(ref.Get()) - , mEnv(nullptr) - {} - - MOZ_IMPLICIT Type(const nsAString& str, JNIEnv* env = GetJNIForThread()) - : Ref(GetString(env, str)) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const char16_t* str, JNIEnv* env = GetJNIForThread()) - : Ref(GetString(env, nsDependentString(str))) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const nsACString& str, JNIEnv* env = GetJNIForThread()) - : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) - , mEnv(env) - {} - - MOZ_IMPLICIT Type(const char* str, JNIEnv* env = GetJNIForThread()) - : Ref(GetString(env, NS_ConvertUTF8toUTF16(str))) - , mEnv(env) - {} - - ~Type() - { - if (mEnv) { - mEnv->DeleteLocalRef(Get()); - } - } -}; - - -// Support conversion from LocalRef* to LocalRef*: -// LocalRef foo; -// Foo::GetFoo(&foo); // error because parameter type is LocalRef*. -// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. -template -class ReturnToLocal -{ -private: - LocalRef* const localRef; - LocalRef objRef; - -public: - explicit ReturnToLocal(LocalRef* ref) : localRef(ref) {} - operator LocalRef*() { return &objRef; } - - ~ReturnToLocal() - { - if (objRef) { - *localRef = mozilla::Move(objRef); - } - } -}; - -template -ReturnToLocal ReturnTo(LocalRef* ref) -{ - return ReturnToLocal(ref); -} - - -// Support conversion from GlobalRef* to LocalRef*: -// GlobalRef foo; -// Foo::GetFoo(&foo); // error because parameter type is LocalRef*. -// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument. -template -class ReturnToGlobal -{ -private: - GlobalRef* const globalRef; - LocalRef objRef; - LocalRef clsRef; - -public: - explicit ReturnToGlobal(GlobalRef* ref) : globalRef(ref) {} - operator LocalRef*() { return &objRef; } - operator LocalRef*() { return &clsRef; } - - ~ReturnToGlobal() - { - if (objRef) { - *globalRef = (clsRef = mozilla::Move(objRef)); - } else if (clsRef) { - *globalRef = clsRef; - } - } -}; - -template -ReturnToGlobal ReturnTo(GlobalRef* ref) -{ - return ReturnToGlobal(ref); -} - -} // namespace jni -} // namespace mozilla - -#endif // mozilla_jni_Refs_h__ diff --git a/widget/android/jni/Types.h b/widget/android/jni/Types.h deleted file mode 100644 index 10b990878b..0000000000 --- a/widget/android/jni/Types.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef mozilla_jni_Types_h__ -#define mozilla_jni_Types_h__ - -#include - -#include "mozilla/jni/Refs.h" -#include "AndroidBridge.h" - -namespace mozilla { -namespace jni { -namespace { - -// TypeAdapter specializations are the interfaces between naive (C++) types such -// as int32_t and JNI types such as jint. The template parameter T is the native -// type, and each TypeAdapter specialization can have the following members: -// -// * Call: JNIEnv member pointer for making a method call that returns T. -// * StaticCall: JNIEnv member pointer for making a static call that returns T. -// * Get: JNIEnv member pointer for getting a field of type T. -// * StaticGet: JNIEnv member pointer for getting a static field of type T. -// * Set: JNIEnv member pointer for setting a field of type T. -// * StaticGet: JNIEnv member pointer for setting a static field of type T. -// * ToNative: static function that converts the JNI type to the native type. -// * FromNative: static function that converts the native type to the JNI type. - -template struct TypeAdapter; - - -// TypeAdapter> applies when jobject is a return value. -template struct TypeAdapter> { - static constexpr auto Call = &JNIEnv::CallObjectMethodA; - static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA; - static constexpr auto Get = &JNIEnv::GetObjectField; - static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField; - - static LocalRef ToNative(JNIEnv* env, jobject instance) { - return LocalRef::Adopt(env, instance); - } -}; - -template constexpr jobject - (JNIEnv::*TypeAdapter>::Call)(jobject, jmethodID, jvalue*); -template constexpr jobject - (JNIEnv::*TypeAdapter>::StaticCall)(jclass, jmethodID, jvalue*); -template constexpr jobject - (JNIEnv::*TypeAdapter>::Get)(jobject, jfieldID); -template constexpr jobject - (JNIEnv::*TypeAdapter>::StaticGet)(jclass, jfieldID); - - -// TypeAdapter> applies when jobject is a parameter value. -template struct TypeAdapter> { - static constexpr auto Set = &JNIEnv::SetObjectField; - static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField; - - static jobject FromNative(JNIEnv*, const Ref& instance) { - return instance.Get(); - } -}; - -template constexpr void - (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID, jobject); -template constexpr void - (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID, jobject); - - -// jstring has its own Param type. -template<> struct TypeAdapter::Type> - : public TypeAdapter -{}; - - -#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \ - \ - template<> struct TypeAdapter { \ - static constexpr auto Call = &JNIEnv::Call ## JNIName ## MethodA; \ - static constexpr auto StaticCall = &JNIEnv::CallStatic ## JNIName ## MethodA; \ - static constexpr auto Get = &JNIEnv::Get ## JNIName ## Field; \ - static constexpr auto StaticGet = &JNIEnv::GetStatic ## JNIName ## Field; \ - static constexpr auto Set = &JNIEnv::Set ## JNIName ## Field; \ - static constexpr auto StaticSet = &JNIEnv::SetStatic ## JNIName ## Field; \ - \ - static JNIType FromNative(JNIEnv*, NativeType val) { \ - return static_cast(val); \ - } \ - static NativeType ToNative(JNIEnv*, JNIType val) { \ - return static_cast(val); \ - } \ - }; \ - \ - constexpr JNIType (JNIEnv::*TypeAdapter::Call) \ - (jobject, jmethodID, jvalue*); \ - constexpr JNIType (JNIEnv::*TypeAdapter::StaticCall) \ - (jclass, jmethodID, jvalue*); \ - constexpr JNIType (JNIEnv::*TypeAdapter::Get) \ - (jobject, jfieldID); \ - constexpr JNIType (JNIEnv::*TypeAdapter::StaticGet) \ - (jclass, jfieldID); \ - constexpr void (JNIEnv::*TypeAdapter::Set) \ - (jobject, jfieldID, JNIType); \ - constexpr void (JNIEnv::*TypeAdapter::StaticSet) \ - (jclass, jfieldID, JNIType) - - -DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte); -DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int); -DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long); -DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float); -DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double); - -#undef DEFINE_PRIMITIVE_TYPE_ADAPTER - -} // namespace -} // namespace jni -} // namespace mozilla - -#endif // mozilla_jni_Types_h__ diff --git a/widget/android/jni/Utils.cpp b/widget/android/jni/Utils.cpp deleted file mode 100644 index 51b4d27d88..0000000000 --- a/widget/android/jni/Utils.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "Utils.h" - -#include "mozilla/Assertions.h" - -#include "GeneratedJNIWrappers.h" -#include "Refs.h" - -namespace mozilla { -namespace jni { - -bool ThrowException(JNIEnv *aEnv, const char *aClass, - const char *aMessage) -{ - MOZ_ASSERT(aEnv, "Invalid thread JNI env"); - - ClassObject::LocalRef cls = - ClassObject::LocalRef::Adopt(aEnv->FindClass(aClass)); - MOZ_ASSERT(cls, "Cannot find exception class"); - - return !aEnv->ThrowNew(cls.Get(), aMessage); -} - -void HandleUncaughtException(JNIEnv *aEnv) -{ - MOZ_ASSERT(aEnv, "Invalid thread JNI env"); - - if (!aEnv->ExceptionCheck()) { - return; - } - - Throwable::LocalRef e = - Throwable::LocalRef::Adopt(aEnv->ExceptionOccurred()); - MOZ_ASSERT(e); - - aEnv->ExceptionClear(); - widget::GoannaAppShell::HandleUncaughtException(nullptr, e); - - // Should be dead by now... - MOZ_CRASH("Failed to handle uncaught exception"); -} - -} // jni -} // mozilla diff --git a/widget/android/jni/Utils.h b/widget/android/jni/Utils.h deleted file mode 100644 index d80b296454..0000000000 --- a/widget/android/jni/Utils.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef mozilla_jni_Utils_h__ -#define mozilla_jni_Utils_h__ - -#include - -#include "mozilla/Types.h" - -/* See the comment in AndroidBridge about this function before using it */ -extern "C" MOZ_EXPORT JNIEnv * GetJNIForThread(); - -namespace mozilla { -namespace jni { - -bool ThrowException(JNIEnv *aEnv, const char *aClass, - const char *aMessage); - -inline bool ThrowException(JNIEnv *aEnv, const char *aMessage) -{ - return ThrowException(aEnv, "java/lang/Exception", aMessage); -} - -void HandleUncaughtException(JNIEnv *aEnv); - -} // jni -} // mozilla - -#endif // mozilla_jni_Utils_h__ diff --git a/widget/android/jni/moz.build b/widget/android/jni/moz.build deleted file mode 100644 index db4145df5d..0000000000 --- a/widget/android/jni/moz.build +++ /dev/null @@ -1,24 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -EXPORTS.mozilla.jni += [ - 'Accessors.h', - 'Refs.h', - 'Types.h', - 'Utils.h', -] - -SOURCES += [ - 'Utils.cpp', -] - -FAIL_ON_WARNINGS = True - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/widget/android', -] diff --git a/widget/android/moz.build b/widget/android/moz.build deleted file mode 100644 index 11602047ad..0000000000 --- a/widget/android/moz.build +++ /dev/null @@ -1,65 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -DIRS += [ - 'bindings', - 'jni', -] - -XPIDL_SOURCES += [ - 'nsIAndroidBridge.idl', -] - -XPIDL_MODULE = 'widget_android' - -EXPORTS += [ - 'AndroidBridge.h', - 'AndroidJavaWrappers.h', - 'AndroidJNIWrapper.h', - 'GeneratedJNIWrappers.h', -] - -SOURCES += [ - 'AndroidBridge.cpp', - 'AndroidDirectTexture.cpp', - 'AndroidGraphicBuffer.cpp', - 'AndroidJavaWrappers.cpp', - 'AndroidJNI.cpp', - 'AndroidJNIWrapper.cpp', - 'APZCCallbackHandler.cpp', - 'GeneratedJNIWrappers.cpp', - 'GfxInfo.cpp', - 'NativeJSContainer.cpp', - 'nsAndroidProtocolHandler.cpp', - 'nsAppShell.cpp', - 'nsClipboard.cpp', - 'nsDeviceContextAndroid.cpp', - 'nsIdleServiceAndroid.cpp', - 'nsIMEPicker.cpp', - 'nsLookAndFeel.cpp', - 'nsPrintOptionsAndroid.cpp', - 'nsScreenManagerAndroid.cpp', - 'nsWidgetFactory.cpp', - 'nsWindow.cpp', -] - -FAIL_ON_WARNINGS = True - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/docshell/base', - '/dom/base', - '/dom/system/android', - '/netwerk/base', - '/netwerk/cache', - '/widget', - '/widget/android/android', -] - -#DEFINES['DEBUG_WIDGETS'] = True diff --git a/widget/android/nsAndroidProtocolHandler.cpp b/widget/android/nsAndroidProtocolHandler.cpp deleted file mode 100644 index e0c307fb41..0000000000 --- a/widget/android/nsAndroidProtocolHandler.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:set ts=4 sw=4 sts=4 et cin: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsAndroidProtocolHandler.h" -#include "nsCOMPtr.h" -#include "nsIChannel.h" -#include "nsIIOService.h" -#include "nsNetUtil.h" -#include "android/log.h" -#include "nsBaseChannel.h" -#include "AndroidBridge.h" -#include "GeneratedJNIWrappers.h" - -using namespace mozilla; - -class AndroidInputStream : public nsIInputStream -{ -public: - AndroidInputStream(jni::Object::Param connection) { - mBridgeInputStream = widget::GoannaAppShell::CreateInputStream(connection); - mBridgeChannel = AndroidBridge::ChannelCreate(mBridgeInputStream); - } - -private: - virtual ~AndroidInputStream() { - } - -public: - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIINPUTSTREAM - -private: - jni::Object::GlobalRef mBridgeInputStream; - jni::Object::GlobalRef mBridgeChannel; -}; - -NS_IMPL_ISUPPORTS(AndroidInputStream, nsIInputStream) - -NS_IMETHODIMP AndroidInputStream::Close(void) { - AndroidBridge::InputStreamClose(mBridgeInputStream); - return NS_OK; -} - -NS_IMETHODIMP AndroidInputStream::Available(uint64_t *_retval) { - *_retval = AndroidBridge::InputStreamAvailable(mBridgeInputStream); - return NS_OK; -} - -NS_IMETHODIMP AndroidInputStream::Read(char *aBuf, uint32_t aCount, uint32_t *_retval) { - return AndroidBridge::InputStreamRead(mBridgeChannel, aBuf, aCount, _retval); -} - -NS_IMETHODIMP AndroidInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) { - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP AndroidInputStream::IsNonBlocking(bool *_retval) { - *_retval = false; - return NS_OK; -} - - -class AndroidChannel : public nsBaseChannel -{ -private: - AndroidChannel(nsIURI *aURI, jni::Object::Param aConnection) { - mConnection = aConnection; - mURI = aURI; - - auto type = widget::GoannaAppShell::ConnectionGetMimeType(mConnection); - if (type) { - SetContentType(nsCString(type)); - } - } - -public: - static AndroidChannel* CreateChannel(nsIURI *aURI) { - nsCString spec; - aURI->GetSpec(spec); - - auto connection = widget::GoannaAppShell::GetConnection(spec); - return connection ? new AndroidChannel(aURI, connection) : nullptr; - } - - virtual ~AndroidChannel() { - } - - virtual nsresult OpenContentStream(bool async, nsIInputStream **result, - nsIChannel** channel) { - nsCOMPtr stream = new AndroidInputStream(mConnection); - NS_ADDREF(*result = stream); - return NS_OK; - } - -private: - jni::Object::GlobalRef mConnection; -}; - -NS_IMPL_ISUPPORTS(nsAndroidProtocolHandler, - nsIProtocolHandler, - nsISupportsWeakReference) - - -NS_IMETHODIMP -nsAndroidProtocolHandler::GetScheme(nsACString &result) -{ - result.AssignLiteral("android"); - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::GetDefaultPort(int32_t *result) -{ - *result = -1; // no port for android: URLs - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval) -{ - // don't override anything. - *_retval = false; - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::GetProtocolFlags(uint32_t *result) -{ - *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE | URI_NORELATIVE | URI_DANGEROUS_TO_LOAD; - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::NewURI(const nsACString &aSpec, - const char *aCharset, - nsIURI *aBaseURI, - nsIURI **result) -{ - nsresult rv; - - nsCOMPtr surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr url(do_QueryInterface(surl, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - surl->SetMutable(false); - - NS_ADDREF(*result = url); - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::NewChannel2(nsIURI* aURI, - nsILoadInfo* aLoadInfo, - nsIChannel** aResult) -{ - nsCOMPtr channel = AndroidChannel::CreateChannel(aURI); - if (!channel) - return NS_ERROR_FAILURE; - - // set the loadInfo on the new channel - nsresult rv = channel->SetLoadInfo(aLoadInfo); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ADDREF(*aResult = channel); - return NS_OK; -} - -NS_IMETHODIMP -nsAndroidProtocolHandler::NewChannel(nsIURI* aURI, - nsIChannel* *aResult) -{ - return NewChannel2(aURI, nullptr, aResult); -} diff --git a/widget/android/nsAndroidProtocolHandler.h b/widget/android/nsAndroidProtocolHandler.h deleted file mode 100644 index 11705dd0a5..0000000000 --- a/widget/android/nsAndroidProtocolHandler.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsAndroidProtocolHandler_h___ -#define nsAndroidProtocolHandler_h___ - -#include "nsIProtocolHandler.h" -#include "nsWeakReference.h" -#include "mozilla/Attributes.h" - -#define NS_ANDROIDPROTOCOLHANDLER_CID \ -{ /* e9cd2b7f-8386-441b-aaf5-0b371846bfd0 */ \ - 0xe9cd2b7f, \ - 0x8386, \ - 0x441b, \ - {0x0b, 0x37, 0x18, 0x46, 0xbf, 0xd0} \ -} - -class nsAndroidProtocolHandler final : public nsIProtocolHandler, - public nsSupportsWeakReference -{ -public: - NS_DECL_THREADSAFE_ISUPPORTS - - // nsIProtocolHandler methods: - NS_DECL_NSIPROTOCOLHANDLER - - // nsAndroidProtocolHandler methods: - nsAndroidProtocolHandler() {} - -private: - ~nsAndroidProtocolHandler() {} -}; - -#endif /* nsAndroidProtocolHandler_h___ */ diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp deleted file mode 100644 index 395dd0f5f9..0000000000 --- a/widget/android/nsAppShell.cpp +++ /dev/null @@ -1,848 +0,0 @@ -/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsAppShell.h" - -#include "base/basictypes.h" -#include "base/message_loop.h" -#include "base/task.h" -#include "mozilla/Hal.h" -#include "nsIScreen.h" -#include "nsIScreenManager.h" -#include "nsWindow.h" -#include "nsThreadUtils.h" -#include "nsICommandLineRunner.h" -#include "nsIObserverService.h" -#include "nsIAppStartup.h" -#include "nsIGeolocationProvider.h" -#include "nsCacheService.h" -#include "nsIDOMEventListener.h" -#include "nsIDOMClientRectList.h" -#include "nsIDOMClientRect.h" -#include "nsIDOMWakeLockListener.h" -#include "nsIPowerManagerService.h" -#include "nsINetworkLinkService.h" -#include "nsCategoryManagerUtils.h" - -#include "mozilla/BackgroundHangMonitor.h" -#include "mozilla/Services.h" -#include "mozilla/unused.h" -#include "mozilla/Preferences.h" -#include "mozilla/Hal.h" -#include "prenv.h" - -#include "AndroidBridge.h" -#include "AndroidBridgeUtilities.h" -#include -#include -#include - -#include "mozilla/dom/ScreenOrientation.h" -#ifdef MOZ_GAMEPAD -#include "mozilla/dom/GamepadService.h" -#endif - -#include "GeckoProfiler.h" -#ifdef MOZ_ANDROID_HISTORY -#include "nsNetUtil.h" -#include "IHistory.h" -#endif - -#ifdef MOZ_LOGGING -#include "prlog.h" -#endif - -#ifdef DEBUG_ANDROID_EVENTS -#define EVLOG(args...) ALOG(args) -#else -#define EVLOG(args...) do { } while (0) -#endif - -using namespace mozilla; - -#ifdef PR_LOGGING -PRLogModuleInfo *gWidgetLog = nullptr; -#endif - -nsIGeolocationUpdate *gLocationCallback = nullptr; -nsAutoPtr gLastSizeChange; - -nsAppShell *nsAppShell::gAppShell = nullptr; - -NS_IMPL_ISUPPORTS_INHERITED(nsAppShell, nsBaseAppShell, nsIObserver) - -class ThumbnailRunnable : public nsRunnable { -public: - ThumbnailRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, - const nsTArray& aPoints, RefCountedJavaObject* aBuffer): - mBrowserApp(aBrowserApp), mPoints(aPoints), mTabId(aTabId), mBuffer(aBuffer) {} - - virtual nsresult Run() { - const auto& buffer = jni::Object::Ref::From(mBuffer->GetObject()); - nsCOMPtr domWindow; - nsCOMPtr tab; - mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab)); - if (!tab) { - widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false); - return NS_ERROR_FAILURE; - } - - tab->GetWindow(getter_AddRefs(domWindow)); - if (!domWindow) { - widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false); - return NS_ERROR_FAILURE; - } - - NS_ASSERTION(mPoints.Length() == 1, "Thumbnail event does not have enough coordinates"); - - bool shouldStore = true; - nsresult rv = AndroidBridge::Bridge()->CaptureThumbnail(domWindow, mPoints[0].x, mPoints[0].y, mTabId, buffer, shouldStore); - widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv), shouldStore); - return rv; - } -private: - nsCOMPtr mBrowserApp; - nsTArray mPoints; - int mTabId; - nsRefPtr mBuffer; -}; - -class WakeLockListener final : public nsIDOMMozWakeLockListener { -private: - ~WakeLockListener() {} - -public: - NS_DECL_ISUPPORTS; - - nsresult Callback(const nsAString& topic, const nsAString& state) { - widget::GoannaAppShell::NotifyWakeLockChanged(topic, state); - return NS_OK; - } -}; - -NS_IMPL_ISUPPORTS(WakeLockListener, nsIDOMMozWakeLockListener) -nsCOMPtr sPowerManagerService = nullptr; -StaticRefPtr sWakeLockListener; - -nsAppShell::nsAppShell() - : mQueueLock("nsAppShell.mQueueLock"), - mCondLock("nsAppShell.mCondLock"), - mQueueCond(mCondLock, "nsAppShell.mQueueCond"), - mQueuedViewportEvent(nullptr) -{ - gAppShell = this; - - if (XRE_GetProcessType() != GeckoProcessType_Default) { - return; - } - - sPowerManagerService = do_GetService(POWERMANAGERSERVICE_CONTRACTID); - - if (sPowerManagerService) { - sWakeLockListener = new WakeLockListener(); - } else { - NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!"); - } - -} - -nsAppShell::~nsAppShell() -{ - gAppShell = nullptr; - - if (sPowerManagerService) { - sPowerManagerService->RemoveWakeLockListener(sWakeLockListener); - - sPowerManagerService = nullptr; - sWakeLockListener = nullptr; - } -} - -void -nsAppShell::NotifyNativeEvent() -{ - MutexAutoLock lock(mCondLock); - mQueueCond.Notify(); -} - -#define PREFNAME_COALESCE_TOUCHES "dom.event.touch.coalescing.enabled" -static const char* kObservedPrefs[] = { - PREFNAME_COALESCE_TOUCHES, - nullptr -}; - -nsresult -nsAppShell::Init() -{ -#ifdef PR_LOGGING - if (!gWidgetLog) - gWidgetLog = PR_NewLogModule("Widget"); -#endif - - nsresult rv = nsBaseAppShell::Init(); - nsCOMPtr obsServ = - mozilla::services::GetObserverService(); - if (obsServ) { - obsServ->AddObserver(this, "xpcom-shutdown", false); - obsServ->AddObserver(this, "browser-delayed-startup-finished", false); - } - - if (sPowerManagerService) - sPowerManagerService->AddWakeLockListener(sWakeLockListener); - - Preferences::AddStrongObservers(this, kObservedPrefs); - mAllowCoalescingTouches = Preferences::GetBool(PREFNAME_COALESCE_TOUCHES, true); - return rv; -} - -NS_IMETHODIMP -nsAppShell::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - if (!strcmp(aTopic, "xpcom-shutdown")) { - // We need to ensure no observers stick around after XPCOM shuts down - // or we'll see crashes, as the app shell outlives XPConnect. - mObserversHash.Clear(); - return nsBaseAppShell::Observe(aSubject, aTopic, aData); - } else if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) && - aData && - nsDependentString(aData).Equals(NS_LITERAL_STRING(PREFNAME_COALESCE_TOUCHES))) { - mAllowCoalescingTouches = Preferences::GetBool(PREFNAME_COALESCE_TOUCHES, true); - return NS_OK; - } else if (!strcmp(aTopic, "browser-delayed-startup-finished")) { - NS_CreateServicesFromCategory("browser-delayed-startup-finished", nullptr, - "browser-delayed-startup-finished"); - } - return NS_OK; -} - -void -nsAppShell::ScheduleNativeEventCallback() -{ - EVLOG("nsAppShell::ScheduleNativeEventCallback pth: %p thread: %p main: %d", (void*) pthread_self(), (void*) NS_GetCurrentThread(), NS_IsMainThread()); - - // this is valid to be called from any thread, so do so. - PostEvent(AndroidGoannaEvent::MakeNativePoke()); -} - -bool -nsAppShell::ProcessNextNativeEvent(bool mayWait) -{ - EVLOG("nsAppShell::ProcessNextNativeEvent %d", mayWait); - - PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent", - js::ProfileEntry::Category::EVENTS); - - nsAutoPtr curEvent; - { - MutexAutoLock lock(mCondLock); - - curEvent = PopNextEvent(); - if (!curEvent && mayWait) { - PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait", - js::ProfileEntry::Category::EVENTS); - - // hmm, should we really hardcode this 10s? -#if defined(DEBUG_ANDROID_EVENTS) - PRTime t0, t1; - EVLOG("nsAppShell: waiting on mQueueCond"); - t0 = PR_Now(); - mQueueCond.Wait(PR_MillisecondsToInterval(10000)); - t1 = PR_Now(); - EVLOG("nsAppShell: wait done, waited %d ms", (int)(t1-t0)/1000); -#else - mQueueCond.Wait(); -#endif - - curEvent = PopNextEvent(); - } - } - - if (!curEvent) - return false; - - mozilla::BackgroundHangMonitor().NotifyActivity(); - - EVLOG("nsAppShell: event %p %d", (void*)curEvent.get(), curEvent->Type()); - - switch (curEvent->Type()) { - case AndroidGoannaEvent::NATIVE_POKE: - NativeEventCallback(); - break; - - case AndroidGoannaEvent::SENSOR_EVENT: { - InfallibleTArray values; - mozilla::hal::SensorType type = (mozilla::hal::SensorType) curEvent->Flags(); - - switch (type) { - // Bug 938035, transfer HAL data for orientation sensor to meet w3c - // spec, ex: HAL report alpha=90 means East but alpha=90 means West - // in w3c spec - case hal::SENSOR_ORIENTATION: - values.AppendElement(360 -curEvent->X()); - values.AppendElement(-curEvent->Y()); - values.AppendElement(-curEvent->Z()); - break; - case hal::SENSOR_LINEAR_ACCELERATION: - case hal::SENSOR_ACCELERATION: - case hal::SENSOR_GYROSCOPE: - case hal::SENSOR_PROXIMITY: - values.AppendElement(curEvent->X()); - values.AppendElement(curEvent->Y()); - values.AppendElement(curEvent->Z()); - break; - - case hal::SENSOR_LIGHT: - values.AppendElement(curEvent->X()); - break; - - default: - __android_log_print(ANDROID_LOG_ERROR, - "Goanna", "### SENSOR_EVENT fired, but type wasn't known %d", - type); - } - - const hal::SensorAccuracyType &accuracy = (hal::SensorAccuracyType) curEvent->MetaState(); - hal::SensorData sdata(type, PR_Now(), values, accuracy); - hal::NotifySensorChange(sdata); - } - break; - - case AndroidGoannaEvent::PROCESS_OBJECT: { - - switch (curEvent->Action()) { - case AndroidGoannaEvent::ACTION_OBJECT_LAYER_CLIENT: - AndroidBridge::Bridge()->SetLayerClient( - widget::GoannaLayerClient::Ref::From(curEvent->Object().wrappedObject())); - break; - } - break; - } - - case AndroidGoannaEvent::LOCATION_EVENT: { - if (!gLocationCallback) - break; - - nsGeoPosition* p = curEvent->GeoPosition(); - if (p) - gLocationCallback->Update(curEvent->GeoPosition()); - else - NS_WARNING("Received location event without geoposition!"); - break; - } - - case AndroidGoannaEvent::APP_BACKGROUNDING: { - nsCOMPtr obsServ = - mozilla::services::GetObserverService(); - obsServ->NotifyObservers(nullptr, "application-background", nullptr); - - NS_NAMED_LITERAL_STRING(minimize, "heap-minimize"); - obsServ->NotifyObservers(nullptr, "memory-pressure", minimize.get()); - - // If we are OOM killed with the disk cache enabled, the entire - // cache will be cleared (bug 105843), so shut down the cache here - // and re-init on foregrounding - if (nsCacheService::GlobalInstance()) { - nsCacheService::GlobalInstance()->Shutdown(); - } - - // We really want to send a notification like profile-before-change, - // but profile-before-change ends up shutting some things down instead - // of flushing data - nsIPrefService* prefs = Preferences::GetService(); - if (prefs) { - // reset the crash loop state - nsCOMPtr prefBranch; - prefs->GetBranch("browser.sessionstore.", getter_AddRefs(prefBranch)); - if (prefBranch) - prefBranch->SetIntPref("recent_crashes", 0); - - prefs->SavePrefFile(nullptr); - } - break; - } - - case AndroidGoannaEvent::APP_FOREGROUNDING: { - // If we are OOM killed with the disk cache enabled, the entire - // cache will be cleared (bug 105843), so shut down cache on backgrounding - // and re-init here - if (nsCacheService::GlobalInstance()) { - nsCacheService::GlobalInstance()->Init(); - } - - // We didn't return from one of our own activities, so restore - // to foreground status - nsCOMPtr obsServ = - mozilla::services::GetObserverService(); - obsServ->NotifyObservers(nullptr, "application-foreground", nullptr); - break; - } - - case AndroidGoannaEvent::THUMBNAIL: { - if (!mBrowserApp) - break; - - int32_t tabId = curEvent->MetaState(); - const nsTArray& points = curEvent->Points(); - RefCountedJavaObject* buffer = curEvent->ByteBuffer(); - nsRefPtr sr = new ThumbnailRunnable(mBrowserApp, tabId, points, buffer); - MessageLoop::current()->PostIdleTask(FROM_HERE, NewRunnableMethod(sr.get(), &ThumbnailRunnable::Run)); - break; - } - - case AndroidGoannaEvent::ZOOMEDVIEW: { - if (!mBrowserApp) - break; - int32_t tabId = curEvent->MetaState(); - const nsTArray& points = curEvent->Points(); - float scaleFactor = (float) curEvent->X(); - nsRefPtr javaBuffer = curEvent->ByteBuffer(); - const auto& mBuffer = jni::Object::Ref::From(javaBuffer->GetObject()); - - nsCOMPtr domWindow; - nsCOMPtr tab; - mBrowserApp->GetBrowserTab(tabId, getter_AddRefs(tab)); - if (!tab) { - NS_ERROR("Can't find tab!"); - break; - } - tab->GetWindow(getter_AddRefs(domWindow)); - if (!domWindow) { - NS_ERROR("Can't find dom window!"); - break; - } - NS_ASSERTION(points.Length() == 2, "ZoomedView event does not have enough coordinates"); - nsIntRect r(points[0].x, points[0].y, points[1].x, points[1].y); - AndroidBridge::Bridge()->CaptureZoomedView(domWindow, r, mBuffer, scaleFactor); - break; - } - - case AndroidGoannaEvent::VIEWPORT: - case AndroidGoannaEvent::BROADCAST: { - if (curEvent->Characters().Length() == 0) - break; - - nsCOMPtr obsServ = - mozilla::services::GetObserverService(); - - const NS_ConvertUTF16toUTF8 topic(curEvent->Characters()); - const nsPromiseFlatString& data = PromiseFlatString(curEvent->CharactersExtra()); - - obsServ->NotifyObservers(nullptr, topic.get(), data.get()); - break; - } - - case AndroidGoannaEvent::TELEMETRY_UI_SESSION_STOP: { - if (curEvent->Characters().Length() == 0) - break; - - nsCOMPtr obs; - mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs)); - if (!obs) - break; - - obs->StopSession( - nsString(curEvent->Characters()).get(), - nsString(curEvent->CharactersExtra()).get(), - curEvent->Time() - ); - break; - } - - case AndroidGoannaEvent::TELEMETRY_UI_SESSION_START: { - if (curEvent->Characters().Length() == 0) - break; - - nsCOMPtr obs; - mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs)); - if (!obs) - break; - - obs->StartSession( - nsString(curEvent->Characters()).get(), - curEvent->Time() - ); - break; - } - - case AndroidGoannaEvent::TELEMETRY_UI_EVENT: { - if (curEvent->Data().Length() == 0) - break; - - nsCOMPtr obs; - mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs)); - if (!obs) - break; - - obs->AddEvent( - nsString(curEvent->Data()).get(), - nsString(curEvent->Characters()).get(), - curEvent->Time(), - nsString(curEvent->CharactersExtra()).get() - ); - break; - } - - case AndroidGoannaEvent::LOAD_URI: { - nsCOMPtr cmdline - (do_CreateInstance("@mozilla.org/toolkit/command-line;1")); - if (!cmdline) - break; - - if (curEvent->Characters().Length() == 0) - break; - - char *uri = ToNewUTF8String(curEvent->Characters()); - if (!uri) - break; - - char *flag = ToNewUTF8String(curEvent->CharactersExtra()); - - const char *argv[4] = { - "dummyappname", - "-url", - uri, - flag ? flag : "" - }; - nsresult rv = cmdline->Init(4, argv, nullptr, nsICommandLine::STATE_REMOTE_AUTO); - if (NS_SUCCEEDED(rv)) - cmdline->Run(); - free(uri); - if (flag) - free(flag); - break; - } - - case AndroidGoannaEvent::SIZE_CHANGED: { - // store the last resize event to dispatch it to new windows with a FORCED_RESIZE event - if (curEvent != gLastSizeChange) { - gLastSizeChange = AndroidGoannaEvent::CopyResizeEvent(curEvent); - } - nsWindow::OnGlobalAndroidEvent(curEvent); - break; - } - - case AndroidGoannaEvent::VISITED: { -#ifdef MOZ_ANDROID_HISTORY - nsCOMPtr history = services::GetHistoryService(); - nsCOMPtr visitedURI; - if (history && - NS_SUCCEEDED(NS_NewURI(getter_AddRefs(visitedURI), - nsString(curEvent->Characters())))) { - history->NotifyVisited(visitedURI); - } -#endif - break; - } - - case AndroidGoannaEvent::NETWORK_CHANGED: { - hal::NotifyNetworkChange(hal::NetworkInformation(curEvent->ConnectionType(), - curEvent->IsWifi(), - curEvent->DHCPGateway())); - break; - } - - case AndroidGoannaEvent::SCREENORIENTATION_CHANGED: { - nsresult rv; - nsCOMPtr screenMgr = - do_GetService("@mozilla.org/gfx/screenmanager;1", &rv); - if (NS_FAILED(rv)) { - NS_ERROR("Can't find nsIScreenManager!"); - break; - } - - nsIntRect rect; - int32_t colorDepth, pixelDepth; - dom::ScreenOrientation orientation; - nsCOMPtr screen; - - screenMgr->GetPrimaryScreen(getter_AddRefs(screen)); - screen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height); - screen->GetColorDepth(&colorDepth); - screen->GetPixelDepth(&pixelDepth); - orientation = - static_cast(curEvent->ScreenOrientation()); - - hal::NotifyScreenConfigurationChange( - hal::ScreenConfiguration(rect, orientation, colorDepth, pixelDepth)); - break; - } - - case AndroidGoannaEvent::CALL_OBSERVER: - { - nsCOMPtr observer; - mObserversHash.Get(curEvent->Characters(), getter_AddRefs(observer)); - - if (observer) { - observer->Observe(nullptr, NS_ConvertUTF16toUTF8(curEvent->CharactersExtra()).get(), - nsString(curEvent->Data()).get()); - } else { - ALOG("Call_Observer event: Observer was not found!"); - } - - break; - } - - case AndroidGoannaEvent::REMOVE_OBSERVER: - mObserversHash.Remove(curEvent->Characters()); - break; - - case AndroidGoannaEvent::ADD_OBSERVER: - AddObserver(curEvent->Characters(), curEvent->Observer()); - break; - - case AndroidGoannaEvent::PREFERENCES_GET: - case AndroidGoannaEvent::PREFERENCES_OBSERVE: { - const nsTArray &prefNames = curEvent->PrefNames(); - size_t count = prefNames.Length(); - nsAutoArrayPtr prefNamePtrs(new const char16_t*[count]); - for (size_t i = 0; i < count; ++i) { - prefNamePtrs[i] = prefNames[i].get(); - } - - if (curEvent->Type() == AndroidGoannaEvent::PREFERENCES_GET) { - mBrowserApp->GetPreferences(curEvent->RequestId(), prefNamePtrs, count); - } else { - mBrowserApp->ObservePreferences(curEvent->RequestId(), prefNamePtrs, count); - } - break; - } - - case AndroidGoannaEvent::PREFERENCES_REMOVE_OBSERVERS: - mBrowserApp->RemovePreferenceObservers(curEvent->RequestId()); - break; - - case AndroidGoannaEvent::LOW_MEMORY: - // TODO hook in memory-reduction stuff for different levels here - if (curEvent->MetaState() >= AndroidGoannaEvent::MEMORY_PRESSURE_MEDIUM) { - nsCOMPtr os = mozilla::services::GetObserverService(); - if (os) { - os->NotifyObservers(nullptr, - "memory-pressure", - MOZ_UTF16("low-memory")); - } - } - break; - - case AndroidGoannaEvent::NETWORK_LINK_CHANGE: - { - nsCOMPtr os = mozilla::services::GetObserverService(); - if (os) { - os->NotifyObservers(nullptr, - NS_NETWORK_LINK_TOPIC, - nsString(curEvent->Characters()).get()); - } - break; - } - - case AndroidGoannaEvent::TELEMETRY_HISTOGRAM_ADD: - Telemetry::Accumulate(NS_ConvertUTF16toUTF8(curEvent->Characters()).get(), - curEvent->Count()); - break; - - case AndroidGoannaEvent::GAMEPAD_ADDREMOVE: { -#ifdef MOZ_GAMEPAD - nsRefPtr svc = - mozilla::dom::GamepadService::GetService(); - if (svc) { - if (curEvent->Action() == AndroidGoannaEvent::ACTION_GAMEPAD_ADDED) { - int svc_id = svc->AddGamepad("android", - mozilla::dom::GamepadMappingType::Standard, - mozilla::dom::kStandardGamepadButtons, - mozilla::dom::kStandardGamepadAxes); - widget::GoannaAppShell::GamepadAdded(curEvent->ID(), - svc_id); - } else if (curEvent->Action() == AndroidGoannaEvent::ACTION_GAMEPAD_REMOVED) { - svc->RemoveGamepad(curEvent->ID()); - } - } -#endif - break; - } - - case AndroidGoannaEvent::GAMEPAD_DATA: { -#ifdef MOZ_GAMEPAD - nsRefPtr svc = - mozilla::dom::GamepadService::GetService(); - if (svc) { - int id = curEvent->ID(); - if (curEvent->Action() == AndroidGoannaEvent::ACTION_GAMEPAD_BUTTON) { - svc->NewButtonEvent(id, curEvent->GamepadButton(), - curEvent->GamepadButtonPressed(), - curEvent->GamepadButtonValue()); - } else if (curEvent->Action() == AndroidGoannaEvent::ACTION_GAMEPAD_AXES) { - int valid = curEvent->Flags(); - const nsTArray& values = curEvent->GamepadValues(); - for (unsigned i = 0; i < values.Length(); i++) { - if (valid & (1<NewAxisMoveEvent(id, i, values[i]); - } - } - } - } -#endif - break; - } - case AndroidGoannaEvent::NOOP: - break; - - default: - nsWindow::OnGlobalAndroidEvent(curEvent); - break; - } - - if (curEvent->AckNeeded()) { - widget::GoannaAppShell::AcknowledgeEvent(); - } - - EVLOG("nsAppShell: -- done event %p %d", (void*)curEvent.get(), curEvent->Type()); - - return true; -} - -void -nsAppShell::ResendLastResizeEvent(nsWindow* aDest) { - if (gLastSizeChange) { - nsWindow::OnGlobalAndroidEvent(gLastSizeChange); - } -} - -AndroidGoannaEvent* -nsAppShell::PopNextEvent() -{ - AndroidGoannaEvent *ae = nullptr; - MutexAutoLock lock(mQueueLock); - if (mEventQueue.Length()) { - ae = mEventQueue[0]; - mEventQueue.RemoveElementAt(0); - if (mQueuedViewportEvent == ae) { - mQueuedViewportEvent = nullptr; - } - } - - return ae; -} - -AndroidGoannaEvent* -nsAppShell::PeekNextEvent() -{ - AndroidGoannaEvent *ae = nullptr; - MutexAutoLock lock(mQueueLock); - if (mEventQueue.Length()) { - ae = mEventQueue[0]; - } - - return ae; -} - -void -nsAppShell::PostEvent(AndroidGoannaEvent *ae) -{ - { - // set this to true when inserting events that we can coalesce - // viewport events across. this is effectively maintaining a whitelist - // of events that are unaffected by viewport changes. - bool allowCoalescingNextViewport = false; - - MutexAutoLock lock(mQueueLock); - EVLOG("nsAppShell::PostEvent %p %d", ae, ae->Type()); - switch (ae->Type()) { - case AndroidGoannaEvent::COMPOSITOR_CREATE: - case AndroidGoannaEvent::COMPOSITOR_PAUSE: - case AndroidGoannaEvent::COMPOSITOR_RESUME: - // Give priority to these events, but maintain their order wrt each other. - { - uint32_t i = 0; - while (i < mEventQueue.Length() && - (mEventQueue[i]->Type() == AndroidGoannaEvent::COMPOSITOR_CREATE || - mEventQueue[i]->Type() == AndroidGoannaEvent::COMPOSITOR_PAUSE || - mEventQueue[i]->Type() == AndroidGoannaEvent::COMPOSITOR_RESUME)) { - i++; - } - EVLOG("nsAppShell: Inserting compositor event %d at position %d to maintain priority order", ae->Type(), i); - mEventQueue.InsertElementAt(i, ae); - } - break; - - case AndroidGoannaEvent::VIEWPORT: - if (mQueuedViewportEvent) { - // drop the previous viewport event now that we have a new one - EVLOG("nsAppShell: Dropping old viewport event at %p in favour of new VIEWPORT event %p", mQueuedViewportEvent, ae); - mEventQueue.RemoveElement(mQueuedViewportEvent); - delete mQueuedViewportEvent; - } - mQueuedViewportEvent = ae; - allowCoalescingNextViewport = true; - - mEventQueue.AppendElement(ae); - break; - - case AndroidGoannaEvent::MOTION_EVENT: - case AndroidGoannaEvent::APZ_INPUT_EVENT: - if (mAllowCoalescingTouches && mEventQueue.Length() > 0) { - int len = mEventQueue.Length(); - AndroidGoannaEvent* event = mEventQueue[len - 1]; - if (ae->CanCoalesceWith(event)) { - // consecutive motion-move events; drop the last one before adding the new one - EVLOG("nsAppShell: Dropping old move event at %p in favour of new move event %p", event, ae); - mEventQueue.RemoveElementAt(len - 1); - delete event; - } - } - mEventQueue.AppendElement(ae); - break; - - case AndroidGoannaEvent::NATIVE_POKE: - allowCoalescingNextViewport = true; - // fall through - - default: - mEventQueue.AppendElement(ae); - break; - } - - // if the event wasn't on our whitelist then reset mQueuedViewportEvent - // so that we don't coalesce future viewport events into the last viewport - // event we added - if (!allowCoalescingNextViewport) - mQueuedViewportEvent = nullptr; - } - NotifyNativeEvent(); -} - -void -nsAppShell::OnResume() -{ -} - -nsresult -nsAppShell::AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver) -{ - NS_ASSERTION(aObserver != nullptr, "nsAppShell::AddObserver: aObserver is null!"); - mObserversHash.Put(aObserverKey, aObserver); - return NS_OK; -} - -// Used by IPC code -namespace mozilla { - -bool ProcessNextEvent() -{ - if (!nsAppShell::gAppShell) { - return false; - } - - return nsAppShell::gAppShell->ProcessNextNativeEvent(true) ? true : false; -} - -void NotifyEvent() -{ - if (nsAppShell::gAppShell) { - nsAppShell::gAppShell->NotifyNativeEvent(); - } -} - -} diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h deleted file mode 100644 index 14646d6a70..0000000000 --- a/widget/android/nsAppShell.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsAppShell_h__ -#define nsAppShell_h__ - -#include "mozilla/CondVar.h" -#include "mozilla/Mutex.h" -#include "nsBaseAppShell.h" -#include "nsCOMPtr.h" -#include "nsTArray.h" -#include "nsInterfaceHashtable.h" -#include "nsIAndroidBridge.h" - -namespace mozilla { -class AndroidGoannaEvent; -bool ProcessNextEvent(); -void NotifyEvent(); -} - -class nsWindow; - -class nsAppShell : - public nsBaseAppShell -{ - typedef mozilla::CondVar CondVar; - typedef mozilla::Mutex Mutex; - -public: - static nsAppShell *gAppShell; - static mozilla::AndroidGoannaEvent *gEarlyEvent; - - nsAppShell(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIOBSERVER - - nsresult Init(); - - void NotifyNativeEvent(); - - virtual bool ProcessNextNativeEvent(bool mayWait); - - void PostEvent(mozilla::AndroidGoannaEvent *event); - void OnResume(); - - nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver); - void ResendLastResizeEvent(nsWindow* aDest); - - void SetBrowserApp(nsIAndroidBrowserApp* aBrowserApp) { - mBrowserApp = aBrowserApp; - } - - void GetBrowserApp(nsIAndroidBrowserApp* *aBrowserApp) { - *aBrowserApp = mBrowserApp; - } - -protected: - virtual void ScheduleNativeEventCallback(); - virtual ~nsAppShell(); - - Mutex mQueueLock; - Mutex mCondLock; - CondVar mQueueCond; - mozilla::AndroidGoannaEvent *mQueuedViewportEvent; - bool mAllowCoalescingTouches; - nsTArray mEventQueue; - nsInterfaceHashtable mObserversHash; - - mozilla::AndroidGoannaEvent *PopNextEvent(); - mozilla::AndroidGoannaEvent *PeekNextEvent(); - - nsCOMPtr mBrowserApp; -}; - -#endif // nsAppShell_h__ - diff --git a/widget/android/nsClipboard.cpp b/widget/android/nsClipboard.cpp deleted file mode 100644 index cf8675be12..0000000000 --- a/widget/android/nsClipboard.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/ContentChild.h" -#include "nsClipboard.h" -#include "nsISupportsPrimitives.h" -#include "AndroidBridge.h" -#include "nsCOMPtr.h" -#include "nsComponentManagerUtils.h" -#include "nsXULAppAPI.h" - -using namespace mozilla; -using mozilla::dom::ContentChild; - -NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard) - -/* The Android clipboard only supports text and doesn't support mime types - * so we assume all clipboard data is text/unicode for now. Documentation - * indicates that support for other data types is planned for future - * releases. - */ - -nsClipboard::nsClipboard() -{ -} - -NS_IMETHODIMP -nsClipboard::SetData(nsITransferable *aTransferable, - nsIClipboardOwner *anOwner, int32_t aWhichClipboard) -{ - if (aWhichClipboard != kGlobalClipboard) - return NS_ERROR_NOT_IMPLEMENTED; - - nsCOMPtr tmp; - uint32_t len; - nsresult rv = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), - &len); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr supportsString = do_QueryInterface(tmp); - // No support for non-text data - NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED); - nsAutoString buffer; - supportsString->GetData(buffer); - - widget::Clipboard::SetClipboardText(buffer); - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard) -{ - if (aWhichClipboard != kGlobalClipboard) - return NS_ERROR_NOT_IMPLEMENTED; - - nsAutoString buffer; - if (!AndroidBridge::Bridge()) - return NS_ERROR_NOT_IMPLEMENTED; - if (!AndroidBridge::Bridge()->GetClipboardText(buffer)) - return NS_ERROR_UNEXPECTED; - - nsresult rv; - nsCOMPtr dataWrapper = - do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = dataWrapper->SetData(buffer); - NS_ENSURE_SUCCESS(rv, rv); - - // If our data flavor has already been added, this will fail. But we don't care - aTransferable->AddDataFlavor(kUnicodeMime); - - nsCOMPtr nsisupportsDataWrapper = - do_QueryInterface(dataWrapper); - rv = aTransferable->SetTransferData(kUnicodeMime, nsisupportsDataWrapper, - buffer.Length() * sizeof(char16_t)); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::EmptyClipboard(int32_t aWhichClipboard) -{ - if (aWhichClipboard != kGlobalClipboard) - return NS_ERROR_NOT_IMPLEMENTED; - widget::Clipboard::ClearText(); - - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::HasDataMatchingFlavors(const char **aFlavorList, - uint32_t aLength, int32_t aWhichClipboard, - bool *aHasText) -{ - *aHasText = false; - if (aWhichClipboard != kGlobalClipboard) - return NS_ERROR_NOT_IMPLEMENTED; - *aHasText = widget::Clipboard::HasText(); - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::SupportsSelectionClipboard(bool *aIsSupported) -{ - *aIsSupported = false; - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::SupportsFindClipboard(bool* _retval) -{ - *_retval = false; - return NS_OK; -} diff --git a/widget/android/nsClipboard.h b/widget/android/nsClipboard.h deleted file mode 100644 index 657a8dea8f..0000000000 --- a/widget/android/nsClipboard.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef NS_CLIPBOARD_H -#define NS_CLIPBOARD_H - -#include "nsIClipboard.h" - -class nsClipboard final : public nsIClipboard -{ -private: - ~nsClipboard() {} - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICLIPBOARD - - nsClipboard(); -}; - -#endif diff --git a/widget/android/nsDeviceContextAndroid.cpp b/widget/android/nsDeviceContextAndroid.cpp deleted file mode 100644 index 9e1c66736c..0000000000 --- a/widget/android/nsDeviceContextAndroid.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsDeviceContextAndroid.h" -#include "nsString.h" -#include "nsIFile.h" -#include "nsIFileStreams.h" -#include "nsAutoPtr.h" -#include "gfxPDFSurface.h" -#include "nsIPrintSettings.h" -#include "nsDirectoryServiceDefs.h" - -NS_IMPL_ISUPPORTS(nsDeviceContextSpecAndroid, nsIDeviceContextSpec) - -NS_IMETHODIMP -nsDeviceContextSpecAndroid::GetSurfaceForPrinter(gfxASurface** aSurface) -{ - nsresult rv = - NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mTempFile)); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString filename("tmp-printing.pdf"); - mTempFile->AppendNative(filename); - rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0660); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); - rv = stream->Init(mTempFile, -1, -1, 0); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr surface; - - // XXX: what should we do here for size? screen size? - gfxSize surfaceSize(480, 800); - - surface = new gfxPDFSurface(stream, surfaceSize); - - - MOZ_ASSERT(surface, "valid address expected"); - surface.swap(*aSurface); - return NS_OK; -} - -NS_IMETHODIMP -nsDeviceContextSpecAndroid::Init(nsIWidget* aWidget, - nsIPrintSettings* aPS, - bool aIsPrintPreview) -{ - mPrintSettings = aPS; - return NS_OK; -} - -NS_IMETHODIMP -nsDeviceContextSpecAndroid::BeginDocument(const nsAString& aTitle, - char16_t* aPrintToFileName, - int32_t aStartPage, - int32_t aEndPage) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsDeviceContextSpecAndroid::EndDocument() -{ - nsXPIDLString targetPath; - nsCOMPtr destFile; - mPrintSettings->GetToFileName(getter_Copies(targetPath)); - - nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), - false, getter_AddRefs(destFile)); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoString destLeafName; - rv = destFile->GetLeafName(destLeafName); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr destDir; - rv = destFile->GetParent(getter_AddRefs(destDir)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mTempFile->MoveTo(destDir, destLeafName); - NS_ENSURE_SUCCESS(rv, rv); - - destFile->SetPermissions(0666); - return NS_OK; -} diff --git a/widget/android/nsDeviceContextAndroid.h b/widget/android/nsDeviceContextAndroid.h deleted file mode 100644 index 72fea46bf3..0000000000 --- a/widget/android/nsDeviceContextAndroid.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsIDeviceContextSpec.h" -#include "nsCOMPtr.h" - -class nsDeviceContextSpecAndroid final : public nsIDeviceContextSpec -{ -private: - ~nsDeviceContextSpecAndroid() {} - -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD GetSurfaceForPrinter(gfxASurface** surface); - - NS_IMETHOD Init(nsIWidget* aWidget, - nsIPrintSettings* aPS, - bool aIsPrintPreview); - NS_IMETHOD BeginDocument(const nsAString& aTitle, - char16_t* aPrintToFileName, - int32_t aStartPage, - int32_t aEndPage); - NS_IMETHOD EndDocument(); - NS_IMETHOD BeginPage() { return NS_OK; } - NS_IMETHOD EndPage() { return NS_OK; } - -private: - nsCOMPtr mPrintSettings; - nsCOMPtr mTempFile; -}; diff --git a/widget/android/nsIAndroidBridge.idl b/widget/android/nsIAndroidBridge.idl deleted file mode 100644 index 5451362352..0000000000 --- a/widget/android/nsIAndroidBridge.idl +++ /dev/null @@ -1,75 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" -#include "nsIDOMWindow.idl" - -[scriptable, uuid(0843f3c1-043e-4c64-9d8c-091370548c05)] -interface nsIBrowserTab : nsISupports { - readonly attribute nsIDOMWindow window; - readonly attribute float scale; -}; - -[scriptable, uuid(08426a73-e70b-4680-9282-630932e2b2bb)] -interface nsIUITelemetryObserver : nsISupports { - void startSession(in wstring name, - in unsigned long timestamp); - void stopSession(in wstring name, - in wstring reason, - in unsigned long timestamp); - void addEvent(in wstring action, - in wstring method, - in unsigned long timestamp, - in wstring extras); -}; - -[scriptable, uuid(78ec5811-78ee-4239-a554-3303f823dbbc)] -interface nsIAndroidBrowserApp : nsISupports { - readonly attribute nsIBrowserTab selectedTab; - nsIBrowserTab getBrowserTab(in int32_t tabId); - void getPreferences(in int32_t requestId, - [array, size_is(count)] in wstring prefNames, - in unsigned long count); - void observePreferences(in int32_t requestId, - [array, size_is(count)] in wstring prefNames, - in unsigned long count); - void removePreferenceObservers(in int32_t requestId); - nsIUITelemetryObserver getUITelemetryObserver(); -}; - -[scriptable, uuid(59cfcb35-69b7-47b2-8155-32b193272666)] -interface nsIAndroidViewport : nsISupports { - readonly attribute float x; - readonly attribute float y; - readonly attribute float width; - readonly attribute float height; - readonly attribute float pageLeft; - readonly attribute float pageTop; - readonly attribute float pageRight; - readonly attribute float pageBottom; - readonly attribute float cssPageLeft; - readonly attribute float cssPageTop; - readonly attribute float cssPageRight; - readonly attribute float cssPageBottom; - readonly attribute float zoom; -}; - -[scriptable, uuid(e1bfbc07-dbae-409d-a5b5-ef57522c1f15)] -interface nsIAndroidDisplayport : nsISupports { - attribute float left; - attribute float top; - attribute float right; - attribute float bottom; - attribute float resolution; -}; - -[scriptable, uuid(1beb70d3-70f3-4742-98cc-a3d301b26c0c)] -interface nsIAndroidBridge : nsISupports -{ - [implicit_jscontext] void handleGoannaMessage(in jsval message); - attribute nsIAndroidBrowserApp browserApp; - nsIAndroidDisplayport getDisplayPort(in boolean aPageSizeUpdate, in boolean isBrowserContentDisplayed, in int32_t tabId, in nsIAndroidViewport metrics); - void contentDocumentChanged(); - boolean isContentDocumentDisplayed(); -}; diff --git a/widget/android/nsIMEPicker.cpp b/widget/android/nsIMEPicker.cpp deleted file mode 100644 index 20245554c2..0000000000 --- a/widget/android/nsIMEPicker.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIMEPicker.h" -#include "AndroidBridge.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsIMEPicker, nsIIMEPicker) - -nsIMEPicker::nsIMEPicker() -{ - /* member initializers and constructor code */ -} - -nsIMEPicker::~nsIMEPicker() -{ - /* destructor code */ -} - -/* void show (); */ -NS_IMETHODIMP nsIMEPicker::Show() -{ - widget::GoannaAppShell::ShowInputMethodPicker(); - return NS_OK; -} diff --git a/widget/android/nsIMEPicker.h b/widget/android/nsIMEPicker.h deleted file mode 100644 index 208cc9995e..0000000000 --- a/widget/android/nsIMEPicker.h +++ /dev/null @@ -1,22 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __nsIMEPicker -#define __nsIMEPicker - -#include "nsIIMEPicker.h" - -class nsIMEPicker final : public nsIIMEPicker -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIIMEPICKER - - nsIMEPicker(); - -private: - ~nsIMEPicker(); -}; - -#endif diff --git a/widget/android/nsIdleServiceAndroid.cpp b/widget/android/nsIdleServiceAndroid.cpp deleted file mode 100644 index 1992d80437..0000000000 --- a/widget/android/nsIdleServiceAndroid.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:expandtab:shiftwidth=4:tabstop=4: - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIdleServiceAndroid.h" -#include "nsIServiceManager.h" - -NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceAndroid, nsIdleService) - -bool -nsIdleServiceAndroid::PollIdleTime(uint32_t *aIdleTime) -{ - return false; -} - -bool -nsIdleServiceAndroid::UsePollMode() -{ - return false; -} diff --git a/widget/android/nsIdleServiceAndroid.h b/widget/android/nsIdleServiceAndroid.h deleted file mode 100644 index af7513a91c..0000000000 --- a/widget/android/nsIdleServiceAndroid.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:expandtab:shiftwidth=4:tabstop=4: - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsIdleServiceAndroid_h__ -#define nsIdleServiceAndroid_h__ - -#include "nsIdleService.h" - -class nsIdleServiceAndroid : public nsIdleService -{ -public: - NS_DECL_ISUPPORTS_INHERITED - - bool PollIdleTime(uint32_t* aIdleTime); - - static already_AddRefed GetInstance() - { - nsRefPtr idleService = nsIdleService::GetInstance(); - if (!idleService) { - idleService = new nsIdleServiceAndroid(); - } - - return idleService.forget().downcast(); - } - -protected: - nsIdleServiceAndroid() { } - virtual ~nsIdleServiceAndroid() { } - bool UsePollMode(); -}; - -#endif // nsIdleServiceAndroid_h__ diff --git a/widget/android/nsLookAndFeel.cpp b/widget/android/nsLookAndFeel.cpp deleted file mode 100644 index fa29a4d7cc..0000000000 --- a/widget/android/nsLookAndFeel.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/ContentChild.h" -#include "nsStyleConsts.h" -#include "nsXULAppAPI.h" -#include "nsLookAndFeel.h" -#include "gfxFont.h" -#include "gfxFontConstants.h" -#include "mozilla/gfx/2D.h" - -using namespace mozilla; -using mozilla::dom::ContentChild; - -bool nsLookAndFeel::mInitializedSystemColors = false; -AndroidSystemColors nsLookAndFeel::mSystemColors; - -bool nsLookAndFeel::mInitializedShowPassword = false; -bool nsLookAndFeel::mShowPassword = true; - -static const char16_t UNICODE_BULLET = 0x2022; - -nsLookAndFeel::nsLookAndFeel() - : nsXPLookAndFeel() -{ -} - -nsLookAndFeel::~nsLookAndFeel() -{ -} - -#define BG_PRELIGHT_COLOR NS_RGB(0xee,0xee,0xee) -#define FG_PRELIGHT_COLOR NS_RGB(0x77,0x77,0x77) -#define BLACK_COLOR NS_RGB(0x00,0x00,0x00) -#define DARK_GRAY_COLOR NS_RGB(0x40,0x40,0x40) -#define GRAY_COLOR NS_RGB(0x80,0x80,0x80) -#define LIGHT_GRAY_COLOR NS_RGB(0xa0,0xa0,0xa0) -#define RED_COLOR NS_RGB(0xff,0x00,0x00) - -nsresult -nsLookAndFeel::GetSystemColors() -{ - if (mInitializedSystemColors) - return NS_OK; - - if (!AndroidBridge::Bridge()) - return NS_ERROR_FAILURE; - - AndroidBridge::Bridge()->GetSystemColors(&mSystemColors); - - mInitializedSystemColors = true; - - return NS_OK; -} - -nsresult -nsLookAndFeel::CallRemoteGetSystemColors() -{ - // An array has to be used to get data from remote process - InfallibleTArray colors; - uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor); - - if (!ContentChild::GetSingleton()->SendGetSystemColors(colorsCount, &colors)) - return NS_ERROR_FAILURE; - - NS_ASSERTION(colors.Length() == colorsCount, "System colors array is incomplete"); - if (colors.Length() == 0) - return NS_ERROR_FAILURE; - - if (colors.Length() < colorsCount) - colorsCount = colors.Length(); - - // Array elements correspond to the members of mSystemColors structure, - // so just copy the memory block - memcpy(&mSystemColors, colors.Elements(), sizeof(nscolor) * colorsCount); - - mInitializedSystemColors = true; - - return NS_OK; -} - -nsresult -nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor) -{ - nsresult rv = NS_OK; - - if (!mInitializedSystemColors) { - if (XRE_GetProcessType() == GeckoProcessType_Default) - rv = GetSystemColors(); - else - rv = CallRemoteGetSystemColors(); - NS_ENSURE_SUCCESS(rv, rv); - } - - // XXX we'll want to use context.obtainStyledAttributes on the java side to - // get all of these; see TextView.java for a good exmaple. - - switch (aID) { - // These colors don't seem to be used for anything anymore in Mozilla - // (except here at least TextSelectBackground and TextSelectForeground) - // The CSS2 colors below are used. - case eColorID_WindowBackground: - aColor = NS_RGB(0xFF, 0xFF, 0xFF); - break; - case eColorID_WindowForeground: - aColor = mSystemColors.textColorPrimary; - break; - case eColorID_WidgetBackground: - aColor = mSystemColors.colorBackground; - break; - case eColorID_WidgetForeground: - aColor = mSystemColors.colorForeground; - break; - case eColorID_WidgetSelectBackground: - aColor = mSystemColors.textColorHighlight; - break; - case eColorID_WidgetSelectForeground: - aColor = mSystemColors.textColorPrimaryInverse; - break; - case eColorID_Widget3DHighlight: - aColor = LIGHT_GRAY_COLOR; - break; - case eColorID_Widget3DShadow: - aColor = DARK_GRAY_COLOR; - break; - case eColorID_TextBackground: - // not used? - aColor = mSystemColors.colorBackground; - break; - case eColorID_TextForeground: - // not used? - aColor = mSystemColors.textColorPrimary; - break; - case eColorID_TextSelectBackground: - case eColorID_IMESelectedRawTextBackground: - case eColorID_IMESelectedConvertedTextBackground: - // still used - aColor = mSystemColors.textColorHighlight; - break; - case eColorID_TextSelectForeground: - case eColorID_IMESelectedRawTextForeground: - case eColorID_IMESelectedConvertedTextForeground: - // still used - aColor = mSystemColors.textColorPrimaryInverse; - break; - case eColorID_IMERawInputBackground: - case eColorID_IMEConvertedTextBackground: - aColor = NS_TRANSPARENT; - break; - case eColorID_IMERawInputForeground: - case eColorID_IMEConvertedTextForeground: - aColor = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_IMERawInputUnderline: - case eColorID_IMEConvertedTextUnderline: - aColor = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_IMESelectedRawTextUnderline: - case eColorID_IMESelectedConvertedTextUnderline: - aColor = NS_TRANSPARENT; - break; - case eColorID_SpellCheckerUnderline: - aColor = RED_COLOR; - break; - - // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors - case eColorID_activeborder: - // active window border - aColor = mSystemColors.colorBackground; - break; - case eColorID_activecaption: - // active window caption background - aColor = mSystemColors.colorBackground; - break; - case eColorID_appworkspace: - // MDI background color - aColor = mSystemColors.colorBackground; - break; - case eColorID_background: - // desktop background - aColor = mSystemColors.colorBackground; - break; - case eColorID_captiontext: - // text in active window caption, size box, and scrollbar arrow box (!) - aColor = mSystemColors.colorForeground; - break; - case eColorID_graytext: - // disabled text in windows, menus, etc. - aColor = mSystemColors.textColorTertiary; - break; - case eColorID_highlight: - // background of selected item - aColor = mSystemColors.textColorHighlight; - break; - case eColorID_highlighttext: - // text of selected item - aColor = mSystemColors.textColorPrimaryInverse; - break; - case eColorID_inactiveborder: - // inactive window border - aColor = mSystemColors.colorBackground; - break; - case eColorID_inactivecaption: - // inactive window caption - aColor = mSystemColors.colorBackground; - break; - case eColorID_inactivecaptiontext: - // text in inactive window caption - aColor = mSystemColors.textColorTertiary; - break; - case eColorID_infobackground: - // tooltip background color - aColor = mSystemColors.colorBackground; - break; - case eColorID_infotext: - // tooltip text color - aColor = mSystemColors.colorForeground; - break; - case eColorID_menu: - // menu background - aColor = mSystemColors.colorBackground; - break; - case eColorID_menutext: - // menu text - aColor = mSystemColors.colorForeground; - break; - case eColorID_scrollbar: - // scrollbar gray area - aColor = mSystemColors.colorBackground; - break; - - case eColorID_threedface: - case eColorID_buttonface: - // 3-D face color - aColor = mSystemColors.colorBackground; - break; - - case eColorID_buttontext: - // text on push buttons - aColor = mSystemColors.colorForeground; - break; - - case eColorID_buttonhighlight: - // 3-D highlighted edge color - case eColorID_threedhighlight: - // 3-D highlighted outer edge color - aColor = LIGHT_GRAY_COLOR; - break; - - case eColorID_threedlightshadow: - // 3-D highlighted inner edge color - aColor = mSystemColors.colorBackground; - break; - - case eColorID_buttonshadow: - // 3-D shadow edge color - case eColorID_threedshadow: - // 3-D shadow inner edge color - aColor = GRAY_COLOR; - break; - - case eColorID_threeddarkshadow: - // 3-D shadow outer edge color - aColor = BLACK_COLOR; - break; - - case eColorID_window: - case eColorID_windowframe: - aColor = mSystemColors.colorBackground; - break; - - case eColorID_windowtext: - aColor = mSystemColors.textColorPrimary; - break; - - case eColorID__moz_eventreerow: - case eColorID__moz_field: - aColor = mSystemColors.colorBackground; - break; - case eColorID__moz_fieldtext: - aColor = mSystemColors.textColorPrimary; - break; - case eColorID__moz_dialog: - aColor = mSystemColors.colorBackground; - break; - case eColorID__moz_dialogtext: - aColor = mSystemColors.colorForeground; - break; - case eColorID__moz_dragtargetzone: - aColor = mSystemColors.textColorHighlight; - break; - case eColorID__moz_buttondefault: - // default button border color - aColor = BLACK_COLOR; - break; - case eColorID__moz_buttonhoverface: - aColor = BG_PRELIGHT_COLOR; - break; - case eColorID__moz_buttonhovertext: - aColor = FG_PRELIGHT_COLOR; - break; - case eColorID__moz_cellhighlight: - case eColorID__moz_html_cellhighlight: - aColor = mSystemColors.textColorHighlight; - break; - case eColorID__moz_cellhighlighttext: - case eColorID__moz_html_cellhighlighttext: - aColor = mSystemColors.textColorPrimaryInverse; - break; - case eColorID__moz_menuhover: - aColor = BG_PRELIGHT_COLOR; - break; - case eColorID__moz_menuhovertext: - aColor = FG_PRELIGHT_COLOR; - break; - case eColorID__moz_oddtreerow: - aColor = NS_TRANSPARENT; - break; - case eColorID__moz_nativehyperlinktext: - aColor = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID__moz_comboboxtext: - aColor = mSystemColors.colorForeground; - break; - case eColorID__moz_combobox: - aColor = mSystemColors.colorBackground; - break; - case eColorID__moz_menubartext: - aColor = mSystemColors.colorForeground; - break; - case eColorID__moz_menubarhovertext: - aColor = FG_PRELIGHT_COLOR; - break; - default: - /* default color is BLACK */ - aColor = 0; - rv = NS_ERROR_FAILURE; - break; - } - - return rv; -} - - -nsresult -nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) -{ - nsresult rv = nsXPLookAndFeel::GetIntImpl(aID, aResult); - if (NS_SUCCEEDED(rv)) - return rv; - - rv = NS_OK; - - switch (aID) { - case eIntID_CaretBlinkTime: - aResult = 500; - break; - - case eIntID_CaretWidth: - aResult = 1; - break; - - case eIntID_ShowCaretDuringSelection: - aResult = 0; - break; - - case eIntID_SelectTextfieldsOnKeyFocus: - // Select textfield content when focused by kbd - // used by EventStateManager::sTextfieldSelectModel - aResult = 1; - break; - - case eIntID_SubmenuDelay: - aResult = 200; - break; - - case eIntID_TooltipDelay: - aResult = 500; - break; - - case eIntID_MenusCanOverlapOSBar: - // we want XUL popups to be able to overlap the task bar. - aResult = 1; - break; - - case eIntID_ScrollArrowStyle: - aResult = eScrollArrowStyle_Single; - break; - - case eIntID_ScrollSliderStyle: - aResult = eScrollThumbStyle_Proportional; - break; - - case eIntID_TouchEnabled: - aResult = 1; - break; - - case eIntID_ColorPickerAvailable: - aResult = 1; - break; - - case eIntID_WindowsDefaultTheme: - case eIntID_WindowsThemeIdentifier: - case eIntID_OperatingSystemVersionIdentifier: - aResult = 0; - rv = NS_ERROR_NOT_IMPLEMENTED; - break; - - case eIntID_SpellCheckerUnderlineStyle: - aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY; - break; - - case eIntID_ScrollbarButtonAutoRepeatBehavior: - aResult = 0; - break; - - default: - aResult = 0; - rv = NS_ERROR_FAILURE; - } - - return rv; -} - -nsresult -nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) -{ - nsresult rv = nsXPLookAndFeel::GetFloatImpl(aID, aResult); - if (NS_SUCCEEDED(rv)) - return rv; - rv = NS_OK; - - switch (aID) { - case eFloatID_IMEUnderlineRelativeSize: - aResult = 1.0f; - break; - - case eFloatID_SpellCheckerUnderlineRelativeSize: - aResult = 1.0f; - break; - - default: - aResult = -1.0; - rv = NS_ERROR_FAILURE; - break; - } - return rv; -} - -/*virtual*/ -bool -nsLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName, - gfxFontStyle& aFontStyle, - float aDevPixPerCSSPixel) -{ - aFontName.AssignLiteral("\"Droid Sans\""); - aFontStyle.style = NS_FONT_STYLE_NORMAL; - aFontStyle.weight = NS_FONT_WEIGHT_NORMAL; - aFontStyle.stretch = NS_FONT_STRETCH_NORMAL; - aFontStyle.size = 9.0 * 96.0f / 72.0f * aDevPixPerCSSPixel; - aFontStyle.systemFont = true; - return true; -} - -/*virtual*/ -bool -nsLookAndFeel::GetEchoPasswordImpl() -{ - if (!mInitializedShowPassword) { - if (XRE_GetProcessType() == GeckoProcessType_Default) { - mShowPassword = widget::GoannaAppShell::GetShowPasswordSetting(); - } else { - ContentChild::GetSingleton()->SendGetShowPasswordSetting(&mShowPassword); - } - mInitializedShowPassword = true; - } - return mShowPassword; -} - -uint32_t -nsLookAndFeel::GetPasswordMaskDelayImpl() -{ - // This value is hard-coded in Android OS's PasswordTransformationMethod.java - return 1500; -} - -/* virtual */ -char16_t -nsLookAndFeel::GetPasswordCharacterImpl() -{ - // This value is hard-coded in Android OS's PasswordTransformationMethod.java - return UNICODE_BULLET; -} diff --git a/widget/android/nsLookAndFeel.h b/widget/android/nsLookAndFeel.h deleted file mode 100644 index 9b33279a8b..0000000000 --- a/widget/android/nsLookAndFeel.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __nsLookAndFeel -#define __nsLookAndFeel - -#include "nsXPLookAndFeel.h" -#include "AndroidBridge.h" - -class nsLookAndFeel: public nsXPLookAndFeel -{ -public: - nsLookAndFeel(); - virtual ~nsLookAndFeel(); - - virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult); - virtual nsresult GetIntImpl(IntID aID, int32_t &aResult); - virtual nsresult GetFloatImpl(FloatID aID, float &aResult); - virtual bool GetFontImpl(FontID aID, nsString& aName, gfxFontStyle& aStyle, - float aDevPixPerCSSPixel); - virtual bool GetEchoPasswordImpl(); - virtual uint32_t GetPasswordMaskDelayImpl(); - virtual char16_t GetPasswordCharacterImpl(); - -protected: - static bool mInitializedSystemColors; - static mozilla::AndroidSystemColors mSystemColors; - static bool mInitializedShowPassword; - static bool mShowPassword; - - nsresult GetSystemColors(); - nsresult CallRemoteGetSystemColors(); -}; - -#endif diff --git a/widget/android/nsPrintOptionsAndroid.cpp b/widget/android/nsPrintOptionsAndroid.cpp deleted file mode 100644 index 90c6e016db..0000000000 --- a/widget/android/nsPrintOptionsAndroid.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsPrintOptionsAndroid.h" - -#include "nsPrintSettingsImpl.h" - -class nsPrintSettingsAndroid : public nsPrintSettings { -public: - nsPrintSettingsAndroid() - { - // The aim here is to set up the objects enough that silent printing works - SetOutputFormat(nsIPrintSettings::kOutputFormatPDF); - SetPrinterName(MOZ_UTF16("PDF printer")); - - } -}; - -nsPrintOptionsAndroid::nsPrintOptionsAndroid() -{ -} - -nsPrintOptionsAndroid::~nsPrintOptionsAndroid() -{ -} - -NS_IMETHODIMP nsPrintOptionsAndroid::CreatePrintSettings(nsIPrintSettings **_retval) -{ - nsPrintSettings * printSettings = new nsPrintSettingsAndroid(); - NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*_retval = printSettings); - (void)InitPrintSettingsFromPrefs(*_retval, false, - nsIPrintSettings::kInitSaveAll); - return NS_OK; -} diff --git a/widget/android/nsPrintOptionsAndroid.h b/widget/android/nsPrintOptionsAndroid.h deleted file mode 100644 index e617949145..0000000000 --- a/widget/android/nsPrintOptionsAndroid.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsPrintOptionsAndroid_h__ -#define nsPrintOptionsAndroid_h__ - -#include "nsPrintOptionsImpl.h" -#include "nsIPrintSettings.h" - -//***************************************************************************** -//*** nsPrintOptions -//***************************************************************************** -class nsPrintOptionsAndroid : public nsPrintOptions -{ -public: - nsPrintOptionsAndroid(); - virtual ~nsPrintOptionsAndroid(); - - NS_IMETHOD CreatePrintSettings(nsIPrintSettings **_retval); -}; - -#endif /* nsPrintOptionsAndroid_h__ */ diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp deleted file mode 100644 index 0da7417219..0000000000 --- a/widget/android/nsScreenManagerAndroid.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#define MOZ_FATAL_ASSERTIONS_FOR_THREAD_SAFETY - -#include "nsScreenManagerAndroid.h" -#include "nsWindow.h" -#include "AndroidBridge.h" - -using namespace mozilla; - -nsScreenAndroid::nsScreenAndroid(void *nativeScreen) -{ -} - -nsScreenAndroid::~nsScreenAndroid() -{ -} - -NS_IMETHODIMP -nsScreenAndroid::GetId(uint32_t *outId) -{ - *outId = 1; - return NS_OK; -} - -NS_IMETHODIMP -nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - gfxIntSize sz = nsWindow::GetAndroidScreenBounds(); - - *outLeft = 0; - *outTop = 0; - - *outWidth = sz.width; - *outHeight = sz.height; - - return NS_OK; -} - - -NS_IMETHODIMP -nsScreenAndroid::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - return GetRect(outLeft, outTop, outWidth, outHeight); -} - - - -NS_IMETHODIMP -nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth) -{ - *aPixelDepth = AndroidBridge::Bridge()->GetScreenDepth(); - return NS_OK; -} - - -NS_IMETHODIMP -nsScreenAndroid::GetColorDepth(int32_t *aColorDepth) -{ - return GetPixelDepth(aColorDepth); -} - -void -nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness) -{ - widget::GoannaAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL); -} - -NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager) - -nsScreenManagerAndroid::nsScreenManagerAndroid() -{ - mOneScreen = new nsScreenAndroid(nullptr); -} - -nsScreenManagerAndroid::~nsScreenManagerAndroid() -{ -} - -NS_IMETHODIMP -nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen) -{ - NS_IF_ADDREF(*outScreen = mOneScreen.get()); - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerAndroid::ScreenForId(uint32_t aId, - nsIScreen **outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -nsScreenManagerAndroid::ScreenForRect(int32_t inLeft, - int32_t inTop, - int32_t inWidth, - int32_t inHeight, - nsIScreen **outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -nsScreenManagerAndroid::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -nsScreenManagerAndroid::GetNumberOfScreens(uint32_t *aNumberOfScreens) -{ - *aNumberOfScreens = 1; - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerAndroid::GetSystemDefaultScale(float *aDefaultScale) -{ - *aDefaultScale = 1.0f; - return NS_OK; -} diff --git a/widget/android/nsScreenManagerAndroid.h b/widget/android/nsScreenManagerAndroid.h deleted file mode 100644 index 37a54654b3..0000000000 --- a/widget/android/nsScreenManagerAndroid.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsScreenManagerAndroid_h___ -#define nsScreenManagerAndroid_h___ - -#include "nsCOMPtr.h" - -#include "nsBaseScreen.h" -#include "nsIScreenManager.h" -#include "WidgetUtils.h" - -class nsScreenAndroid final : public nsBaseScreen -{ -public: - nsScreenAndroid(void *nativeScreen); - ~nsScreenAndroid(); - - NS_IMETHOD GetId(uint32_t* aId); - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - -protected: - virtual void ApplyMinimumBrightness(uint32_t aBrightness) override; -}; - -class nsScreenManagerAndroid final : public nsIScreenManager -{ -private: - ~nsScreenManagerAndroid(); - -public: - nsScreenManagerAndroid(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -protected: - nsCOMPtr mOneScreen; -}; - -#endif /* nsScreenManagerAndroid_h___ */ diff --git a/widget/android/nsWidgetFactory.cpp b/widget/android/nsWidgetFactory.cpp deleted file mode 100644 index a80182370d..0000000000 --- a/widget/android/nsWidgetFactory.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/ModuleUtils.h" -#include "mozilla/WidgetUtils.h" - -#include "nsCOMPtr.h" -#include "nsWidgetsCID.h" -#include "nsAppShell.h" -#include "AndroidBridge.h" - -#include "nsWindow.h" -#include "nsLookAndFeel.h" -#include "nsAppShellSingleton.h" -#include "nsScreenManagerAndroid.h" - -#include "nsIdleServiceAndroid.h" -#include "nsClipboard.h" -#include "nsClipboardHelper.h" -#include "nsTransferable.h" -#include "nsPrintOptionsAndroid.h" -#include "nsPrintSession.h" -#include "nsDeviceContextAndroid.h" -#include "nsHTMLFormatConverter.h" -#include "nsIMEPicker.h" -#include "nsXULAppAPI.h" -#include "nsAndroidProtocolHandler.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerAndroid) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceAndroid, nsIdleServiceAndroid::GetInstance) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsAndroid, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecAndroid) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsIMEPicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidBridge) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidProtocolHandler) - -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} -} - -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_WINDOW_CID); -NS_DEFINE_NAMED_CID(NS_CHILD_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID); -NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID); -NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); -NS_DEFINE_NAMED_CID(NS_IMEPICKER_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); -NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID); -NS_DEFINE_NAMED_CID(NS_ANDROIDPROTOCOLHANDLER_CID); - -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, - { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, - { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor }, - { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerAndroidConstructor }, - { &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceAndroidConstructor }, - { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor }, - { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor }, - { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor }, - { &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsAndroidConstructor }, - { &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor }, - { &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecAndroidConstructor }, - { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor }, - { &kNS_IMEPICKER_CID, false, nullptr, nsIMEPickerConstructor }, - { &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor }, - { &kNS_ANDROIDBRIDGE_CID, false, nullptr, nsAndroidBridgeConstructor }, - { &kNS_ANDROIDPROTOCOLHANDLER_CID, false, nullptr, nsAndroidProtocolHandlerConstructor }, - { nullptr } -}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - { "@mozilla.org/widgets/window/android;1", &kNS_WINDOW_CID }, - { "@mozilla.org/widgets/child_window/android;1", &kNS_CHILD_CID }, - { "@mozilla.org/widget/appshell/android;1", &kNS_APPSHELL_CID }, - { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID }, - { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID }, - { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, - { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID }, - { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID }, - { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID }, - { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID }, - { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID }, - { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, - { "@mozilla.org/imepicker;1", &kNS_IMEPICKER_CID }, - { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, - { "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID }, - { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "android", &kNS_ANDROIDPROTOCOLHANDLER_CID }, - { nullptr } -}; - -static void -nsWidgetAndroidModuleDtor() -{ - // Shutdown all XP level widget classes. - mozilla::widget::WidgetUtils::Shutdown(); - - nsLookAndFeel::Shutdown(); - nsAppShellShutdown(); -} - -static const mozilla::Module kWidgetModule = { - mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - nullptr, - nullptr, - nsAppShellInit, - nsWidgetAndroidModuleDtor -}; - -NSMODULE_DEFN(nsWidgetAndroidModule) = &kWidgetModule; diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp deleted file mode 100644 index 672e4c35b0..0000000000 --- a/widget/android/nsWindow.cpp +++ /dev/null @@ -1,2499 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include -#include - -#include "mozilla/MiscEvents.h" -#include "mozilla/MouseEvents.h" -#include "mozilla/TextEvents.h" -#include "mozilla/TouchEvents.h" - -#include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/ContentChild.h" -#include "mozilla/unused.h" -#include "mozilla/Preferences.h" -#include "mozilla/layers/RenderTrace.h" -#include - -using mozilla::dom::ContentParent; -using mozilla::dom::ContentChild; -using mozilla::unused; - -#include "nsAppShell.h" -#include "nsIdleService.h" -#include "nsWindow.h" -#include "nsIObserverService.h" -#include "nsFocusManager.h" -#include "nsIWidgetListener.h" -#include "nsViewManager.h" - -#include "nsIDOMSimpleGestureEvent.h" - -#include "nsGkAtoms.h" -#include "nsWidgetsCID.h" -#include "nsGfxCIID.h" - -#include "gfxContext.h" - -#include "Layers.h" -#include "mozilla/layers/LayerManagerComposite.h" -#include "mozilla/layers/AsyncCompositionManager.h" -#include "mozilla/layers/APZCTreeManager.h" -#include "GLContext.h" -#include "GLContextProvider.h" -#include "ScopedGLHelpers.h" -#include "mozilla/layers/CompositorOGL.h" -#include "APZCCallbackHandler.h" - -#include "nsTArray.h" - -#include "AndroidBridge.h" -#include "AndroidBridgeUtilities.h" -#include "android_npapi.h" - -#include "imgIEncoder.h" - -#include "nsString.h" -#include "GeckoProfiler.h" // For PROFILER_LABEL -#include "nsIXULRuntime.h" - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::widget; -using namespace mozilla::layers; - -NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget) - -// The dimensions of the current android view -static gfxIntSize gAndroidBounds = gfxIntSize(0, 0); -static gfxIntSize gAndroidScreenBounds; - -#include "mozilla/layers/CompositorChild.h" -#include "mozilla/layers/CompositorParent.h" -#include "mozilla/layers/LayerTransactionParent.h" -#include "mozilla/Mutex.h" -#include "mozilla/Services.h" -#include "nsThreadUtils.h" - -class ContentCreationNotifier; -static StaticRefPtr gContentCreationNotifier; - -// A helper class to send updates when content processes -// are created. Currently an update for the screen size is sent. -class ContentCreationNotifier final : public nsIObserver -{ -private: - ~ContentCreationNotifier() {} - -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) - { - if (!strcmp(aTopic, "ipc:content-created")) { - nsCOMPtr cpo = do_QueryInterface(aSubject); - ContentParent* cp = static_cast(cpo.get()); - unused << cp->SendScreenSizeChanged(gAndroidScreenBounds); - } else if (!strcmp(aTopic, "xpcom-shutdown")) { - nsCOMPtr obs = - mozilla::services::GetObserverService(); - if (obs) { - obs->RemoveObserver(static_cast(this), - "xpcom-shutdown"); - obs->RemoveObserver(static_cast(this), - "ipc:content-created"); - } - gContentCreationNotifier = nullptr; - } - - return NS_OK; - } -}; - -NS_IMPL_ISUPPORTS(ContentCreationNotifier, - nsIObserver) - -static bool gMenu; -static bool gMenuConsumed; - -// All the toplevel windows that have been created; these are in -// stacking order, so the window at gAndroidBounds[0] is the topmost -// one. -static nsTArray gTopLevelWindows; - -static bool sFailedToCreateGLContext = false; - -// Multitouch swipe thresholds in inches -static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4; -static const double SWIPE_MIN_DISTANCE_INCHES = 0.6; - -nsWindow* -nsWindow::TopWindow() -{ - if (!gTopLevelWindows.IsEmpty()) - return gTopLevelWindows[0]; - return nullptr; -} - -void -nsWindow::LogWindow(nsWindow *win, int index, int indent) -{ -#if defined(DEBUG) || defined(FORCE_ALOG) - char spaces[] = " "; - spaces[indent < 20 ? indent : 20] = 0; - ALOG("%s [% 2d] 0x%08x [parent 0x%08x] [% 3d,% 3dx% 3d,% 3d] vis %d type %d", - spaces, index, (intptr_t)win, (intptr_t)win->mParent, - win->mBounds.x, win->mBounds.y, - win->mBounds.width, win->mBounds.height, - win->mIsVisible, win->mWindowType); -#endif -} - -void -nsWindow::DumpWindows() -{ - DumpWindows(gTopLevelWindows); -} - -void -nsWindow::DumpWindows(const nsTArray& wins, int indent) -{ - for (uint32_t i = 0; i < wins.Length(); ++i) { - nsWindow *w = wins[i]; - LogWindow(w, i, indent); - DumpWindows(w->mChildren, indent+1); - } -} - -nsWindow::nsWindow() : - mIsVisible(false), - mParent(nullptr), - mFocus(nullptr), - mIMEComposing(false), - mIMEComposingStart(-1), - mIMEMaskSelectionUpdate(false), - mIMEMaskTextUpdate(false), - mIMEMaskEventsCount(1), // Mask IME events since there's no focus yet - mIMERanges(new TextRangeArray()), - mIMEUpdatingContext(false), - mIMESelectionChanged(false) -{ -} - -nsWindow::~nsWindow() -{ - gTopLevelWindows.RemoveElement(this); - nsWindow *top = FindTopLevel(); - if (top->mFocus == this) - top->mFocus = nullptr; - ALOG("nsWindow %p destructor", (void*)this); - if (mLayerManager == sLayerManager) { - // If this window was the one that created the global OMTC layer manager - // and compositor, then we should null those out. - SetCompositor(nullptr, nullptr, nullptr); - } -} - -bool -nsWindow::IsTopLevel() -{ - return mWindowType == eWindowType_toplevel || - mWindowType == eWindowType_dialog || - mWindowType == eWindowType_invisible; -} - -NS_IMETHODIMP -nsWindow::Create(nsIWidget *aParent, - nsNativeWidget aNativeParent, - const nsIntRect &aRect, - nsWidgetInitData *aInitData) -{ - ALOG("nsWindow[%p]::Create %p [%d %d %d %d]", (void*)this, (void*)aParent, aRect.x, aRect.y, aRect.width, aRect.height); - nsWindow *parent = (nsWindow*) aParent; - if (aNativeParent) { - if (parent) { - ALOG("Ignoring native parent on Android window [%p], since parent was specified (%p %p)", (void*)this, (void*)aNativeParent, (void*)aParent); - } else { - parent = (nsWindow*) aNativeParent; - } - } - - mBounds = aRect; - - // for toplevel windows, bounds are fixed to full screen size - if (!parent) { - mBounds.x = 0; - mBounds.y = 0; - mBounds.width = gAndroidBounds.width; - mBounds.height = gAndroidBounds.height; - } - - BaseCreate(nullptr, mBounds, aInitData); - - NS_ASSERTION(IsTopLevel() || parent, "non top level windowdoesn't have a parent!"); - - if (IsTopLevel()) { - gTopLevelWindows.AppendElement(this); - } - - if (parent) { - parent->mChildren.AppendElement(this); - mParent = parent; - } - -#ifdef DEBUG_ANDROID_WIDGET - DumpWindows(); -#endif - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Destroy(void) -{ - nsBaseWidget::mOnDestroyCalled = true; - - while (mChildren.Length()) { - // why do we still have children? - ALOG("### Warning: Destroying window %p and reparenting child %p to null!", (void*)this, (void*)mChildren[0]); - mChildren[0]->SetParent(nullptr); - } - - if (IsTopLevel()) - gTopLevelWindows.RemoveElement(this); - - SetParent(nullptr); - - nsBaseWidget::OnDestroy(); - -#ifdef DEBUG_ANDROID_WIDGET - DumpWindows(); -#endif - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::ConfigureChildren(const nsTArray& config) -{ - for (uint32_t i = 0; i < config.Length(); ++i) { - nsWindow *childWin = (nsWindow*) config[i].mChild; - childWin->Resize(config[i].mBounds.x, - config[i].mBounds.y, - config[i].mBounds.width, - config[i].mBounds.height, - false); - } - - return NS_OK; -} - -void -nsWindow::RedrawAll() -{ - if (mFocus && mFocus->mWidgetListener) { - mFocus->mWidgetListener->RequestRepaint(); - } -} - -NS_IMETHODIMP -nsWindow::SetParent(nsIWidget *aNewParent) -{ - if ((nsIWidget*)mParent == aNewParent) - return NS_OK; - - // If we had a parent before, remove ourselves from its list of - // children. - if (mParent) - mParent->mChildren.RemoveElement(this); - - mParent = (nsWindow*)aNewParent; - - if (mParent) - mParent->mChildren.AppendElement(this); - - // if we are now in the toplevel window's hierarchy, schedule a redraw - if (FindTopLevel() == nsWindow::TopWindow()) - RedrawAll(); - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::ReparentNativeWidget(nsIWidget *aNewParent) -{ - NS_PRECONDITION(aNewParent, ""); - return NS_OK; -} - -nsIWidget* -nsWindow::GetParent() -{ - return mParent; -} - -float -nsWindow::GetDPI() -{ - if (AndroidBridge::Bridge()) - return AndroidBridge::Bridge()->GetDPI(); - return 160.0f; -} - -double -nsWindow::GetDefaultScaleInternal() -{ - static double density = 0.0; - - if (density != 0.0) { - return density; - } - - density = GoannaAppShell::GetDensity(); - - if (!density) { - density = 1.0; - } - - return density; -} - -NS_IMETHODIMP -nsWindow::Show(bool aState) -{ - ALOG("nsWindow[%p]::Show %d", (void*)this, aState); - - if (mWindowType == eWindowType_invisible) { - ALOG("trying to show invisible window! ignoring.."); - return NS_ERROR_FAILURE; - } - - if (aState == mIsVisible) - return NS_OK; - - mIsVisible = aState; - - if (IsTopLevel()) { - // XXX should we bring this to the front when it's shown, - // if it's a toplevel widget? - - // XXX we should synthesize a NS_MOUSE_EXIT (for old top - // window)/NS_MOUSE_ENTER (for new top window) since we need - // to pretend that the top window always has focus. Not sure - // if Show() is the right place to do this, though. - - if (aState) { - // It just became visible, so send a resize update if necessary - // and bring it to the front. - Resize(0, 0, gAndroidBounds.width, gAndroidBounds.height, false); - BringToFront(); - } else if (nsWindow::TopWindow() == this) { - // find the next visible window to show - unsigned int i; - for (i = 1; i < gTopLevelWindows.Length(); i++) { - nsWindow *win = gTopLevelWindows[i]; - if (!win->mIsVisible) - continue; - - win->BringToFront(); - break; - } - } - } else if (FindTopLevel() == nsWindow::TopWindow()) { - RedrawAll(); - } - -#ifdef DEBUG_ANDROID_WIDGET - DumpWindows(); -#endif - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::SetModal(bool aState) -{ - ALOG("nsWindow[%p]::SetModal %d ignored", (void*)this, aState); - - return NS_OK; -} - -bool -nsWindow::IsVisible() const -{ - return mIsVisible; -} - -NS_IMETHODIMP -nsWindow::ConstrainPosition(bool aAllowSlop, - int32_t *aX, - int32_t *aY) -{ - ALOG("nsWindow[%p]::ConstrainPosition %d [%d %d]", (void*)this, aAllowSlop, *aX, *aY); - - // constrain toplevel windows; children we don't care about - if (IsTopLevel()) { - *aX = 0; - *aY = 0; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Move(double aX, - double aY) -{ - if (IsTopLevel()) - return NS_OK; - - return Resize(aX, - aY, - mBounds.width, - mBounds.height, - true); -} - -NS_IMETHODIMP -nsWindow::Resize(double aWidth, - double aHeight, - bool aRepaint) -{ - return Resize(mBounds.x, - mBounds.y, - aWidth, - aHeight, - aRepaint); -} - -NS_IMETHODIMP -nsWindow::Resize(double aX, - double aY, - double aWidth, - double aHeight, - bool aRepaint) -{ - ALOG("nsWindow[%p]::Resize [%f %f %f %f] (repaint %d)", (void*)this, aX, aY, aWidth, aHeight, aRepaint); - - bool needSizeDispatch = aWidth != mBounds.width || aHeight != mBounds.height; - - mBounds.x = NSToIntRound(aX); - mBounds.y = NSToIntRound(aY); - mBounds.width = NSToIntRound(aWidth); - mBounds.height = NSToIntRound(aHeight); - - if (needSizeDispatch) - OnSizeChanged(gfxIntSize(aWidth, aHeight)); - - // Should we skip honoring aRepaint here? - if (aRepaint && FindTopLevel() == nsWindow::TopWindow()) - RedrawAll(); - - return NS_OK; -} - -void -nsWindow::SetZIndex(int32_t aZIndex) -{ - ALOG("nsWindow[%p]::SetZIndex %d ignored", (void*)this, aZIndex); -} - -NS_IMETHODIMP -nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, - nsIWidget *aWidget, - bool aActivate) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::SetSizeMode(int32_t aMode) -{ - switch (aMode) { - case nsSizeMode_Minimized: - GoannaAppShell::MoveTaskToBack(); - break; - case nsSizeMode_Fullscreen: - MakeFullScreen(true); - break; - } - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Enable(bool aState) -{ - ALOG("nsWindow[%p]::Enable %d ignored", (void*)this, aState); - return NS_OK; -} - -bool -nsWindow::IsEnabled() const -{ - return true; -} - -NS_IMETHODIMP -nsWindow::Invalidate(const nsIntRect &aRect) -{ - return NS_OK; -} - -nsWindow* -nsWindow::FindTopLevel() -{ - nsWindow *toplevel = this; - while (toplevel) { - if (toplevel->IsTopLevel()) - return toplevel; - - toplevel = toplevel->mParent; - } - - ALOG("nsWindow::FindTopLevel(): couldn't find a toplevel or dialog window in this [%p] widget's hierarchy!", (void*)this); - return this; -} - -NS_IMETHODIMP -nsWindow::SetFocus(bool aRaise) -{ - if (!aRaise) { - ALOG("nsWindow::SetFocus: can't set focus without raising, ignoring aRaise = false!"); - } - - nsWindow *top = FindTopLevel(); - top->mFocus = this; - top->BringToFront(); - - return NS_OK; -} - -void -nsWindow::BringToFront() -{ - // If the window to be raised is the same as the currently raised one, - // do nothing. We need to check the focus manager as well, as the first - // window that is created will be first in the window list but won't yet - // be focused. - nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); - nsCOMPtr existingTopWindow; - fm->GetActiveWindow(getter_AddRefs(existingTopWindow)); - if (existingTopWindow && FindTopLevel() == nsWindow::TopWindow()) - return; - - if (!IsTopLevel()) { - FindTopLevel()->BringToFront(); - return; - } - - nsRefPtr kungFuDeathGrip(this); - - nsWindow *oldTop = nullptr; - nsWindow *newTop = this; - if (!gTopLevelWindows.IsEmpty()) - oldTop = gTopLevelWindows[0]; - - gTopLevelWindows.RemoveElement(this); - gTopLevelWindows.InsertElementAt(0, this); - - if (oldTop) { - nsIWidgetListener* listener = oldTop->GetWidgetListener(); - if (listener) { - listener->WindowDeactivated(); - } - } - - if (Destroyed()) { - // somehow the deactivate event handler destroyed this window. - // try to recover by grabbing the next window in line and activating - // that instead - if (gTopLevelWindows.IsEmpty()) - return; - newTop = gTopLevelWindows[0]; - } - - if (mWidgetListener) { - mWidgetListener->WindowActivated(); - } - - // force a window resize - nsAppShell::gAppShell->ResendLastResizeEvent(newTop); - RedrawAll(); -} - -NS_IMETHODIMP -nsWindow::GetScreenBounds(nsIntRect &aRect) -{ - LayoutDeviceIntPoint p = WidgetToScreenOffset(); - - aRect.x = p.x; - aRect.y = p.y; - aRect.width = mBounds.width; - aRect.height = mBounds.height; - - return NS_OK; -} - -LayoutDeviceIntPoint -nsWindow::WidgetToScreenOffset() -{ - LayoutDeviceIntPoint p(0, 0); - nsWindow *w = this; - - while (w && !w->IsTopLevel()) { - p.x += w->mBounds.x; - p.y += w->mBounds.y; - - w = w->mParent; - } - - return p; -} - -NS_IMETHODIMP -nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, - nsEventStatus &aStatus) -{ - aStatus = DispatchEvent(aEvent); - return NS_OK; -} - -nsEventStatus -nsWindow::DispatchEvent(WidgetGUIEvent* aEvent) -{ - if (mWidgetListener) { - nsEventStatus status = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); - - switch (aEvent->message) { - case NS_COMPOSITION_START: - MOZ_ASSERT(!mIMEComposing); - mIMEComposing = true; - break; - case NS_COMPOSITION_COMMIT_AS_IS: - case NS_COMPOSITION_COMMIT: - MOZ_ASSERT(mIMEComposing); - mIMEComposing = false; - mIMEComposingStart = -1; - mIMEComposingText.Truncate(); - break; - case NS_COMPOSITION_CHANGE: - MOZ_ASSERT(mIMEComposing); - mIMEComposingText = aEvent->AsCompositionEvent()->mData; - break; - } - return status; - } - return nsEventStatus_eIgnore; -} - -NS_IMETHODIMP -nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) -{ - GoannaAppShell::SetFullScreen(aFullScreen); - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::SetWindowClass(const nsAString& xulWinType) -{ - return NS_OK; -} - -mozilla::layers::LayerManager* -nsWindow::GetLayerManager(PLayerTransactionChild*, LayersBackend, LayerManagerPersistence, - bool* aAllowRetaining) -{ - if (aAllowRetaining) { - *aAllowRetaining = true; - } - if (mLayerManager) { - return mLayerManager; - } - // for OMTC allow use of the single layer manager/compositor - // shared across all windows - if (ShouldUseOffMainThreadCompositing()) { - return sLayerManager; - } - return nullptr; -} - -void -nsWindow::CreateLayerManager(int aCompositorWidth, int aCompositorHeight) -{ - if (mLayerManager) { - return; - } - - nsWindow *topLevelWindow = FindTopLevel(); - if (!topLevelWindow || topLevelWindow->mWindowType == eWindowType_invisible) { - // don't create a layer manager for an invisible top-level window - return; - } - - mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration); - - if (ShouldUseOffMainThreadCompositing()) { - if (sLayerManager) { - return; - } - CreateCompositor(aCompositorWidth, aCompositorHeight); - if (mLayerManager) { - // for OMTC create a single layer manager and compositor that will be - // used for all windows. - SetCompositor(mLayerManager, mCompositorParent, mCompositorChild); - sCompositorPaused = false; - return; - } - - // If we get here, then off main thread compositing failed to initialize. - sFailedToCreateGLContext = true; - } - - if (!mUseLayersAcceleration || sFailedToCreateGLContext) { - printf_stderr(" -- creating basic, not accelerated\n"); - mLayerManager = CreateBasicLayerManager(); - } -} - -void -nsWindow::OnGlobalAndroidEvent(AndroidGoannaEvent *ae) -{ - nsWindow *win = TopWindow(); - if (!win) - return; - - switch (ae->Type()) { - case AndroidGoannaEvent::FORCED_RESIZE: - win->mBounds.width = 0; - win->mBounds.height = 0; - // also resize the children - for (uint32_t i = 0; i < win->mChildren.Length(); i++) { - win->mChildren[i]->mBounds.width = 0; - win->mChildren[i]->mBounds.height = 0; - } - case AndroidGoannaEvent::SIZE_CHANGED: { - const nsTArray& points = ae->Points(); - NS_ASSERTION(points.Length() == 2, "Size changed does not have enough coordinates"); - - int nw = points[0].x; - int nh = points[0].y; - - if (ae->Type() == AndroidGoannaEvent::FORCED_RESIZE || nw != gAndroidBounds.width || - nh != gAndroidBounds.height) { - gAndroidBounds.width = nw; - gAndroidBounds.height = nh; - - // tell all the windows about the new size - for (size_t i = 0; i < gTopLevelWindows.Length(); ++i) { - if (gTopLevelWindows[i]->mIsVisible) - gTopLevelWindows[i]->Resize(gAndroidBounds.width, - gAndroidBounds.height, - false); - } - } - - int newScreenWidth = points[1].x; - int newScreenHeight = points[1].y; - - if (newScreenWidth == gAndroidScreenBounds.width && - newScreenHeight == gAndroidScreenBounds.height) - break; - - gAndroidScreenBounds.width = newScreenWidth; - gAndroidScreenBounds.height = newScreenHeight; - - if (XRE_GetProcessType() != GeckoProcessType_Default && - !Preferences::GetBool("browser.tabs.remote.desktopbehavior", false)) { - break; - } - - // Tell the content process the new screen size. - nsTArray cplist; - ContentParent::GetAll(cplist); - for (uint32_t i = 0; i < cplist.Length(); ++i) - unused << cplist[i]->SendScreenSizeChanged(gAndroidScreenBounds); - - if (gContentCreationNotifier) - break; - - // If the content process is not created yet, wait until it's - // created and then tell it the screen size. - nsCOMPtr obs = - mozilla::services::GetObserverService(); - if (!obs) - break; - - nsRefPtr notifier = new ContentCreationNotifier; - if (NS_SUCCEEDED(obs->AddObserver(notifier, "ipc:content-created", false))) { - if (NS_SUCCEEDED(obs->AddObserver(notifier, "xpcom-shutdown", false))) - gContentCreationNotifier = notifier; - else - obs->RemoveObserver(notifier, "ipc:content-created"); - } - break; - } - - case AndroidGoannaEvent::APZ_INPUT_EVENT: - case AndroidGoannaEvent::MOTION_EVENT: { - win->UserActivity(); - if (!gTopLevelWindows.IsEmpty()) { - nsIntPoint pt(0,0); - const nsTArray& points = ae->Points(); - if (points.Length() > 0) { - pt = points[0]; - } - pt.x = clamped(pt.x, 0, std::max(gAndroidBounds.width - 1, 0)); - pt.y = clamped(pt.y, 0, std::max(gAndroidBounds.height - 1, 0)); - nsWindow *target = win->FindWindowForPoint(pt); -#if 0 - ALOG("MOTION_EVENT %f,%f -> %p (visible: %d children: %d)", pt.x, pt.y, (void*)target, - target ? target->mIsVisible : 0, - target ? target->mChildren.Length() : 0); - - DumpWindows(); -#endif - if (target) { - bool preventDefaultActions = target->OnMultitouchEvent(ae); - if (!preventDefaultActions && ae->Count() < 2) - target->OnMouseEvent(ae); - } - } - break; - } - - // LongPress events mostly trigger contextmenu options, but can also lead to - // textSelection processing. - case AndroidGoannaEvent::LONG_PRESS: { - win->UserActivity(); - - nsCOMPtr obsServ = mozilla::services::GetObserverService(); - obsServ->NotifyObservers(nullptr, "before-build-contextmenu", nullptr); - - nsIntPoint pt; - const nsTArray& points = ae->Points(); - if (points.Length() > 0) { - pt = nsIntPoint(points[0].x, points[0].y); - } - - // Clamp our point within bounds, and locate the target element for the event. - pt.x = clamped(pt.x, 0, std::max(gAndroidBounds.width - 1, 0)); - pt.y = clamped(pt.y, 0, std::max(gAndroidBounds.height - 1, 0)); - nsWindow *target = win->FindWindowForPoint(pt); - if (target) { - // Send the contextmenu event to Goanna. - target->OnContextmenuEvent(ae); - } - break; - } - - case AndroidGoannaEvent::NATIVE_GESTURE_EVENT: { - nsIntPoint pt(0,0); - const nsTArray& points = ae->Points(); - if (points.Length() > 0) { - pt = points[0]; - } - pt.x = clamped(pt.x, 0, std::max(gAndroidBounds.width - 1, 0)); - pt.y = clamped(pt.y, 0, std::max(gAndroidBounds.height - 1, 0)); - nsWindow *target = win->FindWindowForPoint(pt); - - target->OnNativeGestureEvent(ae); - break; - } - - case AndroidGoannaEvent::KEY_EVENT: - win->UserActivity(); - if (win->mFocus) - win->mFocus->OnKeyEvent(ae); - break; - - case AndroidGoannaEvent::IME_EVENT: - win->UserActivity(); - if (win->mFocus) { - win->mFocus->OnIMEEvent(ae); - } else { - NS_WARNING("Sending unexpected IME event to top window"); - win->OnIMEEvent(ae); - } - break; - - case AndroidGoannaEvent::IME_KEY_EVENT: - // Keys synthesized by Java IME code are saved in the mIMEKeyEvents - // array until the next IME_REPLACE_TEXT event, at which point - // these keys are dispatched in sequence. - if (win->mFocus) { - win->mFocus->mIMEKeyEvents.AppendElement(*ae); - } - break; - - case AndroidGoannaEvent::COMPOSITOR_PAUSE: - // The compositor gets paused when the app is about to go into the - // background. While the compositor is paused, we need to ensure that - // no layer tree updates (from draw events) occur, since the compositor - // cannot make a GL context current in order to process updates. - if (sCompositorChild) { - sCompositorChild->SendPause(); - } - sCompositorPaused = true; - break; - - case AndroidGoannaEvent::COMPOSITOR_CREATE: - win->CreateLayerManager(ae->Width(), ae->Height()); - // Fallthrough - - case AndroidGoannaEvent::COMPOSITOR_RESUME: - // When we receive this, the compositor has already been told to - // resume. (It turns out that waiting till we reach here to tell - // the compositor to resume takes too long, resulting in a black - // flash.) This means it's now safe for layer updates to occur. - // Since we might have prevented one or more draw events from - // occurring while the compositor was paused, we need to schedule - // a draw event now. - if (!sCompositorPaused) { - win->RedrawAll(); - } - break; - } -} - -void -nsWindow::OnSizeChanged(const gfxIntSize& aSize) -{ - ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, aSize.width, aSize.height); - - mBounds.width = aSize.width; - mBounds.height = aSize.height; - - if (mWidgetListener) { - mWidgetListener->WindowResized(this, aSize.width, aSize.height); - } -} - -void -nsWindow::InitEvent(WidgetGUIEvent& event, nsIntPoint* aPoint) -{ - if (aPoint) { - event.refPoint.x = aPoint->x; - event.refPoint.y = aPoint->y; - } else { - event.refPoint.x = 0; - event.refPoint.y = 0; - } - - event.time = PR_Now() / 1000; -} - -gfxIntSize -nsWindow::GetAndroidScreenBounds() -{ - if (XRE_GetProcessType() == GeckoProcessType_Content) { - return ContentChild::GetSingleton()->GetScreenSize(); - } - return gAndroidScreenBounds; -} - -void * -nsWindow::GetNativeData(uint32_t aDataType) -{ - switch (aDataType) { - // used by GLContextProviderEGL, nullptr is EGL_DEFAULT_DISPLAY - case NS_NATIVE_DISPLAY: - return nullptr; - - case NS_NATIVE_WIDGET: - return (void *) this; - } - - return nullptr; -} - -void -nsWindow::OnMouseEvent(AndroidGoannaEvent *ae) -{ - nsRefPtr kungFuDeathGrip(this); - - WidgetMouseEvent event = ae->MakeMouseEvent(this); - if (event.message == NS_EVENT_NULL) { - // invalid event type, abort - return; - } - - // XXX add the double-click handling logic here - DispatchEvent(&event); -} - -void -nsWindow::OnContextmenuEvent(AndroidGoannaEvent *ae) -{ - nsRefPtr kungFuDeathGrip(this); - - CSSPoint pt; - const nsTArray& points = ae->Points(); - if (points.Length() > 0) { - pt = CSSPoint(points[0].x, points[0].y); - } - - // Send the contextmenu event. - WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this, - WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); - contextMenuEvent.refPoint = - RoundedToInt(pt * GetDefaultScale()) - WidgetToScreenOffset(); - contextMenuEvent.ignoreRootScrollFrame = true; - contextMenuEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; - - nsEventStatus contextMenuStatus; - DispatchEvent(&contextMenuEvent, contextMenuStatus); - - // If the contextmenu event was consumed (preventDefault issued), we follow with a - // touchcancel event. This avoids followup touchend events passsing through and - // triggering further element behaviour such as link-clicks. - if (contextMenuStatus == nsEventStatus_eConsumeNoDefault) { - WidgetTouchEvent canceltouchEvent = ae->MakeTouchEvent(this); - canceltouchEvent.message = NS_TOUCH_CANCEL; - DispatchEvent(&canceltouchEvent); - } -} - -bool nsWindow::OnMultitouchEvent(AndroidGoannaEvent *ae) -{ - nsRefPtr kungFuDeathGrip(this); - - // End any composition in progress in case the touch event listener - // modifies the input field value (see bug 856155) - RemoveIMEComposition(); - - // This is set to true once we have called SetPreventPanning() exactly - // once for a given sequence of touch events. It is reset on the start - // of the next sequence. - static bool sDefaultPreventedNotified = false; - static bool sLastWasDownEvent = false; - - bool preventDefaultActions = false; - bool isDownEvent = false; - - WidgetTouchEvent event = ae->MakeTouchEvent(this); - if (event.message != NS_EVENT_NULL) { - nsEventStatus status; - DispatchEvent(&event, status); - // We check mMultipleActionsPrevented because that's what - // sets when someone starts dragging the thumb. It doesn't set the status - // because it doesn't want to prevent the code that gives the input focus - // from running. - preventDefaultActions = (status == nsEventStatus_eConsumeNoDefault || - event.mFlags.mMultipleActionsPrevented); - isDownEvent = (event.message == NS_TOUCH_START); - } - - if (isDownEvent && event.touches.Length() == 1) { - // Since touch events don't get retargeted by PositionedEventTargeting.cpp - // code on Fennec, we dispatch a dummy mouse event that *does* get - // retargeted. The Fennec browser.js code can use this to activate the - // highlight element in case the this touchstart is the start of a tap. - WidgetMouseEvent hittest(true, NS_MOUSE_MOZHITTEST, this, WidgetMouseEvent::eReal); - hittest.refPoint = event.touches[0]->mRefPoint; - hittest.ignoreRootScrollFrame = true; - hittest.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; - nsEventStatus status; - DispatchEvent(&hittest, status); - } - - // if the last event we got was a down event, then by now we know for sure whether - // this block has been default-prevented or not. if we haven't already sent the - // notification for this block, do so now. - if (sLastWasDownEvent && !sDefaultPreventedNotified) { - // if this event is a down event, that means it's the start of a new block, and the - // previous block should not be default-prevented - bool defaultPrevented = isDownEvent ? false : preventDefaultActions; - if (ae->Type() == AndroidGoannaEvent::APZ_INPUT_EVENT) { - widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), defaultPrevented); - } else { - GoannaAppShell::NotifyDefaultPrevented(defaultPrevented); - } - sDefaultPreventedNotified = true; - } - - // now, if this event is a down event, then we might already know that it has been - // default-prevented. if so, we send the notification right away; otherwise we wait - // for the next event. - if (isDownEvent) { - if (preventDefaultActions) { - if (ae->Type() == AndroidGoannaEvent::APZ_INPUT_EVENT) { - widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzInputBlockId(), true); - } else { - GoannaAppShell::NotifyDefaultPrevented(true); - } - sDefaultPreventedNotified = true; - } else { - sDefaultPreventedNotified = false; - } - } - sLastWasDownEvent = isDownEvent; - - return preventDefaultActions; -} - -void -nsWindow::OnNativeGestureEvent(AndroidGoannaEvent *ae) -{ - LayoutDeviceIntPoint pt(ae->Points()[0].x, - ae->Points()[0].y); - double delta = ae->X(); - int msg = 0; - - switch (ae->Action()) { - case AndroidMotionEvent::ACTION_MAGNIFY_START: - msg = NS_SIMPLE_GESTURE_MAGNIFY_START; - mStartDist = delta; - mLastDist = delta; - break; - case AndroidMotionEvent::ACTION_MAGNIFY: - msg = NS_SIMPLE_GESTURE_MAGNIFY_UPDATE; - delta -= mLastDist; - mLastDist += delta; - break; - case AndroidMotionEvent::ACTION_MAGNIFY_END: - msg = NS_SIMPLE_GESTURE_MAGNIFY; - delta -= mStartDist; - break; - default: - return; - } - - nsRefPtr kungFuDeathGrip(this); - DispatchGestureEvent(msg, 0, delta, pt, ae->Time()); -} - -void -nsWindow::DispatchGestureEvent(uint32_t msg, uint32_t direction, double delta, - const LayoutDeviceIntPoint &refPoint, uint64_t time) -{ - WidgetSimpleGestureEvent event(true, msg, this); - - event.direction = direction; - event.delta = delta; - event.modifiers = 0; - event.time = time; - event.refPoint = refPoint; - - DispatchEvent(&event); -} - - -static unsigned int ConvertAndroidKeyCodeToDOMKeyCode(int androidKeyCode) -{ - // Special-case alphanumeric keycodes because they are most common. - if (androidKeyCode >= AKEYCODE_A && - androidKeyCode <= AKEYCODE_Z) { - return androidKeyCode - AKEYCODE_A + NS_VK_A; - } - - if (androidKeyCode >= AKEYCODE_0 && - androidKeyCode <= AKEYCODE_9) { - return androidKeyCode - AKEYCODE_0 + NS_VK_0; - } - - switch (androidKeyCode) { - // KEYCODE_UNKNOWN (0) ... KEYCODE_HOME (3) - case AKEYCODE_BACK: return NS_VK_ESCAPE; - // KEYCODE_CALL (5) ... KEYCODE_POUND (18) - case AKEYCODE_DPAD_UP: return NS_VK_UP; - case AKEYCODE_DPAD_DOWN: return NS_VK_DOWN; - case AKEYCODE_DPAD_LEFT: return NS_VK_LEFT; - case AKEYCODE_DPAD_RIGHT: return NS_VK_RIGHT; - case AKEYCODE_DPAD_CENTER: return NS_VK_RETURN; - case AKEYCODE_VOLUME_UP: return NS_VK_VOLUME_UP; - case AKEYCODE_VOLUME_DOWN: return NS_VK_VOLUME_DOWN; - // KEYCODE_VOLUME_POWER (26) ... KEYCODE_Z (54) - case AKEYCODE_COMMA: return NS_VK_COMMA; - case AKEYCODE_PERIOD: return NS_VK_PERIOD; - case AKEYCODE_ALT_LEFT: return NS_VK_ALT; - case AKEYCODE_ALT_RIGHT: return NS_VK_ALT; - case AKEYCODE_SHIFT_LEFT: return NS_VK_SHIFT; - case AKEYCODE_SHIFT_RIGHT: return NS_VK_SHIFT; - case AKEYCODE_TAB: return NS_VK_TAB; - case AKEYCODE_SPACE: return NS_VK_SPACE; - // KEYCODE_SYM (63) ... KEYCODE_ENVELOPE (65) - case AKEYCODE_ENTER: return NS_VK_RETURN; - case AKEYCODE_DEL: return NS_VK_BACK; // Backspace - case AKEYCODE_GRAVE: return NS_VK_BACK_QUOTE; - // KEYCODE_MINUS (69) - case AKEYCODE_EQUALS: return NS_VK_EQUALS; - case AKEYCODE_LEFT_BRACKET: return NS_VK_OPEN_BRACKET; - case AKEYCODE_RIGHT_BRACKET: return NS_VK_CLOSE_BRACKET; - case AKEYCODE_BACKSLASH: return NS_VK_BACK_SLASH; - case AKEYCODE_SEMICOLON: return NS_VK_SEMICOLON; - // KEYCODE_APOSTROPHE (75) - case AKEYCODE_SLASH: return NS_VK_SLASH; - // KEYCODE_AT (77) ... KEYCODE_MEDIA_FAST_FORWARD (90) - case AKEYCODE_MUTE: return NS_VK_VOLUME_MUTE; - case AKEYCODE_PAGE_UP: return NS_VK_PAGE_UP; - case AKEYCODE_PAGE_DOWN: return NS_VK_PAGE_DOWN; - // KEYCODE_PICTSYMBOLS (94) ... KEYCODE_BUTTON_MODE (110) - case AKEYCODE_ESCAPE: return NS_VK_ESCAPE; - case AKEYCODE_FORWARD_DEL: return NS_VK_DELETE; - case AKEYCODE_CTRL_LEFT: return NS_VK_CONTROL; - case AKEYCODE_CTRL_RIGHT: return NS_VK_CONTROL; - case AKEYCODE_CAPS_LOCK: return NS_VK_CAPS_LOCK; - case AKEYCODE_SCROLL_LOCK: return NS_VK_SCROLL_LOCK; - // KEYCODE_META_LEFT (117) ... KEYCODE_FUNCTION (119) - case AKEYCODE_SYSRQ: return NS_VK_PRINTSCREEN; - case AKEYCODE_BREAK: return NS_VK_PAUSE; - case AKEYCODE_MOVE_HOME: return NS_VK_HOME; - case AKEYCODE_MOVE_END: return NS_VK_END; - case AKEYCODE_INSERT: return NS_VK_INSERT; - // KEYCODE_FORWARD (125) ... KEYCODE_MEDIA_RECORD (130) - case AKEYCODE_F1: return NS_VK_F1; - case AKEYCODE_F2: return NS_VK_F2; - case AKEYCODE_F3: return NS_VK_F3; - case AKEYCODE_F4: return NS_VK_F4; - case AKEYCODE_F5: return NS_VK_F5; - case AKEYCODE_F6: return NS_VK_F6; - case AKEYCODE_F7: return NS_VK_F7; - case AKEYCODE_F8: return NS_VK_F8; - case AKEYCODE_F9: return NS_VK_F9; - case AKEYCODE_F10: return NS_VK_F10; - case AKEYCODE_F11: return NS_VK_F11; - case AKEYCODE_F12: return NS_VK_F12; - case AKEYCODE_NUM_LOCK: return NS_VK_NUM_LOCK; - case AKEYCODE_NUMPAD_0: return NS_VK_NUMPAD0; - case AKEYCODE_NUMPAD_1: return NS_VK_NUMPAD1; - case AKEYCODE_NUMPAD_2: return NS_VK_NUMPAD2; - case AKEYCODE_NUMPAD_3: return NS_VK_NUMPAD3; - case AKEYCODE_NUMPAD_4: return NS_VK_NUMPAD4; - case AKEYCODE_NUMPAD_5: return NS_VK_NUMPAD5; - case AKEYCODE_NUMPAD_6: return NS_VK_NUMPAD6; - case AKEYCODE_NUMPAD_7: return NS_VK_NUMPAD7; - case AKEYCODE_NUMPAD_8: return NS_VK_NUMPAD8; - case AKEYCODE_NUMPAD_9: return NS_VK_NUMPAD9; - case AKEYCODE_NUMPAD_DIVIDE: return NS_VK_DIVIDE; - case AKEYCODE_NUMPAD_MULTIPLY: return NS_VK_MULTIPLY; - case AKEYCODE_NUMPAD_SUBTRACT: return NS_VK_SUBTRACT; - case AKEYCODE_NUMPAD_ADD: return NS_VK_ADD; - case AKEYCODE_NUMPAD_DOT: return NS_VK_DECIMAL; - case AKEYCODE_NUMPAD_COMMA: return NS_VK_SEPARATOR; - case AKEYCODE_NUMPAD_ENTER: return NS_VK_RETURN; - case AKEYCODE_NUMPAD_EQUALS: return NS_VK_EQUALS; - // KEYCODE_NUMPAD_LEFT_PAREN (162) ... KEYCODE_CALCULATOR (210) - - // Needs to confirm the behavior. If the key switches the open state - // of Japanese IME (or switches input character between Hiragana and - // Roman numeric characters), then, it might be better to use - // NS_VK_KANJI which is used for Alt+Zenkaku/Hankaku key on Windows. - case AKEYCODE_ZENKAKU_HANKAKU: return 0; - case AKEYCODE_EISU: return NS_VK_EISU; - case AKEYCODE_MUHENKAN: return NS_VK_NONCONVERT; - case AKEYCODE_HENKAN: return NS_VK_CONVERT; - case AKEYCODE_KATAKANA_HIRAGANA: return 0; - case AKEYCODE_YEN: return NS_VK_BACK_SLASH; // Same as other platforms. - case AKEYCODE_RO: return NS_VK_BACK_SLASH; // Same as other platforms. - case AKEYCODE_KANA: return NS_VK_KANA; - case AKEYCODE_ASSIST: return NS_VK_HELP; - - // the A key is the action key for gamepad devices. - case AKEYCODE_BUTTON_A: return NS_VK_RETURN; - - default: - ALOG("ConvertAndroidKeyCodeToDOMKeyCode: " - "No DOM keycode for Android keycode %d", androidKeyCode); - return 0; - } -} - -static KeyNameIndex -ConvertAndroidKeyCodeToKeyNameIndex(AndroidGoannaEvent& aAndroidGoannaEvent) -{ - int keyCode = aAndroidGoannaEvent.KeyCode(); - // Special-case alphanumeric keycodes because they are most common. - if (keyCode >= AKEYCODE_A && keyCode <= AKEYCODE_Z) { - return KEY_NAME_INDEX_USE_STRING; - } - - if (keyCode >= AKEYCODE_0 && keyCode <= AKEYCODE_9) { - return KEY_NAME_INDEX_USE_STRING; - } - - switch (keyCode) { - -#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex) \ - case aNativeKey: return aKeyNameIndex; - -#include "NativeKeyToDOMKeyName.h" - -#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX - - // KEYCODE_0 (7) ... KEYCODE_9 (16) - case AKEYCODE_STAR: // '*' key - case AKEYCODE_POUND: // '#' key - - // KEYCODE_A (29) ... KEYCODE_Z (54) - - case AKEYCODE_COMMA: // ',' key - case AKEYCODE_PERIOD: // '.' key - case AKEYCODE_SPACE: - case AKEYCODE_GRAVE: // '`' key - case AKEYCODE_MINUS: // '-' key - case AKEYCODE_EQUALS: // '=' key - case AKEYCODE_LEFT_BRACKET: // '[' key - case AKEYCODE_RIGHT_BRACKET: // ']' key - case AKEYCODE_BACKSLASH: // '\' key - case AKEYCODE_SEMICOLON: // ';' key - case AKEYCODE_APOSTROPHE: // ''' key - case AKEYCODE_SLASH: // '/' key - case AKEYCODE_AT: // '@' key - case AKEYCODE_PLUS: // '+' key - - case AKEYCODE_NUMPAD_0: - case AKEYCODE_NUMPAD_1: - case AKEYCODE_NUMPAD_2: - case AKEYCODE_NUMPAD_3: - case AKEYCODE_NUMPAD_4: - case AKEYCODE_NUMPAD_5: - case AKEYCODE_NUMPAD_6: - case AKEYCODE_NUMPAD_7: - case AKEYCODE_NUMPAD_8: - case AKEYCODE_NUMPAD_9: - case AKEYCODE_NUMPAD_DIVIDE: - case AKEYCODE_NUMPAD_MULTIPLY: - case AKEYCODE_NUMPAD_SUBTRACT: - case AKEYCODE_NUMPAD_ADD: - case AKEYCODE_NUMPAD_DOT: - case AKEYCODE_NUMPAD_COMMA: - case AKEYCODE_NUMPAD_EQUALS: - case AKEYCODE_NUMPAD_LEFT_PAREN: - case AKEYCODE_NUMPAD_RIGHT_PAREN: - - case AKEYCODE_YEN: // yen sign key - case AKEYCODE_RO: // Japanese Ro key - return KEY_NAME_INDEX_USE_STRING; - - case AKEYCODE_SOFT_LEFT: - case AKEYCODE_SOFT_RIGHT: - case AKEYCODE_CALL: - case AKEYCODE_ENDCALL: - case AKEYCODE_NUM: // XXX Not sure - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_NOTIFICATION: // XXX Not sure - case AKEYCODE_PICTSYMBOLS: - - case AKEYCODE_BUTTON_A: - case AKEYCODE_BUTTON_B: - case AKEYCODE_BUTTON_C: - case AKEYCODE_BUTTON_X: - case AKEYCODE_BUTTON_Y: - case AKEYCODE_BUTTON_Z: - case AKEYCODE_BUTTON_L1: - case AKEYCODE_BUTTON_R1: - case AKEYCODE_BUTTON_L2: - case AKEYCODE_BUTTON_R2: - case AKEYCODE_BUTTON_THUMBL: - case AKEYCODE_BUTTON_THUMBR: - case AKEYCODE_BUTTON_START: - case AKEYCODE_BUTTON_SELECT: - case AKEYCODE_BUTTON_MODE: - - case AKEYCODE_MUTE: // mutes the microphone - case AKEYCODE_MEDIA_CLOSE: - - case AKEYCODE_DVR: - - case AKEYCODE_BUTTON_1: - case AKEYCODE_BUTTON_2: - case AKEYCODE_BUTTON_3: - case AKEYCODE_BUTTON_4: - case AKEYCODE_BUTTON_5: - case AKEYCODE_BUTTON_6: - case AKEYCODE_BUTTON_7: - case AKEYCODE_BUTTON_8: - case AKEYCODE_BUTTON_9: - case AKEYCODE_BUTTON_10: - case AKEYCODE_BUTTON_11: - case AKEYCODE_BUTTON_12: - case AKEYCODE_BUTTON_13: - case AKEYCODE_BUTTON_14: - case AKEYCODE_BUTTON_15: - case AKEYCODE_BUTTON_16: - - case AKEYCODE_MANNER_MODE: - case AKEYCODE_3D_MODE: - case AKEYCODE_CONTACTS: - return KEY_NAME_INDEX_Unidentified; - - case AKEYCODE_UNKNOWN: - MOZ_ASSERT( - aAndroidGoannaEvent.Action() != AKEY_EVENT_ACTION_MULTIPLE, - "Don't call this when action is AKEY_EVENT_ACTION_MULTIPLE!"); - // It's actually an unknown key if the action isn't ACTION_MULTIPLE. - // However, it might cause text input. So, let's check the value. - return aAndroidGoannaEvent.DOMPrintableKeyValue() ? - KEY_NAME_INDEX_USE_STRING : KEY_NAME_INDEX_Unidentified; - - default: - ALOG("ConvertAndroidKeyCodeToKeyNameIndex: " - "No DOM key name index for Android keycode %d", keyCode); - return KEY_NAME_INDEX_Unidentified; - } -} - -static CodeNameIndex -ConvertAndroidScanCodeToCodeNameIndex(AndroidGoannaEvent& aAndroidGoannaEvent) -{ - switch (aAndroidGoannaEvent.ScanCode()) { - -#define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, aCodeNameIndex) \ - case aNativeKey: return aCodeNameIndex; - -#include "NativeKeyToDOMCodeName.h" - -#undef NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX - - default: - return CODE_NAME_INDEX_UNKNOWN; - } -} - -static void InitPluginEvent(ANPEvent* pluginEvent, ANPKeyActions keyAction, - AndroidGoannaEvent& key) -{ - int androidKeyCode = key.KeyCode(); - uint32_t domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(androidKeyCode); - - int modifiers = 0; - if (key.IsAltPressed()) - modifiers |= kAlt_ANPKeyModifier; - if (key.IsShiftPressed()) - modifiers |= kShift_ANPKeyModifier; - - pluginEvent->inSize = sizeof(ANPEvent); - pluginEvent->eventType = kKey_ANPEventType; - pluginEvent->data.key.action = keyAction; - pluginEvent->data.key.nativeCode = androidKeyCode; - pluginEvent->data.key.virtualCode = domKeyCode; - pluginEvent->data.key.unichar = key.UnicodeChar(); - pluginEvent->data.key.modifiers = modifiers; - pluginEvent->data.key.repeatCount = key.RepeatCount(); -} - -void -nsWindow::InitKeyEvent(WidgetKeyboardEvent& event, AndroidGoannaEvent& key, - ANPEvent* pluginEvent) -{ - event.mKeyNameIndex = ConvertAndroidKeyCodeToKeyNameIndex(key); - if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { - int keyValue = key.DOMPrintableKeyValue(); - if (keyValue) { - event.mKeyValue = static_cast(keyValue); - } - } - event.mCodeNameIndex = ConvertAndroidScanCodeToCodeNameIndex(key); - uint32_t domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(key.KeyCode()); - - if (event.message == NS_KEY_PRESS) { - // Android gives us \n, so filter out some control characters. - int charCode = key.UnicodeChar(); - if (!charCode) { - charCode = key.BaseUnicodeChar(); - } - event.isChar = (charCode >= ' '); - event.charCode = event.isChar ? charCode : 0; - event.keyCode = (event.charCode > 0) ? 0 : domKeyCode; - event.mPluginEvent.Clear(); - } else { -#ifdef DEBUG - if (event.message != NS_KEY_DOWN && event.message != NS_KEY_UP) { - ALOG("InitKeyEvent: unexpected event.message %d", event.message); - } -#endif // DEBUG - - // Flash will want a pluginEvent for keydown and keyup events. - ANPKeyActions action = event.message == NS_KEY_DOWN - ? kDown_ANPKeyAction - : kUp_ANPKeyAction; - InitPluginEvent(pluginEvent, action, key); - - event.isChar = false; - event.charCode = 0; - event.keyCode = domKeyCode; - event.mPluginEvent.Copy(*pluginEvent); - } - - event.modifiers = key.DOMModifiers(); - if (gMenu) { - event.modifiers |= MODIFIER_CONTROL; - } - // For keypress, if the unicode char already has modifiers applied, we - // don't specify extra modifiers. If UnicodeChar() != BaseUnicodeChar() - // it means UnicodeChar() already has modifiers applied. - // Note that on Android 4.x, Alt modifier isn't set when the key input - // causes text input even while right Alt key is pressed. However, this - // is necessary for Android 2.3 compatibility. - if (event.message == NS_KEY_PRESS && - key.UnicodeChar() && key.UnicodeChar() != key.BaseUnicodeChar()) { - event.modifiers &= ~(MODIFIER_ALT | MODIFIER_CONTROL | MODIFIER_META); - } - - event.mIsRepeat = - (event.message == NS_KEY_DOWN || event.message == NS_KEY_PRESS) && - (!!(key.Flags() & AKEY_EVENT_FLAG_LONG_PRESS) || !!key.RepeatCount()); - event.location = - WidgetKeyboardEvent::ComputeLocationFromCodeValue(event.mCodeNameIndex); - event.time = key.Time(); - - if (gMenu) - gMenuConsumed = true; -} - -void -nsWindow::HandleSpecialKey(AndroidGoannaEvent *ae) -{ - nsRefPtr kungFuDeathGrip(this); - nsCOMPtr command; - bool isDown = ae->Action() == AKEY_EVENT_ACTION_DOWN; - bool isLongPress = !!(ae->Flags() & AKEY_EVENT_FLAG_LONG_PRESS); - bool doCommand = false; - uint32_t keyCode = ae->KeyCode(); - - if (isDown) { - switch (keyCode) { - case AKEYCODE_BACK: - if (isLongPress) { - command = nsGkAtoms::Clear; - doCommand = true; - } - break; - case AKEYCODE_MENU: - gMenu = true; - gMenuConsumed = isLongPress; - break; - } - } else { - switch (keyCode) { - case AKEYCODE_BACK: { - // XXX Where is the keydown event for this?? - WidgetKeyboardEvent pressEvent(true, NS_KEY_PRESS, this); - ANPEvent pluginEvent; - InitKeyEvent(pressEvent, *ae, &pluginEvent); - DispatchEvent(&pressEvent); - return; - } - case AKEYCODE_MENU: - gMenu = false; - if (!gMenuConsumed) { - command = nsGkAtoms::Menu; - doCommand = true; - } - break; - case AKEYCODE_SEARCH: - command = nsGkAtoms::Search; - doCommand = true; - break; - default: - ALOG("Unknown special key code!"); - return; - } - } - if (doCommand) { - WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, command, this); - InitEvent(event); - DispatchEvent(&event); - } -} - -void -nsWindow::OnKeyEvent(AndroidGoannaEvent *ae) -{ - nsRefPtr kungFuDeathGrip(this); - RemoveIMEComposition(); - uint32_t msg; - switch (ae->Action()) { - case AKEY_EVENT_ACTION_DOWN: - msg = NS_KEY_DOWN; - break; - case AKEY_EVENT_ACTION_UP: - msg = NS_KEY_UP; - break; - case AKEY_EVENT_ACTION_MULTIPLE: - // Keys with multiple action are handled in Java, - // and we should never see one here - MOZ_CRASH("Cannot handle key with multiple action"); - default: - ALOG("Unknown key action event!"); - return; - } - - bool firePress = ae->Action() == AKEY_EVENT_ACTION_DOWN; - switch (ae->KeyCode()) { - case AKEYCODE_SHIFT_LEFT: - case AKEYCODE_SHIFT_RIGHT: - case AKEYCODE_ALT_LEFT: - case AKEYCODE_ALT_RIGHT: - case AKEYCODE_CTRL_LEFT: - case AKEYCODE_CTRL_RIGHT: - firePress = false; - break; - case AKEYCODE_BACK: - case AKEYCODE_MENU: - case AKEYCODE_SEARCH: - HandleSpecialKey(ae); - return; - } - - nsEventStatus status; - WidgetKeyboardEvent event(true, msg, this); - ANPEvent pluginEvent; - InitKeyEvent(event, *ae, &pluginEvent); - DispatchEvent(&event, status); - - if (Destroyed()) - return; - if (!firePress || status == nsEventStatus_eConsumeNoDefault) { - return; - } - - WidgetKeyboardEvent pressEvent(true, NS_KEY_PRESS, this); - InitKeyEvent(pressEvent, *ae, &pluginEvent); -#ifdef DEBUG_ANDROID_WIDGET - __android_log_print(ANDROID_LOG_INFO, "Goanna", "Dispatching key pressEvent with keyCode %d charCode %d shift %d alt %d sym/ctrl %d metamask %d", pressEvent.keyCode, pressEvent.charCode, pressEvent.IsShift(), pressEvent.IsAlt(), pressEvent.IsControl(), ae->MetaState()); -#endif - DispatchEvent(&pressEvent); -} - -#ifdef DEBUG_ANDROID_IME -#define ALOGIME(args...) ALOG(args) -#else -#define ALOGIME(args...) ((void)0) -#endif - -static nscolor -ConvertAndroidColor(uint32_t argb) -{ - return NS_RGBA((argb & 0x00ff0000) >> 16, - (argb & 0x0000ff00) >> 8, - (argb & 0x000000ff), - (argb & 0xff000000) >> 24); -} - -class AutoIMEMask { -private: - bool mOldMask, *mMask; -public: - AutoIMEMask(bool &mask) : mOldMask(mask), mMask(&mask) { - mask = true; - } - ~AutoIMEMask() { - *mMask = mOldMask; - } -}; - -/* - Remove the composition but leave the text content as-is -*/ -void -nsWindow::RemoveIMEComposition() -{ - // Remove composition on Goanna side - if (!mIMEComposing) - return; - - nsRefPtr kungFuDeathGrip(this); - AutoIMEMask selMask(mIMEMaskSelectionUpdate); - AutoIMEMask textMask(mIMEMaskTextUpdate); - - WidgetCompositionEvent compositionCommitEvent(true, - NS_COMPOSITION_COMMIT_AS_IS, - this); - InitEvent(compositionCommitEvent, nullptr); - DispatchEvent(&compositionCommitEvent); -} - -void -nsWindow::OnIMEEvent(AndroidGoannaEvent *ae) -{ - MOZ_ASSERT(!mIMEMaskTextUpdate); - MOZ_ASSERT(!mIMEMaskSelectionUpdate); - /* - Rules for managing IME between Goanna and Java: - - * Goanna controls the text content, and Java shadows the Goanna text - through text updates - * Java controls the selection, and Goanna shadows the Java selection - through set selection events - * Java controls the composition, and Goanna shadows the Java - composition through update composition events - */ - nsRefPtr kungFuDeathGrip(this); - - if (ae->Action() == AndroidGoannaEvent::IME_ACKNOWLEDGE_FOCUS) { - MOZ_ASSERT(mIMEMaskEventsCount > 0); - mIMEMaskEventsCount--; - if (!mIMEMaskEventsCount) { - // The focusing handshake sequence is complete, and Java is waiting - // on Goanna. Now we can notify Java of the newly focused content - mIMETextChanges.Clear(); - mIMESelectionChanged = false; - // NotifyIMEOfTextChange also notifies selection - // Use 'INT32_MAX / 2' here because subsequent text changes might - // combine with this text change, and overflow might occur if - // we just use INT32_MAX - IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE); - notification.mTextChangeData.mOldEndOffset = - notification.mTextChangeData.mNewEndOffset = INT32_MAX / 2; - NotifyIMEOfTextChange(notification); - FlushIMEChanges(); - } - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT); - return; - - } else if (ae->Action() == AndroidGoannaEvent::IME_UPDATE_CONTEXT) { - GoannaAppShell::NotifyIMEContext(mInputContext.mIMEState.mEnabled, - mInputContext.mHTMLInputType, - mInputContext.mHTMLInputInputmode, - mInputContext.mActionHint); - mIMEUpdatingContext = false; - return; - } - - if (mIMEMaskEventsCount > 0) { - // Still reply to events, but don't do anything else - if (ae->Action() == AndroidGoannaEvent::IME_SYNCHRONIZE || - ae->Action() == AndroidGoannaEvent::IME_COMPOSE_TEXT || - ae->Action() == AndroidGoannaEvent::IME_REPLACE_TEXT) { - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT); - } - return; - } - - switch (ae->Action()) { - case AndroidGoannaEvent::IME_FLUSH_CHANGES: - { - FlushIMEChanges(); - } - break; - - case AndroidGoannaEvent::IME_SYNCHRONIZE: - { - FlushIMEChanges(); - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT); - } - break; - - case AndroidGoannaEvent::IME_REPLACE_TEXT: - case AndroidGoannaEvent::IME_COMPOSE_TEXT: - { - /* - Replace text in Goanna thread from ae->Start() to ae->End() - with the string ae->Characters() - - Selection updates are masked so the result of our temporary - selection event is not passed on to Java - - Text updates are passed on, so the Java text can shadow the - Goanna text - */ - AutoIMEMask selMask(mIMEMaskSelectionUpdate); - - if (!mIMEKeyEvents.IsEmpty() || - mIMEComposingStart < 0 || - ae->Start() != mIMEComposingStart || - ae->End() != mIMEComposingStart + - int32_t(mIMEComposingText.Length())) { - - // Only start a new composition if we have key events, - // if we don't have an existing composition, or - // the replaced text does not match our composition. - RemoveIMEComposition(); - - { - WidgetSelectionEvent event(true, NS_SELECTION_SET, this); - InitEvent(event, nullptr); - event.mOffset = uint32_t(ae->Start()); - event.mLength = uint32_t(ae->End() - ae->Start()); - event.mExpandToClusterBoundary = false; - DispatchEvent(&event); - } - - if (!mIMEKeyEvents.IsEmpty()) { - for (uint32_t i = 0; i < mIMEKeyEvents.Length(); i++) { - OnKeyEvent(&mIMEKeyEvents[i]); - } - mIMEKeyEvents.Clear(); - FlushIMEChanges(); - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT); - // Break out of the switch block - break; - } - - { - WidgetCompositionEvent event( - true, NS_COMPOSITION_START, this); - InitEvent(event, nullptr); - DispatchEvent(&event); - mIMEComposingStart = ae->Start(); - } - } - - { - WidgetCompositionEvent event(true, NS_COMPOSITION_CHANGE, this); - InitEvent(event, nullptr); - event.mData = ae->Characters(); - - if (ae->Action() == AndroidGoannaEvent::IME_COMPOSE_TEXT) { - // Because we're leaving the composition open, we need to - // include proper text ranges to make the editor happy. - TextRange range; - range.mStartOffset = 0; - range.mEndOffset = event.mData.Length(); - range.mRangeType = NS_TEXTRANGE_RAWINPUT; - event.mRanges = new TextRangeArray(); - event.mRanges->AppendElement(range); - } - - DispatchEvent(&event); - } - - // Don't end composition when composing text. - if (ae->Action() != AndroidGoannaEvent::IME_COMPOSE_TEXT) - { - WidgetCompositionEvent compositionCommitEvent( - true, NS_COMPOSITION_COMMIT, this); - InitEvent(compositionCommitEvent, nullptr); - compositionCommitEvent.mData = ae->Characters(); - DispatchEvent(&compositionCommitEvent); - } - - FlushIMEChanges(); - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT); - } - break; - - case AndroidGoannaEvent::IME_SET_SELECTION: - { - /* - Set Goanna selection to ae->Start() to ae->End() - - Selection updates are masked to prevent Java from being - notified of the new selection - */ - AutoIMEMask selMask(mIMEMaskSelectionUpdate); - RemoveIMEComposition(); - WidgetSelectionEvent selEvent(true, NS_SELECTION_SET, this); - InitEvent(selEvent, nullptr); - - int32_t start = ae->Start(), end = ae->End(); - - if (start < 0 || end < 0) { - WidgetQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, - this); - InitEvent(event, nullptr); - DispatchEvent(&event); - MOZ_ASSERT(event.mSucceeded && !event.mWasAsync); - - if (start < 0) - start = int32_t(event.GetSelectionStart()); - if (end < 0) - end = int32_t(event.GetSelectionEnd()); - } - - selEvent.mOffset = std::min(start, end); - selEvent.mLength = std::max(start, end) - selEvent.mOffset; - selEvent.mReversed = start > end; - selEvent.mExpandToClusterBoundary = false; - - DispatchEvent(&selEvent); - } - break; - case AndroidGoannaEvent::IME_ADD_COMPOSITION_RANGE: - { - TextRange range; - range.mStartOffset = ae->Start(); - range.mEndOffset = ae->End(); - range.mRangeType = ae->RangeType(); - range.mRangeStyle.mDefinedStyles = ae->RangeStyles(); - range.mRangeStyle.mLineStyle = ae->RangeLineStyle(); - range.mRangeStyle.mIsBoldLine = ae->RangeBoldLine(); - range.mRangeStyle.mForegroundColor = - ConvertAndroidColor(uint32_t(ae->RangeForeColor())); - range.mRangeStyle.mBackgroundColor = - ConvertAndroidColor(uint32_t(ae->RangeBackColor())); - range.mRangeStyle.mUnderlineColor = - ConvertAndroidColor(uint32_t(ae->RangeLineColor())); - mIMERanges->AppendElement(range); - } - break; - case AndroidGoannaEvent::IME_UPDATE_COMPOSITION: - { - /* - Update the composition from ae->Start() to ae->End() using - information from added ranges. This is only used for - visual indication and does not affect the text content. - Only the offsets are specified and not the text content - to eliminate the possibility of this event altering the - text content unintentionally. - - Selection and text updates are masked so the result of - temporary events are not passed on to Java - */ - AutoIMEMask selMask(mIMEMaskSelectionUpdate); - AutoIMEMask textMask(mIMEMaskTextUpdate); - - WidgetCompositionEvent event(true, NS_COMPOSITION_CHANGE, this); - InitEvent(event, nullptr); - - event.mRanges = new TextRangeArray(); - mIMERanges.swap(event.mRanges); - - if (mIMEComposingStart < 0 || - ae->Start() != mIMEComposingStart || - ae->End() != mIMEComposingStart + - int32_t(mIMEComposingText.Length())) { - - // Only start new composition if we don't have an existing one, - // or if the existing composition doesn't match the new one. - RemoveIMEComposition(); - - { - WidgetSelectionEvent event(true, NS_SELECTION_SET, this); - InitEvent(event, nullptr); - event.mOffset = uint32_t(ae->Start()); - event.mLength = uint32_t(ae->End() - ae->Start()); - event.mExpandToClusterBoundary = false; - DispatchEvent(&event); - } - - { - WidgetQueryContentEvent queryEvent(true, - NS_QUERY_SELECTED_TEXT, - this); - InitEvent(queryEvent, nullptr); - DispatchEvent(&queryEvent); - MOZ_ASSERT(queryEvent.mSucceeded && !queryEvent.mWasAsync); - event.mData = queryEvent.mReply.mString; - - mIMEComposingStart = queryEvent.mReply.mOffset; - } - - { - WidgetCompositionEvent event( - true, NS_COMPOSITION_START, this); - InitEvent(event, nullptr); - DispatchEvent(&event); - } - - } else { - // If the new composition matches the existing composition, - // reuse the old composition. - event.mData = mIMEComposingText; - } - -#ifdef DEBUG_ANDROID_IME - const NS_ConvertUTF16toUTF8 data(event.mData); - const char* text = data.get(); - ALOGIME("IME: IME_SET_TEXT: text=\"%s\", length=%u, range=%u", - text, event.mData.Length(), event.mRanges->Length()); -#endif // DEBUG_ANDROID_IME - - DispatchEvent(&event); - } - break; - - case AndroidGoannaEvent::IME_REMOVE_COMPOSITION: - { - /* - * Remove any previous composition. This is only used for - * visual indication and does not affect the text content. - * - * Selection and text updates are masked so the result of - * temporary events are not passed on to Java - */ - AutoIMEMask selMask(mIMEMaskSelectionUpdate); - AutoIMEMask textMask(mIMEMaskTextUpdate); - RemoveIMEComposition(); - mIMERanges->Clear(); - } - break; - } -} - -nsWindow * -nsWindow::FindWindowForPoint(const nsIntPoint& pt) -{ - if (!mBounds.Contains(pt)) - return nullptr; - - // children mBounds are relative to their parent - nsIntPoint childPoint(pt.x - mBounds.x, pt.y - mBounds.y); - - for (uint32_t i = 0; i < mChildren.Length(); ++i) { - if (mChildren[i]->mBounds.Contains(childPoint)) - return mChildren[i]->FindWindowForPoint(childPoint); - } - - return this; -} - -void -nsWindow::UserActivity() -{ - if (!mIdleService) { - mIdleService = do_GetService("@mozilla.org/widget/idleservice;1"); - } - - if (mIdleService) { - mIdleService->ResetIdleTimeOut(0); - } -} - -nsresult -nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification) -{ - switch (aIMENotification.mMessage) { - case REQUEST_TO_COMMIT_COMPOSITION: - //ALOGIME("IME: REQUEST_TO_COMMIT_COMPOSITION: s=%d", aState); - RemoveIMEComposition(); - GoannaAppShell::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION); - return NS_OK; - case REQUEST_TO_CANCEL_COMPOSITION: - ALOGIME("IME: REQUEST_TO_CANCEL_COMPOSITION"); - - // Cancel composition on Goanna side - if (mIMEComposing) { - nsRefPtr kungFuDeathGrip(this); - - WidgetCompositionEvent compositionCommitEvent( - true, NS_COMPOSITION_COMMIT, this); - InitEvent(compositionCommitEvent, nullptr); - // Dispatch it with empty mData value for canceling the - // composition - DispatchEvent(&compositionCommitEvent); - } - - GoannaAppShell::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION); - return NS_OK; - case NOTIFY_IME_OF_FOCUS: - ALOGIME("IME: NOTIFY_IME_OF_FOCUS"); - GoannaAppShell::NotifyIME(NOTIFY_IME_OF_FOCUS); - return NS_OK; - case NOTIFY_IME_OF_BLUR: - ALOGIME("IME: NOTIFY_IME_OF_BLUR"); - - // Mask events because we lost focus. On the next focus event, - // Goanna will notify Java, and Java will send an acknowledge focus - // event back to Goanna. That is where we unmask event handling - mIMEMaskEventsCount++; - mIMEComposing = false; - mIMEComposingText.Truncate(); - - GoannaAppShell::NotifyIME(NOTIFY_IME_OF_BLUR); - return NS_OK; - case NOTIFY_IME_OF_SELECTION_CHANGE: - if (mIMEMaskSelectionUpdate) { - return NS_OK; - } - - ALOGIME("IME: NOTIFY_IME_OF_SELECTION_CHANGE"); - - PostFlushIMEChanges(); - mIMESelectionChanged = true; - return NS_OK; - case NOTIFY_IME_OF_TEXT_CHANGE: - return NotifyIMEOfTextChange(aIMENotification); - default: - return NS_ERROR_NOT_IMPLEMENTED; - } -} - -NS_IMETHODIMP_(void) -nsWindow::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - nsWindow *top = TopWindow(); - if (top && top->mFocus && this != top->mFocus) { - // We are using an IME event later to notify Java, and the IME event - // will be processed by the focused window. Therefore, to ensure the - // IME event uses the correct mInputContext, we need to let the focused - // window process SetInputContext - top->mFocus->SetInputContext(aContext, aAction); - return; - } - - ALOGIME("IME: SetInputContext: s=0x%X, 0x%X, action=0x%X, 0x%X", - aContext.mIMEState.mEnabled, aContext.mIMEState.mOpen, - aAction.mCause, aAction.mFocusChange); - - mInputContext = aContext; - - // Ensure that opening the virtual keyboard is allowed for this specific - // InputContext depending on the content.ime.strict.policy pref - if (aContext.mIMEState.mEnabled != IMEState::DISABLED && - aContext.mIMEState.mEnabled != IMEState::PLUGIN && - Preferences::GetBool("content.ime.strict_policy", false) && - !aAction.ContentGotFocusByTrustedCause() && - !aAction.UserMightRequestOpenVKB()) { - return; - } - - IMEState::Enabled enabled = aContext.mIMEState.mEnabled; - - // Only show the virtual keyboard for plugins if mOpen is set appropriately. - // This avoids showing it whenever a plugin is focused. Bug 747492 - if (aContext.mIMEState.mEnabled == IMEState::PLUGIN && - aContext.mIMEState.mOpen != IMEState::OPEN) { - enabled = IMEState::DISABLED; - } - - mInputContext.mIMEState.mEnabled = enabled; - - if (enabled == IMEState::ENABLED && aAction.UserMightRequestOpenVKB()) { - // Don't reset keyboard when we should simply open the vkb - GoannaAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB); - return; - } - - if (mIMEUpdatingContext) { - return; - } - AndroidGoannaEvent *event = AndroidGoannaEvent::MakeIMEEvent( - AndroidGoannaEvent::IME_UPDATE_CONTEXT); - nsAppShell::gAppShell->PostEvent(event); - mIMEUpdatingContext = true; -} - -NS_IMETHODIMP_(InputContext) -nsWindow::GetInputContext() -{ - nsWindow *top = TopWindow(); - if (top && top->mFocus && this != top->mFocus) { - // We let the focused window process SetInputContext, - // so we should let it process GetInputContext as well. - return top->mFocus->GetInputContext(); - } - InputContext context = mInputContext; - context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED; - // We assume that there is only one context per process on Android - context.mNativeIMEContext = nullptr; - return context; -} - -void -nsWindow::PostFlushIMEChanges() -{ - if (!mIMETextChanges.IsEmpty() || mIMESelectionChanged) { - // Already posted - return; - } - AndroidGoannaEvent *event = AndroidGoannaEvent::MakeIMEEvent( - AndroidGoannaEvent::IME_FLUSH_CHANGES); - nsAppShell::gAppShell->PostEvent(event); -} - -void -nsWindow::FlushIMEChanges() -{ - nsRefPtr kungFuDeathGrip(this); - for (uint32_t i = 0; i < mIMETextChanges.Length(); i++) { - IMEChange &change = mIMETextChanges[i]; - - if (change.mStart == change.mOldEnd && - change.mStart == change.mNewEnd) { - continue; - } - - WidgetQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, this); - - if (change.mNewEnd != change.mStart) { - InitEvent(event, nullptr); - event.InitForQueryTextContent(change.mStart, - change.mNewEnd - change.mStart); - DispatchEvent(&event); - if (!event.mSucceeded) - return; - } - - GoannaAppShell::NotifyIMEChange(event.mReply.mString, change.mStart, - change.mOldEnd, change.mNewEnd); - } - mIMETextChanges.Clear(); - - if (mIMESelectionChanged) { - WidgetQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, this); - InitEvent(event, nullptr); - - DispatchEvent(&event); - if (!event.mSucceeded) - return; - - GoannaAppShell::NotifyIMEChange(EmptyString(), - int32_t(event.GetSelectionStart()), - int32_t(event.GetSelectionEnd()), -1); - mIMESelectionChanged = false; - } -} - -nsresult -nsWindow::NotifyIMEOfTextChange(const IMENotification& aIMENotification) -{ - MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE, - "NotifyIMEOfTextChange() is called with invaild notification"); - - if (mIMEMaskTextUpdate) - return NS_OK; - - ALOGIME("IME: NotifyIMEOfTextChange: s=%d, oe=%d, ne=%d", - aIMENotification.mTextChangeData.mStartOffset, - aIMENotification.mTextChangeData.mOldEndOffset, - aIMENotification.mTextChangeData.mNewEndOffset); - - /* Make sure Java's selection is up-to-date */ - mIMESelectionChanged = false; - NotifyIME(NOTIFY_IME_OF_SELECTION_CHANGE); - PostFlushIMEChanges(); - - mIMETextChanges.AppendElement(IMEChange(aIMENotification)); - // Now that we added a new range we need to go back and - // update all the ranges before that. - // Ranges that have offsets which follow this new range - // need to be updated to reflect new offsets - int32_t delta = aIMENotification.mTextChangeData.AdditionalLength(); - for (int32_t i = mIMETextChanges.Length() - 2; i >= 0; i--) { - IMEChange &previousChange = mIMETextChanges[i]; - if (previousChange.mStart > - static_cast( - aIMENotification.mTextChangeData.mOldEndOffset)) { - previousChange.mStart += delta; - previousChange.mOldEnd += delta; - previousChange.mNewEnd += delta; - } - } - - // Now go through all ranges to merge any ranges that are connected - // srcIndex is the index of the range to merge from - // dstIndex is the index of the range to potentially merge into - int32_t srcIndex = mIMETextChanges.Length() - 1; - int32_t dstIndex = srcIndex; - - while (--dstIndex >= 0) { - IMEChange &src = mIMETextChanges[srcIndex]; - IMEChange &dst = mIMETextChanges[dstIndex]; - // When merging a more recent change into an older - // change, we need to compare recent change's (start, oldEnd) - // range to the older change's (start, newEnd) - if (src.mOldEnd < dst.mStart || dst.mNewEnd < src.mStart) { - // No overlap between ranges - continue; - } - // When merging two ranges, there are generally four posibilities: - // [----(----]----), (----[----]----), - // [----(----)----], (----[----)----] - // where [----] is the first range and (----) is the second range - // As seen above, the start of the merged range is always the lesser - // of the two start offsets. OldEnd and NewEnd then need to be - // adjusted separately depending on the case. In any case, the change - // in text length of the merged range should be the sum of text length - // changes of the two original ranges, i.e., - // newNewEnd - newOldEnd == newEnd1 - oldEnd1 + newEnd2 - oldEnd2 - dst.mStart = std::min(dst.mStart, src.mStart); - if (src.mOldEnd < dst.mNewEnd) { - // New range overlaps or is within previous range; merge - dst.mNewEnd += src.mNewEnd - src.mOldEnd; - } else { // src.mOldEnd >= dst.mNewEnd - // New range overlaps previous range; merge - dst.mOldEnd += src.mOldEnd - dst.mNewEnd; - dst.mNewEnd = src.mNewEnd; - } - // src merged to dst; delete src. - mIMETextChanges.RemoveElementAt(srcIndex); - // Any ranges that we skip over between src and dst are not mergeable - // so we can safely continue the merge starting at dst - srcIndex = dstIndex; - } - return NS_OK; -} - -nsIMEUpdatePreference -nsWindow::GetIMEUpdatePreference() -{ - return nsIMEUpdatePreference( - nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE | - nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE); -} - -void -nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect) -{ - GoannaLayerClient::LocalRef client = AndroidBridge::Bridge()->GetLayerClient(); - if (!client) { - ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); - return; - } - - AutoLocalJNIFrame jniFrame(client.Env()); - auto frameObj = client->CreateFrame(); - if (!frameObj) { - NS_WARNING("Warning: unable to obtain a LayerRenderer frame; aborting window underlay draw"); - return; - } - - mLayerRendererFrame.Init(client.Env(), frameObj.Get()); - if (!WidgetPaintsBackground()) { - return; - } - - CompositorOGL *compositor = static_cast(aManager->GetCompositor()); - compositor->ResetProgram(); - gl::GLContext* gl = compositor->gl(); - bool scissorEnabled = gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST); - GLint scissorRect[4]; - gl->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorRect); - - client->ActivateProgram(); - if (!mLayerRendererFrame.BeginDrawing(&jniFrame)) return; - if (!mLayerRendererFrame.DrawBackground(&jniFrame)) return; - client->DeactivateProgramAndRestoreState(scissorEnabled, - scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]); -} - -void -nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) -{ - PROFILER_LABEL("nsWindow", "DrawWindowOverlay", - js::ProfileEntry::Category::GRAPHICS); - - if (mLayerRendererFrame.isNull()) { - NS_WARNING("Warning: do not have a LayerRenderer frame; aborting window overlay draw"); - return; - } - - GoannaLayerClient::LocalRef client = AndroidBridge::Bridge()->GetLayerClient(); - - AutoLocalJNIFrame jniFrame(client.Env()); - CompositorOGL *compositor = static_cast(aManager->GetCompositor()); - compositor->ResetProgram(); - gl::GLContext* gl = compositor->gl(); - bool scissorEnabled = gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST); - GLint scissorRect[4]; - gl->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorRect); - - client->ActivateProgram(); - if (!mLayerRendererFrame.DrawForeground(&jniFrame)) return; - if (!mLayerRendererFrame.EndDrawing(&jniFrame)) return; - client->DeactivateProgramAndRestoreState(scissorEnabled, - scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]); - mLayerRendererFrame.Dispose(client.Env()); -} - -// off-main-thread compositor fields and functions - -StaticRefPtr nsWindow::sApzcTreeManager; -StaticRefPtr nsWindow::sLayerManager; -StaticRefPtr nsWindow::sCompositorParent; -StaticRefPtr nsWindow::sCompositorChild; -bool nsWindow::sCompositorPaused = true; - -void -nsWindow::SetCompositor(mozilla::layers::LayerManager* aLayerManager, - mozilla::layers::CompositorParent* aCompositorParent, - mozilla::layers::CompositorChild* aCompositorChild) -{ - sLayerManager = aLayerManager; - sCompositorParent = aCompositorParent; - sCompositorChild = aCompositorChild; -} - -void -nsWindow::ScheduleComposite() -{ - if (sCompositorParent) { - sCompositorParent->ScheduleRenderOnCompositorThread(); - } -} - -void -nsWindow::ScheduleResumeComposition(int width, int height) -{ - if (sCompositorParent && sCompositorParent->ScheduleResumeOnCompositorThread(width, height)) { - sCompositorPaused = false; - } -} - -void -nsWindow::ForceIsFirstPaint() -{ - if (sCompositorParent) { - sCompositorParent->ForceIsFirstPaint(); - } -} - -float -nsWindow::ComputeRenderIntegrity() -{ - if (sCompositorParent) { - return sCompositorParent->ComputeRenderIntegrity(); - } - - return 1.f; -} - -bool -nsWindow::WidgetPaintsBackground() -{ - static bool sWidgetPaintsBackground = true; - static bool sWidgetPaintsBackgroundPrefCached = false; - - if (!sWidgetPaintsBackgroundPrefCached) { - sWidgetPaintsBackgroundPrefCached = true; - mozilla::Preferences::AddBoolVarCache(&sWidgetPaintsBackground, - "android.widget_paints_background", - true); - } - - return sWidgetPaintsBackground; -} - -bool -nsWindow::NeedsPaint() -{ - if (sCompositorPaused || FindTopLevel() != nsWindow::TopWindow() || !GetLayerManager(nullptr)) { - return false; - } - return nsIWidget::NeedsPaint(); -} - -CompositorParent* -nsWindow::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) -{ - return new CompositorParent(this, true, aSurfaceWidth, aSurfaceHeight); -} - -mozilla::layers::APZCTreeManager* -nsWindow::GetAPZCTreeManager() -{ - return sApzcTreeManager; -} - -void -nsWindow::ConfigureAPZCTreeManager() -{ - nsBaseWidget::ConfigureAPZCTreeManager(); - if (!sApzcTreeManager) { - sApzcTreeManager = mAPZC; - } -} - -already_AddRefed -nsWindow::CreateRootContentController() -{ - nsRefPtr controller = - widget::android::APZCCallbackHandler::GetInstance(); - return controller.forget(); -} - -uint64_t -nsWindow::RootLayerTreeId() -{ - MOZ_ASSERT(sCompositorParent); - return sCompositorParent->RootLayerTreeId(); -} diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h deleted file mode 100644 index 0cbb0929fd..0000000000 --- a/widget/android/nsWindow.h +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef NSWINDOW_H_ -#define NSWINDOW_H_ - -#include "nsBaseWidget.h" -#include "gfxPoint.h" -#include "nsIIdleServiceInternal.h" -#include "nsTArray.h" -#include "AndroidJavaWrappers.h" -#include "GeneratedJNIWrappers.h" -#include "mozilla/EventForwards.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/TextRange.h" - -struct ANPEvent; - -namespace mozilla { - class AndroidGoannaEvent; - - namespace layers { - class CompositorParent; - class CompositorChild; - class LayerManager; - class APZCTreeManager; - } -} - -class nsWindow : - public nsBaseWidget -{ -private: - virtual ~nsWindow(); - -public: - using nsBaseWidget::GetLayerManager; - - nsWindow(); - - NS_DECL_ISUPPORTS_INHERITED - - static void OnGlobalAndroidEvent(mozilla::AndroidGoannaEvent *ae); - static gfxIntSize GetAndroidScreenBounds(); - static nsWindow* TopWindow(); - - nsWindow* FindWindowForPoint(const nsIntPoint& pt); - - void OnContextmenuEvent(mozilla::AndroidGoannaEvent *ae); - bool OnMultitouchEvent(mozilla::AndroidGoannaEvent *ae); - void OnNativeGestureEvent(mozilla::AndroidGoannaEvent *ae); - void OnMouseEvent(mozilla::AndroidGoannaEvent *ae); - void OnKeyEvent(mozilla::AndroidGoannaEvent *ae); - void OnIMEEvent(mozilla::AndroidGoannaEvent *ae); - - void OnSizeChanged(const gfxIntSize& aSize); - - void InitEvent(mozilla::WidgetGUIEvent& event, nsIntPoint* aPoint = 0); - - // - // nsIWidget - // - - NS_IMETHOD Create(nsIWidget *aParent, - nsNativeWidget aNativeParent, - const nsIntRect &aRect, - nsWidgetInitData *aInitData); - NS_IMETHOD Destroy(void); - NS_IMETHOD ConfigureChildren(const nsTArray&); - NS_IMETHOD SetParent(nsIWidget* aNewParent); - virtual nsIWidget *GetParent(void); - virtual float GetDPI(); - virtual double GetDefaultScaleInternal(); - NS_IMETHOD Show(bool aState); - NS_IMETHOD SetModal(bool aModal); - virtual bool IsVisible() const; - NS_IMETHOD ConstrainPosition(bool aAllowSlop, - int32_t *aX, - int32_t *aY); - NS_IMETHOD Move(double aX, - double aY); - NS_IMETHOD Resize(double aWidth, - double aHeight, - bool aRepaint); - NS_IMETHOD Resize(double aX, - double aY, - double aWidth, - double aHeight, - bool aRepaint); - void SetZIndex(int32_t aZIndex); - NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, - nsIWidget *aWidget, - bool aActivate); - NS_IMETHOD SetSizeMode(int32_t aMode); - NS_IMETHOD Enable(bool aState); - virtual bool IsEnabled() const; - NS_IMETHOD Invalidate(const nsIntRect &aRect); - NS_IMETHOD SetFocus(bool aRaise = false); - NS_IMETHOD GetScreenBounds(nsIntRect &aRect); - virtual mozilla::LayoutDeviceIntPoint WidgetToScreenOffset(); - NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus); - nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent); - NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr); - NS_IMETHOD SetWindowClass(const nsAString& xulWinType); - - - - NS_IMETHOD SetCursor(nsCursor aCursor) { return NS_ERROR_NOT_IMPLEMENTED; } - NS_IMETHOD SetCursor(imgIContainer* aCursor, - uint32_t aHotspotX, - uint32_t aHotspotY) { return NS_ERROR_NOT_IMPLEMENTED; } - NS_IMETHOD SetHasTransparentBackground(bool aTransparent) { return NS_OK; } - NS_IMETHOD GetHasTransparentBackground(bool& aTransparent) { aTransparent = false; return NS_OK; } - NS_IMETHOD HideWindowChrome(bool aShouldHide) { return NS_ERROR_NOT_IMPLEMENTED; } - virtual void* GetNativeData(uint32_t aDataType); - NS_IMETHOD SetTitle(const nsAString& aTitle) { return NS_OK; } - NS_IMETHOD SetIcon(const nsAString& aIconSpec) { return NS_OK; } - NS_IMETHOD EnableDragDrop(bool aEnable) { return NS_OK; } - NS_IMETHOD CaptureMouse(bool aCapture) { return NS_ERROR_NOT_IMPLEMENTED; } - NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, - bool aDoCapture) { return NS_ERROR_NOT_IMPLEMENTED; } - - NS_IMETHOD GetAttention(int32_t aCycleCount) { return NS_ERROR_NOT_IMPLEMENTED; } - NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent, - int32_t aHorizontal, - int32_t aVertical) - { - return NS_ERROR_NOT_IMPLEMENTED; - } - - NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, - const InputContextAction& aAction); - NS_IMETHOD_(InputContext) GetInputContext(); - - nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification); - virtual nsIMEUpdatePreference GetIMEUpdatePreference(); - - LayerManager* GetLayerManager (PLayerTransactionChild* aShadowManager = nullptr, - LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, - LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, - bool* aAllowRetaining = nullptr); - - NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); - - virtual bool NeedsPaint(); - virtual void DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect); - virtual void DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect); - - virtual mozilla::layers::CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) override; - - static void SetCompositor(mozilla::layers::LayerManager* aLayerManager, - mozilla::layers::CompositorParent* aCompositorParent, - mozilla::layers::CompositorChild* aCompositorChild); - static void ScheduleComposite(); - static void ScheduleResumeComposition(int width, int height); - static void ForceIsFirstPaint(); - static float ComputeRenderIntegrity(); - static mozilla::layers::APZCTreeManager* GetAPZCTreeManager(); - /* RootLayerTreeId() can only be called when GetAPZCTreeManager() returns non-null */ - static uint64_t RootLayerTreeId(); - - virtual bool WidgetPaintsBackground(); - -protected: - void BringToFront(); - nsWindow *FindTopLevel(); - bool IsTopLevel(); - void RemoveIMEComposition(); - void PostFlushIMEChanges(); - void FlushIMEChanges(); - - void ConfigureAPZCTreeManager() override; - already_AddRefed CreateRootContentController() override; - - // Call this function when the users activity is the direct cause of an - // event (like a keypress or mouse click). - void UserActivity(); - - bool mIsVisible; - nsTArray mChildren; - nsWindow* mParent; - nsWindow* mFocus; - - double mStartDist; - double mLastDist; - - nsCOMPtr mIdleService; - - bool mIMEComposing; - int32_t mIMEComposingStart; - nsString mIMEComposingText; - bool mIMEMaskSelectionUpdate, mIMEMaskTextUpdate; - int32_t mIMEMaskEventsCount; // Mask events when > 0 - nsRefPtr mIMERanges; - bool mIMEUpdatingContext; - nsAutoTArray mIMEKeyEvents; - - struct IMEChange { - int32_t mStart, mOldEnd, mNewEnd; - - IMEChange() : - mStart(-1), mOldEnd(-1), mNewEnd(-1) - { - } - IMEChange(const IMENotification& aIMENotification) - : mStart(aIMENotification.mTextChangeData.mStartOffset) - , mOldEnd(aIMENotification.mTextChangeData.mOldEndOffset) - , mNewEnd(aIMENotification.mTextChangeData.mNewEndOffset) - { - MOZ_ASSERT(aIMENotification.mMessage == - mozilla::widget::NOTIFY_IME_OF_TEXT_CHANGE, - "IMEChange initialized with wrong notification"); - MOZ_ASSERT(aIMENotification.mTextChangeData.IsInInt32Range(), - "The text change notification is out of range"); - } - bool IsEmpty() - { - return mStart < 0; - } - }; - nsAutoTArray mIMETextChanges; - bool mIMESelectionChanged; - - InputContext mInputContext; - - virtual nsresult NotifyIMEInternal( - const IMENotification& aIMENotification) override; - - static void DumpWindows(); - static void DumpWindows(const nsTArray& wins, int indent = 0); - static void LogWindow(nsWindow *win, int index, int indent); - -private: - void InitKeyEvent(mozilla::WidgetKeyboardEvent& event, - mozilla::AndroidGoannaEvent& key, - ANPEvent* pluginEvent); - void DispatchGestureEvent(uint32_t msg, uint32_t direction, double delta, - const mozilla::LayoutDeviceIntPoint &refPoint, uint64_t time); - void HandleSpecialKey(mozilla::AndroidGoannaEvent *ae); - void CreateLayerManager(int aCompositorWidth, int aCompositorHeight); - void RedrawAll(); - - mozilla::AndroidLayerRendererFrame mLayerRendererFrame; - - static mozilla::StaticRefPtr sApzcTreeManager; - static mozilla::StaticRefPtr sLayerManager; - static mozilla::StaticRefPtr sCompositorParent; - static mozilla::StaticRefPtr sCompositorChild; - static bool sCompositorPaused; -}; - -#endif /* NSWINDOW_H_ */ diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h index 4fc5135800..1425fd709f 100644 --- a/widget/cocoa/TextInputHandler.h +++ b/widget/cocoa/TextInputHandler.h @@ -1006,6 +1006,8 @@ private: // We cannot access to the NSInputManager during we aren't active, so, the // focused handler can have an IME transaction even if we are deactive. static IMEInputHandler* sFocusedIMEHandler; + + static bool sCachedIsForRTLLangage; }; /** diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index b53bbe37c1..59b067b454 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -21,6 +21,8 @@ #include "nsCocoaUtils.h" #include "WidgetUtils.h" #include "nsPrintfCString.h" +#include "mozilla/unused.h" +#include "mozilla/dom/ContentParent.h" #include "ComplexTextInputPanel.h" using namespace mozilla; @@ -2227,6 +2229,7 @@ TextInputHandler::DoCommandBySelector(const char* aSelector) ******************************************************************************/ bool IMEInputHandler::sStaticMembersInitialized = false; +bool IMEInputHandler::sCachedIsForRTLLangage = false; CFStringRef IMEInputHandler::sLatestIMEOpenedModeInputSourceID = nullptr; IMEInputHandler* IMEInputHandler::sFocusedIMEHandler = nullptr; @@ -2315,6 +2318,20 @@ IMEInputHandler::OnCurrentTextInputSourceChange(CFNotificationCenterRef aCenter, sLastTIS = newTIS; } #endif // #ifdef PR_LOGGING + + /** + * When the direction is changed, all the children are notified. + * No need to treat the initial case separately because it is covered + * by the general case (sCachedIsForRTLLangage is initially false) + */ + if (sCachedIsForRTLLangage != tis.IsForRTLLanguage()) { + nsTArray children; + dom::ContentParent::GetAll(children); + for (uint32_t i = 0; i < children.Length(); i++) { + unused << children[i]->SendBidiKeyboardNotify(tis.IsForRTLLanguage()); + } + sCachedIsForRTLLangage = tis.IsForRTLLanguage(); + } } // static diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index 37105db0b2..d271a9ba3d 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -12,6 +12,7 @@ XPIDL_MODULE = 'widget_cocoa' EXPORTS += [ 'mozView.h', + 'nsBidiKeyboard.h', 'nsChangeObserver.h', 'nsCocoaFeatures.h', 'nsCocoaUtils.h', diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm index af6090d574..c5d3695611 100644 --- a/widget/cocoa/nsWidgetFactory.mm +++ b/widget/cocoa/nsWidgetFactory.mm @@ -135,7 +135,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor }, { &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor }, + { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor, + mozilla::Module::MAIN_PROCESS_ONLY }, { &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor }, { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, @@ -172,7 +173,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID }, { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID }, + { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, + mozilla::Module::MAIN_PROCESS_ONLY }, { "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID }, { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, mozilla::Module::MAIN_PROCESS_ONLY }, diff --git a/widget/gtk/mozgtk/mozgtk.c b/widget/gtk/mozgtk/mozgtk.c index 3b4675962e..0e725e2fec 100644 --- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -42,6 +42,7 @@ STUB(gdk_get_program_class) STUB(gdk_keymap_get_default) STUB(gdk_keymap_get_direction) STUB(gdk_keymap_get_entries_for_keyval) +STUB(gdk_keymap_get_for_display) STUB(gdk_keymap_have_bidi_layouts) STUB(gdk_keymap_translate_keyboard_state) STUB(gdk_keyval_name) diff --git a/widget/gtk/nsBidiKeyboard.cpp b/widget/gtk/nsBidiKeyboard.cpp index 461bf8231e..51102d945e 100644 --- a/widget/gtk/nsBidiKeyboard.cpp +++ b/widget/gtk/nsBidiKeyboard.cpp @@ -10,11 +10,6 @@ #include "nsBidiKeyboard.h" #include -#if (MOZ_WIDGET_GTK == 2) -typedef gboolean (*GdkKeymapHaveBidiLayoutsType)(GdkKeymap *keymap); -static GdkKeymapHaveBidiLayoutsType GdkKeymapHaveBidiLayouts = nullptr; -#endif - NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard) nsBidiKeyboard::nsBidiKeyboard() @@ -25,32 +20,21 @@ nsBidiKeyboard::nsBidiKeyboard() NS_IMETHODIMP nsBidiKeyboard::Reset() { -#if (MOZ_WIDGET_GTK == 2) - PRLibrary *gtklib = nullptr; -#if defined(MOZ_X11) - if (!GdkKeymapHaveBidiLayouts) { - GdkKeymapHaveBidiLayouts = (GdkKeymapHaveBidiLayoutsType) - PR_FindFunctionSymbolAndLibrary("gdk_keymap_have_bidi_layouts", - >klib); - if (gtklib) - PR_UnloadLibrary(gtklib); - } -#endif - + // NB: The default keymap can be null (e.g. in xpcshell). In that case, + // simply assume that we don't have bidi keyboards. mHaveBidiKeyboards = false; - if (GdkKeymapHaveBidiLayouts) - mHaveBidiKeyboards = (*GdkKeymapHaveBidiLayouts)(nullptr); -#else - mHaveBidiKeyboards = gdk_keymap_have_bidi_layouts(gdk_keymap_get_default()); -#endif + + GdkDisplay *display = gdk_display_get_default(); + if (!display) + return NS_OK; + + GdkKeymap *keymap = gdk_keymap_get_for_display(display); + mHaveBidiKeyboards = keymap && gdk_keymap_have_bidi_layouts(keymap); return NS_OK; } nsBidiKeyboard::~nsBidiKeyboard() { -#if (MOZ_WIDGET_GTK == 2) - GdkKeymapHaveBidiLayouts = nullptr; -#endif } NS_IMETHODIMP diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp index 53234ebd46..7847a5ead9 100644 --- a/widget/gtk/nsDragService.cpp +++ b/widget/gtk/nsDragService.cpp @@ -485,6 +485,10 @@ nsDragService::EndDragSession(bool aDoneDrag) // unset our drag action SetDragAction(DRAGDROP_ACTION_NONE); + + // We're done with the drag context. + mTargetDragContextForRemote = nullptr; + return nsBaseDragService::EndDragSession(aDoneDrag); } @@ -1037,7 +1041,7 @@ nsDragService::IsDataFlavorSupported(const char *aDataFlavor, } void -nsDragService::ReplyToDragMotion() +nsDragService::ReplyToDragMotion(GdkDragContext* aDragContext) { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::ReplyToDragMotion %d", mCanDrop)); @@ -1052,13 +1056,16 @@ nsDragService::ReplyToDragMotion() case DRAGDROP_ACTION_LINK: action = GDK_ACTION_LINK; break; + case DRAGDROP_ACTION_NONE: + action = (GdkDragAction)0; + break; default: action = GDK_ACTION_MOVE; break; } } - gdk_drag_status(mTargetDragContext, action, mTargetTime); + gdk_drag_status(aDragContext, action, mTargetTime); } void @@ -1885,12 +1892,16 @@ nsDragService::RunScheduledTask() // protocol is used. if (task == eDragTaskMotion || positionHasChanged) { UpdateDragAction(); + TakeDragEventDispatchedToChildProcess(); // Clear the old value. DispatchMotionEvents(); - if (task == eDragTaskMotion) { - // Reply to tell the source whether we can drop and what - // action would be taken. - ReplyToDragMotion(); + if (TakeDragEventDispatchedToChildProcess()) { + mTargetDragContextForRemote = mTargetDragContext; + } else { + // Reply to tell the source whether we can drop and what + // action would be taken. + ReplyToDragMotion(mTargetDragContext); + } } } @@ -1965,6 +1976,16 @@ nsDragService::UpdateDragAction() SetDragAction(action); } +NS_IMETHODIMP +nsDragService::UpdateDragEffect() +{ + if (mTargetDragContextForRemote) { + ReplyToDragMotion(mTargetDragContextForRemote); + mTargetDragContextForRemote = nullptr; + } + return NS_OK; +} + void nsDragService::DispatchMotionEvents() { diff --git a/widget/gtk/nsDragService.h b/widget/gtk/nsDragService.h index 35fa40638f..88e6a831fa 100644 --- a/widget/gtk/nsDragService.h +++ b/widget/gtk/nsDragService.h @@ -75,6 +75,8 @@ public: NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor, bool *_retval) override; + NS_IMETHOD UpdateDragEffect() override; + // Methods called from nsWindow to handle responding to GTK drag // destination signals @@ -161,6 +163,9 @@ private: // motion or drop events. mTime records the corresponding timestamp. nsCountedRef mTargetWidget; nsCountedRef mTargetDragContext; + // mTargetDragContextForRemote is set while waiting for a reply from + // a child process. + nsCountedRef mTargetDragContextForRemote; guint mTargetTime; // is it OK to drop on us? @@ -208,7 +213,7 @@ private: gboolean RunScheduledTask(); void UpdateDragAction(); void DispatchMotionEvents(); - void ReplyToDragMotion(); + void ReplyToDragMotion(GdkDragContext* aDragContext); gboolean DispatchDropEvent(); }; diff --git a/widget/moz.build b/widget/moz.build index a7d67e4022..d0ec2b083c 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -6,9 +6,9 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT'] -if toolkit in ('cocoa', 'qt', 'android', 'gonk'): +if toolkit in ('cocoa', 'qt', 'gonk'): DIRS += [toolkit] -if toolkit in ('qt', 'android', 'gonk', 'gtk2', 'gtk3'): +if toolkit in ('qt', 'gonk', 'gtk2', 'gtk3'): EXPORTS += ['nsIPrintDialogService.h'] if toolkit == 'windows': @@ -125,6 +125,10 @@ EXPORTS.mozilla += [ 'WidgetUtils.h', ] +EXPORTS.mozilla.widget += [ + 'PuppetBidiKeyboard.h', +] + UNIFIED_SOURCES += [ 'ContentHelper.cpp', 'GfxDriverInfo.cpp', @@ -140,6 +144,7 @@ UNIFIED_SOURCES += [ 'nsClipboardProxy.cpp', 'nsColorPickerProxy.cpp', 'nsContentProcessWidgetFactory.cpp', + 'nsDragServiceProxy.cpp', 'nsFilePickerProxy.cpp', 'nsHTMLFormatConverter.cpp', 'nsIdleService.cpp', @@ -152,6 +157,7 @@ UNIFIED_SOURCES += [ 'nsTransferable.cpp', 'nsXPLookAndFeel.cpp', 'PluginWidgetProxy.cpp', + 'PuppetBidiKeyboard.cpp', 'PuppetWidget.cpp', 'ScreenProxy.cpp', 'SharedWidgetUtils.cpp', @@ -192,8 +198,7 @@ if toolkit in ('cocoa', 'windows'): 'nsBaseClipboard.cpp', ] -if toolkit in ('qt', 'gtk2', 'gtk3', 'cocoa', 'windows', - 'android', 'gonk'): +if toolkit in ('qt', 'gtk2', 'gtk3', 'cocoa', 'windows', 'gonk'): UNIFIED_SOURCES += [ 'nsBaseFilePicker.cpp', ] @@ -213,6 +218,8 @@ MSVC_ENABLE_PGO = True include('/ipc/chromium/chromium-config.mozbuild') LOCAL_INCLUDES += [ + '/dom/base', + '/dom/ipc', '/layout/base', '/layout/forms', '/layout/generic', diff --git a/widget/nsBaseDragService.cpp b/widget/nsBaseDragService.cpp index 8df981878c..3e54202abb 100644 --- a/widget/nsBaseDragService.cpp +++ b/widget/nsBaseDragService.cpp @@ -36,6 +36,9 @@ #include "mozilla/MouseEvents.h" #include "mozilla/Preferences.h" #include "mozilla/gfx/2D.h" +#include "mozilla/unused.h" +#include "nsFrameLoader.h" +#include "TabParent.h" #include "gfxContext.h" #include "gfxPlatform.h" @@ -51,6 +54,7 @@ using namespace mozilla::image; nsBaseDragService::nsBaseDragService() : mCanDrop(false), mOnlyChromeDrop(false), mDoingDrag(false), mHasImage(false), mUserCancelled(false), + mDragEventDispatchedToChildProcess(false), mDragAction(DRAGDROP_ACTION_NONE), mTargetSize(0,0), mImageX(0), mImageY(0), mScreenX(-1), mScreenY(-1), mSuppressLevel(0), mInputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE), @@ -349,7 +353,14 @@ nsBaseDragService::EndDragSession(bool aDoneDrag) } } + for (uint32_t i = 0; i < mChildProcesses.Length(); ++i) { + mozilla::unused << mChildProcesses[i]->SendEndDragSession(aDoneDrag, + mUserCancelled); + } + mChildProcesses.Clear(); + mDoingDrag = false; + mCanDrop = false; mEndingSession = false; // release the source we've been holding on to. @@ -365,6 +376,7 @@ nsBaseDragService::EndDragSession(bool aDoneDrag) mImageY = 0; mScreenX = -1; mScreenY = -1; + mEndDragPoint = nsIntPoint(0, 0); mInputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE; return NS_OK; @@ -460,6 +472,34 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, *aPresContext = presShell->GetPresContext(); + nsCOMPtr flo = do_QueryInterface(dragNode); + if (flo) { + nsRefPtr fl = flo->GetFrameLoader(); + if (fl) { + mozilla::dom::TabParent* tp = + static_cast(fl->GetRemoteBrowser()); + if (tp) { + int32_t x, y; + tp->TakeDragVisualization(*aSurface, x, y); + if (*aSurface) { + if (mImage) { + // Just clear the surface if chrome has overridden it with an image. + *aSurface = nullptr; + } else { + nsIFrame* f = fl->GetOwnerContent()->GetPrimaryFrame(); + if (f) { + aScreenDragRect->x = x; + aScreenDragRect->y = y; + aScreenDragRect->width = (*aSurface)->GetSize().width; + aScreenDragRect->height = (*aSurface)->GetSize().height; + } + return NS_OK; + } + } + } + } + } + // convert mouse position to dev pixels of the prescontext int32_t sx = aScreenX, sy = aScreenY; ConvertToUnscaledDevPixels(*aPresContext, &sx, &sy); @@ -671,3 +711,33 @@ nsBaseDragService::Unsuppress() --mSuppressLevel; return NS_OK; } + +NS_IMETHODIMP +nsBaseDragService::UserCancelled() +{ + mUserCancelled = true; + return NS_OK; +} + +NS_IMETHODIMP +nsBaseDragService::UpdateDragEffect() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsBaseDragService::DragEventDispatchedToChildProcess() +{ + mDragEventDispatchedToChildProcess = true; + return NS_OK; +} + +bool +nsBaseDragService::MaybeAddChildProcess(mozilla::dom::ContentParent* aChild) +{ + if (!mChildProcesses.Contains(aChild)) { + mChildProcesses.AppendElement(aChild); + return true; + } + return false; +} diff --git a/widget/nsBaseDragService.h b/widget/nsBaseDragService.h index 8b8114a383..265b578dc0 100644 --- a/widget/nsBaseDragService.h +++ b/widget/nsBaseDragService.h @@ -15,7 +15,9 @@ #include "nsRect.h" #include "nsPoint.h" #include "mozilla/RefPtr.h" +#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/HTMLCanvasElement.h" +#include "nsTArray.h" // translucency level for drag images #define DRAG_TRANSLUCENCY 0.65 @@ -112,6 +114,15 @@ protected: */ void OpenDragPopup(); + // Returns true if a drag event was dispatched to a child process after + // the previous TakeDragEventDispatchedToChildProcess() call. + bool TakeDragEventDispatchedToChildProcess() + { + bool retval = mDragEventDispatchedToChildProcess; + mDragEventDispatchedToChildProcess = false; + return retval; + } + bool mCanDrop; bool mOnlyChromeDrop; bool mDoingDrag; @@ -123,6 +134,8 @@ protected: // true if the user cancelled the drag operation bool mUserCancelled; + bool mDragEventDispatchedToChildProcess; + uint32_t mDragAction; nsSize mTargetSize; nsCOMPtr mSourceNode; @@ -156,6 +169,8 @@ protected: // The input source of the drag event. Possible values are from nsIDOMMouseEvent. uint16_t mInputSource; + + nsTArray> mChildProcesses; }; #endif // nsBaseDragService_h__ diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 12890a17aa..550b363d15 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1122,7 +1122,7 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) mCompositorChild->OpenSameProcess(mCompositorParent); // Make sure the parent knows it is same process. - mCompositorParent->SetOtherProcessId(kCurrentProcessId); + mCompositorParent->SetOtherProcessId(base::GetCurrentProcId()); if (gfxPrefs::AsyncPanZoomEnabled() && (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child)) { diff --git a/widget/nsContentProcessWidgetFactory.cpp b/widget/nsContentProcessWidgetFactory.cpp index f7b7a6e08c..88e6ec48ff 100644 --- a/widget/nsContentProcessWidgetFactory.cpp +++ b/widget/nsContentProcessWidgetFactory.cpp @@ -9,21 +9,28 @@ #include "nsWidgetsCID.h" #include "nsClipboardProxy.h" #include "nsColorPickerProxy.h" +#include "nsDragServiceProxy.h" #include "nsFilePickerProxy.h" #include "nsScreenManagerProxy.h" +#include "mozilla/widget/PuppetBidiKeyboard.h" using namespace mozilla; +using namespace mozilla::widget; #ifndef MOZ_B2G NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerProxy) +NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard) NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); +NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID); NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); +NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID); NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); static const mozilla::Module::CIDEntry kWidgetCIDs[] = { @@ -31,10 +38,14 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { Module::CONTENT_PROCESS_ONLY }, { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerProxyConstructor, Module::CONTENT_PROCESS_ONLY }, + { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceProxyConstructor, + Module::CONTENT_PROCESS_ONLY }, { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor, Module::CONTENT_PROCESS_ONLY }, { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerProxyConstructor, Module::CONTENT_PROCESS_ONLY }, + { &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor, + mozilla::Module::CONTENT_PROCESS_ONLY }, { nullptr } }; @@ -43,6 +54,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::CONTENT_PROCESS_ONLY }, + { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::CONTENT_PROCESS_ONLY }, { nullptr } }; diff --git a/widget/nsDragServiceProxy.cpp b/widget/nsDragServiceProxy.cpp new file mode 100644 index 0000000000..b03437f4fb --- /dev/null +++ b/widget/nsDragServiceProxy.cpp @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsDragServiceProxy.h" +#include "nsIDocument.h" +#include "nsISupportsPrimitives.h" +#include "mozilla/dom/TabChild.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/unused.h" +#include "nsContentUtils.h" + +NS_IMPL_ISUPPORTS_INHERITED0(nsDragServiceProxy, nsBaseDragService) + +nsDragServiceProxy::nsDragServiceProxy() +{ +} + +nsDragServiceProxy::~nsDragServiceProxy() +{ +} + +NS_IMETHODIMP +nsDragServiceProxy::InvokeDragSession(nsIDOMNode* aDOMNode, + nsISupportsArray* aArrayTransferables, + nsIScriptableRegion* aRegion, + uint32_t aActionType) +{ + nsresult rv = nsBaseDragService::InvokeDragSession(aDOMNode, + aArrayTransferables, + aRegion, + aActionType); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr sourceDocument; + aDOMNode->GetOwnerDocument(getter_AddRefs(sourceDocument)); + nsCOMPtr doc = do_QueryInterface(sourceDocument); + NS_ENSURE_STATE(doc->GetDocShell()); + mozilla::dom::TabChild* child = + mozilla::dom::TabChild::GetFrom(doc->GetDocShell()); + NS_ENSURE_STATE(child); + nsTArray dataTransfers; + nsContentUtils::TransferablesToIPCTransferables(aArrayTransferables, + dataTransfers, + child->Manager(), + nullptr); + + if (mHasImage || mSelection) { + nsIntRect dragRect; + nsPresContext* pc; + mozilla::RefPtr surface; + DrawDrag(mSourceNode, aRegion, mScreenX, mScreenY, + &dragRect, &surface, &pc); + + if (surface) { + mozilla::RefPtr dataSurface = + surface->GetDataSurface(); + mozilla::gfx::DataSourceSurface::MappedSurface map; + dataSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map); + mozilla::gfx::IntSize size = dataSurface->GetSize(); + mozilla::CheckedInt32 requiredBytes = + mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height); + size_t bufLen = requiredBytes.isValid() ? requiredBytes.value() : 0; + mozilla::gfx::SurfaceFormat format = dataSurface->GetFormat(); + // Surface data handling is totally nuts. This is the magic one needs to + // know to access the data. + bufLen = bufLen - map.mStride + (size.width * BytesPerPixel(format)); + nsDependentCString dragImage(reinterpret_cast(map.mData), bufLen); + mozilla::unused << + child->SendInvokeDragSession(dataTransfers, aActionType, dragImage, + size.width, size.height, map.mStride, + static_cast(format), + dragRect.x, dragRect.y); + dataSurface->Unmap(); + StartDragSession(); + return NS_OK; + } + } + + mozilla::unused << child->SendInvokeDragSession(dataTransfers, aActionType, + nsCString(), + 0, 0, 0, 0, 0, 0); + StartDragSession(); + return NS_OK; +} diff --git a/widget/nsDragServiceProxy.h b/widget/nsDragServiceProxy.h new file mode 100644 index 0000000000..8fe35aa0fc --- /dev/null +++ b/widget/nsDragServiceProxy.h @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef NSDRAGSERVICEPROXY_H +#define NSDRAGSERVICEPROXY_H + +#include "nsBaseDragService.h" + +class nsDragServiceProxy : public nsBaseDragService +{ +public: + nsDragServiceProxy(); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIDragService + NS_IMETHOD InvokeDragSession(nsIDOMNode* aDOMNode, + nsISupportsArray* anArrayTransferables, + nsIScriptableRegion* aRegion, + uint32_t aActionType) override; +private: + virtual ~nsDragServiceProxy(); +}; + +#endif // NSDRAGSERVICEPROXY_H diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h index 345ae67c0b..f6de88b14c 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h @@ -211,6 +211,29 @@ struct ParamTraits } }; + +template<> +struct ParamTraits +{ + typedef mozilla::WidgetDragEvent paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, static_cast(aParam)); + WriteParam(aMsg, aParam.userCancelled); + WriteParam(aMsg, aParam.mDefaultPreventedOnContent); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + bool rv = + ReadParam(aMsg, aIter, static_cast(aResult)) && + ReadParam(aMsg, aIter, &aResult->userCancelled) && + ReadParam(aMsg, aIter, &aResult->mDefaultPreventedOnContent); + return rv; + } +}; + template<> struct ParamTraits { diff --git a/widget/nsIDragService.idl b/widget/nsIDragService.idl index 196761e02a..9ca9841519 100644 --- a/widget/nsIDragService.idl +++ b/widget/nsIDragService.idl @@ -15,7 +15,17 @@ interface nsIDOMDragEvent; interface nsIDOMDataTransfer; interface nsISelection; -[scriptable, uuid(82B58ADA-F490-4C3D-B737-1057C4F1D052), builtinclass] +%{C++ +namespace mozilla { +namespace dom { +class ContentParent; +} // namespace dom +} // namespace mozilla +%} + +[ptr] native ContentParentPtr(mozilla::dom::ContentParent); + +[scriptable, uuid(009d4489-4568-4896-9442-19717dd00f15), builtinclass] interface nsIDragService : nsISupports { const long DRAGDROP_ACTION_NONE = 0; @@ -114,6 +124,8 @@ interface nsIDragService : nsISupports void unsuppress(); [noscript] void dragMoved(in long aX, in long aY); + + [notxpcom, nostdcall] boolean maybeAddChildProcess(in ContentParentPtr aChild); }; diff --git a/widget/nsIDragSession.idl b/widget/nsIDragSession.idl index 0fdd44bc18..6b9f603a14 100644 --- a/widget/nsIDragSession.idl +++ b/widget/nsIDragSession.idl @@ -19,7 +19,7 @@ interface nsIDOMDocument; interface nsIDOMNode; interface nsIDOMDataTransfer; -[scriptable, uuid(fde41f6a-c710-46f8-a0a8-1ff76ca4ff57)] +[scriptable, uuid(25bce737-73f0-43c7-bc20-c71044a73c5a)] interface nsIDragSession : nsISupports { /** @@ -80,7 +80,15 @@ interface nsIDragSession : nsISupports * Check to set if any of the native data on the clipboard matches this data flavor */ boolean isDataFlavorSupported ( in string aDataFlavor ) ; - + + void userCancelled(); + + void dragEventDispatchedToChildProcess(); + + // Called when nsIDragSession implementation should update the UI for the + // drag-and-drop based on the data got from the child process in response to + // NS_DRAGDROP_OVER sent from parent process to child process. + void updateDragEffect(); }; diff --git a/widget/nsPrintSettingsImpl.cpp b/widget/nsPrintSettingsImpl.cpp index 83dcbc533c..d84845788c 100644 --- a/widget/nsPrintSettingsImpl.cpp +++ b/widget/nsPrintSettingsImpl.cpp @@ -6,6 +6,7 @@ #include "nsPrintSettingsImpl.h" #include "nsReadableUtils.h" #include "nsIPrintSession.h" +#include "mozilla/RefPtr.h" #define DEFAULT_MARGIN_WIDTH 0.5 diff --git a/widget/nsWidgetsCID.h b/widget/nsWidgetsCID.h index 19dafa2b8e..1473be6488 100644 --- a/widget/nsWidgetsCID.h +++ b/widget/nsWidgetsCID.h @@ -109,6 +109,9 @@ #define NS_BIDIKEYBOARD_CID \ { 0x9f1800ab, 0xf428, 0x4207, { 0xb4, 0x0c, 0xe8, 0x32, 0xe7, 0x7b, 0x01, 0xfc } } +#define PUPPETBIDIKEYBOARD_CID \ +{ 0x689e2586, 0x0344, 0x40b2, {0x83, 0x75, 0x13, 0x67, 0x2d, 0x3b, 0x71, 0x9a } } + #define NS_SCREENMANAGER_CID \ { 0xc401eb80, 0xf9ea, 0x11d3, { 0xbb, 0x6f, 0xe7, 0x32, 0xb7, 0x3e, 0xbe, 0x7c } } diff --git a/xpcom/glue/nsTArray-inl.h b/xpcom/glue/nsTArray-inl.h index 8017714e81..33e70a0420 100644 --- a/xpcom/glue/nsTArray-inl.h +++ b/xpcom/glue/nsTArray-inl.h @@ -196,8 +196,9 @@ nsTArray_base::EnsureCapacity(size_type aCapacity, return ActualAlloc::SuccessResult(); } +// We don't need use Alloc template parameter specified here because failure to +// shrink the capacity will leave the array unchanged. template -template void nsTArray_base::ShrinkCapacity(size_type aElemSize, size_t aElemAlign) @@ -219,20 +220,20 @@ nsTArray_base::ShrinkCapacity(size_type aElemSize, header->mLength = length; Copy::CopyElements(header + 1, mHdr + 1, length, aElemSize); - ActualAlloc::Free(mHdr); + nsTArrayFallibleAllocator::Free(mHdr); mHdr = header; return; } if (length == 0) { MOZ_ASSERT(!IsAutoArray(), "autoarray should have fit 0 elements"); - ActualAlloc::Free(mHdr); + nsTArrayFallibleAllocator::Free(mHdr); mHdr = EmptyHdr(); return; } size_type size = sizeof(Header) + length * aElemSize; - void* ptr = ActualAlloc::Realloc(mHdr, size); + void* ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size); if (!ptr) { return; } @@ -257,7 +258,7 @@ nsTArray_base::ShiftData(index_type aStart, // Compute the resulting length of the array mHdr->mLength += aNewLen - aOldLen; if (mHdr->mLength == 0) { - ShrinkCapacity(aElemSize, aElemAlign); + ShrinkCapacity(aElemSize, aElemAlign); } else { // Maybe nothing needs to be shifted if (num == 0) { diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index a867b7f8ff..45f5730701 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -385,10 +385,10 @@ protected: typename ActualAlloc::ResultTypeProxy EnsureCapacity(size_type aCapacity, size_type aElemSize); - // Resize the storage to the minimum required amount. + // Tries to resize the storage to the minimum required amount. If this fails, + // the array is left as-is. // @param aElemSize The size of an array element. // @param aElemAlign The alignment in bytes of an array element. - template void ShrinkCapacity(size_type aElemSize, size_t aElemAlign); // This method may be called to resize a "gap" in the array by shifting @@ -1807,8 +1807,7 @@ public: // This method may be called to minimize the memory used by this array. void Compact() { - this->template ShrinkCapacity(sizeof(elem_type), - MOZ_ALIGNOF(elem_type)); + ShrinkCapacity(sizeof(elem_type), MOZ_ALIGNOF(elem_type)); } //