Merge remote-tracking branch 'origin/master' into custom

This commit is contained in:
Roy Tam 2020-02-21 07:18:31 +08:00
commit 43b8e8fb16
212 changed files with 94 additions and 52404 deletions

View file

@ -30,7 +30,6 @@ namespace widget {
class WinCompositorWidget;
class X11CompositorWidget;
class AndroidCompositorWidget;
class CompositorWidgetInitData;
// Gecko widgets usually need to communicate with the CompositorWidget with
@ -56,12 +55,9 @@ class CompositorWidgetChild;
class WidgetRenderingContext
{
public:
#if defined(XP_MACOSX)
#ifdef XP_MACOSX
WidgetRenderingContext() : mLayerManager(nullptr) {}
layers::LayerManagerComposite* mLayerManager;
#elif defined(MOZ_WIDGET_ANDROID)
WidgetRenderingContext() : mCompositor(nullptr) {}
layers::Compositor* mCompositor;
#endif
};
@ -262,9 +258,6 @@ public:
virtual X11CompositorWidget* AsX11() {
return nullptr;
}
virtual AndroidCompositorWidget* AsAndroid() {
return nullptr;
}
/**
* Return the platform-specific delegate for the widget, if any.

View file

@ -379,9 +379,6 @@ NS_EVENT_MESSAGE(eDeviceMotion)
NS_EVENT_MESSAGE(eDeviceProximity)
NS_EVENT_MESSAGE(eUserProximity)
NS_EVENT_MESSAGE(eDeviceLight)
#if defined(MOZ_WIDGET_ANDROID)
NS_EVENT_MESSAGE(eOrientationChange)
#endif
// WebVR events
NS_EVENT_MESSAGE(eVRDisplayConnect)

View file

@ -58,7 +58,6 @@ enum class OperatingSystem {
OSX10_10,
OSX10_11,
OSX10_12,
Android,
Ios
};
@ -283,12 +282,6 @@ ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
*aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
return true;
#elif defined(ANDROID)
// Can't use aVersion.ToInteger() because that's not compiled into our code
// unless we have XPCOM_GLUE_AVOID_NSPR disabled.
*aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
return true;
#else
return false;
#endif

View file

@ -280,8 +280,6 @@ BlacklistOSToOperatingSystem(const nsAString& os)
return OperatingSystem::OSX10_11;
else if (os.EqualsLiteral("Darwin 16"))
return OperatingSystem::OSX10_12;
else if (os.EqualsLiteral("Android"))
return OperatingSystem::Android;
// For historical reasons, "All" in blocklist means "All Windows"
else if (os.EqualsLiteral("All"))
return OperatingSystem::Windows;
@ -697,7 +695,7 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
}
}
#if defined(XP_WIN) || defined(ANDROID)
#ifdef XP_WIN
uint64_t driverVersion;
ParseDriverVersion(adapterDriverVersionString, &driverVersion);
#endif
@ -736,7 +734,7 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
continue;
}
#if defined(XP_WIN) || defined(ANDROID)
#ifdef XP_WIN
switch (info[i].mComparisonOp) {
case DRIVER_LESS_THAN:
match = driverVersion < info[i].mDriverVersion;

View file

@ -5,10 +5,6 @@
#include "InProcessCompositorWidget.h"
#include "nsBaseWidget.h"
#if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
#include "mozilla/widget/AndroidCompositorWidget.h"
#endif
namespace mozilla {
namespace widget {
@ -19,11 +15,7 @@ namespace widget {
CompositorWidget::CreateLocal(const CompositorWidgetInitData& aInitData, nsIWidget* aWidget)
{
MOZ_ASSERT(aWidget);
#ifdef MOZ_WIDGET_ANDROID
return new AndroidCompositorWidget(static_cast<nsBaseWidget*>(aWidget));
#else
return new InProcessCompositorWidget(static_cast<nsBaseWidget*>(aWidget));
#endif
}
#endif

View file

@ -21,8 +21,6 @@
#define CODE_MAP_MAC(aCPPCodeName, aNativeKey)
// GTK and Qt on Linux
#define CODE_MAP_X11(aCPPCodeName, aNativeKey)
// Android and Gonk
#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey)
#if defined(XP_WIN)
#undef CODE_MAP_WIN
@ -42,780 +40,613 @@
#define CODE_MAP_X11(aCPPCodeName, aNativeKey) \
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
CODE_NAME_INDEX_##aCPPCodeName)
#elif defined(ANDROID)
#undef CODE_MAP_ANDROID
// aNativeKey is scan code
#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey) \
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
CODE_NAME_INDEX_##aCPPCodeName)
#endif
// Writing system keys
CODE_MAP_WIN(Backquote, 0x0029)
CODE_MAP_MAC(Backquote, kVK_ANSI_Grave)
CODE_MAP_X11(Backquote, 0x0031)
CODE_MAP_ANDROID(Backquote, 0x0029)
CODE_MAP_WIN(Backslash, 0x002B)
CODE_MAP_MAC(Backslash, kVK_ANSI_Backslash)
CODE_MAP_X11(Backslash, 0x0033)
CODE_MAP_ANDROID(Backslash, 0x002B)
CODE_MAP_WIN(Backspace, 0x000E)
CODE_MAP_MAC(Backspace, kVK_Delete)
CODE_MAP_X11(Backspace, 0x0016)
CODE_MAP_ANDROID(Backspace, 0x000E)
CODE_MAP_WIN(BracketLeft, 0x001A)
CODE_MAP_MAC(BracketLeft, kVK_ANSI_LeftBracket)
CODE_MAP_X11(BracketLeft, 0x0022)
CODE_MAP_ANDROID(BracketLeft, 0x001A)
CODE_MAP_WIN(BracketRight, 0x001B)
CODE_MAP_MAC(BracketRight, kVK_ANSI_RightBracket)
CODE_MAP_X11(BracketRight, 0x0023)
CODE_MAP_ANDROID(BracketRight, 0x001B)
CODE_MAP_WIN(Comma, 0x0033)
CODE_MAP_MAC(Comma, kVK_ANSI_Comma)
CODE_MAP_X11(Comma, 0x003B)
CODE_MAP_ANDROID(Comma, 0x00033)
CODE_MAP_WIN(Digit0, 0x000B)
CODE_MAP_MAC(Digit0, kVK_ANSI_0)
CODE_MAP_X11(Digit0, 0x0013)
CODE_MAP_ANDROID(Digit0, 0x000B)
CODE_MAP_WIN(Digit1, 0x0002)
CODE_MAP_MAC(Digit1, kVK_ANSI_1)
CODE_MAP_X11(Digit1, 0x000A)
CODE_MAP_ANDROID(Digit1, 0x0002)
CODE_MAP_WIN(Digit2, 0x0003)
CODE_MAP_MAC(Digit2, kVK_ANSI_2)
CODE_MAP_X11(Digit2, 0x000B)
CODE_MAP_ANDROID(Digit2, 0x0003)
CODE_MAP_WIN(Digit3, 0x0004)
CODE_MAP_MAC(Digit3, kVK_ANSI_3)
CODE_MAP_X11(Digit3, 0x000C)
CODE_MAP_ANDROID(Digit3, 0x0004)
CODE_MAP_WIN(Digit4, 0x0005)
CODE_MAP_MAC(Digit4, kVK_ANSI_4)
CODE_MAP_X11(Digit4, 0x000D)
CODE_MAP_ANDROID(Digit4, 0x0005)
CODE_MAP_WIN(Digit5, 0x0006)
CODE_MAP_MAC(Digit5, kVK_ANSI_5)
CODE_MAP_X11(Digit5, 0x000E)
CODE_MAP_ANDROID(Digit5, 0x0006)
CODE_MAP_WIN(Digit6, 0x0007)
CODE_MAP_MAC(Digit6, kVK_ANSI_6)
CODE_MAP_X11(Digit6, 0x000F)
CODE_MAP_ANDROID(Digit6, 0x0007)
CODE_MAP_WIN(Digit7, 0x0008)
CODE_MAP_MAC(Digit7, kVK_ANSI_7)
CODE_MAP_X11(Digit7, 0x0010)
CODE_MAP_ANDROID(Digit7, 0x0008)
CODE_MAP_WIN(Digit8, 0x0009)
CODE_MAP_MAC(Digit8, kVK_ANSI_8)
CODE_MAP_X11(Digit8, 0x0011)
CODE_MAP_ANDROID(Digit8, 0x0009)
CODE_MAP_WIN(Digit9, 0x000A)
CODE_MAP_MAC(Digit9, kVK_ANSI_9)
CODE_MAP_X11(Digit9, 0x0012)
CODE_MAP_ANDROID(Digit9, 0x000A)
CODE_MAP_WIN(Equal, 0x000D)
CODE_MAP_MAC(Equal, kVK_ANSI_Equal)
CODE_MAP_X11(Equal, 0x0015)
CODE_MAP_ANDROID(Equal, 0x000D)
CODE_MAP_WIN(IntlBackslash, 0x0056)
CODE_MAP_MAC(IntlBackslash, kVK_ISO_Section)
CODE_MAP_X11(IntlBackslash, 0x005E)
CODE_MAP_ANDROID(IntlBackslash, 0x0056)
// Win: IntlHash's scan code is shared with "Backslash" key.
// Mac: IntlHash's virtual key code is shared with "Backslash" key.
// X11: IntlHash's scan code is shared with "Backslash" key.
// Android: IntlHash's scan code is shared with "Backslash" key.
CODE_MAP_WIN(IntlRo, 0x0073)
CODE_MAP_MAC(IntlRo, kVK_JIS_Underscore)
CODE_MAP_X11(IntlRo, 0x0061)
CODE_MAP_ANDROID(IntlRo, 0x0059)
CODE_MAP_WIN(IntlYen, 0x007D)
CODE_MAP_MAC(IntlYen, kVK_JIS_Yen)
CODE_MAP_X11(IntlYen, 0x0084)
CODE_MAP_ANDROID(IntlYen, 0x007C)
CODE_MAP_WIN(KeyA, 0x001E)
CODE_MAP_MAC(KeyA, kVK_ANSI_A)
CODE_MAP_X11(KeyA, 0x0026)
CODE_MAP_ANDROID(KeyA, 0x001E)
CODE_MAP_WIN(KeyB, 0x0030)
CODE_MAP_MAC(KeyB, kVK_ANSI_B)
CODE_MAP_X11(KeyB, 0x0038)
CODE_MAP_ANDROID(KeyB, 0x0030)
CODE_MAP_WIN(KeyC, 0x002E)
CODE_MAP_MAC(KeyC, kVK_ANSI_C)
CODE_MAP_X11(KeyC, 0x0036)
CODE_MAP_ANDROID(KeyC, 0x002E)
CODE_MAP_WIN(KeyD, 0x0020)
CODE_MAP_MAC(KeyD, kVK_ANSI_D)
CODE_MAP_X11(KeyD, 0x0028)
CODE_MAP_ANDROID(KeyD, 0x0020)
CODE_MAP_WIN(KeyE, 0x0012)
CODE_MAP_MAC(KeyE, kVK_ANSI_E)
CODE_MAP_X11(KeyE, 0x001A)
CODE_MAP_ANDROID(KeyE, 0x0012)
CODE_MAP_WIN(KeyF, 0x0021)
CODE_MAP_MAC(KeyF, kVK_ANSI_F)
CODE_MAP_X11(KeyF, 0x0029)
CODE_MAP_ANDROID(KeyF, 0x0021)
CODE_MAP_WIN(KeyG, 0x0022)
CODE_MAP_MAC(KeyG, kVK_ANSI_G)
CODE_MAP_X11(KeyG, 0x002A)
CODE_MAP_ANDROID(KeyG, 0x0022)
CODE_MAP_WIN(KeyH, 0x0023)
CODE_MAP_MAC(KeyH, kVK_ANSI_H)
CODE_MAP_X11(KeyH, 0x002B)
CODE_MAP_ANDROID(KeyH, 0x0023)
CODE_MAP_WIN(KeyI, 0x0017)
CODE_MAP_MAC(KeyI, kVK_ANSI_I)
CODE_MAP_X11(KeyI, 0x001F)
CODE_MAP_ANDROID(KeyI, 0x0017)
CODE_MAP_WIN(KeyJ, 0x0024)
CODE_MAP_MAC(KeyJ, kVK_ANSI_J)
CODE_MAP_X11(KeyJ, 0x002C)
CODE_MAP_ANDROID(KeyJ, 0x0024)
CODE_MAP_WIN(KeyK, 0x0025)
CODE_MAP_MAC(KeyK, kVK_ANSI_K)
CODE_MAP_X11(KeyK, 0x002D)
CODE_MAP_ANDROID(KeyK, 0x0025)
CODE_MAP_WIN(KeyL, 0x0026)
CODE_MAP_MAC(KeyL, kVK_ANSI_L)
CODE_MAP_X11(KeyL, 0x002E)
CODE_MAP_ANDROID(KeyL, 0x0026)
CODE_MAP_WIN(KeyM, 0x0032)
CODE_MAP_MAC(KeyM, kVK_ANSI_M)
CODE_MAP_X11(KeyM, 0x003A)
CODE_MAP_ANDROID(KeyM, 0x0032)
CODE_MAP_WIN(KeyN, 0x0031)
CODE_MAP_MAC(KeyN, kVK_ANSI_N)
CODE_MAP_X11(KeyN, 0x0039)
CODE_MAP_ANDROID(KeyN, 0x0031)
CODE_MAP_WIN(KeyO, 0x0018)
CODE_MAP_MAC(KeyO, kVK_ANSI_O)
CODE_MAP_X11(KeyO, 0x0020)
CODE_MAP_ANDROID(KeyO, 0x0018)
CODE_MAP_WIN(KeyP, 0x0019)
CODE_MAP_MAC(KeyP, kVK_ANSI_P)
CODE_MAP_X11(KeyP, 0x0021)
CODE_MAP_ANDROID(KeyP, 0x0019)
CODE_MAP_WIN(KeyQ, 0x0010)
CODE_MAP_MAC(KeyQ, kVK_ANSI_Q)
CODE_MAP_X11(KeyQ, 0x0018)
CODE_MAP_ANDROID(KeyQ, 0x0010)
CODE_MAP_WIN(KeyR, 0x0013)
CODE_MAP_MAC(KeyR, kVK_ANSI_R)
CODE_MAP_X11(KeyR, 0x001B)
CODE_MAP_ANDROID(KeyR, 0x0013)
CODE_MAP_WIN(KeyS, 0x001F)
CODE_MAP_MAC(KeyS, kVK_ANSI_S)
CODE_MAP_X11(KeyS, 0x0027)
CODE_MAP_ANDROID(KeyS, 0x001F)
CODE_MAP_WIN(KeyT, 0x0014)
CODE_MAP_MAC(KeyT, kVK_ANSI_T)
CODE_MAP_X11(KeyT, 0x001C)
CODE_MAP_ANDROID(KeyT, 0x0014)
CODE_MAP_WIN(KeyU, 0x0016)
CODE_MAP_MAC(KeyU, kVK_ANSI_U)
CODE_MAP_X11(KeyU, 0x001E)
CODE_MAP_ANDROID(KeyU, 0x0016)
CODE_MAP_WIN(KeyV, 0x002F)
CODE_MAP_MAC(KeyV, kVK_ANSI_V)
CODE_MAP_X11(KeyV, 0x0037)
CODE_MAP_ANDROID(KeyV, 0x002F)
CODE_MAP_WIN(KeyW, 0x0011)
CODE_MAP_MAC(KeyW, kVK_ANSI_W)
CODE_MAP_X11(KeyW, 0x0019)
CODE_MAP_ANDROID(KeyW, 0x0011)
CODE_MAP_WIN(KeyX, 0x002D)
CODE_MAP_MAC(KeyX, kVK_ANSI_X)
CODE_MAP_X11(KeyX, 0x0035)
CODE_MAP_ANDROID(KeyX, 0x002D)
CODE_MAP_WIN(KeyY, 0x0015)
CODE_MAP_MAC(KeyY, kVK_ANSI_Y)
CODE_MAP_X11(KeyY, 0x001D)
CODE_MAP_ANDROID(KeyY, 0x0015)
CODE_MAP_WIN(KeyZ, 0x002C)
CODE_MAP_MAC(KeyZ, kVK_ANSI_Z)
CODE_MAP_X11(KeyZ, 0x0034)
CODE_MAP_ANDROID(KeyZ, 0x002C)
CODE_MAP_WIN(Minus, 0x000C)
CODE_MAP_MAC(Minus, kVK_ANSI_Minus)
CODE_MAP_X11(Minus, 0x0014)
CODE_MAP_ANDROID(Minus, 0x000C)
CODE_MAP_WIN(Period, 0x0034)
CODE_MAP_MAC(Period, kVK_ANSI_Period)
CODE_MAP_X11(Period, 0x003C)
CODE_MAP_ANDROID(Period, 0x0034)
CODE_MAP_WIN(Quote, 0x0028)
CODE_MAP_MAC(Quote, kVK_ANSI_Quote)
CODE_MAP_X11(Quote, 0x0030)
CODE_MAP_ANDROID(Quote, 0x0028)
CODE_MAP_WIN(Semicolon, 0x0027)
CODE_MAP_MAC(Semicolon, kVK_ANSI_Semicolon)
CODE_MAP_X11(Semicolon, 0x002F)
CODE_MAP_ANDROID(Semicolon, 0x0027)
CODE_MAP_WIN(Slash, 0x0035)
CODE_MAP_MAC(Slash, kVK_ANSI_Slash)
CODE_MAP_X11(Slash, 0x003D)
CODE_MAP_ANDROID(Slash, 0x0035)
// Functional keys
CODE_MAP_WIN(AltLeft, 0x0038)
CODE_MAP_MAC(AltLeft, kVK_Option)
CODE_MAP_X11(AltLeft, 0x0040)
CODE_MAP_ANDROID(AltLeft, 0x0038)
CODE_MAP_WIN(AltRight, 0xE038)
CODE_MAP_MAC(AltRight, kVK_RightOption)
CODE_MAP_X11(AltRight, 0x006C)
CODE_MAP_ANDROID(AltRight, 0x0064)
CODE_MAP_WIN(CapsLock, 0x003A)
CODE_MAP_MAC(CapsLock, kVK_CapsLock)
CODE_MAP_X11(CapsLock, 0x0042)
CODE_MAP_ANDROID(CapsLock, 0x003A)
CODE_MAP_WIN(ContextMenu, 0xE05D)
CODE_MAP_MAC(ContextMenu, kVK_PC_ContextMenu)
CODE_MAP_X11(ContextMenu, 0x0087)
CODE_MAP_ANDROID(ContextMenu, 0x007F)
CODE_MAP_WIN(ControlLeft, 0x001D)
CODE_MAP_MAC(ControlLeft, kVK_Control)
CODE_MAP_X11(ControlLeft, 0x0025)
CODE_MAP_ANDROID(ControlLeft, 0x001D)
CODE_MAP_WIN(ControlRight, 0xE01D)
CODE_MAP_MAC(ControlRight, kVK_RightControl)
CODE_MAP_X11(ControlRight, 0x0069)
CODE_MAP_ANDROID(ControlRight, 0x0061)
CODE_MAP_WIN(Enter, 0x001C)
CODE_MAP_MAC(Enter, kVK_Return)
CODE_MAP_X11(Enter, 0x0024)
CODE_MAP_ANDROID(Enter, 0x001C)
CODE_MAP_WIN(OSLeft, 0xE05B)
CODE_MAP_MAC(OSLeft, kVK_Command)
CODE_MAP_X11(OSLeft, 0x0085)
CODE_MAP_ANDROID(OSLeft, 0x007D)
CODE_MAP_WIN(OSRight, 0xE05C)
CODE_MAP_MAC(OSRight, kVK_RightCommand)
CODE_MAP_X11(OSRight, 0x0086)
CODE_MAP_ANDROID(OSRight, 0x007E)
CODE_MAP_WIN(ShiftLeft, 0x002A)
CODE_MAP_MAC(ShiftLeft, kVK_Shift)
CODE_MAP_X11(ShiftLeft, 0x0032)
CODE_MAP_ANDROID(ShiftLeft, 0x002A)
CODE_MAP_WIN(ShiftRight, 0x0036)
CODE_MAP_MAC(ShiftRight, kVK_RightShift)
CODE_MAP_X11(ShiftRight, 0x003E)
CODE_MAP_ANDROID(ShiftRight, 0x0036)
CODE_MAP_WIN(Space, 0x0039)
CODE_MAP_MAC(Space, kVK_Space)
CODE_MAP_X11(Space, 0x0041)
CODE_MAP_ANDROID(Space, 0x0039)
CODE_MAP_WIN(Tab, 0x000F)
CODE_MAP_MAC(Tab, kVK_Tab)
CODE_MAP_X11(Tab, 0x0017)
CODE_MAP_ANDROID(Tab, 0x000F)
// IME keys
CODE_MAP_WIN(Convert, 0x0079)
CODE_MAP_X11(Convert, 0x0064)
CODE_MAP_ANDROID(Convert, 0x005C)
CODE_MAP_WIN(Lang1, 0x0072) // for non-Korean layout
CODE_MAP_WIN(Lang1, 0xE0F2) // for Korean layout
CODE_MAP_MAC(Lang1, kVK_JIS_Kana)
CODE_MAP_X11(Lang1, 0x0082)
CODE_MAP_ANDROID(Lang1, 0x007A)
CODE_MAP_WIN(Lang2, 0x0071) // for non-Korean layout
CODE_MAP_WIN(Lang2, 0xE0F1) // for Korean layout
CODE_MAP_MAC(Lang2, kVK_JIS_Eisu)
CODE_MAP_X11(Lang2, 0x0083)
CODE_MAP_ANDROID(Lang2, 0x007B)
CODE_MAP_WIN(KanaMode, 0x0070)
CODE_MAP_X11(KanaMode, 0x0065)
CODE_MAP_ANDROID(KanaMode, 0x005D)
CODE_MAP_WIN(NonConvert, 0x007B)
CODE_MAP_X11(NonConvert, 0x0066)
CODE_MAP_ANDROID(NonConvert, 0x005E)
// Control pad section
CODE_MAP_WIN(Delete, 0xE053)
CODE_MAP_MAC(Delete, kVK_ForwardDelete)
CODE_MAP_X11(Delete, 0x0077)
CODE_MAP_ANDROID(Delete, 0x006F)
CODE_MAP_WIN(End, 0xE04F)
CODE_MAP_MAC(End, kVK_End)
CODE_MAP_X11(End, 0x0073)
CODE_MAP_ANDROID(End, 0x006B)
CODE_MAP_MAC(Help, kVK_Help) // Insert key on PC keyboard
CODE_MAP_X11(Help, 0x0092) // Help key on Sun keyboard
CODE_MAP_ANDROID(Help, 0x008A) // Help key on Sun keyboard
CODE_MAP_WIN(Home, 0xE047)
CODE_MAP_MAC(Home, kVK_Home)
CODE_MAP_X11(Home, 0x006E)
CODE_MAP_ANDROID(Home, 0x0066)
CODE_MAP_WIN(Insert, 0xE052)
CODE_MAP_X11(Insert, 0x0076)
CODE_MAP_ANDROID(Insert, 0x006E)
CODE_MAP_WIN(PageDown, 0xE051)
CODE_MAP_MAC(PageDown, kVK_PageDown)
CODE_MAP_X11(PageDown, 0x0075)
CODE_MAP_ANDROID(PageDown, 0x006D)
CODE_MAP_WIN(PageUp, 0xE049)
CODE_MAP_MAC(PageUp, kVK_PageUp)
CODE_MAP_X11(PageUp, 0x0070)
CODE_MAP_ANDROID(PageUp, 0x0068)
// Arrow pad section
CODE_MAP_WIN(ArrowDown, 0xE050)
CODE_MAP_MAC(ArrowDown, kVK_DownArrow)
CODE_MAP_X11(ArrowDown, 0x0074)
CODE_MAP_ANDROID(ArrowDown, 0x006C)
CODE_MAP_WIN(ArrowLeft, 0xE04B)
CODE_MAP_MAC(ArrowLeft, kVK_LeftArrow)
CODE_MAP_X11(ArrowLeft, 0x0071)
CODE_MAP_ANDROID(ArrowLeft, 0x0069)
CODE_MAP_WIN(ArrowRight, 0xE04D)
CODE_MAP_MAC(ArrowRight, kVK_RightArrow)
CODE_MAP_X11(ArrowRight, 0x0072)
CODE_MAP_ANDROID(ArrowRight, 0x006A)
CODE_MAP_WIN(ArrowUp, 0xE048)
CODE_MAP_MAC(ArrowUp, kVK_UpArrow)
CODE_MAP_X11(ArrowUp, 0x006F)
CODE_MAP_ANDROID(ArrowUp, 0x0067)
// Numpad section
CODE_MAP_WIN(NumLock, 0xE045) // MSDN says 0x0045, though...
CODE_MAP_MAC(NumLock, kVK_ANSI_KeypadClear)
CODE_MAP_X11(NumLock, 0x004D)
CODE_MAP_ANDROID(NumLock, 0x0045)
CODE_MAP_WIN(Numpad0, 0x0052)
CODE_MAP_MAC(Numpad0, kVK_ANSI_Keypad0)
CODE_MAP_X11(Numpad0, 0x005A)
CODE_MAP_ANDROID(Numpad0, 0x0052)
CODE_MAP_WIN(Numpad1, 0x004F)
CODE_MAP_MAC(Numpad1, kVK_ANSI_Keypad1)
CODE_MAP_X11(Numpad1, 0x0057)
CODE_MAP_ANDROID(Numpad1, 0x004F)
CODE_MAP_WIN(Numpad2, 0x0050)
CODE_MAP_MAC(Numpad2, kVK_ANSI_Keypad2)
CODE_MAP_X11(Numpad2, 0x0058)
CODE_MAP_ANDROID(Numpad2, 0x0050)
CODE_MAP_WIN(Numpad3, 0x0051)
CODE_MAP_MAC(Numpad3, kVK_ANSI_Keypad3)
CODE_MAP_X11(Numpad3, 0x0059)
CODE_MAP_ANDROID(Numpad3, 0x0051)
CODE_MAP_WIN(Numpad4, 0x004B)
CODE_MAP_MAC(Numpad4, kVK_ANSI_Keypad4)
CODE_MAP_X11(Numpad4, 0x0053)
CODE_MAP_ANDROID(Numpad4, 0x004B)
CODE_MAP_WIN(Numpad5, 0x004C)
CODE_MAP_MAC(Numpad5, kVK_ANSI_Keypad5)
CODE_MAP_X11(Numpad5, 0x0054)
CODE_MAP_ANDROID(Numpad5, 0x004C)
CODE_MAP_WIN(Numpad6, 0x004D)
CODE_MAP_MAC(Numpad6, kVK_ANSI_Keypad6)
CODE_MAP_X11(Numpad6, 0x0055)
CODE_MAP_ANDROID(Numpad6, 0x004D)
CODE_MAP_WIN(Numpad7, 0x0047)
CODE_MAP_MAC(Numpad7, kVK_ANSI_Keypad7)
CODE_MAP_X11(Numpad7, 0x004F)
CODE_MAP_ANDROID(Numpad7, 0x0047)
CODE_MAP_WIN(Numpad8, 0x0048)
CODE_MAP_MAC(Numpad8, kVK_ANSI_Keypad8)
CODE_MAP_X11(Numpad8, 0x0050)
CODE_MAP_ANDROID(Numpad8, 0x0048)
CODE_MAP_WIN(Numpad9, 0x0049)
CODE_MAP_MAC(Numpad9, kVK_ANSI_Keypad9)
CODE_MAP_X11(Numpad9, 0x0051)
CODE_MAP_ANDROID(Numpad9, 0x0049)
CODE_MAP_WIN(NumpadAdd, 0x004E)
CODE_MAP_MAC(NumpadAdd, kVK_ANSI_KeypadPlus)
CODE_MAP_X11(NumpadAdd, 0x0056)
CODE_MAP_ANDROID(NumpadAdd, 0x004E)
CODE_MAP_WIN(NumpadComma, 0x007E)
CODE_MAP_MAC(NumpadComma, kVK_JIS_KeypadComma)
CODE_MAP_X11(NumpadComma, 0x0081)
CODE_MAP_ANDROID(NumpadComma, 0x0079)
CODE_MAP_WIN(NumpadDecimal, 0x0053)
CODE_MAP_MAC(NumpadDecimal, kVK_ANSI_KeypadDecimal)
CODE_MAP_X11(NumpadDecimal, 0x005B)
CODE_MAP_ANDROID(NumpadDecimal, 0x0053)
CODE_MAP_WIN(NumpadDivide, 0xE035)
CODE_MAP_MAC(NumpadDivide, kVK_ANSI_KeypadDivide)
CODE_MAP_X11(NumpadDivide, 0x006A)
CODE_MAP_ANDROID(NumpadDivide, 0x0062)
CODE_MAP_WIN(NumpadEnter, 0xE01C)
CODE_MAP_MAC(NumpadEnter, kVK_ANSI_KeypadEnter)
CODE_MAP_MAC(NumpadEnter, kVK_Powerbook_KeypadEnter)
CODE_MAP_X11(NumpadEnter, 0x0068)
CODE_MAP_ANDROID(NumpadEnter, 0x0060)
CODE_MAP_WIN(NumpadEqual, 0x0059)
CODE_MAP_MAC(NumpadEqual, kVK_ANSI_KeypadEquals)
CODE_MAP_X11(NumpadEqual, 0x007D)
CODE_MAP_ANDROID(NumpadEqual, 0x0075)
CODE_MAP_WIN(NumpadMultiply, 0x0037)
CODE_MAP_MAC(NumpadMultiply, kVK_ANSI_KeypadMultiply)
CODE_MAP_X11(NumpadMultiply, 0x003F)
CODE_MAP_ANDROID(NumpadMultiply, 0x0037)
CODE_MAP_WIN(NumpadSubtract, 0x004A)
CODE_MAP_MAC(NumpadSubtract, kVK_ANSI_KeypadMinus)
CODE_MAP_X11(NumpadSubtract, 0x0052)
CODE_MAP_ANDROID(NumpadSubtract, 0x004A)
// Function section
CODE_MAP_WIN(Escape, 0x0001)
CODE_MAP_MAC(Escape, kVK_Escape)
CODE_MAP_X11(Escape, 0x0009)
CODE_MAP_ANDROID(Escape, 0x0001)
CODE_MAP_WIN(F1, 0x003B)
CODE_MAP_MAC(F1, kVK_F1)
CODE_MAP_X11(F1, 0x0043)
CODE_MAP_ANDROID(F1, 0x003B)
CODE_MAP_WIN(F2, 0x003C)
CODE_MAP_MAC(F2, kVK_F2)
CODE_MAP_X11(F2, 0x0044)
CODE_MAP_ANDROID(F2, 0x003C)
CODE_MAP_WIN(F3, 0x003D)
CODE_MAP_MAC(F3, kVK_F3)
CODE_MAP_X11(F3, 0x0045)
CODE_MAP_ANDROID(F3, 0x003D)
CODE_MAP_WIN(F4, 0x003E)
CODE_MAP_MAC(F4, kVK_F4)
CODE_MAP_X11(F4, 0x0046)
CODE_MAP_ANDROID(F4, 0x003E)
CODE_MAP_WIN(F5, 0x003F)
CODE_MAP_MAC(F5, kVK_F5)
CODE_MAP_X11(F5, 0x0047)
CODE_MAP_ANDROID(F5, 0x003F)
CODE_MAP_WIN(F6, 0x0040)
CODE_MAP_MAC(F6, kVK_F6)
CODE_MAP_X11(F6, 0x0048)
CODE_MAP_ANDROID(F6, 0x0040)
CODE_MAP_WIN(F7, 0x0041)
CODE_MAP_MAC(F7, kVK_F7)
CODE_MAP_X11(F7, 0x0049)
CODE_MAP_ANDROID(F7, 0x0041)
CODE_MAP_WIN(F8, 0x0042)
CODE_MAP_MAC(F8, kVK_F8)
CODE_MAP_X11(F8, 0x004A)
CODE_MAP_ANDROID(F8, 0x0042)
CODE_MAP_WIN(F9, 0x0043)
CODE_MAP_MAC(F9, kVK_F9)
CODE_MAP_X11(F9, 0x004B)
CODE_MAP_ANDROID(F9, 0x0043)
CODE_MAP_WIN(F10, 0x0044)
CODE_MAP_MAC(F10, kVK_F10)
CODE_MAP_X11(F10, 0x004C)
CODE_MAP_ANDROID(F10, 0x0044)
CODE_MAP_WIN(F11, 0x0057)
CODE_MAP_MAC(F11, kVK_F11)
CODE_MAP_X11(F11, 0x005F)
CODE_MAP_ANDROID(F11, 0x0057)
CODE_MAP_WIN(F12, 0x0058)
CODE_MAP_MAC(F12, kVK_F12)
CODE_MAP_X11(F12, 0x0060)
CODE_MAP_ANDROID(F12, 0x0058)
CODE_MAP_WIN(F13, 0x0064)
CODE_MAP_MAC(F13, kVK_F13) // PrintScreen on PC keyboard
CODE_MAP_X11(F13, 0x00BF)
CODE_MAP_ANDROID(F13, 0x00B7)
CODE_MAP_WIN(F14, 0x0065)
CODE_MAP_MAC(F14, kVK_F14) // ScrollLock on PC keyboard
CODE_MAP_X11(F14, 0x00C0)
CODE_MAP_ANDROID(F14, 0x00B8)
CODE_MAP_WIN(F15, 0x0066)
CODE_MAP_MAC(F15, kVK_F15) // Pause on PC keyboard
CODE_MAP_X11(F15, 0x00C1)
CODE_MAP_ANDROID(F15, 0x00B9)
CODE_MAP_WIN(F16, 0x0067)
CODE_MAP_MAC(F16, kVK_F16)
CODE_MAP_X11(F16, 0x00C2)
CODE_MAP_ANDROID(F16, 0x00BA)
CODE_MAP_WIN(F17, 0x0068)
CODE_MAP_MAC(F17, kVK_F17)
CODE_MAP_X11(F17, 0x00C3)
CODE_MAP_ANDROID(F17, 0x00BB)
CODE_MAP_WIN(F18, 0x0069)
CODE_MAP_MAC(F18, kVK_F18)
CODE_MAP_X11(F18, 0x00C4)
CODE_MAP_ANDROID(F18, 0x00BC)
CODE_MAP_WIN(F19, 0x006A)
CODE_MAP_MAC(F19, kVK_F19)
CODE_MAP_X11(F19, 0x00C5)
CODE_MAP_ANDROID(F19, 0x00BD)
CODE_MAP_WIN(F20, 0x006B)
CODE_MAP_MAC(F20, kVK_F20)
CODE_MAP_X11(F20, 0x00C6)
CODE_MAP_ANDROID(F20, 0x00BE)
CODE_MAP_WIN(F21, 0x006C)
CODE_MAP_X11(F21, 0x00C7)
CODE_MAP_ANDROID(F21, 0x00BF)
CODE_MAP_WIN(F22, 0x006D)
CODE_MAP_X11(F22, 0x00C8)
CODE_MAP_ANDROID(F22, 0x00C0)
CODE_MAP_WIN(F23, 0x006E)
CODE_MAP_X11(F23, 0x00C9)
CODE_MAP_ANDROID(F23, 0x00C1)
CODE_MAP_WIN(F24, 0x0076)
CODE_MAP_X11(F24, 0x00CA)
CODE_MAP_ANDROID(F24, 0x00C2)
CODE_MAP_MAC(Fn, kVK_Function) // not available?
CODE_MAP_ANDROID(Fn, 0x01D0)
CODE_MAP_WIN(PrintScreen, 0xE037)
CODE_MAP_WIN(PrintScreen, 0x0054) // Alt + PrintScreen
CODE_MAP_X11(PrintScreen, 0x006B)
CODE_MAP_ANDROID(PrintScreen, 0x0063)
CODE_MAP_WIN(ScrollLock, 0x0046)
CODE_MAP_X11(ScrollLock, 0x004E)
CODE_MAP_ANDROID(ScrollLock, 0x0046)
CODE_MAP_WIN(Pause, 0x0045)
CODE_MAP_WIN(Pause, 0xE046) // Ctrl + Pause
CODE_MAP_X11(Pause, 0x007F)
CODE_MAP_ANDROID(Pause, 0x0077)
// Media keys
CODE_MAP_WIN(BrowserBack, 0xE06A)
CODE_MAP_X11(BrowserBack, 0x00A6)
CODE_MAP_ANDROID(BrowserBack, 0x009E)
CODE_MAP_WIN(BrowserFavorites, 0xE066)
CODE_MAP_X11(BrowserFavorites, 0x00A4)
CODE_MAP_ANDROID(BrowserFavorites, 0x009C)
CODE_MAP_WIN(BrowserForward, 0xE069)
CODE_MAP_X11(BrowserForward, 0x00A7)
CODE_MAP_ANDROID(BrowserForward, 0x009F)
CODE_MAP_WIN(BrowserHome, 0xE032)
CODE_MAP_X11(BrowserHome, 0x00B4)
// CODE_MAP_ANDROID(BrowserHome) // not available? works as Home key.
CODE_MAP_WIN(BrowserRefresh, 0xE067)
CODE_MAP_X11(BrowserRefresh, 0x00B5)
CODE_MAP_ANDROID(BrowserRefresh, 0x00AD)
CODE_MAP_WIN(BrowserSearch, 0xE065)
CODE_MAP_X11(BrowserSearch, 0x00E1)
CODE_MAP_ANDROID(BrowserSearch, 0x00D9)
CODE_MAP_WIN(BrowserStop, 0xE068)
CODE_MAP_X11(BrowserStop, 0x0088)
CODE_MAP_ANDROID(BrowserStop, 0x0080)
// CODE_MAP_WIN(Eject) // not available?
// CODE_MAP_MAC(Eject) // not available?
CODE_MAP_X11(Eject, 0x00A9)
CODE_MAP_ANDROID(Eject, 0x00A1)
CODE_MAP_WIN(LaunchApp1, 0xE06B)
CODE_MAP_X11(LaunchApp1, 0x0098)
CODE_MAP_ANDROID(LaunchApp1, 0x0090)
CODE_MAP_WIN(LaunchApp2, 0xE021)
CODE_MAP_X11(LaunchApp2, 0x0094)
// CODE_MAP_ANDROID(LaunchApp2) // not available?
CODE_MAP_WIN(LaunchMail, 0xE06C)
CODE_MAP_X11(LaunchMail, 0x00A3)
// CODE_MAP_ANDROID(LaunchMail) // not available?
CODE_MAP_WIN(MediaPlayPause, 0xE022)
CODE_MAP_X11(MediaPlayPause, 0x00AC)
CODE_MAP_ANDROID(MediaPlayPause, 0x00A4)
CODE_MAP_WIN(MediaSelect, 0xE06D)
CODE_MAP_X11(MediaSelect, 0x00B3)
// CODE_MAP_ANDROID(MediaSelect) // not available?
CODE_MAP_WIN(MediaStop, 0xE024)
CODE_MAP_X11(MediaStop, 0x00AE)
CODE_MAP_ANDROID(MediaStop, 0x00A6)
CODE_MAP_WIN(MediaTrackNext, 0xE019)
CODE_MAP_X11(MediaTrackNext, 0x00AB)
CODE_MAP_ANDROID(MediaTrackNext, 0x00A3)
CODE_MAP_WIN(MediaTrackPrevious, 0xE010)
CODE_MAP_X11(MediaTrackPrevious, 0x00AD)
CODE_MAP_ANDROID(MediaTrackPrevious, 0x00A5)
CODE_MAP_WIN(Power, 0xE05E)
CODE_MAP_MAC(Power, 0x007F) // On 10.7 and 10.8 only
// CODE_MAP_X11(Power) // not available?
CODE_MAP_ANDROID(Power, 0x0074)
// CODE_MAP_WIN(Sleep) // not available?
// CODE_MAP_X11(Sleep) // not available?
CODE_MAP_ANDROID(Sleep, 0x008E)
CODE_MAP_WIN(VolumeDown, 0xE02E)
CODE_MAP_MAC(VolumeDown, kVK_VolumeDown) // not available?
CODE_MAP_X11(VolumeDown, 0x007A)
CODE_MAP_ANDROID(VolumeDown, 0x0072)
CODE_MAP_WIN(VolumeMute, 0xE020)
CODE_MAP_MAC(VolumeMute, kVK_Mute) // not available?
CODE_MAP_X11(VolumeMute, 0x0079)
CODE_MAP_ANDROID(VolumeMute, 0x0071)
CODE_MAP_WIN(VolumeUp, 0xE030)
CODE_MAP_MAC(VolumeUp, kVK_VolumeUp) // not available?
CODE_MAP_X11(VolumeUp, 0x007B)
CODE_MAP_ANDROID(VolumeUp, 0x0073) // side of body, not on keyboard
// CODE_MAP_WIN(WakeUp) // not available?
CODE_MAP_X11(WakeUp, 0x0097)
CODE_MAP_ANDROID(WakeUp, 0x008F)
// Legacy editing keys
CODE_MAP_X11(Again, 0x0089) // Again key on Sun keyboard
CODE_MAP_ANDROID(Again, 0x0081) // Again key on Sun keyboard
CODE_MAP_X11(Copy, 0x008D) // Copy key on Sun keyboard
CODE_MAP_ANDROID(Copy, 0x0085) // Copy key on Sun keyboard
CODE_MAP_X11(Cut, 0x0091) // Cut key on Sun keyboard
CODE_MAP_ANDROID(Cut, 0x0089) // Cut key on Sun keyboard
CODE_MAP_X11(Find, 0x0090) // Find key on Sun keyboard
CODE_MAP_ANDROID(Find, 0x0088) // Find key on Sun keyboard
CODE_MAP_X11(Open, 0x008E) // Open key on Sun keyboard
CODE_MAP_ANDROID(Open, 0x0086) // Open key on Sun keyboard
CODE_MAP_X11(Paste, 0x008F) // Paste key on Sun keyboard
CODE_MAP_ANDROID(Paste, 0x0087) // Paste key on Sun keyboard
CODE_MAP_X11(Props, 0x008A) // Props key on Sun keyboard
CODE_MAP_ANDROID(Props, 0x0082) // Props key on Sun keyboard
CODE_MAP_X11(Select, 0x008C) // Front key on Sun keyboard
CODE_MAP_ANDROID(Select, 0x0084) // Front key on Sun keyboard
CODE_MAP_X11(Undo, 0x008B) // Undo key on Sun keyboard
CODE_MAP_ANDROID(Undo, 0x0083) // Undo key on Sun keyboard
#undef CODE_MAP_WIN
#undef CODE_MAP_MAC
#undef CODE_MAP_X11
#undef CODE_MAP_ANDROID

View file

@ -25,7 +25,6 @@
#define KEY_MAP_COCOA(aCPPKeyName, aNativeKey)
// GTK
#define KEY_MAP_GTK(aCPPKeyName, aNativeKey)
#define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey)
#if defined(XP_WIN)
#if defined(NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
@ -71,10 +70,6 @@
#undef KEY_MAP_GTK
#define KEY_MAP_GTK(aCPPKeyName, aNativeKey) \
NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
#elif defined(ANDROID)
#undef KEY_MAP_ANDROID
#define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey) \
NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
#endif
/******************************************************************************
@ -88,8 +83,6 @@ KEY_MAP_COCOA (Alt, kVK_Option)
KEY_MAP_COCOA (Alt, kVK_RightOption)
KEY_MAP_GTK (Alt, GDK_Alt_L)
KEY_MAP_GTK (Alt, GDK_Alt_R)
KEY_MAP_ANDROID (Alt, AKEYCODE_ALT_LEFT)
KEY_MAP_ANDROID (Alt, AKEYCODE_ALT_RIGHT)
// AltGraph
KEY_MAP_GTK (AltGraph, GDK_Mode_switch /* same as GDK_kana_switch,
@ -109,7 +102,6 @@ KEY_MAP_GTK (AltGraph, GDK_ISO_Level5_Lock)
KEY_MAP_WIN (CapsLock, VK_CAPITAL)
KEY_MAP_COCOA (CapsLock, kVK_CapsLock)
KEY_MAP_GTK (CapsLock, GDK_Caps_Lock)
KEY_MAP_ANDROID (CapsLock, AKEYCODE_CAPS_LOCK)
// Control
KEY_MAP_WIN (Control, VK_CONTROL)
@ -119,25 +111,19 @@ KEY_MAP_COCOA (Control, kVK_Control)
KEY_MAP_COCOA (Control, kVK_RightControl)
KEY_MAP_GTK (Control, GDK_Control_L)
KEY_MAP_GTK (Control, GDK_Control_R)
KEY_MAP_ANDROID (Control, AKEYCODE_CTRL_LEFT)
KEY_MAP_ANDROID (Control, AKEYCODE_CTRL_RIGHT)
// Fn
KEY_MAP_COCOA (Fn, kVK_Function)
KEY_MAP_ANDROID (Fn, AKEYCODE_FUNCTION)
// Meta
KEY_MAP_COCOA (Meta, kVK_Command)
KEY_MAP_COCOA (Meta, kVK_RightCommand)
KEY_MAP_GTK (Meta, GDK_Meta_L)
KEY_MAP_GTK (Meta, GDK_Meta_R)
KEY_MAP_ANDROID (Meta, AKEYCODE_META_LEFT)
KEY_MAP_ANDROID (Meta, AKEYCODE_META_RIGHT)
// NumLock
KEY_MAP_WIN (NumLock, VK_NUMLOCK)
KEY_MAP_GTK (NumLock, GDK_Num_Lock)
KEY_MAP_ANDROID (NumLock, AKEYCODE_NUM_LOCK)
// OS
KEY_MAP_WIN (OS, VK_LWIN)
@ -150,7 +136,6 @@ KEY_MAP_GTK (OS, GDK_Hyper_R)
// ScrollLock
KEY_MAP_WIN (ScrollLock, VK_SCROLL)
KEY_MAP_GTK (ScrollLock, GDK_Scroll_Lock)
KEY_MAP_ANDROID (ScrollLock, AKEYCODE_SCROLL_LOCK)
// Shift
KEY_MAP_WIN (Shift, VK_SHIFT)
@ -161,11 +146,8 @@ KEY_MAP_COCOA (Shift, kVK_RightShift)
KEY_MAP_GTK (Shift, GDK_Shift_L)
KEY_MAP_GTK (Shift, GDK_Shift_R)
KEY_MAP_GTK (Shift, GDK_Shift_Lock) // Let's treat as Shift key (bug 769159)
KEY_MAP_ANDROID (Shift, AKEYCODE_SHIFT_LEFT)
KEY_MAP_ANDROID (Shift, AKEYCODE_SHIFT_RIGHT)
// Symbol
KEY_MAP_ANDROID (Symbol, AKEYCODE_SYM)
/******************************************************************************
* Whitespace Keys
@ -179,8 +161,6 @@ KEY_MAP_GTK (Enter, GDK_Return)
KEY_MAP_GTK (Enter, GDK_KP_Enter)
KEY_MAP_GTK (Enter, GDK_ISO_Enter)
KEY_MAP_GTK (Enter, GDK_3270_Enter)
KEY_MAP_ANDROID (Enter, AKEYCODE_ENTER)
KEY_MAP_ANDROID (Enter, AKEYCODE_NUMPAD_ENTER)
// Tab
KEY_MAP_WIN (Tab, VK_TAB)
@ -188,7 +168,6 @@ KEY_MAP_COCOA (Tab, kVK_Tab)
KEY_MAP_GTK (Tab, GDK_Tab)
KEY_MAP_GTK (Tab, GDK_ISO_Left_Tab) // Shift+Tab
KEY_MAP_GTK (Tab, GDK_KP_Tab)
KEY_MAP_ANDROID (Tab, AKEYCODE_TAB)
/******************************************************************************
* Navigation Keys
@ -198,56 +177,48 @@ KEY_MAP_WIN (ArrowDown, VK_DOWN)
KEY_MAP_COCOA (ArrowDown, kVK_DownArrow)
KEY_MAP_GTK (ArrowDown, GDK_Down)
KEY_MAP_GTK (ArrowDown, GDK_KP_Down)
KEY_MAP_ANDROID (ArrowDown, AKEYCODE_DPAD_DOWN)
// ArrowLeft
KEY_MAP_WIN (ArrowLeft, VK_LEFT)
KEY_MAP_COCOA (ArrowLeft, kVK_LeftArrow)
KEY_MAP_GTK (ArrowLeft, GDK_Left)
KEY_MAP_GTK (ArrowLeft, GDK_KP_Left)
KEY_MAP_ANDROID (ArrowLeft, AKEYCODE_DPAD_LEFT)
// ArrowRight
KEY_MAP_WIN (ArrowRight, VK_RIGHT)
KEY_MAP_COCOA (ArrowRight, kVK_RightArrow)
KEY_MAP_GTK (ArrowRight, GDK_Right)
KEY_MAP_GTK (ArrowRight, GDK_KP_Right)
KEY_MAP_ANDROID (ArrowRight, AKEYCODE_DPAD_RIGHT)
// ArrowUp
KEY_MAP_WIN (ArrowUp, VK_UP)
KEY_MAP_COCOA (ArrowUp, kVK_UpArrow)
KEY_MAP_GTK (ArrowUp, GDK_Up)
KEY_MAP_GTK (ArrowUp, GDK_KP_Up)
KEY_MAP_ANDROID (ArrowUp, AKEYCODE_DPAD_UP)
// End
KEY_MAP_WIN (End, VK_END)
KEY_MAP_COCOA (End, kVK_End)
KEY_MAP_GTK (End, GDK_End)
KEY_MAP_GTK (End, GDK_KP_End)
KEY_MAP_ANDROID (End, AKEYCODE_MOVE_END)
// Home
KEY_MAP_WIN (Home, VK_HOME)
KEY_MAP_COCOA (Home, kVK_Home)
KEY_MAP_GTK (Home, GDK_Home)
KEY_MAP_GTK (Home, GDK_KP_Home)
KEY_MAP_ANDROID (Home, AKEYCODE_MOVE_HOME)
// PageDown
KEY_MAP_WIN (PageDown, VK_NEXT)
KEY_MAP_COCOA (PageDown, kVK_PageDown)
KEY_MAP_GTK (PageDown, GDK_Page_Down /* same as GDK_Next */)
KEY_MAP_GTK (PageDown, GDK_KP_Page_Down /* same as GDK_KP_Next */)
KEY_MAP_ANDROID (PageDown, AKEYCODE_PAGE_DOWN)
// PageUp
KEY_MAP_WIN (PageUp, VK_PRIOR)
KEY_MAP_COCOA (PageUp, kVK_PageUp)
KEY_MAP_GTK (PageUp, GDK_Page_Up /* same as GDK_Prior */)
KEY_MAP_GTK (PageUp, GDK_KP_Page_Up /* same as GDK_KP_Prior */)
KEY_MAP_ANDROID (PageUp, AKEYCODE_PAGE_UP)
/******************************************************************************
* Editing Keys
@ -256,14 +227,12 @@ KEY_MAP_ANDROID (PageUp, AKEYCODE_PAGE_UP)
KEY_MAP_WIN (Backspace, VK_BACK)
KEY_MAP_COCOA (Backspace, kVK_PC_Backspace)
KEY_MAP_GTK (Backspace, GDK_BackSpace)
KEY_MAP_ANDROID (Backspace, AKEYCODE_DEL)
// Clear
KEY_MAP_WIN (Clear, VK_CLEAR)
KEY_MAP_WIN (Clear, VK_OEM_CLEAR)
KEY_MAP_COCOA (Clear, kVK_ANSI_KeypadClear)
KEY_MAP_GTK (Clear, GDK_Clear)
KEY_MAP_ANDROID (Clear, AKEYCODE_CLEAR)
// Copy
KEY_MAP_WIN_CMD (Copy, APPCOMMAND_COPY)
@ -282,7 +251,6 @@ KEY_MAP_WIN (Delete, VK_DELETE)
KEY_MAP_COCOA (Delete, kVK_PC_Delete)
KEY_MAP_GTK (Delete, GDK_Delete)
KEY_MAP_GTK (Delete, GDK_KP_Delete)
KEY_MAP_ANDROID (Delete, AKEYCODE_FORWARD_DEL)
// EraseEof
KEY_MAP_WIN (EraseEof, VK_EREOF)
@ -296,7 +264,6 @@ KEY_MAP_GTK (ExSel, GDK_3270_ExSelect) // legacy IBM keyboard layout
KEY_MAP_WIN (Insert, VK_INSERT)
KEY_MAP_GTK (Insert, GDK_Insert)
KEY_MAP_GTK (Insert, GDK_KP_Insert)
KEY_MAP_ANDROID (Insert, AKEYCODE_INSERT)
// Paste
KEY_MAP_WIN_CMD (Paste, APPCOMMAND_PASTE)
@ -315,7 +282,6 @@ KEY_MAP_GTK (Undo, GDK_Undo)
******************************************************************************/
// Accept
KEY_MAP_WIN (Accept, VK_ACCEPT)
KEY_MAP_ANDROID (Accept, AKEYCODE_DPAD_CENTER)
// Attn
KEY_MAP_WIN_OTH (Attn, VK_ATTN) // not valid with Japanese keyboard layout
@ -329,13 +295,11 @@ KEY_MAP_GTK (Cancel, GDK_Cancel)
KEY_MAP_WIN (ContextMenu, VK_APPS)
KEY_MAP_COCOA (ContextMenu, kVK_PC_ContextMenu)
KEY_MAP_GTK (ContextMenu, GDK_Menu)
KEY_MAP_ANDROID (ContextMenu, AKEYCODE_MENU)
// Escape
KEY_MAP_WIN (Escape, VK_ESCAPE)
KEY_MAP_COCOA (Escape, kVK_Escape)
KEY_MAP_GTK (Escape, GDK_Escape)
KEY_MAP_ANDROID (Escape, AKEYCODE_ESCAPE)
// Execute
KEY_MAP_WIN (Execute, VK_EXECUTE)
@ -350,14 +314,12 @@ KEY_MAP_WIN (Help, VK_HELP)
KEY_MAP_WIN_CMD (Help, APPCOMMAND_HELP)
KEY_MAP_COCOA (Help, kVK_Help)
KEY_MAP_GTK (Help, GDK_Help)
KEY_MAP_ANDROID (Help, AKEYCODE_ASSIST)
// Pause
KEY_MAP_WIN (Pause, VK_PAUSE)
KEY_MAP_GTK (Pause, GDK_Pause)
// Break is typically mapped to Alt+Pause or Ctrl+Pause on GTK.
KEY_MAP_GTK (Pause, GDK_Break)
KEY_MAP_ANDROID (Pause, AKEYCODE_BREAK)
// Play
KEY_MAP_WIN (Play, VK_PLAY)
@ -369,11 +331,9 @@ KEY_MAP_GTK (Select, GDK_Select)
// ZoomIn
KEY_MAP_GTK (ZoomIn, GDK_ZoomIn)
KEY_MAP_ANDROID (ZoomIn, AKEYCODE_ZOOM_IN)
// ZoomOut
KEY_MAP_GTK (ZoomOut, GDK_ZoomOut)
KEY_MAP_ANDROID (ZoomOut, AKEYCODE_ZOOM_OUT)
/******************************************************************************
* Device Keys
@ -386,13 +346,11 @@ KEY_MAP_GTK (BrightnessUp, GDK_MonBrightnessUp)
// Eject
KEY_MAP_GTK (Eject, GDK_Eject)
KEY_MAP_ANDROID (Eject, AKEYCODE_MEDIA_EJECT)
// LogOff
KEY_MAP_GTK (LogOff, GDK_LogOff)
// Power
KEY_MAP_ANDROID (Power, AKEYCODE_POWER)
// PowerOff
KEY_MAP_GTK (PowerOff, GDK_PowerDown)
@ -403,7 +361,6 @@ KEY_MAP_WIN (PrintScreen, VK_SNAPSHOT)
KEY_MAP_GTK (PrintScreen, GDK_3270_PrintScreen)
KEY_MAP_GTK (PrintScreen, GDK_Print)
KEY_MAP_GTK (PrintScreen, GDK_Sys_Req)
KEY_MAP_ANDROID (PrintScreen, AKEYCODE_SYSRQ)
// Hibernate
KEY_MAP_GTK (Hibernate, GDK_Hibernate)
@ -437,7 +394,6 @@ KEY_MAP_GTK (Compose, GDK_Multi_key) // "Multi Key" is "Compose key" on X
// Convert
KEY_MAP_WIN (Convert, VK_CONVERT)
KEY_MAP_GTK (Convert, GDK_Henkan)
KEY_MAP_ANDROID (Convert, AKEYCODE_HENKAN)
// Dead
KEY_MAP_GTK (Dead, GDK_dead_grave)
@ -497,19 +453,16 @@ KEY_MAP_GTK (GroupLast, GDK_ISO_Last_Group)
// GroupNext
KEY_MAP_GTK (GroupNext, GDK_ISO_Next_Group)
KEY_MAP_ANDROID (GroupNext, AKEYCODE_LANGUAGE_SWITCH)
// GroupPrevious
KEY_MAP_GTK (GroupPrevious, GDK_ISO_Prev_Group)
// ModeChange
KEY_MAP_WIN (ModeChange, VK_MODECHANGE)
KEY_MAP_ANDROID (ModeChange, AKEYCODE_SWITCH_CHARSET)
// NonConvert
KEY_MAP_WIN (NonConvert, VK_NONCONVERT)
KEY_MAP_GTK (NonConvert, GDK_Muhenkan)
KEY_MAP_ANDROID (NonConvert, AKEYCODE_MUHENKAN)
// PreviousCandidate
KEY_MAP_GTK (PreviousCandidate, GDK_PreviousCandidate) // OADG 109, Mae Koho
@ -534,7 +487,6 @@ KEY_MAP_WIN (JunjaMode, VK_JUNJA)
******************************************************************************/
// Eisu
KEY_MAP_COCOA (Eisu, kVK_JIS_Eisu)
KEY_MAP_ANDROID (Eisu, AKEYCODE_EISU)
// Hankaku
KEY_MAP_WIN_JPN (Hankaku, VK_OEM_AUTO)
@ -546,7 +498,6 @@ KEY_MAP_GTK (Hiragana, GDK_Hiragana)
// HiraganaKatakana
KEY_MAP_GTK (HiraganaKatakana, GDK_Hiragana_Katakana)
KEY_MAP_ANDROID (HiraganaKatakana, AKEYCODE_KATAKANA_HIRAGANA)
// KanaMode
// VK_KANA is never used with modern Japanese keyboard, however, IE maps it to
@ -560,8 +511,6 @@ KEY_MAP_GTK (KanaMode, GDK_Kana_Shift)
KEY_MAP_WIN_JPN (KanjiMode, VK_KANJI /* same as VK_HANJA */)
KEY_MAP_COCOA (KanjiMode, kVK_JIS_Kana) // Kana key opens IME
KEY_MAP_GTK (KanjiMode, GDK_Kanji) // Typically, Alt + Hankaku/Zenkaku key
// Assuming that KANA key of Android is the Kana key on Mac keyboard.
KEY_MAP_ANDROID (KanjiMode, AKEYCODE_KANA)
// Katakana
KEY_MAP_WIN_JPN (Katakana, VK_OEM_FINISH)
@ -577,7 +526,6 @@ KEY_MAP_GTK (Zenkaku, GDK_Zenkaku)
// ZenkakuHankaku
KEY_MAP_GTK (ZenkakuHankaku, GDK_Zenkaku_Hankaku)
KEY_MAP_ANDROID (ZenkakuHankaku, AKEYCODE_ZENKAKU_HANKAKU)
/******************************************************************************
* General-Purpose Function Keys
@ -587,76 +535,64 @@ KEY_MAP_WIN (F1, VK_F1)
KEY_MAP_COCOA (F1, kVK_F1)
KEY_MAP_GTK (F1, GDK_F1)
KEY_MAP_GTK (F1, GDK_KP_F1)
KEY_MAP_ANDROID (F1, AKEYCODE_F1)
// F2
KEY_MAP_WIN (F2, VK_F2)
KEY_MAP_COCOA (F2, kVK_F2)
KEY_MAP_GTK (F2, GDK_F2)
KEY_MAP_GTK (F2, GDK_KP_F2)
KEY_MAP_ANDROID (F2, AKEYCODE_F2)
// F3
KEY_MAP_WIN (F3, VK_F3)
KEY_MAP_COCOA (F3, kVK_F3)
KEY_MAP_GTK (F3, GDK_F3)
KEY_MAP_GTK (F3, GDK_KP_F3)
KEY_MAP_ANDROID (F3, AKEYCODE_F3)
// F4
KEY_MAP_WIN (F4, VK_F4)
KEY_MAP_COCOA (F4, kVK_F4)
KEY_MAP_GTK (F4, GDK_F4)
KEY_MAP_GTK (F4, GDK_KP_F4)
KEY_MAP_ANDROID (F4, AKEYCODE_F4)
// F5
KEY_MAP_WIN (F5, VK_F5)
KEY_MAP_COCOA (F5, kVK_F5)
KEY_MAP_GTK (F5, GDK_F5)
KEY_MAP_ANDROID (F5, AKEYCODE_F5)
// F6
KEY_MAP_WIN (F6, VK_F6)
KEY_MAP_COCOA (F6, kVK_F6)
KEY_MAP_GTK (F6, GDK_F6)
KEY_MAP_ANDROID (F6, AKEYCODE_F6)
// F7
KEY_MAP_WIN (F7, VK_F7)
KEY_MAP_COCOA (F7, kVK_F7)
KEY_MAP_GTK (F7, GDK_F7)
KEY_MAP_ANDROID (F7, AKEYCODE_F7)
// F8
KEY_MAP_WIN (F8, VK_F8)
KEY_MAP_COCOA (F8, kVK_F8)
KEY_MAP_GTK (F8, GDK_F8)
KEY_MAP_ANDROID (F8, AKEYCODE_F8)
// F9
KEY_MAP_WIN (F9, VK_F9)
KEY_MAP_COCOA (F9, kVK_F9)
KEY_MAP_GTK (F9, GDK_F9)
KEY_MAP_ANDROID (F9, AKEYCODE_F9)
// F10
KEY_MAP_WIN (F10, VK_F10)
KEY_MAP_COCOA (F10, kVK_F10)
KEY_MAP_GTK (F10, GDK_F10)
KEY_MAP_ANDROID (F10, AKEYCODE_F10)
// F11
KEY_MAP_WIN (F11, VK_F11)
KEY_MAP_COCOA (F11, kVK_F11)
KEY_MAP_GTK (F11, GDK_F11 /* same as GDK_L1 */)
KEY_MAP_ANDROID (F11, AKEYCODE_F11)
// F12
KEY_MAP_WIN (F12, VK_F12)
KEY_MAP_COCOA (F12, kVK_F12)
KEY_MAP_GTK (F12, GDK_F12 /* same as GDK_L2 */)
KEY_MAP_ANDROID (F12, AKEYCODE_F12)
// F13
KEY_MAP_WIN (F13, VK_F13)
@ -751,11 +687,9 @@ KEY_MAP_GTK (F35, GDK_F35 /* same as GDK_R15 */)
******************************************************************************/
// ChannelDown
KEY_MAP_WIN_CMD (ChannelDown, APPCOMMAND_MEDIA_CHANNEL_DOWN)
KEY_MAP_ANDROID (ChannelDown, AKEYCODE_CHANNEL_DOWN)
// ChannelUp
KEY_MAP_WIN_CMD (ChannelUp, APPCOMMAND_MEDIA_CHANNEL_UP)
KEY_MAP_ANDROID (ChannelUp, AKEYCODE_CHANNEL_UP)
// Close
// NOTE: This is not a key to close disk tray, this is a key to close document
@ -778,45 +712,37 @@ KEY_MAP_GTK (MailSend, GDK_Send)
// MediaPause
KEY_MAP_WIN_CMD (MediaPause, APPCOMMAND_MEDIA_PAUSE)
KEY_MAP_GTK (MediaPause, GDK_AudioPause)
KEY_MAP_ANDROID (MediaPause, AKEYCODE_MEDIA_PAUSE)
// MediaPlay
KEY_MAP_WIN_CMD (MediaPlay, APPCOMMAND_MEDIA_PLAY)
KEY_MAP_GTK (MediaPlay, GDK_AudioPlay)
KEY_MAP_ANDROID (MediaPlay, AKEYCODE_MEDIA_PLAY)
// MediaPlayPause
KEY_MAP_WIN (MediaPlayPause, VK_MEDIA_PLAY_PAUSE)
KEY_MAP_WIN_CMD (MediaPlayPause, APPCOMMAND_MEDIA_PLAY_PAUSE)
KEY_MAP_ANDROID (MediaPlayPause, AKEYCODE_MEDIA_PLAY_PAUSE)
// MediaRecord
KEY_MAP_WIN_CMD (MediaRecord, APPCOMMAND_MEDIA_RECORD)
KEY_MAP_GTK (MediaRecord, GDK_AudioRecord)
KEY_MAP_ANDROID (MediaRecord, AKEYCODE_MEDIA_RECORD)
// MediaRewind
KEY_MAP_WIN_CMD (MediaRewind, APPCOMMAND_MEDIA_REWIND)
KEY_MAP_GTK (MediaRewind, GDK_AudioRewind)
KEY_MAP_ANDROID (MediaRewind, AKEYCODE_MEDIA_REWIND)
// MediaStop
KEY_MAP_WIN (MediaStop, VK_MEDIA_STOP)
KEY_MAP_WIN_CMD (MediaStop, APPCOMMAND_MEDIA_STOP)
KEY_MAP_GTK (MediaStop, GDK_AudioStop)
KEY_MAP_ANDROID (MediaStop, AKEYCODE_MEDIA_STOP)
// MediaTrackNext
KEY_MAP_WIN (MediaTrackNext, VK_MEDIA_NEXT_TRACK)
KEY_MAP_WIN_CMD (MediaTrackNext, APPCOMMAND_MEDIA_NEXTTRACK)
KEY_MAP_GTK (MediaTrackNext, GDK_AudioNext)
KEY_MAP_ANDROID (MediaTrackNext, AKEYCODE_MEDIA_NEXT)
// MediaTrackPrevious
KEY_MAP_WIN (MediaTrackPrevious, VK_MEDIA_PREV_TRACK)
KEY_MAP_WIN_CMD (MediaTrackPrevious, APPCOMMAND_MEDIA_PREVIOUSTRACK)
KEY_MAP_GTK (MediaTrackPrevious, GDK_AudioPrev)
KEY_MAP_ANDROID (MediaTrackPrevious, AKEYCODE_MEDIA_PREVIOUS)
// New
KEY_MAP_WIN_CMD (New, APPCOMMAND_NEW)
@ -851,38 +777,32 @@ KEY_MAP_WIN (AudioVolumeDown, VK_VOLUME_DOWN)
KEY_MAP_WIN_CMD (AudioVolumeDown, APPCOMMAND_VOLUME_DOWN)
KEY_MAP_COCOA (AudioVolumeDown, kVK_VolumeDown)
KEY_MAP_GTK (AudioVolumeDown, GDK_AudioLowerVolume)
KEY_MAP_ANDROID (AudioVolumeDown, AKEYCODE_VOLUME_DOWN)
// AudioVolumeUp
KEY_MAP_WIN (AudioVolumeUp, VK_VOLUME_UP)
KEY_MAP_WIN_CMD (AudioVolumeUp, APPCOMMAND_VOLUME_UP)
KEY_MAP_COCOA (AudioVolumeUp, kVK_VolumeUp)
KEY_MAP_GTK (AudioVolumeUp, GDK_AudioRaiseVolume)
KEY_MAP_ANDROID (AudioVolumeUp, AKEYCODE_VOLUME_UP)
// AudioVolumeMute
KEY_MAP_WIN (AudioVolumeMute, VK_VOLUME_MUTE)
KEY_MAP_WIN_CMD (AudioVolumeMute, APPCOMMAND_VOLUME_MUTE)
KEY_MAP_COCOA (AudioVolumeMute, kVK_Mute)
KEY_MAP_GTK (AudioVolumeMute, GDK_AudioMute)
KEY_MAP_ANDROID (AudioVolumeMute, AKEYCODE_VOLUME_MUTE)
/******************************************************************************
* Application Keys
******************************************************************************/
// LaunchCalculator
KEY_MAP_GTK (LaunchCalculator, GDK_Calculator)
KEY_MAP_ANDROID (LaunchCalculator, AKEYCODE_CALCULATOR)
// LaunchCalendar
KEY_MAP_GTK (LaunchCalendar, GDK_Calendar)
KEY_MAP_ANDROID (LaunchCalendar, AKEYCODE_CALENDAR)
// LaunchMail
KEY_MAP_WIN (LaunchMail, VK_LAUNCH_MAIL)
KEY_MAP_WIN_CMD (LaunchMail, APPCOMMAND_LAUNCH_MAIL)
KEY_MAP_GTK (LaunchMail, GDK_Mail)
KEY_MAP_ANDROID (LaunchMail, AKEYCODE_ENVELOPE)
// LaunchMediaPlayer
KEY_MAP_WIN (LaunchMediaPlayer, VK_LAUNCH_MEDIA_SELECT)
@ -895,7 +815,6 @@ KEY_MAP_GTK (LaunchMediaPlayer, GDK_AudioMedia)
// LaunchMusicPlayer
KEY_MAP_GTK (LaunchMusicPlayer, GDK_Music)
KEY_MAP_ANDROID (LaunchMusicPlayer, AKEYCODE_MUSIC)
// LaunchMyComputer
KEY_MAP_GTK (LaunchMyComputer, GDK_MyComputer)
@ -909,7 +828,6 @@ KEY_MAP_GTK (LaunchSpreadsheet, GDK_Excel)
// LaunchWebBrowser
KEY_MAP_GTK (LaunchWebBrowser, GDK_WWW)
KEY_MAP_ANDROID (LaunchWebBrowser, AKEYCODE_EXPLORER)
// LaunchWebCam
KEY_MAP_GTK (LaunchWebCam, GDK_WebCam)
@ -980,18 +898,15 @@ KEY_MAP_GTK (LaunchApplication16, GDK_LaunchF)
KEY_MAP_WIN (BrowserBack, VK_BROWSER_BACK)
KEY_MAP_WIN_CMD (BrowserBack, APPCOMMAND_BROWSER_BACKWARD)
KEY_MAP_GTK (BrowserBack, GDK_Back)
KEY_MAP_ANDROID (BrowserBack, AKEYCODE_BACK)
// BrowserFavorites
KEY_MAP_WIN (BrowserFavorites, VK_BROWSER_FAVORITES)
KEY_MAP_WIN_CMD (BrowserFavorites, APPCOMMAND_BROWSER_FAVORITES)
KEY_MAP_ANDROID (BrowserFavorites, AKEYCODE_BOOKMARK)
// BrowserForward
KEY_MAP_WIN (BrowserForward, VK_BROWSER_FORWARD)
KEY_MAP_WIN_CMD (BrowserForward, APPCOMMAND_BROWSER_FORWARD)
KEY_MAP_GTK (BrowserForward, GDK_Forward)
KEY_MAP_ANDROID (BrowserForward, AKEYCODE_FORWARD)
// BrowserHome
KEY_MAP_WIN (BrowserHome, VK_BROWSER_HOME)
@ -1008,7 +923,6 @@ KEY_MAP_GTK (BrowserRefresh, GDK_Reload)
KEY_MAP_WIN (BrowserSearch, VK_BROWSER_SEARCH)
KEY_MAP_WIN_CMD (BrowserSearch, APPCOMMAND_BROWSER_SEARCH)
KEY_MAP_GTK (BrowserSearch, GDK_Search)
KEY_MAP_ANDROID (BrowserSearch, AKEYCODE_SEARCH)
// BrowserStop
KEY_MAP_WIN (BrowserStop, VK_BROWSER_STOP)
@ -1019,88 +933,67 @@ KEY_MAP_GTK (BrowserStop, GDK_Stop)
* Mobile Phone Keys
******************************************************************************/
// Call
KEY_MAP_ANDROID (Call, AKEYCODE_CALL)
// Camera
KEY_MAP_ANDROID (Camera, AKEYCODE_CAMERA)
// CameraFocus
KEY_MAP_ANDROID (CameraFocus, AKEYCODE_FOCUS)
// GoHome
KEY_MAP_ANDROID (GoHome, AKEYCODE_HOME)
/******************************************************************************
* TV Keys
******************************************************************************/
// TV
KEY_MAP_ANDROID (TV, AKEYCODE_TV)
// TVInput
KEY_MAP_ANDROID (TVInput, AKEYCODE_TV_INPUT)
// TVPower
KEY_MAP_ANDROID (TVPower, AKEYCODE_TV_POWER)
/******************************************************************************
* Media Controller Keys
******************************************************************************/
// AVRInput
KEY_MAP_ANDROID (AVRInput, AKEYCODE_AVR_INPUT)
// AVRPower
KEY_MAP_ANDROID (AVRPower, AKEYCODE_AVR_POWER)
// ColorF0Red
KEY_MAP_GTK (ColorF0Red, GDK_Red)
KEY_MAP_ANDROID (ColorF0Red, AKEYCODE_PROG_RED)
// ColorF1Green
KEY_MAP_GTK (ColorF1Green, GDK_Green)
KEY_MAP_ANDROID (ColorF1Green, AKEYCODE_PROG_GREEN)
// ColorF2Yellow
KEY_MAP_GTK (ColorF2Yellow, GDK_Yellow)
KEY_MAP_ANDROID (ColorF2Yellow, AKEYCODE_PROG_YELLOW)
// ColorF3Blue
KEY_MAP_GTK (ColorF3Blue, GDK_Blue)
KEY_MAP_ANDROID (ColorF3Blue, AKEYCODE_PROG_BLUE)
// Dimmer
KEY_MAP_GTK (Dimmer, GDK_BrightnessAdjust)
// Guide
KEY_MAP_ANDROID (Guide, AKEYCODE_GUIDE)
// Info
KEY_MAP_ANDROID (Info, AKEYCODE_INFO)
// MediaFastForward
KEY_MAP_WIN_CMD (MediaFastForward, APPCOMMAND_MEDIA_FAST_FORWARD)
KEY_MAP_GTK (MediaFastForward, GDK_AudioForward)
KEY_MAP_ANDROID (MediaFastForward, AKEYCODE_MEDIA_FAST_FORWARD)
// MediaLast
// PinPToggle
KEY_MAP_ANDROID (PinPToggle, AKEYCODE_WINDOW)
// RandomToggle
KEY_MAP_GTK (RandomToggle, GDK_AudioRandomPlay)
// Settings
KEY_MAP_ANDROID (Settings, AKEYCODE_SETTINGS)
// STBInput
KEY_MAP_ANDROID (STBInput, AKEYCODE_STB_INPUT)
// STBPower
KEY_MAP_ANDROID (STBPower, AKEYCODE_STB_POWER)
// Subtitle
KEY_MAP_GTK (Subtitle, GDK_Subtitle)
KEY_MAP_ANDROID (Subtitle, AKEYCODE_CAPTIONS)
// VideoModeNext
KEY_MAP_GTK (VideoModeNext, GDK_Next_VMode)
@ -1112,10 +1005,8 @@ KEY_MAP_WIN (ZoomToggle, VK_ZOOM)
* Keys not defined by any standards
******************************************************************************/
// SoftLeft
KEY_MAP_ANDROID (SoftLeft, AKEYCODE_SOFT_LEFT)
// SoftRight
KEY_MAP_ANDROID (SoftRight, AKEYCODE_SOFT_RIGHT)
#undef KEY_MAP_WIN
#undef KEY_MAP_WIN_JPN
@ -1124,4 +1015,3 @@ KEY_MAP_ANDROID (SoftRight, AKEYCODE_SOFT_RIGHT)
#undef KEY_MAP_WIN_CMD
#undef KEY_MAP_COCOA
#undef KEY_MAP_GTK
#undef KEY_MAP_ANDROID

View file

@ -1,89 +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 "ANRReporter.h"
#include "GeckoProfiler.h"
#include <unistd.h>
namespace mozilla {
bool
ANRReporter::RequestNativeStack(bool aUnwind)
{
if (profiler_is_active()) {
// Don't proceed if profiler is already running
return 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[] =
{"GeckoMain", "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 true;
}
jni::String::LocalRef
ANRReporter::GetNativeStack()
{
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();
// Pointer to a profile JSON string
typedef mozilla::UniquePtr<char[]> 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 jni::String::Param(profile.get());
}
return nullptr;
}
void
ANRReporter::ReleaseNativeStack()
{
if (!profiler_is_active()) {
// Maybe profiler support is disabled?
return;
}
profiler_stop();
}
} // namespace

View file

@ -1,26 +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 ANRReporter_h__
#define ANRReporter_h__
#include "FennecJNINatives.h"
namespace mozilla {
class ANRReporter : public java::ANRReporter::Natives<ANRReporter>
{
private:
ANRReporter();
public:
static bool RequestNativeStack(bool aUnwind);
static jni::String::LocalRef GetNativeStack();
static void ReleaseNativeStack();
};
} // namespace
#endif // ANRReporter_h__

View file

@ -1,126 +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 "AndroidAlerts.h"
#include "GeneratedJNIWrappers.h"
#include "nsAlertsUtils.h"
namespace mozilla {
namespace widget {
NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)
StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap;
NS_IMETHODIMP
AndroidAlerts::ShowAlertNotification(const nsAString & aImageUrl,
const nsAString & aAlertTitle,
const nsAString & aAlertText,
bool aAlertTextClickable,
const nsAString & aAlertCookie,
nsIObserver * aAlertListener,
const nsAString & aAlertName,
const nsAString & aBidi,
const nsAString & aLang,
const nsAString & aData,
nsIPrincipal * aPrincipal,
bool aInPrivateBrowsing,
bool aRequireInteraction)
{
MOZ_ASSERT_UNREACHABLE("Should be implemented by nsAlertsService.");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
nsIObserver* aAlertListener)
{
return ShowPersistentNotification(EmptyString(), aAlert, aAlertListener);
}
NS_IMETHODIMP
AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
nsIAlertNotification* aAlert,
nsIObserver* aAlertListener)
{
// nsAlertsService disables our alerts backend if we ever return failure
// here. To keep the backend enabled, we always return NS_OK even if we
// encounter an error here.
nsresult rv;
nsAutoString imageUrl;
rv = aAlert->GetImageURL(imageUrl);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsAutoString title;
rv = aAlert->GetTitle(title);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsAutoString text;
rv = aAlert->GetText(text);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsAutoString cookie;
rv = aAlert->GetCookie(cookie);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsAutoString name;
rv = aAlert->GetName(name);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsCOMPtr<nsIPrincipal> principal;
rv = aAlert->GetPrincipal(getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, NS_OK);
nsAutoString host;
nsAlertsUtils::GetSourceHostPort(principal, host);
if (aPersistentData.IsEmpty() && aAlertListener) {
if (!sListenerMap) {
sListenerMap = new ListenerMap();
}
// This will remove any observers already registered for this name.
sListenerMap->Put(name, aAlertListener);
}
java::GeckoAppShell::ShowNotification(
name, cookie, title, text, host, imageUrl,
!aPersistentData.IsEmpty() ? jni::StringParam(aPersistentData)
: jni::StringParam(nullptr));
return NS_OK;
}
NS_IMETHODIMP
AndroidAlerts::CloseAlert(const nsAString& aAlertName,
nsIPrincipal* aPrincipal)
{
// We delete the entry in sListenerMap later, when CloseNotification calls
// NotifyListener.
java::GeckoAppShell::CloseNotification(aAlertName);
return NS_OK;
}
void
AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
const char16_t* aCookie)
{
if (!sListenerMap) {
return;
}
nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName);
if (!listener) {
return;
}
listener->Observe(nullptr, aTopic, aCookie);
if (NS_LITERAL_CSTRING("alertfinished").Equals(aTopic)) {
sListenerMap->Remove(aName);
}
}
} // namespace widget
} // namespace mozilla

View file

@ -1,44 +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 mozilla_widget_AndroidAlerts_h__
#define mozilla_widget_AndroidAlerts_h__
#include "nsInterfaceHashtable.h"
#include "nsCOMPtr.h"
#include "nsHashKeys.h"
#include "nsIAlertsService.h"
#include "nsIObserver.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace widget {
class AndroidAlerts : public nsIAlertsService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIALERTSSERVICE
AndroidAlerts() {}
static void NotifyListener(const nsAString& aName, const char* aTopic,
const char16_t* aCookie);
protected:
virtual ~AndroidAlerts()
{
sListenerMap = nullptr;
}
using ListenerMap = nsInterfaceHashtable<nsStringHashKey, nsIObserver>;
static StaticAutoPtr<ListenerMap> sListenerMap;
};
} // namespace widget
} // namespace mozilla
#endif // nsAndroidAlerts_h__

File diff suppressed because it is too large Load diff

View file

@ -1,419 +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 <jni.h>
#include <android/log.h>
#include <cstdlib>
#include <pthread.h>
#include "APKOpen.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "GeneratedJNIWrappers.h"
#include "nsIMutableArray.h"
#include "nsIMIMEInfo.h"
#include "nsColor.h"
#include "gfxRect.h"
#include "nsIAndroidBridge.h"
#include "nsIDOMDOMCursor.h"
#include "mozilla/Likely.h"
#include "mozilla/Mutex.h"
#include "mozilla/Types.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/jni/Utils.h"
#include "nsIObserver.h"
#include "nsDataHashtable.h"
#include "Units.h"
// Some debug #defines
// #define DEBUG_ANDROID_EVENTS
// #define DEBUG_ANDROID_WIDGET
class nsPIDOMWindowOuter;
namespace base {
class Thread;
} // end namespace base
typedef void* EGLSurface;
namespace mozilla {
class AutoLocalJNIFrame;
class Runnable;
namespace hal {
class BatteryInformation;
class NetworkInformation;
} // namespace hal
// The order and number of the members in this structure must correspond
// to the attrsAppearance array in GeckoAppShell.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 MessageCursorContinueCallback : public nsICursorContinueCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICURSORCONTINUECALLBACK
MessageCursorContinueCallback(int aRequestId)
: mRequestId(aRequestId)
{
}
private:
virtual ~MessageCursorContinueCallback()
{
}
int mRequestId;
};
class AndroidBridge final
{
public:
enum {
// Values for NotifyIME, in addition to values from the Gecko
// 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 // AndroidGeckoGLLayerClient
};
static bool IsJavaUiThread() {
return pthread_equal(pthread_self(), ::getJavaUiThread());
}
static void ConstructBridge();
static void DeconstructBridge();
static AndroidBridge *Bridge() {
return sBridge;
}
void ContentDocumentChanged(mozIDOMWindowProxy* aDOMWindow);
bool IsContentDocumentDisplayed(mozIDOMWindowProxy* aDOMWindow);
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());
bool GetHWEncoderCapability();
bool GetHWDecoderCapability();
void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType);
void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt);
bool GetClipboardText(nsAString& aText);
int GetDPI();
int GetScreenDepth();
void Vibrate(const nsTArray<uint32_t>& aPattern);
void GetSystemColors(AndroidSystemColors *aColors);
void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf);
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);
// 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 HandleGeckoMessage(JSContext* cx, JS::HandleObject message);
void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
// 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();
uint16_t GetScreenAngle();
int GetAPIVersion() { return mAPIVersion; }
nsresult GetProxyForURI(const nsACString & aSpec,
const nsACString & aScheme,
const nsACString & aHost,
const int32_t aPort,
nsACString & aResult);
bool PumpMessageLoop();
// 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 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);
protected:
static nsDataHashtable<nsStringHashKey, nsString> sStoragePaths;
static AndroidBridge* sBridge;
AndroidBridge();
~AndroidBridge();
int mAPIVersion;
// intput stream
jclass jReadableByteChannel;
jclass jChannels;
jmethodID jChannelCreate;
jmethodID jByteBufferRead;
jclass jInputStream;
jmethodID jClose;
jmethodID jAvailable;
jmethodID jCalculateLength;
// some convinient types to have around
jclass jStringClass;
jni::Object::GlobalRef mMessageQueue;
jfieldID mMessageQueueMessages;
jmethodID mMessageQueueNext;
private:
class DelayedTask;
nsTArray<DelayedTask> mUiTaskQueue;
mozilla::Mutex mUiTaskQueueLock;
public:
void PostTaskToUiThread(already_AddRefed<Runnable> 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(jni::GetClassRef(jEnv, name))
{}
~AutoJNIClass() {
mEnv->DeleteLocalRef(mClass);
}
jclass getRawRef() const {
return mClass;
}
jclass getGlobalRef() const {
return static_cast<jclass>(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 : jni::GetGeckoThreadEnv();
}
AutoJObject(JNIEnv* aJNIEnv, jobject aObject)
{
mJNIEnv = aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv();
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(jni::GetGeckoThreadEnv())
, mHasFrameBeenPushed(false)
{
MOZ_ASSERT(mJNIEnv);
Push();
}
AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 15)
: mEntries(nEntries)
, mJNIEnv(aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv())
, mHasFrameBeenPushed(false)
{
MOZ_ASSERT(mJNIEnv);
Push();
}
~AutoLocalJNIFrame() {
if (mHasFrameBeenPushed) {
Pop();
}
}
JNIEnv* GetEnv() {
return mJNIEnv;
}
bool CheckForException() {
if (mJNIEnv->ExceptionCheck()) {
MOZ_CATCH_JNI_EXCEPTION(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 <typename ReturnType = jobject>
ReturnType Pop(ReturnType aResult = nullptr) {
MOZ_ASSERT(mHasFrameBeenPushed);
mHasFrameBeenPushed = false;
return static_cast<ReturnType>(
mJNIEnv->PopLocalFrame(static_cast<jobject>(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 nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIANDROIDBRIDGE
NS_DECL_NSIOBSERVER
nsAndroidBridge();
private:
~nsAndroidBridge();
void AddObservers();
void RemoveObservers();
void UpdateAudioPlayingWindows(uint64_t aWindowId, bool aPlaying);
nsTArray<uint64_t> mAudioPlayingWindows;
protected:
};
#endif /* AndroidBridge_h__ */

View file

@ -1,13 +0,0 @@
#ifndef ALOG
#if defined(DEBUG) || defined(FORCE_ALOG)
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## 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

View file

@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 et 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 "AndroidCompositorWidget.h"
#include "nsWindow.h"
namespace mozilla {
namespace widget {
void
AndroidCompositorWidget::SetFirstPaintViewport(const LayerIntPoint& aOffset,
const CSSToLayerScale& aZoom,
const CSSRect& aCssPageRect)
{
auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
if (!layerClient) {
return;
}
layerClient->SetFirstPaintViewport(
float(aOffset.x), float(aOffset.y), aZoom.scale, aCssPageRect.x,
aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
AndroidCompositorWidget::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
const CSSToParentLayerScale& aZoom,
const CSSRect& aCssPageRect,
const CSSRect& aDisplayPort,
const CSSToLayerScale& aPaintedResolution,
bool aLayersUpdated,
int32_t aPaintSyncId,
ScreenMargin& aFixedLayerMargins)
{
auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
if (!layerClient) {
return;
}
// convert the displayport rect from document-relative CSS pixels to
// document-relative device pixels
LayerIntRect dp = gfx::RoundedToInt(aDisplayPort * aPaintedResolution);
java::ViewTransform::LocalRef viewTransform = layerClient->SyncFrameMetrics(
aScrollOffset.x, aScrollOffset.y, aZoom.scale,
aCssPageRect.x, aCssPageRect.y,
aCssPageRect.XMost(), aCssPageRect.YMost(),
dp.x, dp.y, dp.width, dp.height,
aPaintedResolution.scale, aLayersUpdated, aPaintSyncId);
MOZ_ASSERT(viewTransform, "No view transform object!");
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
}
} // namespace widget
} // namespace mozilla

View file

@ -1,44 +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 mozilla_widget_AndroidCompositorWidget_h
#define mozilla_widget_AndroidCompositorWidget_h
#include "mozilla/widget/InProcessCompositorWidget.h"
namespace mozilla {
namespace widget {
/**
* AndroidCompositorWidget inherits from InProcessCompositorWidget because
* Android does not support OOP compositing yet. Once it does,
* AndroidCompositorWidget will be made to inherit from CompositorWidget
* instead.
*/
class AndroidCompositorWidget final : public InProcessCompositorWidget
{
public:
using InProcessCompositorWidget::InProcessCompositorWidget;
AndroidCompositorWidget* AsAndroid() override { return this; }
void SetFirstPaintViewport(const LayerIntPoint& aOffset,
const CSSToLayerScale& aZoom,
const CSSRect& aCssPageRect);
void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
const CSSToParentLayerScale& aZoom,
const CSSRect& aCssPageRect,
const CSSRect& aDisplayPort,
const CSSToLayerScale& aPaintedResolution,
bool aLayersUpdated,
int32_t aPaintSyncId,
ScreenMargin& aFixedLayerMargins);
};
} // namespace widget
} // namespace mozilla
#endif // mozilla_widget_AndroidCompositorWidget_h

View file

@ -1,157 +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 "AndroidContentController.h"
#include "AndroidBridge.h"
#include "base/message_loop.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/IAPZCTreeManager.h"
#include "nsIObserverService.h"
#include "nsLayoutUtils.h"
#include "nsWindow.h"
using mozilla::layers::IAPZCTreeManager;
namespace mozilla {
namespace widget {
void
AndroidContentController::Destroy()
{
mAndroidWindow = nullptr;
ChromeProcessController::Destroy();
}
void
AndroidContentController::NotifyDefaultPrevented(IAPZCTreeManager* aManager,
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 Gecko thread, so we
// have to throw it onto the other thread.
AndroidBridge::Bridge()->PostTaskToUiThread(NewRunnableMethod<uint64_t, bool>(
aManager, &IAPZCTreeManager::ContentReceivedInputBlock,
aInputBlockId, aDefaultPrevented), 0);
return;
}
aManager->ContentReceivedInputBlock(aInputBlockId, aDefaultPrevented);
}
void
AndroidContentController::DispatchSingleTapToObservers(const LayoutDevicePoint& aPoint,
const ScrollableLayerGuid& aGuid) const
{
nsIContent* content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
nsPresContext* context = content
? mozilla::layers::APZCCallbackHelper::GetPresContextForContent(content)
: nullptr;
if (!context) {
return;
}
CSSPoint point = mozilla::layers::APZCCallbackHelper::ApplyCallbackTransform(
aPoint / context->CSSToDevPixelScale(), aGuid);
nsPresContext* rcdContext = context->GetToplevelContentDocumentPresContext();
if (rcdContext && rcdContext->PresShell()->ScaleToResolution()) {
// We need to convert from the root document to the root content document,
// by unapplying the resolution that's on the content document.
const float resolution = rcdContext->PresShell()->GetResolution();
point.x /= resolution;
point.y /= resolution;
}
CSSIntPoint rounded = RoundedToInt(point);
nsAppShell::PostEvent([rounded] {
nsCOMPtr<nsIObserverService> obsServ =
mozilla::services::GetObserverService();
if (!obsServ) {
return;
}
nsPrintfCString data("{\"x\":%d,\"y\":%d}", rounded.x, rounded.y);
obsServ->NotifyObservers(nullptr, "Gesture:SingleTap",
NS_ConvertASCIItoUTF16(data).get());
});
}
void
AndroidContentController::HandleTap(TapType aType, const LayoutDevicePoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
// This function will get invoked first on the Java UI thread, and then
// again on the main thread (because of the code in ChromeProcessController::
// HandleTap). We want to post the SingleTap message once; it can be
// done from either thread but we need access to the callback transform
// so we do it from the main thread.
if (NS_IsMainThread() &&
(aType == TapType::eSingleTap || aType == TapType::eSecondTap)) {
DispatchSingleTapToObservers(aPoint, aGuid);
}
ChromeProcessController::HandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId);
}
void
AndroidContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
{
AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs);
}
void
AndroidContentController::UpdateOverscrollVelocity(const float aX, const float aY, const bool aIsRootContent)
{
if (aIsRootContent && mAndroidWindow) {
mAndroidWindow->UpdateOverscrollVelocity(aX, aY);
}
}
void
AndroidContentController::UpdateOverscrollOffset(const float aX, const float aY, const bool aIsRootContent)
{
if (aIsRootContent && mAndroidWindow) {
mAndroidWindow->UpdateOverscrollOffset(aX, aY);
}
}
void
AndroidContentController::SetScrollingRootContent(const bool isRootContent)
{
if (mAndroidWindow) {
mAndroidWindow->SetScrollingRootContent(isRootContent);
}
}
void
AndroidContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg)
{
// This function may get invoked twice, if the first invocation is not on
// the main thread then the ChromeProcessController version of this function
// will redispatch to the main thread. We want to make sure that our handling
// only happens on the main thread.
ChromeProcessController::NotifyAPZStateChange(aGuid, aChange, aArg);
if (NS_IsMainThread()) {
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (aChange == layers::GeckoContentController::APZStateChange::eTransformEnd) {
// This is used by tests to determine when the APZ is done doing whatever
// it's doing. XXX generify this as needed when writing additional tests.
observerService->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
observerService->NotifyObservers(nullptr, "PanZoom:StateChange", u"NOTHING");
} else if (aChange == layers::GeckoContentController::APZStateChange::eTransformBegin) {
observerService->NotifyObservers(nullptr, "PanZoom:StateChange", u"PANNING");
}
}
}
} // namespace widget
} // namespace mozilla

View file

@ -1,59 +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 AndroidContentController_h__
#define AndroidContentController_h__
#include "mozilla/layers/ChromeProcessController.h"
#include "mozilla/EventForwards.h" // for Modifiers
#include "mozilla/StaticPtr.h"
#include "mozilla/TimeStamp.h"
#include "nsIDOMWindowUtils.h"
#include "nsTArray.h"
#include "nsWindow.h"
namespace mozilla {
namespace layers {
class APZEventState;
class IAPZCTreeManager;
}
namespace widget {
class AndroidContentController final
: public mozilla::layers::ChromeProcessController
{
public:
AndroidContentController(nsWindow* aWindow,
mozilla::layers::APZEventState* aAPZEventState,
mozilla::layers::IAPZCTreeManager* aAPZCTreeManager)
: mozilla::layers::ChromeProcessController(aWindow, aAPZEventState, aAPZCTreeManager)
, mAndroidWindow(aWindow)
{}
// ChromeProcessController methods
virtual void Destroy() override;
void HandleTap(TapType aType, const LayoutDevicePoint& aPoint, Modifiers aModifiers,
const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override;
void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
void UpdateOverscrollVelocity(const float aX, const float aY, const bool aIsRootContent) override;
void UpdateOverscrollOffset(const float aX, const float aY, const bool aIsRootContent) override;
void SetScrollingRootContent(const bool isRootContent) override;
void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override;
static void NotifyDefaultPrevented(mozilla::layers::IAPZCTreeManager* aManager,
uint64_t aInputBlockId, bool aDefaultPrevented);
private:
nsWindow* mAndroidWindow;
void DispatchSingleTapToObservers(const LayoutDevicePoint& aPoint,
const ScrollableLayerGuid& aGuid) const;
};
} // namespace widget
} // namespace mozilla
#endif

View file

@ -1,58 +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"
#include "nsRect.h"
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_ */

View file

@ -1,72 +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"
#include "nsRect.h"
typedef void* EGLImageKHR;
typedef void* EGLClientBuffer;
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_ */

View file

@ -1,47 +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 "AndroidContentController.h"
#include "AndroidGraphicBuffer.h"
#include <jni.h>
#include <pthread.h>
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include "nsAppShell.h"
#include "nsWindow.h"
#include <android/log.h>
#include "nsIObserverService.h"
#include "mozilla/Services.h"
#include "nsThreadUtils.h"
#include "mozilla/Unused.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "nsPluginInstanceOwner.h"
#include "AndroidSurfaceTexture.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::widget;
/* Forward declare all the JNI methods as extern "C" */
extern "C" {
/*
* Incoming JNI methods
*/
}

View file

@ -1,140 +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 <android/log.h>
#include <dlfcn.h>
#include <prthread.h>
#include "mozilla/DebugOnly.h"
#include "mozilla/Assertions.h"
#include "mozilla/SyncRunnable.h"
#include "nsThreadUtils.h"
#include "AndroidBridge.h"
extern "C" {
jclass __jsjni_GetGlobalClassRef(const char *className);
}
class GetGlobalClassRefRunnable : public mozilla::Runnable {
public:
GetGlobalClassRefRunnable(const char *className, jclass *foundClass) :
mClassName(className), mResult(foundClass) {}
NS_IMETHOD Run() override {
*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::jni::GetGeckoThreadEnv();
return env->FindClass(className);
}
jclass
__jsjni_GetGlobalClassRef(const char *className) {
// root class globally
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
jclass globalRef = static_cast<jclass>(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) {
if (NS_IsMainThread()) {
return __jsjni_GetGlobalClassRef(className);
}
nsCOMPtr<nsIThread> mainThread;
mozilla::DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(mainThread));
MOZ_ASSERT(NS_SUCCEEDED(rv));
jclass foundClass;
nsCOMPtr<nsIRunnable> runnable_ref(new GetGlobalClassRefRunnable(className,
&foundClass));
RefPtr<mozilla::SyncRunnable> sr = new mozilla::SyncRunnable(runnable_ref);
sr->DispatchToThread(mainThread);
if (!foundClass)
return nullptr;
return foundClass;
}
__attribute__ ((visibility("default")))
jmethodID
jsjni_GetStaticMethodID(jclass methodClass,
const char *methodName,
const char *signature) {
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
return env->GetStaticMethodID(methodClass, methodName, signature);
}
__attribute__ ((visibility("default")))
bool
jsjni_ExceptionCheck() {
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
return env->ExceptionCheck();
}
__attribute__ ((visibility("default")))
void
jsjni_CallStaticVoidMethodA(jclass cls,
jmethodID method,
jvalue *values) {
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
mozilla::AutoLocalJNIFrame jniFrame(env);
env->CallStaticVoidMethodA(cls, method, values);
}
__attribute__ ((visibility("default")))
int
jsjni_CallStaticIntMethodA(jclass cls,
jmethodID method,
jvalue *values) {
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
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() {
JavaVM* jvm;
JNIEnv* const env = mozilla::jni::GetGeckoThreadEnv();
MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
return jvm;
}
__attribute__ ((visibility("default")))
JNIEnv* jsjni_GetJNIForThread() {
return mozilla::jni::GetEnvForThread();
}
// For compatibility with JNI.jsm; some addons bundle their own JNI.jsm,
// so we cannot just change the function name used in JNI.jsm.
__attribute__ ((visibility("default")))
JNIEnv* GetJNIForThread() {
return mozilla::jni::GetEnvForThread();
}
}

View file

@ -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 <jni.h>
#include <android/log.h>
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__ */

View file

@ -1,62 +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"
using namespace mozilla;
nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv)
{
if (!jstr) {
SetIsVoid(true);
return;
}
JNIEnv *jni = jenv;
if (!jni) {
jni = jni::GetGeckoThreadEnv();
}
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<const char16_t*>(jCharPtr), len);
}
jni->ReleaseStringChars(jstr, jCharPtr);
}
nsJNICString::nsJNICString(jstring jstr, JNIEnv *jenv)
{
if (!jstr) {
SetIsVoid(true);
return;
}
JNIEnv *jni = jenv;
if (!jni) {
jni = jni::GetGeckoThreadEnv();
}
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);
}

View file

@ -1,218 +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 <jni.h>
#include <android/input.h>
#include <android/log.h>
#include <android/api-level.h>
#include "nsRect.h"
#include "nsString.h"
#include "nsTArray.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 nsIWidget;
namespace mozilla {
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 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 nsJNIString : public nsString
{
public:
nsJNIString(jstring jstr, JNIEnv *jenv);
};
class nsJNICString : public nsCString
{
public:
nsJNICString(jstring jstr, JNIEnv *jenv);
};
}
#endif

View file

@ -1,30 +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 GeckoBatteryManager_h
#define GeckoBatteryManager_h
#include "GeneratedJNINatives.h"
#include "nsAppShell.h"
#include "mozilla/Hal.h"
namespace mozilla {
class GeckoBatteryManager final
: public java::GeckoBatteryManager::Natives<GeckoBatteryManager>
{
public:
static void
OnBatteryChange(double aLevel, bool aCharging, double aRemainingTime)
{
hal::NotifyBatteryChange(
hal::BatteryInformation(aLevel, aCharging, aRemainingTime));
}
};
} // namespace mozilla
#endif // GeckoBatteryManager_h

View file

@ -1,53 +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 GeckoNetworkManager_h
#define GeckoNetworkManager_h
#include "GeneratedJNINatives.h"
#include "nsAppShell.h"
#include "nsCOMPtr.h"
#include "nsINetworkLinkService.h"
#include "mozilla/Services.h"
namespace mozilla {
class GeckoNetworkManager final
: public java::GeckoNetworkManager::Natives<GeckoNetworkManager>
{
GeckoNetworkManager() = delete;
public:
static void
OnConnectionChanged(int32_t aType, jni::String::Param aSubType,
bool aIsWifi, int32_t aGateway)
{
hal::NotifyNetworkChange(hal::NetworkInformation(
aType, aIsWifi, aGateway));
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->NotifyObservers(nullptr,
NS_NETWORK_LINK_TYPE_TOPIC,
aSubType->ToString().get());
}
}
static void
OnStatusChanged(jni::String::Param aStatus)
{
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->NotifyObservers(nullptr,
NS_NETWORK_LINK_TOPIC,
aStatus->ToString().get());
}
}
};
} // namespace mozilla
#endif // GeckoNetworkManager_h

View file

@ -1,55 +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 GeckoScreenOrientation_h
#define GeckoScreenOrientation_h
#include "GeneratedJNINatives.h"
#include "nsAppShell.h"
#include "nsCOMPtr.h"
#include "nsIScreenManager.h"
#include "mozilla/Hal.h"
#include "mozilla/dom/ScreenOrientation.h"
namespace mozilla {
class GeckoScreenOrientation final
: public java::GeckoScreenOrientation::Natives<GeckoScreenOrientation>
{
GeckoScreenOrientation() = delete;
public:
static void
OnOrientationChange(int16_t aOrientation, int16_t aAngle)
{
nsCOMPtr<nsIScreenManager> screenMgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
nsCOMPtr<nsIScreen> screen;
if (!screenMgr || NS_FAILED(screenMgr->GetPrimaryScreen(
getter_AddRefs(screen))) || !screen) {
return;
}
nsIntRect rect;
int32_t colorDepth, pixelDepth;
if (NS_FAILED(screen->GetRect(&rect.x, &rect.y,
&rect.width, &rect.height)) ||
NS_FAILED(screen->GetColorDepth(&colorDepth)) ||
NS_FAILED(screen->GetPixelDepth(&pixelDepth))) {
return;
}
hal::NotifyScreenConfigurationChange(hal::ScreenConfiguration(
rect, static_cast<dom::ScreenOrientationInternal>(aOrientation),
aAngle, colorDepth, pixelDepth));
}
};
} // namespace mozilla
#endif // GeckoScreenOrientation_h

View file

@ -1,526 +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 Java methods and rerun the build. Manually updating this file
// will cause your build to fail.
#ifndef GeneratedJNINatives_h
#define GeneratedJNINatives_h
#include "GeneratedJNIWrappers.h"
#include "mozilla/jni/Natives.h"
namespace mozilla {
namespace java {
template<class Impl>
class AlarmReceiver::Natives : public mozilla::jni::NativeImpl<AlarmReceiver, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod AlarmReceiver::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<AlarmReceiver::NotifyAlarmFired_t>(
mozilla::jni::NativeStub<AlarmReceiver::NotifyAlarmFired_t, Impl>
::template Wrap<&Impl::NotifyAlarmFired>)
};
template<class Impl>
class AndroidGamepadManager::Natives : public mozilla::jni::NativeImpl<AndroidGamepadManager, Impl>
{
public:
static const JNINativeMethod methods[3];
};
template<class Impl>
const JNINativeMethod AndroidGamepadManager::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnAxisChange_t>(
mozilla::jni::NativeStub<AndroidGamepadManager::OnAxisChange_t, Impl>
::template Wrap<&Impl::OnAxisChange>),
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnButtonChange_t>(
mozilla::jni::NativeStub<AndroidGamepadManager::OnButtonChange_t, Impl>
::template Wrap<&Impl::OnButtonChange>),
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnGamepadChange_t>(
mozilla::jni::NativeStub<AndroidGamepadManager::OnGamepadChange_t, Impl>
::template Wrap<&Impl::OnGamepadChange>)
};
template<class Impl>
class GeckoAppShell::Natives : public mozilla::jni::NativeImpl<GeckoAppShell, Impl>
{
public:
static const JNINativeMethod methods[8];
};
template<class Impl>
const JNINativeMethod GeckoAppShell::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyObservers_t>(
mozilla::jni::NativeStub<GeckoAppShell::NotifyObservers_t, Impl>
::template Wrap<&Impl::NotifyObservers>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyAlertListener_t>(
mozilla::jni::NativeStub<GeckoAppShell::NotifyAlertListener_t, Impl>
::template Wrap<&Impl::NotifyAlertListener>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyUriVisited_t>(
mozilla::jni::NativeStub<GeckoAppShell::NotifyUriVisited_t, Impl>
::template Wrap<&Impl::NotifyUriVisited>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnFullScreenPluginHidden_t>(
mozilla::jni::NativeStub<GeckoAppShell::OnFullScreenPluginHidden_t, Impl>
::template Wrap<&Impl::OnFullScreenPluginHidden>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnLocationChanged_t>(
mozilla::jni::NativeStub<GeckoAppShell::OnLocationChanged_t, Impl>
::template Wrap<&Impl::OnLocationChanged>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnSensorChanged_t>(
mozilla::jni::NativeStub<GeckoAppShell::OnSensorChanged_t, Impl>
::template Wrap<&Impl::OnSensorChanged>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::ReportJavaCrash_t>(
mozilla::jni::NativeStub<GeckoAppShell::ReportJavaCrash_t, Impl>
::template Wrap<&Impl::ReportJavaCrash>),
mozilla::jni::MakeNativeMethod<GeckoAppShell::SyncNotifyObservers_t>(
mozilla::jni::NativeStub<GeckoAppShell::SyncNotifyObservers_t, Impl>
::template Wrap<&Impl::SyncNotifyObservers>)
};
template<class Impl>
class GeckoAppShell::CameraCallback::Natives : public mozilla::jni::NativeImpl<CameraCallback, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod GeckoAppShell::CameraCallback::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoAppShell::CameraCallback::OnFrameData_t>(
mozilla::jni::NativeStub<GeckoAppShell::CameraCallback::OnFrameData_t, Impl>
::template Wrap<&Impl::OnFrameData>)
};
template<class Impl>
class GeckoBatteryManager::Natives : public mozilla::jni::NativeImpl<GeckoBatteryManager, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod GeckoBatteryManager::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoBatteryManager::OnBatteryChange_t>(
mozilla::jni::NativeStub<GeckoBatteryManager::OnBatteryChange_t, Impl>
::template Wrap<&Impl::OnBatteryChange>)
};
template<class Impl>
class GeckoEditable::Natives : public mozilla::jni::NativeImpl<GeckoEditable, Impl>
{
public:
static const JNINativeMethod methods[7];
};
template<class Impl>
const JNINativeMethod GeckoEditable::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoEditable::DisposeNative_t>(
mozilla::jni::NativeStub<GeckoEditable::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeAddCompositionRange_t>(
mozilla::jni::NativeStub<GeckoEditable::OnImeAddCompositionRange_t, Impl>
::template Wrap<&Impl::OnImeAddCompositionRange>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeReplaceText_t>(
mozilla::jni::NativeStub<GeckoEditable::OnImeReplaceText_t, Impl>
::template Wrap<&Impl::OnImeReplaceText>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeRequestCursorUpdates_t>(
mozilla::jni::NativeStub<GeckoEditable::OnImeRequestCursorUpdates_t, Impl>
::template Wrap<&Impl::OnImeRequestCursorUpdates>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeSynchronize_t>(
mozilla::jni::NativeStub<GeckoEditable::OnImeSynchronize_t, Impl>
::template Wrap<&Impl::OnImeSynchronize>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeUpdateComposition_t>(
mozilla::jni::NativeStub<GeckoEditable::OnImeUpdateComposition_t, Impl>
::template Wrap<&Impl::OnImeUpdateComposition>),
mozilla::jni::MakeNativeMethod<GeckoEditable::OnKeyEvent_t>(
mozilla::jni::NativeStub<GeckoEditable::OnKeyEvent_t, Impl>
::template Wrap<&Impl::OnKeyEvent>)
};
template<class Impl>
class GeckoNetworkManager::Natives : public mozilla::jni::NativeImpl<GeckoNetworkManager, Impl>
{
public:
static const JNINativeMethod methods[2];
};
template<class Impl>
const JNINativeMethod GeckoNetworkManager::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoNetworkManager::OnConnectionChanged_t>(
mozilla::jni::NativeStub<GeckoNetworkManager::OnConnectionChanged_t, Impl>
::template Wrap<&Impl::OnConnectionChanged>),
mozilla::jni::MakeNativeMethod<GeckoNetworkManager::OnStatusChanged_t>(
mozilla::jni::NativeStub<GeckoNetworkManager::OnStatusChanged_t, Impl>
::template Wrap<&Impl::OnStatusChanged>)
};
template<class Impl>
class GeckoScreenOrientation::Natives : public mozilla::jni::NativeImpl<GeckoScreenOrientation, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod GeckoScreenOrientation::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoScreenOrientation::OnOrientationChange_t>(
mozilla::jni::NativeStub<GeckoScreenOrientation::OnOrientationChange_t, Impl>
::template Wrap<&Impl::OnOrientationChange>)
};
template<class Impl>
class GeckoThread::Natives : public mozilla::jni::NativeImpl<GeckoThread, Impl>
{
public:
static const JNINativeMethod methods[6];
};
template<class Impl>
const JNINativeMethod GeckoThread::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoThread::CreateServices_t>(
mozilla::jni::NativeStub<GeckoThread::CreateServices_t, Impl>
::template Wrap<&Impl::CreateServices>),
mozilla::jni::MakeNativeMethod<GeckoThread::OnPause_t>(
mozilla::jni::NativeStub<GeckoThread::OnPause_t, Impl>
::template Wrap<&Impl::OnPause>),
mozilla::jni::MakeNativeMethod<GeckoThread::OnResume_t>(
mozilla::jni::NativeStub<GeckoThread::OnResume_t, Impl>
::template Wrap<&Impl::OnResume>),
mozilla::jni::MakeNativeMethod<GeckoThread::RunUiThreadCallback_t>(
mozilla::jni::NativeStub<GeckoThread::RunUiThreadCallback_t, Impl>
::template Wrap<&Impl::RunUiThreadCallback>),
mozilla::jni::MakeNativeMethod<GeckoThread::SpeculativeConnect_t>(
mozilla::jni::NativeStub<GeckoThread::SpeculativeConnect_t, Impl>
::template Wrap<&Impl::SpeculativeConnect>),
mozilla::jni::MakeNativeMethod<GeckoThread::WaitOnGecko_t>(
mozilla::jni::NativeStub<GeckoThread::WaitOnGecko_t, Impl>
::template Wrap<&Impl::WaitOnGecko>)
};
template<class Impl>
class GeckoView::Window::Natives : public mozilla::jni::NativeImpl<Window, Impl>
{
public:
static const JNINativeMethod methods[5];
};
template<class Impl>
const JNINativeMethod GeckoView::Window::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoView::Window::Close_t>(
mozilla::jni::NativeStub<GeckoView::Window::Close_t, Impl>
::template Wrap<&Impl::Close>),
mozilla::jni::MakeNativeMethod<GeckoView::Window::DisposeNative_t>(
mozilla::jni::NativeStub<GeckoView::Window::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>),
mozilla::jni::MakeNativeMethod<GeckoView::Window::LoadUri_t>(
mozilla::jni::NativeStub<GeckoView::Window::LoadUri_t, Impl>
::template Wrap<&Impl::LoadUri>),
mozilla::jni::MakeNativeMethod<GeckoView::Window::Open_t>(
mozilla::jni::NativeStub<GeckoView::Window::Open_t, Impl>
::template Wrap<&Impl::Open>),
mozilla::jni::MakeNativeMethod<GeckoView::Window::Reattach_t>(
mozilla::jni::NativeStub<GeckoView::Window::Reattach_t, Impl>
::template Wrap<&Impl::Reattach>)
};
template<class Impl>
class PrefsHelper::Natives : public mozilla::jni::NativeImpl<PrefsHelper, Impl>
{
public:
static const JNINativeMethod methods[4];
};
template<class Impl>
const JNINativeMethod PrefsHelper::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<PrefsHelper::AddObserver_t>(
mozilla::jni::NativeStub<PrefsHelper::AddObserver_t, Impl>
::template Wrap<&Impl::AddObserver>),
mozilla::jni::MakeNativeMethod<PrefsHelper::GetPrefs_t>(
mozilla::jni::NativeStub<PrefsHelper::GetPrefs_t, Impl>
::template Wrap<&Impl::GetPrefs>),
mozilla::jni::MakeNativeMethod<PrefsHelper::RemoveObserver_t>(
mozilla::jni::NativeStub<PrefsHelper::RemoveObserver_t, Impl>
::template Wrap<&Impl::RemoveObserver>),
mozilla::jni::MakeNativeMethod<PrefsHelper::SetPref_t>(
mozilla::jni::NativeStub<PrefsHelper::SetPref_t, Impl>
::template Wrap<&Impl::SetPref>)
};
template<class Impl>
class SurfaceTextureListener::Natives : public mozilla::jni::NativeImpl<SurfaceTextureListener, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod SurfaceTextureListener::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<SurfaceTextureListener::OnFrameAvailable_t>(
mozilla::jni::NativeStub<SurfaceTextureListener::OnFrameAvailable_t, Impl>
::template Wrap<&Impl::OnFrameAvailable>)
};
template<class Impl>
class LayerView::Compositor::Natives : public mozilla::jni::NativeImpl<Compositor, Impl>
{
public:
static const JNINativeMethod methods[7];
};
template<class Impl>
const JNINativeMethod LayerView::Compositor::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<LayerView::Compositor::AttachToJava_t>(
mozilla::jni::NativeStub<LayerView::Compositor::AttachToJava_t, Impl>
::template Wrap<&Impl::AttachToJava>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::CreateCompositor_t>(
mozilla::jni::NativeStub<LayerView::Compositor::CreateCompositor_t, Impl>
::template Wrap<&Impl::CreateCompositor>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::DisposeNative_t>(
mozilla::jni::NativeStub<LayerView::Compositor::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::OnSizeChanged_t>(
mozilla::jni::NativeStub<LayerView::Compositor::OnSizeChanged_t, Impl>
::template Wrap<&Impl::OnSizeChanged>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncInvalidateAndScheduleComposite_t>(
mozilla::jni::NativeStub<LayerView::Compositor::SyncInvalidateAndScheduleComposite_t, Impl>
::template Wrap<&Impl::SyncInvalidateAndScheduleComposite>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncPauseCompositor_t>(
mozilla::jni::NativeStub<LayerView::Compositor::SyncPauseCompositor_t, Impl>
::template Wrap<&Impl::SyncPauseCompositor>),
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncResumeResizeCompositor_t>(
mozilla::jni::NativeStub<LayerView::Compositor::SyncResumeResizeCompositor_t, Impl>
::template Wrap<&Impl::SyncResumeResizeCompositor>)
};
template<class Impl>
class NativePanZoomController::Natives : public mozilla::jni::NativeImpl<NativePanZoomController, Impl>
{
public:
static const JNINativeMethod methods[7];
};
template<class Impl>
const JNINativeMethod NativePanZoomController::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<NativePanZoomController::AdjustScrollForSurfaceShift_t>(
mozilla::jni::NativeStub<NativePanZoomController::AdjustScrollForSurfaceShift_t, Impl>
::template Wrap<&Impl::AdjustScrollForSurfaceShift>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::DisposeNative_t>(
mozilla::jni::NativeStub<NativePanZoomController::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMotionEvent_t>(
mozilla::jni::NativeStub<NativePanZoomController::HandleMotionEvent_t, Impl>
::template Wrap<&Impl::HandleMotionEvent>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMotionEventVelocity_t>(
mozilla::jni::NativeStub<NativePanZoomController::HandleMotionEventVelocity_t, Impl>
::template Wrap<&Impl::HandleMotionEventVelocity>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMouseEvent_t>(
mozilla::jni::NativeStub<NativePanZoomController::HandleMouseEvent_t, Impl>
::template Wrap<&Impl::HandleMouseEvent>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleScrollEvent_t>(
mozilla::jni::NativeStub<NativePanZoomController::HandleScrollEvent_t, Impl>
::template Wrap<&Impl::HandleScrollEvent>),
mozilla::jni::MakeNativeMethod<NativePanZoomController::SetIsLongpressEnabled_t>(
mozilla::jni::NativeStub<NativePanZoomController::SetIsLongpressEnabled_t, Impl>
::template Wrap<&Impl::SetIsLongpressEnabled>)
};
template<class Impl>
class NativeJSContainer::Natives : public mozilla::jni::NativeImpl<NativeJSContainer, Impl>
{
public:
static const JNINativeMethod methods[2];
};
template<class Impl>
const JNINativeMethod NativeJSContainer::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<NativeJSContainer::Clone2_t>(
mozilla::jni::NativeStub<NativeJSContainer::Clone2_t, Impl>
::template Wrap<&Impl::Clone>),
mozilla::jni::MakeNativeMethod<NativeJSContainer::DisposeNative_t>(
mozilla::jni::NativeStub<NativeJSContainer::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>)
};
template<class Impl>
class NativeJSObject::Natives : public mozilla::jni::NativeImpl<NativeJSObject, Impl>
{
public:
static const JNINativeMethod methods[27];
};
template<class Impl>
const JNINativeMethod NativeJSObject::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBoolean_t>(
mozilla::jni::NativeStub<NativeJSObject::GetBoolean_t, Impl>
::template Wrap<&Impl::GetBoolean>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBooleanArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetBooleanArray_t, Impl>
::template Wrap<&Impl::GetBooleanArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBundle_t>(
mozilla::jni::NativeStub<NativeJSObject::GetBundle_t, Impl>
::template Wrap<&Impl::GetBundle>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBundleArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetBundleArray_t, Impl>
::template Wrap<&Impl::GetBundleArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetDouble_t>(
mozilla::jni::NativeStub<NativeJSObject::GetDouble_t, Impl>
::template Wrap<&Impl::GetDouble>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetDoubleArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetDoubleArray_t, Impl>
::template Wrap<&Impl::GetDoubleArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetInt_t>(
mozilla::jni::NativeStub<NativeJSObject::GetInt_t, Impl>
::template Wrap<&Impl::GetInt>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetIntArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetIntArray_t, Impl>
::template Wrap<&Impl::GetIntArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetObject_t>(
mozilla::jni::NativeStub<NativeJSObject::GetObject_t, Impl>
::template Wrap<&Impl::GetObject>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetObjectArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetObjectArray_t, Impl>
::template Wrap<&Impl::GetObjectArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetString_t>(
mozilla::jni::NativeStub<NativeJSObject::GetString_t, Impl>
::template Wrap<&Impl::GetString>),
mozilla::jni::MakeNativeMethod<NativeJSObject::GetStringArray_t>(
mozilla::jni::NativeStub<NativeJSObject::GetStringArray_t, Impl>
::template Wrap<&Impl::GetStringArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::Has_t>(
mozilla::jni::NativeStub<NativeJSObject::Has_t, Impl>
::template Wrap<&Impl::Has>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBoolean_t>(
mozilla::jni::NativeStub<NativeJSObject::OptBoolean_t, Impl>
::template Wrap<&Impl::OptBoolean>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBooleanArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptBooleanArray_t, Impl>
::template Wrap<&Impl::OptBooleanArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBundle_t>(
mozilla::jni::NativeStub<NativeJSObject::OptBundle_t, Impl>
::template Wrap<&Impl::OptBundle>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBundleArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptBundleArray_t, Impl>
::template Wrap<&Impl::OptBundleArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptDouble_t>(
mozilla::jni::NativeStub<NativeJSObject::OptDouble_t, Impl>
::template Wrap<&Impl::OptDouble>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptDoubleArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptDoubleArray_t, Impl>
::template Wrap<&Impl::OptDoubleArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptInt_t>(
mozilla::jni::NativeStub<NativeJSObject::OptInt_t, Impl>
::template Wrap<&Impl::OptInt>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptIntArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptIntArray_t, Impl>
::template Wrap<&Impl::OptIntArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptObject_t>(
mozilla::jni::NativeStub<NativeJSObject::OptObject_t, Impl>
::template Wrap<&Impl::OptObject>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptObjectArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptObjectArray_t, Impl>
::template Wrap<&Impl::OptObjectArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptString_t>(
mozilla::jni::NativeStub<NativeJSObject::OptString_t, Impl>
::template Wrap<&Impl::OptString>),
mozilla::jni::MakeNativeMethod<NativeJSObject::OptStringArray_t>(
mozilla::jni::NativeStub<NativeJSObject::OptStringArray_t, Impl>
::template Wrap<&Impl::OptStringArray>),
mozilla::jni::MakeNativeMethod<NativeJSObject::ToBundle_t>(
mozilla::jni::NativeStub<NativeJSObject::ToBundle_t, Impl>
::template Wrap<&Impl::ToBundle>),
mozilla::jni::MakeNativeMethod<NativeJSObject::ToString_t>(
mozilla::jni::NativeStub<NativeJSObject::ToString_t, Impl>
::template Wrap<&Impl::ToString>)
};
} /* java */
} /* mozilla */
#endif // GeneratedJNINatives_h

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,605 +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;
}
// This spoofed value wins, even if the environment variable
// MOZ_GFX_SPOOF_GL_VENDOR was set.
void SpoofVendor(const nsCString& s) {
mVendor = s;
}
const nsCString& Renderer() {
EnsureInitialized();
return mRenderer;
}
// This spoofed value wins, even if the environment variable
// MOZ_GFX_SPOOF_GL_RENDERER was set.
void SpoofRenderer(const nsCString& s) {
mRenderer = s;
}
const nsCString& Version() {
EnsureInitialized();
return mVersion;
}
// This spoofed value wins, even if the environment variable
// MOZ_GFX_SPOOF_GL_VERSION was set.
void SpoofVersion(const nsCString& s) {
mVersion = s;
}
void EnsureInitialized() {
if (mReady) {
return;
}
RefPtr<gl::GLContext> gl;
nsCString discardFailureId;
gl = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE,
&discardFailureId);
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();
if (mVendor.IsEmpty()) {
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));
}
}
if (mRenderer.IsEmpty()) {
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));
}
}
if (mVersion.IsEmpty()) {
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)
, mOSVersionInteger(0)
, mSDKVersion(0)
{
}
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;
}
NS_IMETHODIMP
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
{
return NS_ERROR_FAILURE;
}
void
GfxInfo::EnsureInitialized()
{
if (mInitialized)
return;
if (!mozilla::AndroidBridge::Bridge()) {
gfxWarning() << "AndroidBridge missing during initialization";
return;
}
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());
}
if (mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &mSDKVersion)) {
// the HARDWARE field isn't available on Android SDK < 8, but we require 9+ anyway.
MOZ_ASSERT(mSDKVersion >= 8);
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", mHardware)) {
mAdapterDescription.AppendPrintf(", Hardware: %s", NS_LossyConvertUTF16toASCII(mHardware).get());
}
} else {
mSDKVersion = 0;
}
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());
AddCrashReportAnnotations();
mInitialized = true;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
{
EnsureInitialized();
aAdapterDescription = NS_ConvertASCIItoUTF16(mAdapterDescription);
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
{
EnsureInitialized();
aAdapterRAM.Truncate();
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
{
EnsureInitialized();
aAdapterDriver.Truncate();
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
{
EnsureInitialized();
aAdapterDriverVersion = NS_ConvertASCIItoUTF16(mGLStrings->Version());
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
{
EnsureInitialized();
aAdapterDriverDate.Truncate();
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
{
EnsureInitialized();
aAdapterVendorID = NS_ConvertASCIItoUTF16(mGLStrings->Vendor());
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
{
EnsureInitialized();
aAdapterDeviceID = NS_ConvertASCIItoUTF16(mGLStrings->Renderer());
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
{
EnsureInitialized();
return NS_ERROR_FAILURE;
}
void
GfxInfo::AddCrashReportAnnotations()
{
/*** STUB ***/
}
const nsTArray<GfxDriverInfo>&
GfxInfo::GetGfxDriverInfo()
{
if (mDriverInfo->IsEmpty()) {
APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Android,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAll), GfxDriverInfo::allDevices,
nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK,
DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions,
"FEATURE_OK_FORCE_OPENGL" );
}
return *mDriverInfo;
}
nsresult
GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
int32_t *aStatus,
nsAString &aSuggestedDriverVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo,
nsACString &aFailureId,
OperatingSystem* aOS /* = nullptr */)
{
NS_ENSURE_ARG_POINTER(aStatus);
aSuggestedDriverVersion.SetIsVoid(true);
*aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
OperatingSystem os = mOS;
if (aOS)
*aOS = os;
if (mShutdownOccurred) {
return NS_OK;
}
// 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 == nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION) {
if (mSDKVersion < 11) {
// It's slower than software due to not having a compositing fast path
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
aFailureId = "FEATURE_FAILURE_CANVAS_2D_SDK";
} else if (mGLStrings->Renderer().Find("Vivante GC1000") != -1) {
// Blocklist Vivante GC1000. See bug 1248183.
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILED_CANVAS_2D_HW";
} else {
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
}
return NS_OK;
}
if (aFeature == FEATURE_WEBGL_OPENGL) {
if (mGLStrings->Renderer().Find("Adreno 200") != -1 ||
mGLStrings->Renderer().Find("Adreno 205") != -1)
{
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_ADRENO_20x";
return NS_OK;
}
if (mHardware.EqualsLiteral("ville")) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_VILLE";
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;
aFailureId = "FEATURE_FAILURE_STAGE_HW";
return NS_OK;
}
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;
aFailureId = "FEATURE_FAILURE_4_1_HW";
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;
aFailureId = "FEATURE_FAILURE_4_2_HW";
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;
aFailureId = "FEATURE_FAILURE_4_3_SONY";
return NS_OK;
}
}
}
if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_ENCODE) {
if (mozilla::AndroidBridge::Bridge()) {
*aStatus = mozilla::AndroidBridge::Bridge()->GetHWEncoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_WEBRTC_ENCODE";
return NS_OK;
}
}
if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_DECODE) {
if (mozilla::AndroidBridge::Bridge()) {
*aStatus = mozilla::AndroidBridge::Bridge()->GetHWDecoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_WEBRTC_DECODE";
return NS_OK;
}
}
if (aFeature == FEATURE_VP8_HW_DECODE || aFeature == FEATURE_VP9_HW_DECODE) {
NS_LossyConvertUTF16toASCII model(mModel);
bool isBlocked =
// GIFV crash, see bug 1232911.
model.Equals("GT-N8013", nsCaseInsensitiveCStringComparator());
if (isBlocked) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_VPx";
} else {
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
}
return NS_OK;
}
}
return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
}
#ifdef DEBUG
// Implement nsIGfxInfoDebug
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
{
mGLStrings->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID));
return NS_OK;
}
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
{
mGLStrings->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID));
return NS_OK;
}
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
{
mGLStrings->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion));
return NS_OK;
}
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;
}
}
}

View file

@ -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 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) override;
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled) override;
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion) override;
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams) override;
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription) override;
NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver) override;
NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID) override;
NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID) override;
NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID) override;
NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM) override;
NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate) override;
NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription) override;
NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver) override;
NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID) override;
NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID) override;
NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID) override;
NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
using GfxInfoBase::GetFeatureStatus;
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
using GfxInfoBase::GetWebGLParameter;
void EnsureInitialized();
virtual nsString Model() override;
virtual nsString Hardware() override;
virtual nsString Product() override;
virtual nsString Manufacturer() override;
#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<GfxDriverInfo>& aDriverInfo,
nsACString &aFailureId,
OperatingSystem* aOS = nullptr) override;
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
private:
void AddCrashReportAnnotations();
bool mInitialized;
class GLStrings;
UniquePtr<GLStrings> mGLStrings;
nsCString mAdapterDescription;
OperatingSystem mOS;
nsString mModel, mHardware, mManufacturer, mProduct;
nsCString mOSVersion;
uint32_t mOSVersionInteger;
int32_t mSDKVersion;
};
} // namespace widget
} // namespace mozilla
#endif /* __mozilla_widget_GfxInfo_h__ */

View file

@ -1,881 +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 <jni.h>
#include "Bundle.h"
#include "GeneratedJNINatives.h"
#include "MainThreadUtils.h"
#include "jsapi.h"
#include "nsJSUtils.h"
#include <mozilla/Vector.h>
#include <mozilla/jni/Accessors.h>
#include <mozilla/jni/Refs.h>
#include <mozilla/jni/Utils.h>
/**
* NativeJSContainer.cpp implements the native methods in both
* NativeJSContainer and NativeJSObject, using JSAPI to retrieve values from a
* JSObject and using JNI to return those values to Java code.
*/
namespace mozilla {
namespace widget {
namespace {
bool CheckThread()
{
if (!NS_IsMainThread()) {
jni::ThrowException("java/lang/IllegalThreadStateException",
"Not on Gecko thread");
return false;
}
return true;
}
template<class C, typename T> bool
CheckJNIArgument(const jni::Ref<C, T>& arg)
{
if (!arg) {
jni::ThrowException("java/lang/IllegalArgumentException",
"Null argument");
}
return !!arg;
}
nsresult
CheckSDKCall(nsresult rv)
{
if (NS_FAILED(rv)) {
jni::ThrowException("java/lang/UnsupportedOperationException",
"SDK JNI call failed");
}
return rv;
}
// Convert a JNI string to a char16_t string that JSAPI expects.
class JSJNIString final
{
JNIEnv* const mEnv;
jni::String::Param mJNIString;
const char16_t* const mJSString;
public:
JSJNIString(JNIEnv* env, jni::String::Param str)
: mEnv(env)
, mJNIString(str)
, mJSString(!str ? nullptr : reinterpret_cast<const char16_t*>(
mEnv->GetStringChars(str.Get(), nullptr)))
{}
~JSJNIString() {
if (mJNIString) {
mEnv->ReleaseStringChars(mJNIString.Get(),
reinterpret_cast<const jchar*>(mJSString));
}
}
operator const char16_t*() const {
return mJSString;
}
size_t Length() const {
return static_cast<size_t>(mEnv->GetStringLength(mJNIString.Get()));
}
};
} // namepsace
class NativeJSContainerImpl final
: public NativeJSObject::Natives<NativeJSContainerImpl>
, public NativeJSContainer::Natives<NativeJSContainerImpl>
{
typedef NativeJSContainerImpl Self;
typedef NativeJSContainer::Natives<NativeJSContainerImpl> ContainerBase;
typedef NativeJSObject::Natives<NativeJSContainerImpl> ObjectBase;
typedef JS::PersistentRooted<JSObject*> PersistentObject;
JNIEnv* const mEnv;
// Context that the object is valid in
JSContext* const mJSContext;
// Root JS object
PersistentObject mJSObject;
// Children objects
Vector<NativeJSObject::GlobalRef, 0> mChildren;
bool CheckObject() const
{
if (!mJSObject) {
jni::ThrowException("java/lang/NullPointerException",
"Null JSObject");
}
return !!mJSObject;
}
bool CheckJSCall(bool result) const
{
if (!result) {
JS_ClearPendingException(mJSContext);
jni::ThrowException("java/lang/UnsupportedOperationException",
"JSAPI call failed");
}
return result;
}
// Check that a JS Value contains a particular property type as indicaed by
// the property's InValue method (e.g. StringProperty::InValue).
bool CheckProperty(bool (Self::*InValue)(JS::HandleValue) const,
JS::HandleValue val) const
{
if (!(this->*InValue)(val)) {
// XXX this can happen when converting a double array inside a
// Bundle, because double arrays can be misidentified as an int
// array. The workaround is to add a dummy first element to the
// array that is a floating point value, i.e. [0.5, ...].
jni::ThrowException(
"org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
"Property type mismatch");
return false;
}
return true;
}
// Primitive properties
template<bool (JS::Value::*IsType)() const> bool
PrimitiveInValue(JS::HandleValue val) const
{
return (static_cast<const JS::Value&>(val).*IsType)();
}
template<typename U, U (JS::Value::*ToType)() const> U
PrimitiveFromValue(JS::HandleValue val) const
{
return (static_cast<const JS::Value&>(val).*ToType)();
}
template<class Prop> typename Prop::NativeArray
PrimitiveNewArray(JS::HandleObject array, size_t length) const
{
typedef typename Prop::JNIType JNIType;
// Fill up a temporary buffer for our array, then use
// JNIEnv::Set*ArrayRegion to fill out array in one go.
UniquePtr<JNIType[]> buffer = MakeUnique<JNIType[]>(length);
for (size_t i = 0; i < length; i++) {
JS::RootedValue elem(mJSContext);
if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
!CheckProperty(Prop::InValue, elem)) {
return nullptr;
}
buffer[i] = JNIType((this->*Prop::FromValue)(elem));
}
auto jarray = Prop::NativeArray::Adopt(
mEnv, (mEnv->*Prop::NewJNIArray)(length));
if (!jarray) {
return nullptr;
}
(mEnv->*Prop::SetJNIArrayRegion)(
jarray.Get(), 0, length, buffer.get());
if (mEnv->ExceptionCheck()) {
return nullptr;
}
return jarray;
}
template<typename U, typename UA, typename V, typename VA,
bool (JS::Value::*IsType)() const,
U (JS::Value::*ToType)() const,
VA (JNIEnv::*NewArray_)(jsize),
void (JNIEnv::*SetArrayRegion_)(VA, jsize, jsize, const V*)>
struct PrimitiveProperty
{
// C++ type for a primitive property (e.g. bool)
typedef U NativeType;
// C++ type for the fallback value used in opt* methods
typedef U NativeFallback;
// Type for an array of the primitive type (e.g. BooleanArray::LocalRef)
typedef typename UA::LocalRef NativeArray;
// Type for the fallback value used in opt*Array methods
typedef const typename UA::Ref ArrayFallback;
// JNI type (e.g. jboolean)
typedef V JNIType;
// JNIEnv function to create a new JNI array of the primiive type
typedef decltype(NewArray_) NewJNIArray_t;
static constexpr NewJNIArray_t NewJNIArray = NewArray_;
// JNIEnv function to fill a JNI array of the primiive type
typedef decltype(SetArrayRegion_) SetJNIArrayRegion_t;
static constexpr SetJNIArrayRegion_t SetJNIArrayRegion = SetArrayRegion_;
// Function to determine if a JS Value contains the primitive type
typedef decltype(&Self::PrimitiveInValue<IsType>) InValue_t;
static constexpr InValue_t InValue = &Self::PrimitiveInValue<IsType>;
// Function to convert a JS Value to the primitive type
typedef decltype(&Self::PrimitiveFromValue<U, ToType>) FromValue_t;
static constexpr FromValue_t FromValue
= &Self::PrimitiveFromValue<U, ToType>;
// Function to convert a JS array to a JNI array
typedef decltype(&Self::PrimitiveNewArray<PrimitiveProperty>) NewArray_t;
static constexpr NewArray_t NewArray
= &Self::PrimitiveNewArray<PrimitiveProperty>;
};
// String properties
bool StringInValue(JS::HandleValue val) const
{
return val.isString();
}
jni::String::LocalRef
StringFromValue(const JS::HandleString str) const
{
nsAutoJSString autoStr;
if (!CheckJSCall(autoStr.init(mJSContext, str))) {
return nullptr;
}
// StringParam can automatically convert a nsString to jstring.
return jni::StringParam(autoStr, mEnv);
}
jni::String::LocalRef
StringFromValue(JS::HandleValue val)
{
const JS::RootedString str(mJSContext, val.toString());
return StringFromValue(str);
}
// Bundle properties
sdk::Bundle::LocalRef
BundleFromValue(const JS::HandleObject obj)
{
JS::Rooted<JS::IdVector> ids(mJSContext, JS::IdVector(mJSContext));
if (!CheckJSCall(JS_Enumerate(mJSContext, obj, &ids))) {
return nullptr;
}
const size_t length = ids.length();
sdk::Bundle::LocalRef newBundle(mEnv);
NS_ENSURE_SUCCESS(CheckSDKCall(
sdk::Bundle::New(length, &newBundle)), nullptr);
// Iterate through each property of the JS object. For each property,
// determine its type from a list of supported types, and convert that
// proeprty to the supported type.
for (size_t i = 0; i < ids.length(); i++) {
const JS::RootedId id(mJSContext, ids[i]);
JS::RootedValue idVal(mJSContext);
if (!CheckJSCall(JS_IdToValue(mJSContext, id, &idVal))) {
return nullptr;
}
const JS::RootedString idStr(mJSContext,
JS::ToString(mJSContext, idVal));
if (!CheckJSCall(!!idStr)) {
return nullptr;
}
jni::String::LocalRef name = StringFromValue(idStr);
JS::RootedValue val(mJSContext);
if (!name ||
!CheckJSCall(JS_GetPropertyById(mJSContext, obj, id, &val))) {
return nullptr;
}
#define PUT_IN_BUNDLE_IF_TYPE_IS(TYPE) \
if ((this->*TYPE##Property::InValue)(val)) { \
auto jval = (this->*TYPE##Property::FromValue)(val); \
if (mEnv->ExceptionCheck()) { \
return nullptr; \
} \
NS_ENSURE_SUCCESS(CheckSDKCall( \
newBundle->Put##TYPE(name, jval)), 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.
// XXX empty arrays are treated as boolean arrays. Workaround is
// to always have a dummy element to create a non-empty array.
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.
// When that happens, the Bundle conversion will fail.
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.
jni::ThrowException("java/lang/UnsupportedOperationException",
"Unsupported property type");
return nullptr;
}
return jni::Object::LocalRef::Adopt(newBundle.Env(),
newBundle.Forget());
}
sdk::Bundle::LocalRef
BundleFromValue(JS::HandleValue val)
{
if (val.isNull()) {
return nullptr;
}
JS::RootedObject object(mJSContext, &val.toObject());
return BundleFromValue(object);
}
// Object properties
bool ObjectInValue(JS::HandleValue val) const
{
return val.isObjectOrNull();
}
NativeJSObject::LocalRef
ObjectFromValue(JS::HandleValue val)
{
if (val.isNull()) {
return nullptr;
}
JS::RootedObject object(mJSContext, &val.toObject());
return CreateChild(object);
}
template<class Prop> typename Prop::NativeArray
ObjectNewArray(JS::HandleObject array, size_t length)
{
auto jarray = Prop::NativeArray::Adopt(mEnv, mEnv->NewObjectArray(
length, typename Prop::ClassType::Context().ClassRef(),
nullptr));
if (!jarray) {
return nullptr;
}
// For object arrays, we have to set each element separately.
for (size_t i = 0; i < length; i++) {
JS::RootedValue elem(mJSContext);
if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
!CheckProperty(Prop::InValue, elem)) {
return nullptr;
}
mEnv->SetObjectArrayElement(
jarray.Get(), i, (this->*Prop::FromValue)(elem).Get());
if (mEnv->ExceptionCheck()) {
return nullptr;
}
}
return jarray;
}
template<class Class,
bool (Self::*InValue_)(JS::HandleValue) const,
typename Class::LocalRef (Self::*FromValue_)(JS::HandleValue)>
struct BaseObjectProperty
{
// JNI class for the object type (e.g. jni::String)
typedef Class ClassType;
// See comments in PrimitiveProperty.
typedef typename ClassType::LocalRef NativeType;
typedef const typename ClassType::Ref NativeFallback;
typedef typename jni::ObjectArray::LocalRef NativeArray;
typedef const jni::ObjectArray::Ref ArrayFallback;
typedef decltype(InValue_) InValue_t;
static constexpr InValue_t InValue = InValue_;
typedef decltype(FromValue_) FromValue_t;
static constexpr FromValue_t FromValue = FromValue_;
typedef decltype(&Self::ObjectNewArray<BaseObjectProperty>) NewArray_t;
static constexpr NewArray_t NewArray
= &Self::ObjectNewArray<BaseObjectProperty>;
};
// Array properties
template<class Prop> bool
ArrayInValue(JS::HandleValue val) const
{
if (!val.isObject()) {
return false;
}
JS::RootedObject obj(mJSContext, &val.toObject());
bool isArray;
uint32_t length = 0;
if (!JS_IsArrayObject(mJSContext, obj, &isArray) ||
!isArray ||
!JS_GetArrayLength(mJSContext, obj, &length)) {
JS_ClearPendingException(mJSContext);
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(mJSContext);
if (!JS_GetElement(mJSContext, obj, 0, &element)) {
JS_ClearPendingException(mJSContext);
return false;
}
return (this->*Prop::InValue)(element);
}
template<class Prop> typename Prop::NativeArray
ArrayFromValue(JS::HandleValue val)
{
JS::RootedObject obj(mJSContext, &val.toObject());
uint32_t length = 0;
if (!CheckJSCall(JS_GetArrayLength(mJSContext, obj, &length))) {
return nullptr;
}
return (this->*Prop::NewArray)(obj, length);
}
template<class Prop>
struct ArrayProperty
{
// See comments in PrimitiveProperty.
typedef typename Prop::NativeArray NativeType;
typedef typename Prop::ArrayFallback NativeFallback;
typedef decltype(&Self::ArrayInValue<Prop>) InValue_t;
static constexpr InValue_t InValue
= &Self::ArrayInValue<Prop>;
typedef decltype(&Self::ArrayFromValue<Prop>) FromValue_t;
static constexpr FromValue_t FromValue
= &Self::ArrayFromValue<Prop>;
};
// "Has" property is a special property type that is used to implement
// NativeJSObject.has, by returning true from InValue and FromValue for
// every existing property, and having false as the fallback value for
// when a property doesn't exist.
bool HasValue(JS::HandleValue val) const
{
return true;
}
struct HasProperty
{
// See comments in PrimitiveProperty.
typedef bool NativeType;
typedef bool NativeFallback;
typedef decltype(&Self::HasValue) HasValue_t;
static constexpr HasValue_t InValue = &Self::HasValue;
static constexpr HasValue_t FromValue = &Self::HasValue;
};
// 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<
bool, jni::BooleanArray, jboolean, jbooleanArray,
&JS::Value::isBoolean, &JS::Value::toBoolean,
&JNIEnv::NewBooleanArray, &JNIEnv::SetBooleanArrayRegion>
BooleanProperty;
typedef PrimitiveProperty<
double, jni::DoubleArray, jdouble, jdoubleArray,
&JS::Value::isNumber, &JS::Value::toNumber,
&JNIEnv::NewDoubleArray, &JNIEnv::SetDoubleArrayRegion>
DoubleProperty;
typedef PrimitiveProperty<
int32_t, jni::IntArray, jint, jintArray,
&JS::Value::isInt32, &JS::Value::toInt32,
&JNIEnv::NewIntArray, &JNIEnv::SetIntArrayRegion>
IntProperty;
typedef BaseObjectProperty<
jni::String, &Self::StringInValue, &Self::StringFromValue>
StringProperty;
typedef BaseObjectProperty<
sdk::Bundle, &Self::ObjectInValue, &Self::BundleFromValue>
BundleProperty;
typedef BaseObjectProperty<
NativeJSObject, &Self::ObjectInValue, &Self::ObjectFromValue>
ObjectProperty;
typedef ArrayProperty<BooleanProperty> BooleanArrayProperty;
typedef ArrayProperty<DoubleProperty> DoubleArrayProperty;
typedef ArrayProperty<IntProperty> IntArrayProperty;
typedef ArrayProperty<StringProperty> StringArrayProperty;
typedef ArrayProperty<BundleProperty> BundleArrayProperty;
typedef ArrayProperty<ObjectProperty> ObjectArrayProperty;
template<class Prop>
typename Prop::NativeType
GetProperty(jni::String::Param name,
typename Prop::NativeFallback* fallback = nullptr)
{
if (!CheckThread() || !CheckObject()) {
return typename Prop::NativeType();
}
const JSJNIString nameStr(mEnv, name);
JS::RootedValue val(mJSContext);
if (!CheckJNIArgument(name) ||
!CheckJSCall(JS_GetUCProperty(
mJSContext, mJSObject, nameStr, nameStr.Length(), &val))) {
return typename Prop::NativeType();
}
// Strictly, null is different from undefined in JS. However, in
// practice, null is often used to indicate a property doesn't exist in
// the same manner as undefined. Therefore, we treat null in the same
// way as undefined when checking property existence (bug 1014965).
if (val.isUndefined() || val.isNull()) {
if (fallback) {
return mozilla::Move(*fallback);
}
jni::ThrowException(
"org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
"Property does not exist");
return typename Prop::NativeType();
}
if (!CheckProperty(Prop::InValue, val)) {
return typename Prop::NativeType();
}
return (this->*Prop::FromValue)(val);
}
NativeJSObject::LocalRef CreateChild(JS::HandleObject object)
{
auto instance = NativeJSObject::New();
mozilla::UniquePtr<NativeJSContainerImpl> impl(
new NativeJSContainerImpl(instance.Env(), mJSContext, object));
ObjectBase::AttachNative(instance, mozilla::Move(impl));
if (!mChildren.append(NativeJSObject::GlobalRef(instance))) {
MOZ_CRASH();
}
return instance;
}
NativeJSContainerImpl(JNIEnv* env, JSContext* cx, JS::HandleObject object)
: mEnv(env)
, mJSContext(cx)
, mJSObject(cx, object)
{}
public:
~NativeJSContainerImpl()
{
// Dispose of all children on destruction. The children will in turn
// dispose any of their children (i.e. our grandchildren) and so on.
NativeJSObject::LocalRef child(mEnv);
for (size_t i = 0; i < mChildren.length(); i++) {
child = mChildren[i];
ObjectBase::GetNative(child)->ObjectBase::DisposeNative(child);
}
}
static NativeJSContainer::LocalRef
CreateInstance(JSContext* cx, JS::HandleObject object)
{
auto instance = NativeJSContainer::New();
mozilla::UniquePtr<NativeJSContainerImpl> impl(
new NativeJSContainerImpl(instance.Env(), cx, object));
ContainerBase::AttachNative(instance, mozilla::Move(impl));
return instance;
}
// NativeJSContainer methods
void DisposeNative(const NativeJSContainer::LocalRef& instance)
{
if (!CheckThread()) {
return;
}
ContainerBase::DisposeNative(instance);
}
NativeJSContainer::LocalRef Clone()
{
if (!CheckThread()) {
return nullptr;
}
return CreateInstance(mJSContext, mJSObject);
}
// NativeJSObject methods
bool GetBoolean(jni::String::Param name)
{
return GetProperty<BooleanProperty>(name);
}
bool OptBoolean(jni::String::Param name, bool fallback)
{
return GetProperty<BooleanProperty>(name, &fallback);
}
jni::BooleanArray::LocalRef
GetBooleanArray(jni::String::Param name)
{
return GetProperty<BooleanArrayProperty>(name);
}
jni::BooleanArray::LocalRef
OptBooleanArray(jni::String::Param name, jni::BooleanArray::Param fallback)
{
return GetProperty<BooleanArrayProperty>(name, &fallback);
}
jni::Object::LocalRef
GetBundle(jni::String::Param name)
{
return GetProperty<BundleProperty>(name);
}
jni::Object::LocalRef
OptBundle(jni::String::Param name, jni::Object::Param fallback)
{
// Because the GetProperty expects a sdk::Bundle::Param,
// we have to do conversions here from jni::Object::Param.
const auto& fb = sdk::Bundle::Ref::From(fallback.Get());
return GetProperty<BundleProperty>(name, &fb);
}
jni::ObjectArray::LocalRef
GetBundleArray(jni::String::Param name)
{
return GetProperty<BundleArrayProperty>(name);
}
jni::ObjectArray::LocalRef
OptBundleArray(jni::String::Param name, jni::ObjectArray::Param fallback)
{
return GetProperty<BundleArrayProperty>(name, &fallback);
}
double GetDouble(jni::String::Param name)
{
return GetProperty<DoubleProperty>(name);
}
double OptDouble(jni::String::Param name, double fallback)
{
return GetProperty<DoubleProperty>(name, &fallback);
}
jni::DoubleArray::LocalRef
GetDoubleArray(jni::String::Param name)
{
return GetProperty<DoubleArrayProperty>(name);
}
jni::DoubleArray::LocalRef
OptDoubleArray(jni::String::Param name, jni::DoubleArray::Param fallback)
{
jni::DoubleArray::LocalRef fb(fallback);
return GetProperty<DoubleArrayProperty>(name, &fb);
}
int GetInt(jni::String::Param name)
{
return GetProperty<IntProperty>(name);
}
int OptInt(jni::String::Param name, int fallback)
{
return GetProperty<IntProperty>(name, &fallback);
}
jni::IntArray::LocalRef
GetIntArray(jni::String::Param name)
{
return GetProperty<IntArrayProperty>(name);
}
jni::IntArray::LocalRef
OptIntArray(jni::String::Param name, jni::IntArray::Param fallback)
{
jni::IntArray::LocalRef fb(fallback);
return GetProperty<IntArrayProperty>(name, &fb);
}
NativeJSObject::LocalRef
GetObject(jni::String::Param name)
{
return GetProperty<ObjectProperty>(name);
}
NativeJSObject::LocalRef
OptObject(jni::String::Param name, NativeJSObject::Param fallback)
{
return GetProperty<ObjectProperty>(name, &fallback);
}
jni::ObjectArray::LocalRef
GetObjectArray(jni::String::Param name)
{
return GetProperty<ObjectArrayProperty>(name);
}
jni::ObjectArray::LocalRef
OptObjectArray(jni::String::Param name, jni::ObjectArray::Param fallback)
{
return GetProperty<ObjectArrayProperty>(name, &fallback);
}
jni::String::LocalRef
GetString(jni::String::Param name)
{
return GetProperty<StringProperty>(name);
}
jni::String::LocalRef
OptString(jni::String::Param name, jni::String::Param fallback)
{
return GetProperty<StringProperty>(name, &fallback);
}
jni::ObjectArray::LocalRef
GetStringArray(jni::String::Param name)
{
return GetProperty<StringArrayProperty>(name);
}
jni::ObjectArray::LocalRef
OptStringArray(jni::String::Param name, jni::ObjectArray::Param fallback)
{
return GetProperty<StringArrayProperty>(name, &fallback);
}
bool Has(jni::String::Param name)
{
bool no = false;
// Fallback to false indicating no such property.
return GetProperty<HasProperty>(name, &no);
}
jni::Object::LocalRef ToBundle()
{
if (!CheckThread() || !CheckObject()) {
return nullptr;
}
return BundleFromValue(mJSObject);
}
private:
static bool AppendJSON(const char16_t* buf, uint32_t len, void* data)
{
static_cast<nsAutoString*>(data)->Append(buf, len);
return true;
}
public:
jni::String::LocalRef ToString()
{
if (!CheckThread() || !CheckObject()) {
return nullptr;
}
JS::RootedValue value(mJSContext, JS::ObjectValue(*mJSObject));
nsAutoString json;
if (!CheckJSCall(JS_Stringify(mJSContext, &value, nullptr,
JS::NullHandleValue, AppendJSON, &json))) {
return nullptr;
}
return jni::StringParam(json, mEnv);
}
};
// Define the "static constexpr" members of our property types (e.g.
// PrimitiveProperty<>::InValue). This is tricky because there are a lot of
// template parameters, so we use macros to make it simpler.
#define DEFINE_PRIMITIVE_PROPERTY_MEMBER(Name) \
template<typename U, typename UA, typename V, typename VA, \
bool (JS::Value::*I)() const, \
U (JS::Value::*T)() const, \
VA (JNIEnv::*N)(jsize), \
void (JNIEnv::*S)(VA, jsize, jsize, const V*)> \
constexpr typename NativeJSContainerImpl \
::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name##_t \
NativeJSContainerImpl::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name
DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewJNIArray);
DEFINE_PRIMITIVE_PROPERTY_MEMBER(SetJNIArrayRegion);
DEFINE_PRIMITIVE_PROPERTY_MEMBER(InValue);
DEFINE_PRIMITIVE_PROPERTY_MEMBER(FromValue);
DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewArray);
#undef DEFINE_PRIMITIVE_PROPERTY_MEMBER
#define DEFINE_OBJECT_PROPERTY_MEMBER(Name) \
template<class C, \
bool (NativeJSContainerImpl::*I)(JS::HandleValue) const, \
typename C::LocalRef (NativeJSContainerImpl::*F)(JS::HandleValue)> \
constexpr typename NativeJSContainerImpl \
::BaseObjectProperty<C, I, F>::Name##_t \
NativeJSContainerImpl::BaseObjectProperty<C, I, F>::Name
DEFINE_OBJECT_PROPERTY_MEMBER(InValue);
DEFINE_OBJECT_PROPERTY_MEMBER(FromValue);
DEFINE_OBJECT_PROPERTY_MEMBER(NewArray);
#undef DEFINE_OBJECT_PROPERTY_MEMBER
template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
::InValue_t NativeJSContainerImpl::ArrayProperty<P>::InValue;
template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
::FromValue_t NativeJSContainerImpl::ArrayProperty<P>::FromValue;
constexpr NativeJSContainerImpl::HasProperty::HasValue_t
NativeJSContainerImpl::HasProperty::InValue;
constexpr NativeJSContainerImpl::HasProperty::HasValue_t
NativeJSContainerImpl::HasProperty::FromValue;
NativeJSContainer::LocalRef
CreateNativeJSContainer(JSContext* cx, JS::HandleObject object)
{
return NativeJSContainerImpl::CreateInstance(cx, object);
}
} // namespace widget
} // namespace mozilla

View file

@ -1,22 +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 "GeneratedJNIWrappers.h"
#include "jsapi.h"
namespace mozilla {
namespace widget {
java::NativeJSContainer::LocalRef
CreateNativeJSContainer(JSContext* cx, JS::HandleObject object);
} // namespace widget
} // namespace mozilla
#endif // NativeJSObject_h__

View file

@ -1,324 +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 PrefsHelper_h
#define PrefsHelper_h
#include "GeneratedJNINatives.h"
#include "MainThreadUtils.h"
#include "nsAppShell.h"
#include "nsCOMPtr.h"
#include "nsVariant.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
namespace mozilla {
class PrefsHelper
: public java::PrefsHelper::Natives<PrefsHelper>
{
PrefsHelper() = delete;
static bool GetVariantPref(nsIObserverService* aObsServ,
nsIWritableVariant* aVariant,
jni::Object::Param aPrefHandler,
const jni::String::LocalRef& aPrefName)
{
if (NS_FAILED(aObsServ->NotifyObservers(aVariant, "android-get-pref",
aPrefName->ToString().get()))) {
return false;
}
uint16_t varType = nsIDataType::VTYPE_EMPTY;
if (NS_FAILED(aVariant->GetDataType(&varType))) {
return false;
}
int32_t type = java::PrefsHelper::PREF_INVALID;
bool boolVal = false;
int32_t intVal = 0;
nsAutoString strVal;
switch (varType) {
case nsIDataType::VTYPE_BOOL:
type = java::PrefsHelper::PREF_BOOL;
if (NS_FAILED(aVariant->GetAsBool(&boolVal))) {
return false;
}
break;
case nsIDataType::VTYPE_INT32:
type = java::PrefsHelper::PREF_INT;
if (NS_FAILED(aVariant->GetAsInt32(&intVal))) {
return false;
}
break;
case nsIDataType::VTYPE_ASTRING:
type = java::PrefsHelper::PREF_STRING;
if (NS_FAILED(aVariant->GetAsAString(strVal))) {
return false;
}
break;
default:
return false;
}
jni::StringParam jstrVal(type == java::PrefsHelper::PREF_STRING ?
jni::StringParam(strVal, aPrefName.Env()) :
jni::StringParam(nullptr));
if (aPrefHandler) {
java::PrefsHelper::CallPrefHandler(
aPrefHandler, type, aPrefName,
boolVal, intVal, jstrVal);
} else {
java::PrefsHelper::OnPrefChange(
aPrefName, type, boolVal, intVal, jstrVal);
}
return true;
}
static bool SetVariantPref(nsIObserverService* aObsServ,
nsIWritableVariant* aVariant,
jni::String::Param aPrefName,
bool aFlush,
int32_t aType,
bool aBoolVal,
int32_t aIntVal,
jni::String::Param aStrVal)
{
nsresult rv = NS_ERROR_FAILURE;
switch (aType) {
case java::PrefsHelper::PREF_BOOL:
rv = aVariant->SetAsBool(aBoolVal);
break;
case java::PrefsHelper::PREF_INT:
rv = aVariant->SetAsInt32(aIntVal);
break;
case java::PrefsHelper::PREF_STRING:
rv = aVariant->SetAsAString(aStrVal->ToString());
break;
}
if (NS_SUCCEEDED(rv)) {
rv = aObsServ->NotifyObservers(aVariant, "android-set-pref",
aPrefName->ToString().get());
}
uint16_t varType = nsIDataType::VTYPE_EMPTY;
if (NS_SUCCEEDED(rv)) {
rv = aVariant->GetDataType(&varType);
}
// We use set-to-empty to signal the pref was handled.
const bool handled = varType == nsIDataType::VTYPE_EMPTY;
if (NS_SUCCEEDED(rv) && handled && aFlush) {
rv = Preferences::GetService()->SavePrefFile(nullptr);
}
if (NS_SUCCEEDED(rv)) {
return handled;
}
NS_WARNING(nsPrintfCString("Failed to set pref %s",
aPrefName->ToCString().get()).get());
// Pretend we handled the pref.
return true;
}
public:
static void GetPrefs(const jni::Class::LocalRef& aCls,
jni::ObjectArray::Param aPrefNames,
jni::Object::Param aPrefHandler)
{
nsTArray<jni::Object::LocalRef> nameRefArray(aPrefNames->GetElements());
nsCOMPtr<nsIObserverService> obsServ;
nsCOMPtr<nsIWritableVariant> value;
nsAdoptingString strVal;
for (jni::Object::LocalRef& nameRef : nameRefArray) {
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
const nsCString& name = nameStr->ToCString();
int32_t type = java::PrefsHelper::PREF_INVALID;
bool boolVal = false;
int32_t intVal = 0;
switch (Preferences::GetType(name.get())) {
case nsIPrefBranch::PREF_BOOL:
type = java::PrefsHelper::PREF_BOOL;
boolVal = Preferences::GetBool(name.get());
break;
case nsIPrefBranch::PREF_INT:
type = java::PrefsHelper::PREF_INT;
intVal = Preferences::GetInt(name.get());
break;
case nsIPrefBranch::PREF_STRING:
type = java::PrefsHelper::PREF_STRING;
strVal = Preferences::GetLocalizedString(name.get());
if (!strVal) {
strVal = Preferences::GetString(name.get());
}
break;
default:
// Pref not found; try to find it.
if (!obsServ) {
obsServ = services::GetObserverService();
if (!obsServ) {
continue;
}
}
if (value) {
value->SetAsEmpty();
} else {
value = new nsVariant();
}
if (!GetVariantPref(obsServ, value,
aPrefHandler, nameStr)) {
NS_WARNING(nsPrintfCString("Failed to get pref %s",
name.get()).get());
}
continue;
}
java::PrefsHelper::CallPrefHandler(
aPrefHandler, type, nameStr, boolVal, intVal,
jni::StringParam(type == java::PrefsHelper::PREF_STRING ?
jni::StringParam(strVal, aCls.Env()) :
jni::StringParam(nullptr)));
}
java::PrefsHelper::CallPrefHandler(
aPrefHandler, java::PrefsHelper::PREF_FINISH,
nullptr, false, 0, nullptr);
}
static void SetPref(jni::String::Param aPrefName,
bool aFlush,
int32_t aType,
bool aBoolVal,
int32_t aIntVal,
jni::String::Param aStrVal)
{
const nsCString& name = aPrefName->ToCString();
if (Preferences::GetType(name.get()) == nsIPrefBranch::PREF_INVALID) {
// No pref; try asking first.
nsCOMPtr<nsIObserverService> obsServ =
services::GetObserverService();
nsCOMPtr<nsIWritableVariant> value = new nsVariant();
if (obsServ && SetVariantPref(obsServ, value, aPrefName, aFlush,
aType, aBoolVal, aIntVal, aStrVal)) {
// The "pref" has changed; send a notification.
GetVariantPref(obsServ, value, nullptr,
jni::String::LocalRef(aPrefName));
return;
}
}
switch (aType) {
case java::PrefsHelper::PREF_BOOL:
Preferences::SetBool(name.get(), aBoolVal);
break;
case java::PrefsHelper::PREF_INT:
Preferences::SetInt(name.get(), aIntVal);
break;
case java::PrefsHelper::PREF_STRING:
Preferences::SetString(name.get(), aStrVal->ToString());
break;
default:
MOZ_ASSERT(false, "Invalid pref type");
}
if (aFlush) {
Preferences::GetService()->SavePrefFile(nullptr);
}
}
static void AddObserver(const jni::Class::LocalRef& aCls,
jni::ObjectArray::Param aPrefNames,
jni::Object::Param aPrefHandler,
jni::ObjectArray::Param aPrefsToObserve)
{
// Call observer immediately with existing pref values.
GetPrefs(aCls, aPrefNames, aPrefHandler);
if (!aPrefsToObserve) {
return;
}
nsTArray<jni::Object::LocalRef> nameRefArray(
aPrefsToObserve->GetElements());
nsAppShell* const appShell = nsAppShell::Get();
MOZ_ASSERT(appShell);
for (jni::Object::LocalRef& nameRef : nameRefArray) {
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
MOZ_ALWAYS_SUCCEEDS(Preferences::AddStrongObserver(
appShell, nameStr->ToCString().get()));
}
}
static void RemoveObserver(const jni::Class::LocalRef& aCls,
jni::ObjectArray::Param aPrefsToUnobserve)
{
nsTArray<jni::Object::LocalRef> nameRefArray(
aPrefsToUnobserve->GetElements());
nsAppShell* const appShell = nsAppShell::Get();
MOZ_ASSERT(appShell);
for (jni::Object::LocalRef& nameRef : nameRefArray) {
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
MOZ_ALWAYS_SUCCEEDS(Preferences::RemoveObserver(
appShell, nameStr->ToCString().get()));
}
}
static void OnPrefChange(const char16_t* aData)
{
const nsCString& name = NS_LossyConvertUTF16toASCII(aData);
int32_t type = -1;
bool boolVal = false;
int32_t intVal = false;
nsAdoptingString strVal;
switch (Preferences::GetType(name.get())) {
case nsIPrefBranch::PREF_BOOL:
type = java::PrefsHelper::PREF_BOOL;
boolVal = Preferences::GetBool(name.get());
break;
case nsIPrefBranch::PREF_INT:
type = java::PrefsHelper::PREF_INT;
intVal = Preferences::GetInt(name.get());
break;
case nsIPrefBranch::PREF_STRING:
type = java::PrefsHelper::PREF_STRING;
strVal = Preferences::GetLocalizedString(name.get());
if (!strVal) {
strVal = Preferences::GetString(name.get());
}
break;
default:
NS_WARNING(nsPrintfCString("Invalid pref %s",
name.get()).get());
return;
}
java::PrefsHelper::OnPrefChange(
name, type, boolVal, intVal,
jni::StringParam(type == java::PrefsHelper::PREF_STRING ?
jni::StringParam(strVal) : jni::StringParam(nullptr)));
}
};
} // namespace
#endif // PrefsHelper_h

View file

@ -1,2 +0,0 @@
android.graphics.Rect
android.graphics.RectF

View file

@ -1 +0,0 @@
android.os.Bundle

View file

@ -1 +0,0 @@
android.view.KeyEvent

View file

@ -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/.
# 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 \
$(NULL)
sdk_processor := \
$(JAVA) \
-Dcom.android.tools.lint.bindir='$(ANDROID_TOOLS)' \
-classpath $(subst $(NULL) ,:,$(strip $(annotation_processor_jar_files))) \
org.mozilla.gecko.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 $(annotation_processor_jar_files)
$(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16

View file

@ -1,5 +0,0 @@
android.media.MediaCodec
android.media.MediaCodec$BufferInfo
android.media.MediaCodec$CryptoInfo
android.media.MediaDrm$KeyStatus
android.media.MediaFormat

View file

@ -1 +0,0 @@
android.view.MotionEvent

View file

@ -1,2 +0,0 @@
android.graphics.SurfaceTexture
android.view.Surface

View file

@ -1 +0,0 @@
android.view.ViewConfiguration

View file

@ -1,41 +0,0 @@
# -*- Mode: python; 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 = [
'AndroidRect',
'Bundle',
'KeyEvent',
'MediaCodec',
'MotionEvent',
'SurfaceTexture',
'ViewConfiguration'
]
SOURCES += ['!%s.cpp' % stem for stem in generated]
EXPORTS += ['!%s.h' % stem 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 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 += [f[1:] for f in SOURCES]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/widget/android',
]

View file

@ -1,244 +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 Java methods and rerun the build. Manually updating this file
// will cause your build to fail.
#ifndef FennecJNINatives_h
#define FennecJNINatives_h
#include "FennecJNIWrappers.h"
#include "mozilla/jni/Natives.h"
namespace mozilla {
namespace java {
template<class Impl>
class ANRReporter::Natives : public mozilla::jni::NativeImpl<ANRReporter, Impl>
{
public:
static const JNINativeMethod methods[3];
};
template<class Impl>
const JNINativeMethod ANRReporter::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<ANRReporter::GetNativeStack_t>(
mozilla::jni::NativeStub<ANRReporter::GetNativeStack_t, Impl>
::template Wrap<&Impl::GetNativeStack>),
mozilla::jni::MakeNativeMethod<ANRReporter::ReleaseNativeStack_t>(
mozilla::jni::NativeStub<ANRReporter::ReleaseNativeStack_t, Impl>
::template Wrap<&Impl::ReleaseNativeStack>),
mozilla::jni::MakeNativeMethod<ANRReporter::RequestNativeStack_t>(
mozilla::jni::NativeStub<ANRReporter::RequestNativeStack_t, Impl>
::template Wrap<&Impl::RequestNativeStack>)
};
template<class Impl>
class GeckoJavaSampler::Natives : public mozilla::jni::NativeImpl<GeckoJavaSampler, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod GeckoJavaSampler::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<GeckoJavaSampler::GetProfilerTime_t>(
mozilla::jni::NativeStub<GeckoJavaSampler::GetProfilerTime_t, Impl>
::template Wrap<&Impl::GetProfilerTime>)
};
template<class Impl>
class MemoryMonitor::Natives : public mozilla::jni::NativeImpl<MemoryMonitor, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod MemoryMonitor::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<MemoryMonitor::DispatchMemoryPressure_t>(
mozilla::jni::NativeStub<MemoryMonitor::DispatchMemoryPressure_t, Impl>
::template Wrap<&Impl::DispatchMemoryPressure>)
};
template<class Impl>
class PresentationMediaPlayerManager::Natives : public mozilla::jni::NativeImpl<PresentationMediaPlayerManager, Impl>
{
public:
static const JNINativeMethod methods[3];
};
template<class Impl>
const JNINativeMethod PresentationMediaPlayerManager::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::AddPresentationSurface_t>(
mozilla::jni::NativeStub<PresentationMediaPlayerManager::AddPresentationSurface_t, Impl>
::template Wrap<&Impl::AddPresentationSurface>),
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t>(
mozilla::jni::NativeStub<PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t, Impl>
::template Wrap<&Impl::InvalidateAndScheduleComposite>),
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::RemovePresentationSurface_t>(
mozilla::jni::NativeStub<PresentationMediaPlayerManager::RemovePresentationSurface_t, Impl>
::template Wrap<&Impl::RemovePresentationSurface>)
};
template<class Impl>
class ScreenManagerHelper::Natives : public mozilla::jni::NativeImpl<ScreenManagerHelper, Impl>
{
public:
static const JNINativeMethod methods[2];
};
template<class Impl>
const JNINativeMethod ScreenManagerHelper::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<ScreenManagerHelper::AddDisplay_t>(
mozilla::jni::NativeStub<ScreenManagerHelper::AddDisplay_t, Impl>
::template Wrap<&Impl::AddDisplay>),
mozilla::jni::MakeNativeMethod<ScreenManagerHelper::RemoveDisplay_t>(
mozilla::jni::NativeStub<ScreenManagerHelper::RemoveDisplay_t, Impl>
::template Wrap<&Impl::RemoveDisplay>)
};
template<class Impl>
class Telemetry::Natives : public mozilla::jni::NativeImpl<Telemetry, Impl>
{
public:
static const JNINativeMethod methods[5];
};
template<class Impl>
const JNINativeMethod Telemetry::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<Telemetry::AddHistogram_t>(
mozilla::jni::NativeStub<Telemetry::AddHistogram_t, Impl>
::template Wrap<&Impl::AddHistogram>),
mozilla::jni::MakeNativeMethod<Telemetry::AddKeyedHistogram_t>(
mozilla::jni::NativeStub<Telemetry::AddKeyedHistogram_t, Impl>
::template Wrap<&Impl::AddKeyedHistogram>),
mozilla::jni::MakeNativeMethod<Telemetry::AddUIEvent_t>(
mozilla::jni::NativeStub<Telemetry::AddUIEvent_t, Impl>
::template Wrap<&Impl::AddUIEvent>),
mozilla::jni::MakeNativeMethod<Telemetry::StartUISession_t>(
mozilla::jni::NativeStub<Telemetry::StartUISession_t, Impl>
::template Wrap<&Impl::StartUISession>),
mozilla::jni::MakeNativeMethod<Telemetry::StopUISession_t>(
mozilla::jni::NativeStub<Telemetry::StopUISession_t, Impl>
::template Wrap<&Impl::StopUISession>)
};
template<class Impl>
class ThumbnailHelper::Natives : public mozilla::jni::NativeImpl<ThumbnailHelper, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod ThumbnailHelper::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<ThumbnailHelper::RequestThumbnail_t>(
mozilla::jni::NativeStub<ThumbnailHelper::RequestThumbnail_t, Impl>
::template Wrap<&Impl::RequestThumbnail>)
};
template<class Impl>
class ZoomedView::Natives : public mozilla::jni::NativeImpl<ZoomedView, Impl>
{
public:
static const JNINativeMethod methods[1];
};
template<class Impl>
const JNINativeMethod ZoomedView::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<ZoomedView::RequestZoomedViewData_t>(
mozilla::jni::NativeStub<ZoomedView::RequestZoomedViewData_t, Impl>
::template Wrap<&Impl::RequestZoomedViewData>)
};
template<class Impl>
class CodecProxy::NativeCallbacks::Natives : public mozilla::jni::NativeImpl<NativeCallbacks, Impl>
{
public:
static const JNINativeMethod methods[5];
};
template<class Impl>
const JNINativeMethod CodecProxy::NativeCallbacks::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::DisposeNative_t>(
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::DisposeNative_t, Impl>
::template Wrap<&Impl::DisposeNative>),
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnError_t>(
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnError_t, Impl>
::template Wrap<&Impl::OnError>),
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnInputExhausted_t>(
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnInputExhausted_t, Impl>
::template Wrap<&Impl::OnInputExhausted>),
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutput_t>(
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutput_t, Impl>
::template Wrap<&Impl::OnOutput>),
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t>(
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t, Impl>
::template Wrap<&Impl::OnOutputFormatChanged>)
};
template<class Impl>
class MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives : public mozilla::jni::NativeImpl<NativeMediaDrmProxyCallbacks, Impl>
{
public:
static const JNINativeMethod methods[7];
};
template<class Impl>
const JNINativeMethod MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives<Impl>::methods[] = {
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t, Impl>
::template Wrap<&Impl::OnRejectPromise>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t, Impl>
::template Wrap<&Impl::OnSessionBatchedKeyChanged>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t, Impl>
::template Wrap<&Impl::OnSessionClosed>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t, Impl>
::template Wrap<&Impl::OnSessionCreated>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t, Impl>
::template Wrap<&Impl::OnSessionError>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t, Impl>
::template Wrap<&Impl::OnSessionMessage>),
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t>(
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t, Impl>
::template Wrap<&Impl::OnSessionUpdated>)
};
} /* java */
} /* mozilla */
#endif // FennecJNINatives_h

View file

@ -1,443 +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 Java methods and rerun the build. Manually updating this file
// will cause your build to fail.
#include "FennecJNIWrappers.h"
#include "mozilla/jni/Accessors.h"
namespace mozilla {
namespace java {
const char ANRReporter::name[] =
"org/mozilla/gecko/ANRReporter";
constexpr char ANRReporter::GetNativeStack_t::name[];
constexpr char ANRReporter::GetNativeStack_t::signature[];
constexpr char ANRReporter::ReleaseNativeStack_t::name[];
constexpr char ANRReporter::ReleaseNativeStack_t::signature[];
constexpr char ANRReporter::RequestNativeStack_t::name[];
constexpr char ANRReporter::RequestNativeStack_t::signature[];
const char DownloadsIntegration::name[] =
"org/mozilla/gecko/DownloadsIntegration";
constexpr char DownloadsIntegration::GetTemporaryDownloadDirectory_t::name[];
constexpr char DownloadsIntegration::GetTemporaryDownloadDirectory_t::signature[];
auto DownloadsIntegration::GetTemporaryDownloadDirectory() -> mozilla::jni::String::LocalRef
{
return mozilla::jni::Method<GetTemporaryDownloadDirectory_t>::Call(DownloadsIntegration::Context(), nullptr);
}
constexpr char DownloadsIntegration::ScanMedia_t::name[];
constexpr char DownloadsIntegration::ScanMedia_t::signature[];
auto DownloadsIntegration::ScanMedia(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -> void
{
return mozilla::jni::Method<ScanMedia_t>::Call(DownloadsIntegration::Context(), nullptr, a0, a1);
}
const char GeckoJavaSampler::name[] =
"org/mozilla/gecko/GeckoJavaSampler";
constexpr char GeckoJavaSampler::GetFrameName_t::name[];
constexpr char GeckoJavaSampler::GetFrameName_t::signature[];
auto GeckoJavaSampler::GetFrameName(int32_t a0, int32_t a1, int32_t a2) -> mozilla::jni::String::LocalRef
{
return mozilla::jni::Method<GetFrameName_t>::Call(GeckoJavaSampler::Context(), nullptr, a0, a1, a2);
}
constexpr char GeckoJavaSampler::GetProfilerTime_t::name[];
constexpr char GeckoJavaSampler::GetProfilerTime_t::signature[];
constexpr char GeckoJavaSampler::GetSampleTime_t::name[];
constexpr char GeckoJavaSampler::GetSampleTime_t::signature[];
auto GeckoJavaSampler::GetSampleTime(int32_t a0, int32_t a1) -> double
{
return mozilla::jni::Method<GetSampleTime_t>::Call(GeckoJavaSampler::Context(), nullptr, a0, a1);
}
constexpr char GeckoJavaSampler::GetThreadName_t::name[];
constexpr char GeckoJavaSampler::GetThreadName_t::signature[];
auto GeckoJavaSampler::GetThreadName(int32_t a0) -> mozilla::jni::String::LocalRef
{
return mozilla::jni::Method<GetThreadName_t>::Call(GeckoJavaSampler::Context(), nullptr, a0);
}
constexpr char GeckoJavaSampler::Pause_t::name[];
constexpr char GeckoJavaSampler::Pause_t::signature[];
auto GeckoJavaSampler::Pause() -> void
{
return mozilla::jni::Method<Pause_t>::Call(GeckoJavaSampler::Context(), nullptr);
}
constexpr char GeckoJavaSampler::Start_t::name[];
constexpr char GeckoJavaSampler::Start_t::signature[];
auto GeckoJavaSampler::Start(int32_t a0, int32_t a1) -> void
{
return mozilla::jni::Method<Start_t>::Call(GeckoJavaSampler::Context(), nullptr, a0, a1);
}
constexpr char GeckoJavaSampler::Stop_t::name[];
constexpr char GeckoJavaSampler::Stop_t::signature[];
auto GeckoJavaSampler::Stop() -> void
{
return mozilla::jni::Method<Stop_t>::Call(GeckoJavaSampler::Context(), nullptr);
}
constexpr char GeckoJavaSampler::Unpause_t::name[];
constexpr char GeckoJavaSampler::Unpause_t::signature[];
auto GeckoJavaSampler::Unpause() -> void
{
return mozilla::jni::Method<Unpause_t>::Call(GeckoJavaSampler::Context(), nullptr);
}
const char MemoryMonitor::name[] =
"org/mozilla/gecko/MemoryMonitor";
constexpr char MemoryMonitor::DispatchMemoryPressure_t::name[];
constexpr char MemoryMonitor::DispatchMemoryPressure_t::signature[];
const char PresentationMediaPlayerManager::name[] =
"org/mozilla/gecko/PresentationMediaPlayerManager";
constexpr char PresentationMediaPlayerManager::AddPresentationSurface_t::name[];
constexpr char PresentationMediaPlayerManager::AddPresentationSurface_t::signature[];
constexpr char PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t::name[];
constexpr char PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t::signature[];
constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::name[];
constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::signature[];
const char ScreenManagerHelper::name[] =
"org/mozilla/gecko/ScreenManagerHelper";
constexpr char ScreenManagerHelper::AddDisplay_t::name[];
constexpr char ScreenManagerHelper::AddDisplay_t::signature[];
constexpr char ScreenManagerHelper::RemoveDisplay_t::name[];
constexpr char ScreenManagerHelper::RemoveDisplay_t::signature[];
const char Telemetry::name[] =
"org/mozilla/gecko/Telemetry";
constexpr char Telemetry::AddHistogram_t::name[];
constexpr char Telemetry::AddHistogram_t::signature[];
constexpr char Telemetry::AddKeyedHistogram_t::name[];
constexpr char Telemetry::AddKeyedHistogram_t::signature[];
constexpr char Telemetry::AddUIEvent_t::name[];
constexpr char Telemetry::AddUIEvent_t::signature[];
constexpr char Telemetry::StartUISession_t::name[];
constexpr char Telemetry::StartUISession_t::signature[];
constexpr char Telemetry::StopUISession_t::name[];
constexpr char Telemetry::StopUISession_t::signature[];
const char ThumbnailHelper::name[] =
"org/mozilla/gecko/ThumbnailHelper";
constexpr char ThumbnailHelper::NotifyThumbnail_t::name[];
constexpr char ThumbnailHelper::NotifyThumbnail_t::signature[];
auto ThumbnailHelper::NotifyThumbnail(mozilla::jni::ByteBuffer::Param a0, mozilla::jni::Object::Param a1, bool a2, bool a3) -> void
{
return mozilla::jni::Method<NotifyThumbnail_t>::Call(ThumbnailHelper::Context(), nullptr, a0, a1, a2, a3);
}
constexpr char ThumbnailHelper::RequestThumbnail_t::name[];
constexpr char ThumbnailHelper::RequestThumbnail_t::signature[];
const char ZoomedView::name[] =
"org/mozilla/gecko/ZoomedView";
constexpr char ZoomedView::RequestZoomedViewData_t::name[];
constexpr char ZoomedView::RequestZoomedViewData_t::signature[];
const char AudioFocusAgent::name[] =
"org/mozilla/gecko/media/AudioFocusAgent";
constexpr char AudioFocusAgent::NotifyStartedPlaying_t::name[];
constexpr char AudioFocusAgent::NotifyStartedPlaying_t::signature[];
auto AudioFocusAgent::NotifyStartedPlaying() -> void
{
return mozilla::jni::Method<NotifyStartedPlaying_t>::Call(AudioFocusAgent::Context(), nullptr);
}
constexpr char AudioFocusAgent::NotifyStoppedPlaying_t::name[];
constexpr char AudioFocusAgent::NotifyStoppedPlaying_t::signature[];
auto AudioFocusAgent::NotifyStoppedPlaying() -> void
{
return mozilla::jni::Method<NotifyStoppedPlaying_t>::Call(AudioFocusAgent::Context(), nullptr);
}
const char CodecProxy::name[] =
"org/mozilla/gecko/media/CodecProxy";
constexpr char CodecProxy::Create_t::name[];
constexpr char CodecProxy::Create_t::signature[];
auto CodecProxy::Create(mozilla::jni::Object::Param a0, mozilla::jni::Object::Param a1, mozilla::jni::Object::Param a2) -> CodecProxy::LocalRef
{
return mozilla::jni::Method<Create_t>::Call(CodecProxy::Context(), nullptr, a0, a1, a2);
}
constexpr char CodecProxy::Flush_t::name[];
constexpr char CodecProxy::Flush_t::signature[];
auto CodecProxy::Flush() const -> bool
{
return mozilla::jni::Method<Flush_t>::Call(CodecProxy::mCtx, nullptr);
}
constexpr char CodecProxy::Input_t::name[];
constexpr char CodecProxy::Input_t::signature[];
auto CodecProxy::Input(mozilla::jni::ByteBuffer::Param a0, mozilla::jni::Object::Param a1, mozilla::jni::Object::Param a2) const -> bool
{
return mozilla::jni::Method<Input_t>::Call(CodecProxy::mCtx, nullptr, a0, a1, a2);
}
constexpr char CodecProxy::Release_t::name[];
constexpr char CodecProxy::Release_t::signature[];
auto CodecProxy::Release() const -> bool
{
return mozilla::jni::Method<Release_t>::Call(CodecProxy::mCtx, nullptr);
}
const char CodecProxy::NativeCallbacks::name[] =
"org/mozilla/gecko/media/CodecProxy$NativeCallbacks";
constexpr char CodecProxy::NativeCallbacks::New_t::name[];
constexpr char CodecProxy::NativeCallbacks::New_t::signature[];
auto CodecProxy::NativeCallbacks::New() -> NativeCallbacks::LocalRef
{
return mozilla::jni::Constructor<New_t>::Call(NativeCallbacks::Context(), nullptr);
}
constexpr char CodecProxy::NativeCallbacks::DisposeNative_t::name[];
constexpr char CodecProxy::NativeCallbacks::DisposeNative_t::signature[];
constexpr char CodecProxy::NativeCallbacks::OnError_t::name[];
constexpr char CodecProxy::NativeCallbacks::OnError_t::signature[];
constexpr char CodecProxy::NativeCallbacks::OnInputExhausted_t::name[];
constexpr char CodecProxy::NativeCallbacks::OnInputExhausted_t::signature[];
constexpr char CodecProxy::NativeCallbacks::OnOutput_t::name[];
constexpr char CodecProxy::NativeCallbacks::OnOutput_t::signature[];
constexpr char CodecProxy::NativeCallbacks::OnOutputFormatChanged_t::name[];
constexpr char CodecProxy::NativeCallbacks::OnOutputFormatChanged_t::signature[];
const char MediaDrmProxy::name[] =
"org/mozilla/gecko/media/MediaDrmProxy";
constexpr char MediaDrmProxy::CanDecode_t::name[];
constexpr char MediaDrmProxy::CanDecode_t::signature[];
auto MediaDrmProxy::CanDecode(mozilla::jni::String::Param a0) -> bool
{
return mozilla::jni::Method<CanDecode_t>::Call(MediaDrmProxy::Context(), nullptr, a0);
}
constexpr char MediaDrmProxy::IsCryptoSchemeSupported_t::name[];
constexpr char MediaDrmProxy::IsCryptoSchemeSupported_t::signature[];
auto MediaDrmProxy::IsCryptoSchemeSupported(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -> bool
{
return mozilla::jni::Method<IsCryptoSchemeSupported_t>::Call(MediaDrmProxy::Context(), nullptr, a0, a1);
}
constexpr char MediaDrmProxy::CloseSession_t::name[];
constexpr char MediaDrmProxy::CloseSession_t::signature[];
auto MediaDrmProxy::CloseSession(int32_t a0, mozilla::jni::String::Param a1) const -> void
{
return mozilla::jni::Method<CloseSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1);
}
constexpr char MediaDrmProxy::Create_t::name[];
constexpr char MediaDrmProxy::Create_t::signature[];
auto MediaDrmProxy::Create(mozilla::jni::String::Param a0, mozilla::jni::Object::Param a1, bool a2) -> MediaDrmProxy::LocalRef
{
return mozilla::jni::Method<Create_t>::Call(MediaDrmProxy::Context(), nullptr, a0, a1, a2);
}
constexpr char MediaDrmProxy::CreateSession_t::name[];
constexpr char MediaDrmProxy::CreateSession_t::signature[];
auto MediaDrmProxy::CreateSession(int32_t a0, int32_t a1, mozilla::jni::String::Param a2, mozilla::jni::ByteArray::Param a3) const -> void
{
return mozilla::jni::Method<CreateSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1, a2, a3);
}
constexpr char MediaDrmProxy::Destroy_t::name[];
constexpr char MediaDrmProxy::Destroy_t::signature[];
auto MediaDrmProxy::Destroy() const -> void
{
return mozilla::jni::Method<Destroy_t>::Call(MediaDrmProxy::mCtx, nullptr);
}
constexpr char MediaDrmProxy::IsSchemeSupported_t::name[];
constexpr char MediaDrmProxy::IsSchemeSupported_t::signature[];
auto MediaDrmProxy::IsSchemeSupported(mozilla::jni::String::Param a0) -> bool
{
return mozilla::jni::Method<IsSchemeSupported_t>::Call(MediaDrmProxy::Context(), nullptr, a0);
}
constexpr char MediaDrmProxy::UpdateSession_t::name[];
constexpr char MediaDrmProxy::UpdateSession_t::signature[];
auto MediaDrmProxy::UpdateSession(int32_t a0, mozilla::jni::String::Param a1, mozilla::jni::ByteArray::Param a2) const -> void
{
return mozilla::jni::Method<UpdateSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1, a2);
}
const char16_t MediaDrmProxy::AAC[] = u"audio/mp4a-latm";
const char16_t MediaDrmProxy::AVC[] = u"video/avc";
const char16_t MediaDrmProxy::OPUS[] = u"audio/opus";
const char16_t MediaDrmProxy::VORBIS[] = u"audio/vorbis";
const char16_t MediaDrmProxy::VP8[] = u"video/x-vnd.on2.vp8";
const char16_t MediaDrmProxy::VP9[] = u"video/x-vnd.on2.vp9";
const char MediaDrmProxy::NativeMediaDrmProxyCallbacks::name[] =
"org/mozilla/gecko/media/MediaDrmProxy$NativeMediaDrmProxyCallbacks";
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::New_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::New_t::signature[];
auto MediaDrmProxy::NativeMediaDrmProxyCallbacks::New() -> NativeMediaDrmProxyCallbacks::LocalRef
{
return mozilla::jni::Constructor<New_t>::Call(NativeMediaDrmProxyCallbacks::Context(), nullptr);
}
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t::signature[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t::name[];
constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t::signature[];
const char Sample::name[] =
"org/mozilla/gecko/media/Sample";
constexpr char Sample::WriteToByteBuffer_t::name[];
constexpr char Sample::WriteToByteBuffer_t::signature[];
auto Sample::WriteToByteBuffer(mozilla::jni::ByteBuffer::Param a0) const -> void
{
return mozilla::jni::Method<WriteToByteBuffer_t>::Call(Sample::mCtx, nullptr, a0);
}
constexpr char Sample::Info_t::name[];
constexpr char Sample::Info_t::signature[];
auto Sample::Info() const -> mozilla::jni::Object::LocalRef
{
return mozilla::jni::Field<Info_t>::Get(Sample::mCtx, nullptr);
}
auto Sample::Info(mozilla::jni::Object::Param a0) const -> void
{
return mozilla::jni::Field<Info_t>::Set(Sample::mCtx, nullptr, a0);
}
const char SessionKeyInfo::name[] =
"org/mozilla/gecko/media/SessionKeyInfo";
constexpr char SessionKeyInfo::New_t::name[];
constexpr char SessionKeyInfo::New_t::signature[];
auto SessionKeyInfo::New(mozilla::jni::ByteArray::Param a0, int32_t a1) -> SessionKeyInfo::LocalRef
{
return mozilla::jni::Constructor<New_t>::Call(SessionKeyInfo::Context(), nullptr, a0, a1);
}
constexpr char SessionKeyInfo::KeyId_t::name[];
constexpr char SessionKeyInfo::KeyId_t::signature[];
auto SessionKeyInfo::KeyId() const -> mozilla::jni::ByteArray::LocalRef
{
return mozilla::jni::Field<KeyId_t>::Get(SessionKeyInfo::mCtx, nullptr);
}
auto SessionKeyInfo::KeyId(mozilla::jni::ByteArray::Param a0) const -> void
{
return mozilla::jni::Field<KeyId_t>::Set(SessionKeyInfo::mCtx, nullptr, a0);
}
constexpr char SessionKeyInfo::Status_t::name[];
constexpr char SessionKeyInfo::Status_t::signature[];
auto SessionKeyInfo::Status() const -> int32_t
{
return mozilla::jni::Field<Status_t>::Get(SessionKeyInfo::mCtx, nullptr);
}
auto SessionKeyInfo::Status(int32_t a0) const -> void
{
return mozilla::jni::Field<Status_t>::Set(SessionKeyInfo::mCtx, nullptr, a0);
}
const char Restrictions::name[] =
"org/mozilla/gecko/restrictions/Restrictions";
constexpr char Restrictions::IsAllowed_t::name[];
constexpr char Restrictions::IsAllowed_t::signature[];
auto Restrictions::IsAllowed(int32_t a0, mozilla::jni::String::Param a1) -> bool
{
return mozilla::jni::Method<IsAllowed_t>::Call(Restrictions::Context(), nullptr, a0, a1);
}
constexpr char Restrictions::IsUserRestricted_t::name[];
constexpr char Restrictions::IsUserRestricted_t::signature[];
auto Restrictions::IsUserRestricted() -> bool
{
return mozilla::jni::Method<IsUserRestricted_t>::Call(Restrictions::Context(), nullptr);
}
} /* java */
} /* mozilla */

File diff suppressed because it is too large Load diff

View file

@ -1,27 +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 MemoryMonitor_h
#define MemoryMonitor_h
#include "FennecJNINatives.h"
#include "nsMemoryPressure.h"
namespace mozilla {
class MemoryMonitor final
: public java::MemoryMonitor::Natives<MemoryMonitor>
{
public:
static void
DispatchMemoryPressure()
{
NS_DispatchMemoryPressure(MemoryPressureState::MemPressure_New);
}
};
} // namespace mozilla
#endif // MemoryMonitor_h

View file

@ -1,97 +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 mozilla_widget_Telemetry_h__
#define mozilla_widget_Telemetry_h__
#include "FennecJNINatives.h"
#include "nsAppShell.h"
#include "nsIAndroidBridge.h"
#include "mozilla/Telemetry.h"
namespace mozilla {
namespace widget {
class Telemetry final
: public java::Telemetry::Natives<Telemetry>
{
Telemetry() = delete;
static already_AddRefed<nsIUITelemetryObserver>
GetObserver()
{
nsAppShell* const appShell = nsAppShell::Get();
if (!appShell) {
return nullptr;
}
nsCOMPtr<nsIAndroidBrowserApp> browserApp = appShell->GetBrowserApp();
nsCOMPtr<nsIUITelemetryObserver> obs;
if (!browserApp || NS_FAILED(browserApp->GetUITelemetryObserver(
getter_AddRefs(obs))) || !obs) {
return nullptr;
}
return obs.forget();
}
public:
static void
AddHistogram(jni::String::Param aName, int32_t aValue)
{
MOZ_ASSERT(aName);
}
static void
AddKeyedHistogram(jni::String::Param aName, jni::String::Param aKey,
int32_t aValue)
{
MOZ_ASSERT(aName && aKey);
}
static void
StartUISession(jni::String::Param aName, int64_t aTimestamp)
{
MOZ_ASSERT(aName);
nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver();
if (obs) {
obs->StartSession(aName->ToString().get(), aTimestamp);
}
}
static void
StopUISession(jni::String::Param aName, jni::String::Param aReason,
int64_t aTimestamp)
{
MOZ_ASSERT(aName);
nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver();
if (obs) {
obs->StopSession(aName->ToString().get(),
aReason ? aReason->ToString().get() : nullptr,
aTimestamp);
}
}
static void
AddUIEvent(jni::String::Param aAction, jni::String::Param aMethod,
int64_t aTimestamp, jni::String::Param aExtras)
{
MOZ_ASSERT(aAction);
nsCOMPtr<nsIUITelemetryObserver> obs = GetObserver();
if (obs) {
obs->AddEvent(aAction->ToString().get(),
aMethod ? aMethod->ToString().get() : nullptr,
aTimestamp,
aExtras ? aExtras->ToString().get() : nullptr);
}
}
};
} // namespace widget
} // namespace mozilla
#endif // mozilla_widget_Telemetry_h__

View file

@ -1,302 +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 ThumbnailHelper_h
#define ThumbnailHelper_h
#include "AndroidBridge.h"
#include "FennecJNINatives.h"
#include "gfxPlatform.h"
#include "mozIDOMWindow.h"
#include "nsAppShell.h"
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsIDOMWindowUtils.h"
#include "nsIDOMClientRect.h"
#include "nsIDocShell.h"
#include "nsIHttpChannel.h"
#include "nsIPresShell.h"
#include "nsIURI.h"
#include "nsPIDOMWindow.h"
#include "nsPresContext.h"
#include "mozilla/Preferences.h"
namespace mozilla {
class ThumbnailHelper final
: public java::ThumbnailHelper::Natives<ThumbnailHelper>
, public java::ZoomedView::Natives<ThumbnailHelper>
{
ThumbnailHelper() = delete;
static already_AddRefed<mozIDOMWindowProxy>
GetWindowForTab(int32_t aTabId)
{
nsAppShell* const appShell = nsAppShell::Get();
if (!appShell) {
return nullptr;
}
nsCOMPtr<nsIAndroidBrowserApp> browserApp = appShell->GetBrowserApp();
if (!browserApp) {
return nullptr;
}
nsCOMPtr<mozIDOMWindowProxy> window;
nsCOMPtr<nsIBrowserTab> tab;
if (NS_FAILED(browserApp->GetBrowserTab(aTabId, getter_AddRefs(tab))) ||
!tab ||
NS_FAILED(tab->GetWindow(getter_AddRefs(window))) ||
!window) {
return nullptr;
}
return window.forget();
}
// 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)
{
nsCOMPtr<nsIChannel> channel;
if (NS_FAILED(docShell->GetCurrentDocumentChannel(
getter_AddRefs(channel))) || !channel) {
return false;
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
if (!httpChannel) {
// Allow storing non-HTTP thumbnails.
return true;
}
// Don't store thumbnails for sites that didn't load or have
// Cache-Control: no-store.
uint32_t responseStatus = 0;
bool isNoStoreResponse = false;
if (NS_FAILED(httpChannel->GetResponseStatus(&responseStatus)) ||
(responseStatus / 100) != 2 ||
NS_FAILED(httpChannel->IsNoStoreResponse(&isNoStoreResponse)) ||
isNoStoreResponse) {
return false;
}
// Deny storage if we're viewing a HTTPS page with a 'Cache-Control'
// header having a value that is not 'public', unless enabled by user.
nsCOMPtr<nsIURI> uri;
bool isHttps = false;
if (NS_FAILED(channel->GetURI(getter_AddRefs(uri))) ||
!uri ||
NS_FAILED(uri->SchemeIs("https", &isHttps))) {
return false;
}
if (!isHttps ||
Preferences::GetBool("browser.cache.disk_cache_ssl", false)) {
// Allow storing non-HTTPS thumbnails, and HTTPS ones if enabled by
// user.
return true;
}
nsAutoCString cacheControl;
if (NS_FAILED(httpChannel->GetResponseHeader(
NS_LITERAL_CSTRING("Cache-Control"), cacheControl))) {
return false;
}
if (cacheControl.IsEmpty() ||
cacheControl.LowerCaseEqualsLiteral("public")) {
// Allow no cache-control, or public cache-control.
return true;
}
return false;
}
// Return a non-null nsIDocShell to indicate success.
static already_AddRefed<nsIDocShell>
GetThumbnailAndDocShell(mozIDOMWindowProxy* aWindow,
jni::ByteBuffer::Param aData,
int32_t aThumbWidth, int32_t aThumbHeight,
const CSSRect& aPageRect, float aZoomFactor)
{
nsCOMPtr<nsPIDOMWindowOuter> win = nsPIDOMWindowOuter::From(aWindow);
nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
RefPtr<nsPresContext> presContext;
if (!docShell || NS_FAILED(docShell->GetPresContext(
getter_AddRefs(presContext))) || !presContext) {
return nullptr;
}
uint8_t* const data = static_cast<uint8_t*>(aData->Address());
if (!data) {
return nullptr;
}
const bool is24bit = !AndroidBridge::Bridge() ||
AndroidBridge::Bridge()->GetScreenDepth() == 24;
const uint32_t stride = aThumbWidth * (is24bit ? 4 : 2);
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForData(
data,
IntSize(aThumbWidth, aThumbHeight),
stride,
is24bit ? SurfaceFormat::B8G8R8A8
: SurfaceFormat::R5G6B5_UINT16);
if (!dt || !dt->IsValid()) {
return nullptr;
}
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(context); // checked the draw target above
context->SetMatrix(context->CurrentMatrix().Scale(
aZoomFactor * float(aThumbWidth) / aPageRect.width,
aZoomFactor * float(aThumbHeight) / aPageRect.height));
const nsRect drawRect(
nsPresContext::CSSPixelsToAppUnits(aPageRect.x),
nsPresContext::CSSPixelsToAppUnits(aPageRect.y),
nsPresContext::CSSPixelsToAppUnits(aPageRect.width),
nsPresContext::CSSPixelsToAppUnits(aPageRect.height));
const uint32_t renderDocFlags =
nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
nsIPresShell::RENDER_DOCUMENT_RELATIVE;
const nscolor bgColor = NS_RGB(255, 255, 255);
if (NS_FAILED(presShell->RenderDocument(
drawRect, renderDocFlags, bgColor, context))) {
return nullptr;
}
if (is24bit) {
gfxUtils::ConvertBGRAtoRGBA(data, stride * aThumbHeight);
}
return docShell.forget();
}
public:
static void Init()
{
java::ThumbnailHelper::Natives<ThumbnailHelper>::Init();
java::ZoomedView::Natives<ThumbnailHelper>::Init();
}
template<class Functor>
static void OnNativeCall(Functor&& aCall)
{
class IdleEvent : public nsAppShell::LambdaEvent<Functor>
{
using Base = nsAppShell::LambdaEvent<Functor>;
public:
IdleEvent(Functor&& aCall)
: Base(Forward<Functor>(aCall))
{}
void Run() override
{
MessageLoop::current()->PostIdleTask(
NS_NewRunnableFunction(Move(Base::lambda)));
}
};
// Invoke RequestThumbnail on the main thread when the thread is idle.
nsAppShell::PostEvent(MakeUnique<IdleEvent>(Forward<Functor>(aCall)));
}
static void
RequestThumbnail(jni::ByteBuffer::Param aData, jni::Object::Param aTab,
int32_t aTabId, int32_t aWidth, int32_t aHeight)
{
nsCOMPtr<mozIDOMWindowProxy> window = GetWindowForTab(aTabId);
if (!window || !aData) {
java::ThumbnailHelper::NotifyThumbnail(
aData, aTab, /* success */ false, /* store */ false);
return;
}
// take a screenshot, as wide as possible, proportional to the destination size
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
nsCOMPtr<nsIDOMClientRect> rect;
float pageLeft = 0.0f, pageTop = 0.0f, pageWidth = 0.0f, pageHeight = 0.0f;
if (!utils ||
NS_FAILED(utils->GetRootBounds(getter_AddRefs(rect))) ||
!rect ||
NS_FAILED(rect->GetLeft(&pageLeft)) ||
NS_FAILED(rect->GetTop(&pageTop)) ||
NS_FAILED(rect->GetWidth(&pageWidth)) ||
NS_FAILED(rect->GetHeight(&pageHeight)) ||
int32_t(pageWidth) == 0 || int32_t(pageHeight) == 0) {
java::ThumbnailHelper::NotifyThumbnail(
aData, aTab, /* success */ false, /* store */ false);
return;
}
const float aspectRatio = float(aWidth) / float(aHeight);
if (pageWidth / aspectRatio < pageHeight) {
pageHeight = pageWidth / aspectRatio;
} else {
pageWidth = pageHeight * aspectRatio;
}
nsCOMPtr<nsIDocShell> docShell = GetThumbnailAndDocShell(
window, aData, aWidth, aHeight,
CSSRect(pageLeft, pageTop, pageWidth, pageHeight),
/* aZoomFactor */ 1.0f);
const bool success = !!docShell;
const bool store = success ? ShouldStoreThumbnail(docShell) : false;
java::ThumbnailHelper::NotifyThumbnail(aData, aTab, success, store);
}
static void
RequestZoomedViewData(jni::ByteBuffer::Param aData, int32_t aTabId,
int32_t aX, int32_t aY,
int32_t aWidth, int32_t aHeight, float aScale)
{
nsCOMPtr<mozIDOMWindowProxy> window = GetWindowForTab(aTabId);
if (!window || !aData) {
return;
}
nsCOMPtr<nsPIDOMWindowOuter> win = nsPIDOMWindowOuter::From(window);
nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
RefPtr<nsPresContext> presContext;
if (!docShell || NS_FAILED(docShell->GetPresContext(
getter_AddRefs(presContext))) || !presContext) {
return;
}
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
LayoutDeviceRect rect = LayoutDeviceRect(aX, aY, aWidth, aHeight);
const float resolution = presShell->GetCumulativeResolution();
rect.Scale(1.0f / LayoutDeviceToLayerScale(resolution).scale);
docShell = GetThumbnailAndDocShell(
window, aData, aWidth, aHeight, CSSRect::FromAppUnits(
rect.ToAppUnits(rect, presContext->AppUnitsPerDevPixel())),
aScale);
if (docShell) {
java::LayerView::UpdateZoomedView(aData);
}
}
};
} // namespace mozilla
#endif // ThumbnailHelper_h

View file

@ -1,21 +0,0 @@
# -*- Mode: python; 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 += [
'FennecJNINatives.h',
'FennecJNIWrappers.h',
]
UNIFIED_SOURCES += [
'FennecJNIWrappers.cpp',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/widget',
'/widget/android',
]

View file

@ -1,274 +0,0 @@
#ifndef mozilla_jni_Accessors_h__
#define mozilla_jni_Accessors_h__
#include <jni.h>
#include "mozilla/jni/Refs.h"
#include "mozilla/jni/Types.h"
#include "mozilla/jni/Utils.h"
#include "AndroidBridge.h"
namespace mozilla {
namespace jni {
namespace detail {
// 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;
};
} // namespace detail
using namespace detail;
// Base class for Method<>, Field<>, and Constructor<>.
class Accessor
{
static void GetNsresult(JNIEnv* env, nsresult* rv)
{
if (env->ExceptionCheck()) {
#ifdef MOZ_CHECK_JNI
env->ExceptionDescribe();
#endif
env->ExceptionClear();
*rv = NS_ERROR_FAILURE;
} else {
*rv = NS_OK;
}
}
protected:
// Called after making a JNIEnv call.
template<class Traits>
static void EndAccess(const typename Traits::Owner::Context& ctx,
nsresult* rv)
{
if (Traits::exceptionMode == ExceptionMode::ABORT) {
MOZ_CATCH_JNI_EXCEPTION(ctx.Env());
} else if (Traits::exceptionMode == ExceptionMode::NSRESULT) {
GetNsresult(ctx.Env(), rv);
}
}
};
// Member<> is used to call a JNI method given a traits class.
template<class Traits, typename ReturnType = typename Traits::ReturnType>
class Method : public Accessor
{
typedef Accessor Base;
typedef typename Traits::Owner::Context Context;
protected:
static jmethodID sID;
static void BeginAccess(const Context& ctx)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT,
"Dispatching not supported for method call");
if (sID) {
return;
}
if (Traits::isStatic) {
MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticMethodID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
} else {
MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetMethodID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
}
}
static void EndAccess(const Context& ctx, nsresult* rv)
{
return Base::EndAccess<Traits>(ctx, rv);
}
public:
template<typename... Args>
static ReturnType Call(const Context& ctx, nsresult* rv, const Args&... args)
{
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
jvalue jargs[] = {
Value(TypeAdapter<Args>::FromNative(env, args)).val ...
};
auto result = TypeAdapter<ReturnType>::ToNative(env,
Traits::isStatic ?
(env->*TypeAdapter<ReturnType>::StaticCall)(
ctx.RawClassRef(), sID, jargs) :
(env->*TypeAdapter<ReturnType>::Call)(
ctx.Get(), sID, jargs));
EndAccess(ctx, rv);
return result;
}
};
// Define sID member.
template<class T, typename R> jmethodID Method<T, R>::sID;
// Specialize void because C++ forbids us from
// using a "void" temporary result variable.
template<class Traits>
class Method<Traits, void> : public Method<Traits, bool>
{
typedef Method<Traits, bool> Base;
typedef typename Traits::Owner::Context Context;
public:
template<typename... Args>
static void Call(const Context& ctx, nsresult* rv,
const Args&... args)
{
JNIEnv* const env = ctx.Env();
Base::BeginAccess(ctx);
jvalue jargs[] = {
Value(TypeAdapter<Args>::FromNative(env, args)).val ...
};
if (Traits::isStatic) {
env->CallStaticVoidMethodA(ctx.RawClassRef(), Base::sID, jargs);
} else {
env->CallVoidMethodA(ctx.Get(), Base::sID, jargs);
}
Base::EndAccess(ctx, rv);
}
};
// Constructor<> is used to construct a JNI instance given a traits class.
template<class Traits>
class Constructor : protected Method<Traits, typename Traits::ReturnType> {
typedef typename Traits::Owner::Context Context;
typedef typename Traits::ReturnType ReturnType;
typedef Method<Traits, ReturnType> Base;
public:
template<typename... Args>
static ReturnType Call(const Context& ctx, nsresult* rv,
const Args&... args)
{
JNIEnv* const env = ctx.Env();
Base::BeginAccess(ctx);
jvalue jargs[] = {
Value(TypeAdapter<Args>::FromNative(env, args)).val ...
};
auto result = TypeAdapter<ReturnType>::ToNative(
env, env->NewObjectA(ctx.RawClassRef(), Base::sID, jargs));
Base::EndAccess(ctx, rv);
return result;
}
};
// Field<> is used to access a JNI field given a traits class.
template<class Traits>
class Field : public Accessor
{
typedef Accessor Base;
typedef typename Traits::Owner::Context Context;
typedef typename Traits::ReturnType GetterType;
typedef typename Traits::SetterType SetterType;
private:
static jfieldID sID;
static void BeginAccess(const Context& ctx)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT,
"Dispatching not supported for field access");
if (sID) {
return;
}
if (Traits::isStatic) {
MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetStaticFieldID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
} else {
MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetFieldID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
}
}
static void EndAccess(const Context& ctx, nsresult* rv)
{
return Base::EndAccess<Traits>(ctx, rv);
}
public:
static GetterType Get(const Context& ctx, nsresult* rv)
{
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
auto result = TypeAdapter<GetterType>::ToNative(
env, Traits::isStatic ?
(env->*TypeAdapter<GetterType>::StaticGet)
(ctx.RawClassRef(), sID) :
(env->*TypeAdapter<GetterType>::Get)
(ctx.Get(), sID));
EndAccess(ctx, rv);
return result;
}
static void Set(const Context& ctx, nsresult* rv, SetterType val)
{
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
if (Traits::isStatic) {
(env->*TypeAdapter<SetterType>::StaticSet)(
ctx.RawClassRef(), sID,
TypeAdapter<SetterType>::FromNative(env, val));
} else {
(env->*TypeAdapter<SetterType>::Set)(
ctx.Get(), sID,
TypeAdapter<SetterType>::FromNative(env, val));
}
EndAccess(ctx, rv);
}
};
// Define sID member.
template<class T> jfieldID Field<T>::sID;
// Define the sClassRef member declared in Refs.h and
// used by Method and Field above.
template<class C, typename T> jclass Context<C, T>::sClassRef;
} // namespace jni
} // namespace mozilla
#endif // mozilla_jni_Accessors_h__

View file

@ -1,707 +0,0 @@
#ifndef mozilla_jni_Natives_h__
#define mozilla_jni_Natives_h__
#include <jni.h>
#include "mozilla/IndexSequence.h"
#include "mozilla/Move.h"
#include "mozilla/Tuple.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/Unused.h"
#include "mozilla/jni/Accessors.h"
#include "mozilla/jni/Refs.h"
#include "mozilla/jni/Types.h"
#include "mozilla/jni/Utils.h"
namespace mozilla {
namespace jni {
/**
* C++ classes implementing instance (non-static) native methods can choose
* from one of two ownership models, when associating a C++ object with a Java
* instance.
*
* * If the C++ class inherits from mozilla::SupportsWeakPtr, weak pointers
* will be used. The Java instance will store and own the pointer to a
* WeakPtr object. The C++ class itself is otherwise not owned or directly
* referenced. To attach a Java instance to a C++ instance, pass in a pointer
* to the C++ class (i.e. MyClass*).
*
* class MyClass : public SupportsWeakPtr<MyClass>
* , public MyJavaClass::Natives<MyClass>
* {
* // ...
*
* public:
* MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MyClass)
* using MyJavaClass::Natives<MyClass>::Dispose;
*
* void AttachTo(const MyJavaClass::LocalRef& instance)
* {
* MyJavaClass::Natives<MyClass>::AttachInstance(instance, this);
*
* // "instance" does NOT own "this", so the C++ object
* // lifetime is separate from the Java object lifetime.
* }
* };
*
* * If the C++ class doesn't inherit from mozilla::SupportsWeakPtr, the Java
* instance will store and own a pointer to the C++ object itself. This
* pointer must not be stored or deleted elsewhere. To attach a Java instance
* to a C++ instance, pass in a reference to a UniquePtr of the C++ class
* (i.e. UniquePtr<MyClass>).
*
* class MyClass : public MyJavaClass::Natives<MyClass>
* {
* // ...
*
* public:
* using MyJavaClass::Natives<MyClass>::Dispose;
*
* static void AttachTo(const MyJavaClass::LocalRef& instance)
* {
* MyJavaClass::Natives<MyClass>::AttachInstance(
* instance, mozilla::MakeUnique<MyClass>());
*
* // "instance" owns the newly created C++ object, so the C++
* // object is destroyed as soon as instance.dispose() is called.
* }
* };
*/
namespace detail {
inline uintptr_t CheckNativeHandle(JNIEnv* env, uintptr_t handle)
{
if (!handle) {
if (!env->ExceptionCheck()) {
ThrowException(env, "java/lang/NullPointerException",
"Null native pointer");
}
return 0;
}
return handle;
}
template<class Impl, bool UseWeakPtr = mozilla::IsBaseOf<
SupportsWeakPtr<Impl>, Impl>::value /* = false */>
struct NativePtr
{
static Impl* Get(JNIEnv* env, jobject instance)
{
return reinterpret_cast<Impl*>(CheckNativeHandle(
env, GetNativeHandle(env, instance)));
}
template<class LocalRef>
static Impl* Get(const LocalRef& instance)
{
return Get(instance.Env(), instance.Get());
}
template<class LocalRef>
static void Set(const LocalRef& instance, UniquePtr<Impl>&& ptr)
{
Clear(instance);
SetNativeHandle(instance.Env(), instance.Get(),
reinterpret_cast<uintptr_t>(ptr.release()));
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
}
template<class LocalRef>
static void Clear(const LocalRef& instance)
{
UniquePtr<Impl> ptr(reinterpret_cast<Impl*>(
GetNativeHandle(instance.Env(), instance.Get())));
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
if (ptr) {
SetNativeHandle(instance.Env(), instance.Get(), 0);
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
}
}
};
template<class Impl>
struct NativePtr<Impl, /* UseWeakPtr = */ true>
{
static Impl* Get(JNIEnv* env, jobject instance)
{
const auto ptr = reinterpret_cast<WeakPtr<Impl>*>(
CheckNativeHandle(env, GetNativeHandle(env, instance)));
if (!ptr) {
return nullptr;
}
Impl* const impl = *ptr;
if (!impl) {
ThrowException(env, "java/lang/NullPointerException",
"Native object already released");
}
return impl;
}
template<class LocalRef>
static Impl* Get(const LocalRef& instance)
{
return Get(instance.Env(), instance.Get());
}
template<class LocalRef>
static void Set(const LocalRef& instance, Impl* ptr)
{
Clear(instance);
SetNativeHandle(instance.Env(), instance.Get(),
reinterpret_cast<uintptr_t>(new WeakPtr<Impl>(ptr)));
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
}
template<class LocalRef>
static void Clear(const LocalRef& instance)
{
const auto ptr = reinterpret_cast<WeakPtr<Impl>*>(
GetNativeHandle(instance.Env(), instance.Get()));
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
if (ptr) {
SetNativeHandle(instance.Env(), instance.Get(), 0);
MOZ_CATCH_JNI_EXCEPTION(instance.Env());
delete ptr;
}
}
};
} // namespace detail
using namespace detail;
/**
* For JNI native methods that are dispatched to a proxy, i.e. using
* @WrapForJNI(dispatchTo = "proxy"), the implementing C++ class must provide a
* OnNativeCall member. Subsequently, every native call is automatically
* wrapped in a functor object, and the object is passed to OnNativeCall. The
* OnNativeCall implementation can choose to invoke the call, save it, dispatch
* it to a different thread, etc. Each copy of functor may only be invoked
* once.
*
* class MyClass : public MyJavaClass::Natives<MyClass>
* {
* // ...
*
* template<class Functor>
* class ProxyRunnable final : public Runnable
* {
* Functor mCall;
* public:
* ProxyRunnable(Functor&& call) : mCall(mozilla::Move(call)) {}
* virtual void run() override { mCall(); }
* };
*
* public:
* template<class Functor>
* static void OnNativeCall(Functor&& call)
* {
* RunOnAnotherThread(new ProxyRunnable(mozilla::Move(call)));
* }
* };
*/
namespace detail {
// ProxyArg is used to handle JNI ref arguments for proxies. Because a proxied
// call may happen outside of the original JNI native call, we must save all
// JNI ref arguments as global refs to avoid the arguments going out of scope.
template<typename T>
struct ProxyArg
{
static_assert(mozilla::IsPod<T>::value, "T must be primitive type");
// Primitive types can be saved by value.
typedef T Type;
typedef typename TypeAdapter<T>::JNIType JNIType;
static void Clear(JNIEnv* env, Type&) {}
static Type From(JNIEnv* env, JNIType val)
{
return TypeAdapter<T>::ToNative(env, val);
}
};
template<class C, typename T>
struct ProxyArg<Ref<C, T>>
{
// Ref types need to be saved by global ref.
typedef typename C::GlobalRef Type;
typedef typename TypeAdapter<Ref<C, T>>::JNIType JNIType;
static void Clear(JNIEnv* env, Type& ref) { ref.Clear(env); }
static Type From(JNIEnv* env, JNIType val)
{
return Type(env, C::Ref::From(val));
}
};
template<typename C> struct ProxyArg<const C&> : ProxyArg<C> {};
template<> struct ProxyArg<StringParam> : ProxyArg<String::Ref> {};
template<class C> struct ProxyArg<LocalRef<C>> : ProxyArg<typename C::Ref> {};
// ProxyNativeCall implements the functor object that is passed to OnNativeCall
template<class Impl, class Owner, bool IsStatic,
bool HasThisArg /* has instance/class local ref in the call */,
typename... Args>
class ProxyNativeCall : public AbstractCall
{
// "this arg" refers to the Class::LocalRef (for static methods) or
// Owner::LocalRef (for instance methods) that we optionally (as indicated
// by HasThisArg) pass into the destination C++ function.
typedef typename mozilla::Conditional<IsStatic,
Class, Owner>::Type ThisArgClass;
typedef typename mozilla::Conditional<IsStatic,
jclass, jobject>::Type ThisArgJNIType;
// Type signature of the destination C++ function, which matches the
// Method template parameter in NativeStubImpl::Wrap.
typedef typename mozilla::Conditional<IsStatic,
typename mozilla::Conditional<HasThisArg,
void (*) (const Class::LocalRef&, Args...),
void (*) (Args...)>::Type,
typename mozilla::Conditional<HasThisArg,
void (Impl::*) (const typename Owner::LocalRef&, Args...),
void (Impl::*) (Args...)>::Type>::Type NativeCallType;
// Destination C++ function.
NativeCallType mNativeCall;
// Saved this arg.
typename ThisArgClass::GlobalRef mThisArg;
// Saved arguments.
mozilla::Tuple<typename ProxyArg<Args>::Type...> mArgs;
// We cannot use IsStatic and HasThisArg directly (without going through
// extra hoops) because GCC complains about invalid overloads, so we use
// another pair of template parameters, Static and ThisArg.
template<bool Static, bool ThisArg, size_t... Indices>
typename mozilla::EnableIf<Static && ThisArg, void>::Type
Call(const Class::LocalRef& cls,
mozilla::IndexSequence<Indices...>) const
{
(*mNativeCall)(cls, mozilla::Get<Indices>(mArgs)...);
}
template<bool Static, bool ThisArg, size_t... Indices>
typename mozilla::EnableIf<Static && !ThisArg, void>::Type
Call(const Class::LocalRef& cls,
mozilla::IndexSequence<Indices...>) const
{
(*mNativeCall)(mozilla::Get<Indices>(mArgs)...);
}
template<bool Static, bool ThisArg, size_t... Indices>
typename mozilla::EnableIf<!Static && ThisArg, void>::Type
Call(const typename Owner::LocalRef& inst,
mozilla::IndexSequence<Indices...>) const
{
Impl* const impl = NativePtr<Impl>::Get(inst);
MOZ_CATCH_JNI_EXCEPTION(inst.Env());
(impl->*mNativeCall)(inst, mozilla::Get<Indices>(mArgs)...);
}
template<bool Static, bool ThisArg, size_t... Indices>
typename mozilla::EnableIf<!Static && !ThisArg, void>::Type
Call(const typename Owner::LocalRef& inst,
mozilla::IndexSequence<Indices...>) const
{
Impl* const impl = NativePtr<Impl>::Get(inst);
MOZ_CATCH_JNI_EXCEPTION(inst.Env());
(impl->*mNativeCall)(mozilla::Get<Indices>(mArgs)...);
}
template<size_t... Indices>
void Clear(JNIEnv* env, mozilla::IndexSequence<Indices...>)
{
int dummy[] = {
(ProxyArg<Args>::Clear(env, Get<Indices>(mArgs)), 0)...
};
mozilla::Unused << dummy;
}
public:
// The class that implements the call target.
typedef Impl TargetClass;
typedef typename ThisArgClass::Param ThisArgType;
static const bool isStatic = IsStatic;
ProxyNativeCall(ThisArgJNIType thisArg,
NativeCallType nativeCall,
JNIEnv* env,
typename ProxyArg<Args>::JNIType... args)
: mNativeCall(nativeCall)
, mThisArg(env, ThisArgClass::Ref::From(thisArg))
, mArgs(ProxyArg<Args>::From(env, args)...)
{}
ProxyNativeCall(ProxyNativeCall&&) = default;
ProxyNativeCall(const ProxyNativeCall&) = default;
// Get class ref for static calls or object ref for instance calls.
typename ThisArgClass::Param GetThisArg() const { return mThisArg; }
// Return if target is the given function pointer / pointer-to-member.
// Because we can only compare pointers of the same type, we use a
// templated overload that is chosen only if given a different type of
// pointer than our target pointer type.
bool IsTarget(NativeCallType call) const { return call == mNativeCall; }
template<typename T> bool IsTarget(T&&) const { return false; }
// Redirect the call to another function / class member with the same
// signature as the original target. Crash if given a wrong signature.
void SetTarget(NativeCallType call) { mNativeCall = call; }
template<typename T> void SetTarget(T&&) const { MOZ_CRASH(); }
void operator()() override
{
JNIEnv* const env = GetEnvForThread();
typename ThisArgClass::LocalRef thisArg(env, mThisArg);
Call<IsStatic, HasThisArg>(
thisArg, typename IndexSequenceFor<Args...>::Type());
// Clear all saved global refs. We do this after the call is invoked,
// and not inside the destructor because we already have a JNIEnv here,
// so it's more efficient to clear out the saved args here. The
// downside is that the call can only be invoked once.
Clear(env, typename IndexSequenceFor<Args...>::Type());
mThisArg.Clear(env);
}
};
template<class Impl, bool HasThisArg, typename... Args>
struct Dispatcher
{
template<class Traits, bool IsStatic = Traits::isStatic,
typename... ProxyArgs>
static typename EnableIf<
Traits::dispatchTarget == DispatchTarget::PROXY, void>::Type
Run(ProxyArgs&&... args)
{
Impl::OnNativeCall(ProxyNativeCall<
Impl, typename Traits::Owner, IsStatic,
HasThisArg, Args...>(Forward<ProxyArgs>(args)...));
}
template<class Traits, bool IsStatic = Traits::isStatic,
typename ThisArg, typename... ProxyArgs>
static typename EnableIf<
Traits::dispatchTarget == DispatchTarget::GECKO, void>::Type
Run(ThisArg thisArg, ProxyArgs&&... args)
{
// For a static method, do not forward the "this arg" (i.e. the class
// local ref) if the implementation does not request it. This saves us
// a pair of calls to add/delete global ref.
DispatchToGeckoThread(MakeUnique<ProxyNativeCall<
Impl, typename Traits::Owner, IsStatic, HasThisArg,
Args...>>(HasThisArg || !IsStatic ? thisArg : nullptr,
Forward<ProxyArgs>(args)...));
}
template<class Traits, bool IsStatic = false, typename... ProxyArgs>
static typename EnableIf<
Traits::dispatchTarget == DispatchTarget::CURRENT, void>::Type
Run(ProxyArgs&&... args) {}
};
} // namespace detail
// Wrapper methods that convert arguments from the JNI types to the native
// types, e.g. from jobject to jni::Object::Ref. For instance methods, the
// wrapper methods also convert calls to calls on objects.
//
// We need specialization for static/non-static because the two have different
// signatures (jobject vs jclass and Impl::*Method vs *Method).
// We need specialization for return type, because void return type requires
// us to not deal with the return value.
// Bug 1207642 - Work around Dalvik bug by realigning stack on JNI entry
#ifdef __i386__
#define MOZ_JNICALL JNICALL __attribute__((force_align_arg_pointer))
#else
#define MOZ_JNICALL JNICALL
#endif
template<class Traits, class Impl, class Args = typename Traits::Args>
class NativeStub;
template<class Traits, class Impl, typename... Args>
class NativeStub<Traits, Impl, jni::Args<Args...>>
{
using Owner = typename Traits::Owner;
using ReturnType = typename Traits::ReturnType;
static constexpr bool isStatic = Traits::isStatic;
static constexpr bool isVoid = mozilla::IsVoid<ReturnType>::value;
struct VoidType { using JNIType = void; };
using ReturnJNIType = typename Conditional<
isVoid, VoidType, TypeAdapter<ReturnType>>::Type::JNIType;
using ReturnTypeForNonVoidInstance = typename Conditional<
!isStatic && !isVoid, ReturnType, VoidType>::Type;
using ReturnTypeForVoidInstance = typename Conditional<
!isStatic && isVoid, ReturnType, VoidType&>::Type;
using ReturnTypeForNonVoidStatic = typename Conditional<
isStatic && !isVoid, ReturnType, VoidType>::Type;
using ReturnTypeForVoidStatic = typename Conditional<
isStatic && isVoid, ReturnType, VoidType&>::Type;
static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT || isVoid,
"Dispatched calls must have void return type");
public:
// Non-void instance method
template<ReturnTypeForNonVoidInstance (Impl::*Method) (Args...)>
static MOZ_JNICALL ReturnJNIType
Wrap(JNIEnv* env, jobject instance,
typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
Impl* const impl = NativePtr<Impl>::Get(env, instance);
if (!impl) {
// There is a pending JNI exception at this point.
return ReturnJNIType();
}
return TypeAdapter<ReturnType>::FromNative(env,
(impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...));
}
// Non-void instance method with instance reference
template<ReturnTypeForNonVoidInstance (Impl::*Method)
(const typename Owner::LocalRef&, Args...)>
static MOZ_JNICALL ReturnJNIType
Wrap(JNIEnv* env, jobject instance,
typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
Impl* const impl = NativePtr<Impl>::Get(env, instance);
if (!impl) {
// There is a pending JNI exception at this point.
return ReturnJNIType();
}
auto self = Owner::LocalRef::Adopt(env, instance);
const auto res = TypeAdapter<ReturnType>::FromNative(env,
(impl->*Method)(self, TypeAdapter<Args>::ToNative(env, args)...));
self.Forget();
return res;
}
// Void instance method
template<ReturnTypeForVoidInstance (Impl::*Method) (Args...)>
static MOZ_JNICALL void
Wrap(JNIEnv* env, jobject instance,
typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
Dispatcher<Impl, /* HasThisArg */ false, Args...>::
template Run<Traits>(instance, Method, env, args...);
return;
}
Impl* const impl = NativePtr<Impl>::Get(env, instance);
if (!impl) {
// There is a pending JNI exception at this point.
return;
}
(impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...);
}
// Void instance method with instance reference
template<ReturnTypeForVoidInstance (Impl::*Method)
(const typename Owner::LocalRef&, Args...)>
static MOZ_JNICALL void
Wrap(JNIEnv* env, jobject instance,
typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
Dispatcher<Impl, /* HasThisArg */ true, Args...>::
template Run<Traits>(instance, Method, env, args...);
return;
}
Impl* const impl = NativePtr<Impl>::Get(env, instance);
if (!impl) {
// There is a pending JNI exception at this point.
return;
}
auto self = Owner::LocalRef::Adopt(env, instance);
(impl->*Method)(self, TypeAdapter<Args>::ToNative(env, args)...);
self.Forget();
}
// Overload for DisposeNative
template<ReturnTypeForVoidInstance (*DisposeNative)
(const typename Owner::LocalRef&)>
static MOZ_JNICALL void
Wrap(JNIEnv* env, jobject instance)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
using LocalRef = typename Owner::LocalRef;
Dispatcher<Impl, /* HasThisArg */ false, const LocalRef&>::
template Run<Traits, /* IsStatic */ true>(
/* ThisArg */ nullptr, DisposeNative, env, instance);
return;
}
auto self = Owner::LocalRef::Adopt(env, instance);
(Impl::DisposeNative)(self);
self.Forget();
}
// Non-void static method
template<ReturnTypeForNonVoidStatic (*Method) (Args...)>
static MOZ_JNICALL ReturnJNIType
Wrap(JNIEnv* env, jclass, typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
return TypeAdapter<ReturnType>::FromNative(env,
(*Method)(TypeAdapter<Args>::ToNative(env, args)...));
}
// Non-void static method with class reference
template<ReturnTypeForNonVoidStatic (*Method)
(const Class::LocalRef&, Args...)>
static MOZ_JNICALL ReturnJNIType
Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
auto clazz = Class::LocalRef::Adopt(env, cls);
const auto res = TypeAdapter<ReturnType>::FromNative(env,
(*Method)(clazz, TypeAdapter<Args>::ToNative(env, args)...));
clazz.Forget();
return res;
}
// Void static method
template<ReturnTypeForVoidStatic (*Method) (Args...)>
static MOZ_JNICALL void
Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
Dispatcher<Impl, /* HasThisArg */ false, Args...>::
template Run<Traits>(cls, Method, env, args...);
return;
}
(*Method)(TypeAdapter<Args>::ToNative(env, args)...);
}
// Void static method with class reference
template<ReturnTypeForVoidStatic (*Method)
(const Class::LocalRef&, Args...)>
static MOZ_JNICALL void
Wrap(JNIEnv* env, jclass cls, typename TypeAdapter<Args>::JNIType... args)
{
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
if (Traits::dispatchTarget != DispatchTarget::CURRENT) {
Dispatcher<Impl, /* HasThisArg */ true, Args...>::
template Run<Traits>(cls, Method, env, args...);
return;
}
auto clazz = Class::LocalRef::Adopt(env, cls);
(*Method)(clazz, TypeAdapter<Args>::ToNative(env, args)...);
clazz.Forget();
}
};
// Generate a JNINativeMethod from a native
// method's traits class and a wrapped stub.
template<class Traits, typename Ret, typename... Args>
constexpr JNINativeMethod MakeNativeMethod(MOZ_JNICALL Ret (*stub)(JNIEnv*, Args...))
{
return {
Traits::name,
Traits::signature,
reinterpret_cast<void*>(stub)
};
}
// Class inherited by implementing class.
template<class Cls, class Impl>
class NativeImpl
{
typedef typename Cls::template Natives<Impl> Natives;
static bool sInited;
public:
static void Init() {
if (sInited) {
return;
}
const auto& ctx = typename Cls::Context();
ctx.Env()->RegisterNatives(
ctx.ClassRef(), Natives::methods,
sizeof(Natives::methods) / sizeof(Natives::methods[0]));
MOZ_CATCH_JNI_EXCEPTION(ctx.Env());
sInited = true;
}
protected:
// Associate a C++ instance with a Java instance.
static void AttachNative(const typename Cls::LocalRef& instance,
SupportsWeakPtr<Impl>* ptr)
{
static_assert(mozilla::IsBaseOf<SupportsWeakPtr<Impl>, Impl>::value,
"Attach with UniquePtr&& when not using WeakPtr");
return NativePtr<Impl>::Set(instance, static_cast<Impl*>(ptr));
}
static void AttachNative(const typename Cls::LocalRef& instance,
UniquePtr<Impl>&& ptr)
{
static_assert(!mozilla::IsBaseOf<SupportsWeakPtr<Impl>, Impl>::value,
"Attach with SupportsWeakPtr* when using WeakPtr");
return NativePtr<Impl>::Set(instance, mozilla::Move(ptr));
}
// Get the C++ instance associated with a Java instance.
// There is always a pending exception if the return value is nullptr.
static Impl* GetNative(const typename Cls::LocalRef& instance) {
return NativePtr<Impl>::Get(instance);
}
static void DisposeNative(const typename Cls::LocalRef& instance) {
NativePtr<Impl>::Clear(instance);
}
NativeImpl() {
// Initialize on creation if not already initialized.
Init();
}
};
// Define static member.
template<class C, class I>
bool NativeImpl<C, I>::sInited;
} // namespace jni
} // namespace mozilla
#endif // mozilla_jni_Natives_h__

View file

@ -1,953 +0,0 @@
#ifndef mozilla_jni_Refs_h__
#define mozilla_jni_Refs_h__
#include <jni.h>
#include "mozilla/Move.h"
#include "mozilla/jni/Utils.h"
#include "nsError.h" // for nsresult
#include "nsString.h"
#include "nsTArray.h"
namespace mozilla {
namespace jni {
// Wrapped object reference (e.g. jobject, jclass, etc...)
template<class Cls, typename JNIType> class Ref;
// Represents a calling context for JNI methods.
template<class Cls, typename JNIType> class Context;
// Wrapped local reference that inherits from Ref.
template<class Cls> class LocalRef;
// Wrapped global reference that inherits from Ref.
template<class Cls> class GlobalRef;
// Wrapped dangling reference that's owned by someone else.
template<class Cls> class DependentRef;
// Class to hold the native types of a method's arguments.
// For example, if a method has signature (ILjava/lang/String;)V,
// its arguments class would be jni::Args<int32_t, jni::String::Param>
template<typename...>
struct Args {};
class Object;
// Base class for Ref and its specializations.
template<class Cls, typename Type>
class Ref
{
template<class C, typename T> friend class Ref;
using Self = Ref<Cls, Type>;
using bool_type = void (Self::*)() const;
void non_null_reference() const {}
// A Cls-derivative that allows copying
// (e.g. when acting as a return value).
struct CopyableCtx : public Context<Cls, Type>
{
CopyableCtx(JNIEnv* env, Type instance)
: Context<Cls, Type>(env, instance)
{}
CopyableCtx(const CopyableCtx& cls)
: Context<Cls, Type>(cls.Env(), cls.Get())
{}
};
// Private 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&) = default;
protected:
static JNIEnv* FindEnv()
{
return Cls::callingThread == CallingThread::GECKO ?
GetGeckoThreadEnv() : GetEnvForThread();
}
Type mInstance;
// 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.
explicit Ref(Type instance) : mInstance(instance) {}
public:
using JNIType = Type;
// Construct a Ref form a raw JNI reference.
static Ref<Cls, Type> From(JNIType obj)
{
return Ref<Cls, Type>(obj);
}
// Construct a Ref form a generic object reference.
static Ref<Cls, Type> From(const Ref<Object, jobject>& obj)
{
return Ref<Cls, Type>(JNIType(obj.Get()));
}
MOZ_IMPLICIT Ref(decltype(nullptr)) : mInstance(nullptr) {}
// Get the raw JNI reference.
JNIType Get() const
{
return mInstance;
}
bool operator==(const Ref& other) const
{
// Treat two references of the same object as being the same.
return mInstance == other.mInstance || JNI_FALSE !=
FindEnv()->IsSameObject(mInstance, other.mInstance);
}
bool operator!=(const Ref& other) const
{
return !operator==(other);
}
bool operator==(decltype(nullptr)) const
{
return !mInstance;
}
bool operator!=(decltype(nullptr)) const
{
return !!mInstance;
}
CopyableCtx operator->() const
{
return CopyableCtx(FindEnv(), mInstance);
}
// Any ref can be cast to an object ref.
operator Ref<Object, jobject>() const
{
return Ref<Object, jobject>(mInstance);
}
// Null checking (e.g. !!ref) using the safe-bool idiom.
operator bool_type() const
{
return 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;
};
// Represents a calling context for JNI methods.
template<class Cls, typename Type>
class Context : public Ref<Cls, Type>
{
using Ref = jni::Ref<Cls, Type>;
static jclass sClassRef; // global reference
protected:
JNIEnv* const mEnv;
public:
static jclass RawClassRef()
{
return sClassRef;
}
Context()
: Ref(nullptr)
, mEnv(Ref::FindEnv())
{}
Context(JNIEnv* env, Type instance)
: Ref(instance)
, mEnv(env)
{}
jclass ClassRef() const
{
if (!sClassRef) {
const jclass cls = GetClassRef(mEnv, Cls::name);
sClassRef = jclass(mEnv->NewGlobalRef(cls));
mEnv->DeleteLocalRef(cls);
}
return sClassRef;
}
JNIEnv* Env() const
{
return mEnv;
}
bool operator==(const Ref& other) const
{
// Treat two references of the same object as being the same.
return Ref::mInstance == other.mInstance || JNI_FALSE !=
mEnv->IsSameObject(Ref::mInstance, other.mInstance);
}
bool operator!=(const Ref& other) const
{
return !operator==(other);
}
bool operator==(decltype(nullptr)) const
{
return !Ref::mInstance;
}
bool operator!=(decltype(nullptr)) const
{
return !!Ref::mInstance;
}
Cls operator->() const
{
MOZ_ASSERT(Ref::mInstance, "Null jobject");
return Cls(*this);
}
};
template<class Cls, typename Type = jobject>
class ObjectBase
{
protected:
const jni::Context<Cls, Type>& mCtx;
jclass ClassRef() const { return mCtx.ClassRef(); }
JNIEnv* Env() const { return mCtx.Env(); }
Type Instance() const { return mCtx.Get(); }
public:
using Ref = jni::Ref<Cls, Type>;
using Context = jni::Context<Cls, Type>;
using LocalRef = jni::LocalRef<Cls>;
using GlobalRef = jni::GlobalRef<Cls>;
using Param = const Ref&;
static const CallingThread callingThread = CallingThread::ANY;
static const char name[];
explicit ObjectBase(const Context& ctx) : mCtx(ctx) {}
Cls* operator->()
{
return static_cast<Cls*>(this);
}
};
// Binding for a plain jobject.
class Object : public ObjectBase<Object, jobject>
{
public:
explicit Object(const Context& ctx) : ObjectBase<Object, jobject>(ctx) {}
};
// Binding for a built-in object reference other than jobject.
template<typename T>
class TypedObject : public ObjectBase<TypedObject<T>, T>
{
public:
explicit TypedObject(const Context<TypedObject<T>, T>& ctx)
: ObjectBase<TypedObject<T>, T>(ctx)
{}
};
// Define bindings for built-in types.
using String = TypedObject<jstring>;
using Class = TypedObject<jclass>;
using Throwable = TypedObject<jthrowable>;
using BooleanArray = TypedObject<jbooleanArray>;
using ByteArray = TypedObject<jbyteArray>;
using CharArray = TypedObject<jcharArray>;
using ShortArray = TypedObject<jshortArray>;
using IntArray = TypedObject<jintArray>;
using LongArray = TypedObject<jlongArray>;
using FloatArray = TypedObject<jfloatArray>;
using DoubleArray = TypedObject<jdoubleArray>;
using ObjectArray = TypedObject<jobjectArray>;
namespace detail {
// See explanation in LocalRef.
template<class Cls> struct GenericObject { using Type = Object; };
template<> struct GenericObject<Object>
{
struct Type {
using Ref = jni::Ref<Type, jobject>;
using Context = jni::Context<Type, jobject>;
};
};
template<class Cls> struct GenericLocalRef
{
template<class C> struct Type : jni::Object {};
};
template<> struct GenericLocalRef<Object>
{
template<class C> using Type = jni::LocalRef<C>;
};
} // namespace
template<class Cls>
class LocalRef : public Cls::Context
{
template<class C> friend class LocalRef;
using Ctx = typename Cls::Context;
using Ref = typename Cls::Ref;
using JNIType = typename Ref::JNIType;
// In order to be able to convert LocalRef<Object> to LocalRef<Cls>, we
// need constructors and copy assignment operators that take in a
// LocalRef<Object> argument. However, if Cls *is* Object, we would have
// duplicated constructors and operators with LocalRef<Object> arguments. To
// avoid this conflict, we use GenericObject, which is defined as Object for
// LocalRef<non-Object> and defined as a dummy class for LocalRef<Object>.
using GenericObject = typename detail::GenericObject<Cls>::Type;
// Similarly, GenericLocalRef is useed to convert LocalRef<Cls> to,
// LocalRef<Object>. It's defined as LocalRef<C> for Cls == Object,
// and defined as a dummy template class for Cls != Object.
template<class C> using GenericLocalRef
= typename detail::GenericLocalRef<Cls>::template Type<C>;
static JNIType NewLocalRef(JNIEnv* env, JNIType obj)
{
return JNIType(obj ? env->NewLocalRef(obj) : nullptr);
}
LocalRef(JNIEnv* env, JNIType instance) : Ctx(env, instance) {}
LocalRef& swap(LocalRef& other)
{
auto instance = other.mInstance;
other.mInstance = Ctx::mInstance;
Ctx::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(JNIType instance)
{
return LocalRef(Ref::FindEnv(), instance);
}
static LocalRef Adopt(JNIEnv* env, JNIType instance)
{
return LocalRef(env, instance);
}
// Copy constructor.
LocalRef(const LocalRef<Cls>& ref)
: Ctx(ref.mEnv, NewLocalRef(ref.mEnv, ref.mInstance))
{}
// Move constructor.
LocalRef(LocalRef<Cls>&& ref)
: Ctx(ref.mEnv, ref.mInstance)
{
ref.mInstance = nullptr;
}
explicit LocalRef(JNIEnv* env = Ref::FindEnv())
: Ctx(env, nullptr)
{}
// Construct a LocalRef from any Ref,
// which means creating a new local reference.
MOZ_IMPLICIT LocalRef(const Ref& ref)
: Ctx(Ref::FindEnv(), nullptr)
{
Ctx::mInstance = NewLocalRef(Ctx::mEnv, ref.Get());
}
LocalRef(JNIEnv* env, const Ref& ref)
: Ctx(env, NewLocalRef(env, ref.Get()))
{}
// Move a LocalRef<Object> into a LocalRef<Cls> without
// creating/deleting local references.
MOZ_IMPLICIT LocalRef(LocalRef<GenericObject>&& ref)
: Ctx(ref.mEnv, JNIType(ref.mInstance))
{
ref.mInstance = nullptr;
}
template<class C>
MOZ_IMPLICIT LocalRef(GenericLocalRef<C>&& ref)
: Ctx(ref.mEnv, ref.mInstance)
{
ref.mInstance = nullptr;
}
// Implicitly converts nullptr to LocalRef.
MOZ_IMPLICIT LocalRef(decltype(nullptr))
: Ctx(Ref::FindEnv(), nullptr)
{}
~LocalRef()
{
if (Ctx::mInstance) {
Ctx::mEnv->DeleteLocalRef(Ctx::mInstance);
Ctx::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.
typename Ref::JNIType Forget()
{
const auto obj = Ctx::Get();
Ctx::mInstance = nullptr;
return obj;
}
LocalRef<Cls>& operator=(LocalRef<Cls> ref)
{
return swap(ref);
}
LocalRef<Cls>& operator=(const Ref& ref)
{
LocalRef<Cls> newRef(Ctx::mEnv, ref);
return swap(newRef);
}
LocalRef<Cls>& operator=(LocalRef<GenericObject>&& ref)
{
LocalRef<Cls> newRef(mozilla::Move(ref));
return swap(newRef);
}
template<class C>
LocalRef<Cls>& operator=(GenericLocalRef<C>&& ref)
{
LocalRef<Cls> newRef(mozilla::Move(ref));
return swap(newRef);
}
LocalRef<Cls>& operator=(decltype(nullptr))
{
LocalRef<Cls> newRef(Ctx::mEnv, nullptr);
return swap(newRef);
}
};
template<class Cls>
class GlobalRef : public Cls::Ref
{
using Ref = typename Cls::Ref;
using JNIType = typename Ref::JNIType;
static JNIType NewGlobalRef(JNIEnv* env, JNIType instance)
{
return JNIType(instance ? env->NewGlobalRef(instance) : nullptr);
}
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(NewGlobalRef(GetEnvForThread(), ref.mInstance))
{}
// Move constructor
GlobalRef(GlobalRef&& ref)
: Ref(ref.mInstance)
{
ref.mInstance = nullptr;
}
MOZ_IMPLICIT GlobalRef(const Ref& ref)
: Ref(NewGlobalRef(GetEnvForThread(), ref.Get()))
{}
GlobalRef(JNIEnv* env, const Ref& ref)
: Ref(NewGlobalRef(env, ref.Get()))
{}
MOZ_IMPLICIT GlobalRef(const LocalRef<Cls>& ref)
: Ref(NewGlobalRef(ref.Env(), ref.Get()))
{}
// Implicitly converts nullptr to GlobalRef.
MOZ_IMPLICIT GlobalRef(decltype(nullptr))
: Ref(nullptr)
{}
~GlobalRef()
{
if (Ref::mInstance) {
Clear(GetEnvForThread());
}
}
// 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.
typename Ref::JNIType Forget()
{
const auto obj = Ref::Get();
Ref::mInstance = nullptr;
return obj;
}
void Clear(JNIEnv* env)
{
if (Ref::mInstance) {
env->DeleteGlobalRef(Ref::mInstance);
Ref::mInstance = nullptr;
}
}
GlobalRef<Cls>& operator=(GlobalRef<Cls> ref)
{
return swap(ref);
}
GlobalRef<Cls>& operator=(const Ref& ref)
{
GlobalRef<Cls> newRef(ref);
return swap(newRef);
}
GlobalRef<Cls>& operator=(const LocalRef<Cls>& ref)
{
GlobalRef<Cls> newRef(ref);
return swap(newRef);
}
GlobalRef<Cls>& operator=(decltype(nullptr))
{
GlobalRef<Cls> newRef(nullptr);
return swap(newRef);
}
};
template<class Cls>
class DependentRef : public Cls::Ref
{
using Ref = typename Cls::Ref;
public:
DependentRef(typename Ref::JNIType instance)
: Ref(instance)
{}
DependentRef(const DependentRef& ref)
: Ref(ref.Get())
{}
};
class StringParam;
template<>
class TypedObject<jstring> : public ObjectBase<TypedObject<jstring>, jstring>
{
using Base = ObjectBase<TypedObject<jstring>, jstring>;
public:
using Param = const StringParam&;
explicit TypedObject(const Context& ctx) : Base(ctx) {}
size_t Length() const
{
const size_t ret = Base::Env()->GetStringLength(Base::Instance());
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
return ret;
}
nsString ToString() const
{
const jchar* const str = Base::Env()->GetStringChars(
Base::Instance(), nullptr);
const jsize len = Base::Env()->GetStringLength(Base::Instance());
nsString result(reinterpret_cast<const char16_t*>(str), len);
Base::Env()->ReleaseStringChars(Base::Instance(), str);
return result;
}
nsCString ToCString() const
{
return NS_ConvertUTF16toUTF8(ToString());
}
// Convert jstring to a nsString.
operator nsString() const
{
return ToString();
}
// Convert jstring to a nsCString.
operator nsCString() const
{
return ToCString();
}
};
// Define a custom parameter type for String,
// which accepts both String::Ref and nsAString/nsACString
class StringParam : public String::Ref
{
using Ref = String::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<const jchar*>(str.BeginReading()),
str.Length());
MOZ_CATCH_JNI_EXCEPTION(env);
return result;
}
public:
MOZ_IMPLICIT StringParam(decltype(nullptr))
: Ref(nullptr)
, mEnv(nullptr)
{}
MOZ_IMPLICIT StringParam(const Ref& ref)
: Ref(ref.Get())
, mEnv(nullptr)
{}
MOZ_IMPLICIT StringParam(const nsAString& str, JNIEnv* env = Ref::FindEnv())
: Ref(GetString(env, str))
, mEnv(env)
{}
MOZ_IMPLICIT StringParam(const char16_t* str, JNIEnv* env = Ref::FindEnv())
: Ref(GetString(env, nsDependentString(str)))
, mEnv(env)
{}
MOZ_IMPLICIT StringParam(const nsACString& str, JNIEnv* env = Ref::FindEnv())
: Ref(GetString(env, NS_ConvertUTF8toUTF16(str)))
, mEnv(env)
{}
MOZ_IMPLICIT StringParam(const char* str, JNIEnv* env = Ref::FindEnv())
: Ref(GetString(env, NS_ConvertUTF8toUTF16(str)))
, mEnv(env)
{}
StringParam(StringParam&& other)
: Ref(other.Get())
, mEnv(other.mEnv)
{
other.mInstance = nullptr;
}
~StringParam()
{
if (mEnv && Get()) {
mEnv->DeleteLocalRef(Get());
}
}
operator String::LocalRef() const
{
// We can't return our existing ref because the returned
// LocalRef could be freed first, so we need a new local ref.
return String::LocalRef(mEnv ? mEnv : Ref::FindEnv(), *this);
}
};
namespace detail {
template<typename T> struct TypeAdapter;
}
// Ref specialization for arrays.
template<typename JNIType, class ElementType>
class ArrayRefBase : public ObjectBase<TypedObject<JNIType>, JNIType>
{
using Base = ObjectBase<TypedObject<JNIType>, JNIType>;
public:
explicit ArrayRefBase(const Context<TypedObject<JNIType>, JNIType>& ctx)
: Base(ctx)
{}
static typename Base::LocalRef New(const ElementType* data, size_t length) {
using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType;
static_assert(sizeof(ElementType) == sizeof(JNIElemType),
"Size of native type must match size of JNI type");
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
auto result =
(jenv->*detail::TypeAdapter<ElementType>::NewArray)(length);
MOZ_CATCH_JNI_EXCEPTION(jenv);
(jenv->*detail::TypeAdapter<ElementType>::SetArray)(
result, jsize(0), length,
reinterpret_cast<const JNIElemType*>(data));
MOZ_CATCH_JNI_EXCEPTION(jenv);
return Base::LocalRef::Adopt(jenv, result);
}
size_t Length() const
{
const size_t ret = Base::Env()->GetArrayLength(Base::Instance());
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
return ret;
}
ElementType GetElement(size_t index) const
{
using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType;
static_assert(sizeof(ElementType) == sizeof(JNIElemType),
"Size of native type must match size of JNI type");
ElementType ret;
(Base::Env()->*detail::TypeAdapter<ElementType>::GetArray)(
Base::Instance(), jsize(index), 1,
reinterpret_cast<JNIElemType*>(&ret));
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
return ret;
}
nsTArray<ElementType> GetElements() const
{
using JNIElemType = typename detail::TypeAdapter<ElementType>::JNIType;
static_assert(sizeof(ElementType) == sizeof(JNIElemType),
"Size of native type must match size of JNI type");
const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance()));
nsTArray<ElementType> array((size_t(len)));
array.SetLength(size_t(len));
(Base::Env()->*detail::TypeAdapter<ElementType>::GetArray)(
Base::Instance(), 0, len,
reinterpret_cast<JNIElemType*>(array.Elements()));
return array;
}
ElementType operator[](size_t index) const
{
return GetElement(index);
}
operator nsTArray<ElementType>() const
{
return GetElements();
}
};
#define DEFINE_PRIMITIVE_ARRAY_REF(JNIType, ElementType) \
template<> \
class TypedObject<JNIType> : public ArrayRefBase<JNIType, ElementType> \
{ \
public: \
explicit TypedObject(const Context& ctx) \
: ArrayRefBase<JNIType, ElementType>(ctx) \
{} \
}
DEFINE_PRIMITIVE_ARRAY_REF(jbooleanArray, bool);
DEFINE_PRIMITIVE_ARRAY_REF(jbyteArray, int8_t);
DEFINE_PRIMITIVE_ARRAY_REF(jcharArray, char16_t);
DEFINE_PRIMITIVE_ARRAY_REF(jshortArray, int16_t);
DEFINE_PRIMITIVE_ARRAY_REF(jintArray, int32_t);
DEFINE_PRIMITIVE_ARRAY_REF(jlongArray, int64_t);
DEFINE_PRIMITIVE_ARRAY_REF(jfloatArray, float);
DEFINE_PRIMITIVE_ARRAY_REF(jdoubleArray, double);
#undef DEFINE_PRIMITIVE_ARRAY_REF
class ByteBuffer : public ObjectBase<ByteBuffer, jobject>
{
public:
explicit ByteBuffer(const Context& ctx)
: ObjectBase<ByteBuffer, jobject>(ctx)
{}
static LocalRef New(void* data, size_t capacity)
{
JNIEnv* const env = GetEnvForThread();
const auto ret = LocalRef::Adopt(
env, env->NewDirectByteBuffer(data, jlong(capacity)));
MOZ_CATCH_JNI_EXCEPTION(env);
return ret;
}
void* Address()
{
void* const ret = Env()->GetDirectBufferAddress(Instance());
MOZ_CATCH_JNI_EXCEPTION(Env());
return ret;
}
size_t Capacity()
{
const size_t ret = size_t(Env()->GetDirectBufferCapacity(Instance()));
MOZ_CATCH_JNI_EXCEPTION(Env());
return ret;
}
};
template<>
class TypedObject<jobjectArray>
: public ObjectBase<TypedObject<jobjectArray>, jobjectArray>
{
using Base = ObjectBase<TypedObject<jobjectArray>, jobjectArray>;
public:
explicit TypedObject(const Context& ctx) : Base(ctx) {}
size_t Length() const
{
const size_t ret = Base::Env()->GetArrayLength(Base::Instance());
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
return ret;
}
Object::LocalRef GetElement(size_t index) const
{
auto ret = Object::LocalRef::Adopt(
Base::Env(), Base::Env()->GetObjectArrayElement(
Base::Instance(), jsize(index)));
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
return ret;
}
nsTArray<Object::LocalRef> GetElements() const
{
const jsize len = size_t(Base::Env()->GetArrayLength(Base::Instance()));
nsTArray<Object::LocalRef> array((size_t(len)));
for (jsize i = 0; i < len; i++) {
array.AppendElement(Object::LocalRef::Adopt(
Base::Env(), Base::Env()->GetObjectArrayElement(
Base::Instance(), i)));
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
}
return array;
}
Object::LocalRef operator[](size_t index) const
{
return GetElement(index);
}
operator nsTArray<Object::LocalRef>() const
{
return GetElements();
}
void SetElement(size_t index, Object::Param element) const
{
Base::Env()->SetObjectArrayElement(
Base::Instance(), jsize(index), element.Get());
MOZ_CATCH_JNI_EXCEPTION(Base::Env());
}
};
// Support conversion from LocalRef<T>* to LocalRef<Object>*:
// LocalRef<Foo> foo;
// Foo::GetFoo(&foo); // error because parameter type is LocalRef<Object>*.
// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument.
template<class Cls>
class ReturnToLocal
{
private:
LocalRef<Cls>* const localRef;
LocalRef<Object> objRef;
public:
explicit ReturnToLocal(LocalRef<Cls>* ref) : localRef(ref) {}
operator LocalRef<Object>*() { return &objRef; }
~ReturnToLocal()
{
if (objRef) {
*localRef = mozilla::Move(objRef);
}
}
};
template<class Cls>
ReturnToLocal<Cls> ReturnTo(LocalRef<Cls>* ref)
{
return ReturnToLocal<Cls>(ref);
}
// Support conversion from GlobalRef<T>* to LocalRef<Object/T>*:
// GlobalRef<Foo> foo;
// Foo::GetFoo(&foo); // error because parameter type is LocalRef<Foo>*.
// Foo::GetFoo(ReturnTo(&foo)); // OK because ReturnTo converts the argument.
template<class Cls>
class ReturnToGlobal
{
private:
GlobalRef<Cls>* const globalRef;
LocalRef<Object> objRef;
LocalRef<Cls> clsRef;
public:
explicit ReturnToGlobal(GlobalRef<Cls>* ref) : globalRef(ref) {}
operator LocalRef<Object>*() { return &objRef; }
operator LocalRef<Cls>*() { return &clsRef; }
~ReturnToGlobal()
{
if (objRef) {
*globalRef = (clsRef = mozilla::Move(objRef));
} else if (clsRef) {
*globalRef = clsRef;
}
}
};
template<class Cls>
ReturnToGlobal<Cls> ReturnTo(GlobalRef<Cls>* ref)
{
return ReturnToGlobal<Cls>(ref);
}
} // namespace jni
} // namespace mozilla
#endif // mozilla_jni_Refs_h__

View file

@ -1,140 +0,0 @@
#ifndef mozilla_jni_Types_h__
#define mozilla_jni_Types_h__
#include <jni.h>
#include "mozilla/jni/Refs.h"
namespace mozilla {
namespace jni {
namespace detail {
// TypeAdapter specializations are the interfaces between native/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<typename T> struct TypeAdapter;
// TypeAdapter<LocalRef<Cls>> applies when jobject is a return value.
template<class Cls> struct TypeAdapter<LocalRef<Cls>> {
using JNIType = typename Cls::Ref::JNIType;
static constexpr auto Call = &JNIEnv::CallObjectMethodA;
static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
static constexpr auto Get = &JNIEnv::GetObjectField;
static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;
// Declare instance as jobject because JNI methods return
// jobject even if the return value is really jstring, etc.
static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) {
return LocalRef<Cls>::Adopt(env, JNIType(instance));
}
static JNIType FromNative(JNIEnv*, LocalRef<Cls>&& instance) {
return instance.Forget();
}
};
// clang is picky about function types, including attributes that modify the calling
// convention, lining up. GCC appears to be somewhat less so.
#ifdef __clang__
#define MOZ_JNICALL_ABI JNICALL
#else
#define MOZ_JNICALL_ABI
#endif
template<class Cls> constexpr jobject
(JNIEnv::*TypeAdapter<LocalRef<Cls>>::Call)(jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI;
template<class Cls> constexpr jobject
(JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticCall)(jclass, jmethodID, jvalue*) MOZ_JNICALL_ABI;
template<class Cls> constexpr jobject
(JNIEnv::*TypeAdapter<LocalRef<Cls>>::Get)(jobject, jfieldID);
template<class Cls> constexpr jobject
(JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticGet)(jclass, jfieldID);
// TypeAdapter<Ref<Cls>> applies when jobject is a parameter value.
template<class Cls, typename T> struct TypeAdapter<Ref<Cls, T>> {
using JNIType = typename Ref<Cls, T>::JNIType;
static constexpr auto Set = &JNIEnv::SetObjectField;
static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;
static DependentRef<Cls> ToNative(JNIEnv* env, JNIType instance) {
return DependentRef<Cls>(instance);
}
static JNIType FromNative(JNIEnv*, const Ref<Cls, T>& instance) {
return instance.Get();
}
};
template<class Cls, typename T> constexpr void
(JNIEnv::*TypeAdapter<Ref<Cls, T>>::Set)(jobject, jfieldID, jobject);
template<class Cls, typename T> constexpr void
(JNIEnv::*TypeAdapter<Ref<Cls, T>>::StaticSet)(jclass, jfieldID, jobject);
// jstring has its own Param type.
template<> struct TypeAdapter<StringParam>
: public TypeAdapter<String::Ref>
{};
template<class Cls> struct TypeAdapter<const Cls&>
: public TypeAdapter<Cls>
{};
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \
\
template<> struct TypeAdapter<NativeType> { \
using JNI##Type = JNIType; \
\
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 constexpr auto GetArray = &JNIEnv::Get ## JNIName ## ArrayRegion; \
static constexpr auto SetArray = &JNIEnv::Set ## JNIName ## ArrayRegion; \
static constexpr auto NewArray = &JNIEnv::New ## JNIName ## Array; \
\
static JNIType FromNative(JNIEnv*, NativeType val) { \
return static_cast<JNIType>(val); \
} \
static NativeType ToNative(JNIEnv*, JNIType val) { \
return static_cast<NativeType>(val); \
} \
}
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 detail
using namespace detail;
} // namespace jni
} // namespace mozilla
#endif // mozilla_jni_Types_h__

View file

@ -1,291 +0,0 @@
#include "Utils.h"
#include "Types.h"
#include <android/log.h>
#include <pthread.h>
#include "mozilla/Assertions.h"
#include "GeneratedJNIWrappers.h"
#include "nsAppShell.h"
namespace mozilla {
namespace jni {
namespace detail {
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \
\
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Call) \
(jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI; \
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticCall) \
(jclass, jmethodID, jvalue*) MOZ_JNICALL_ABI; \
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Get) \
(jobject, jfieldID) ABIName; \
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::StaticGet) \
(jclass, jfieldID) ABIName; \
constexpr void (JNIEnv::*TypeAdapter<NativeType>::Set) \
(jobject, jfieldID, JNIType) ABIName; \
constexpr void (JNIEnv::*TypeAdapter<NativeType>::StaticSet) \
(jclass, jfieldID, JNIType) ABIName; \
constexpr void (JNIEnv::*TypeAdapter<NativeType>::GetArray) \
(JNIType ## Array, jsize, jsize, JNIType*)
DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float, MOZ_JNICALL_ABI);
DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double, MOZ_JNICALL_ABI);
#undef DEFINE_PRIMITIVE_TYPE_ADAPTER
} // namespace detail
template<> const char ObjectBase<Object, jobject>::name[] = "java/lang/Object";
template<> const char ObjectBase<TypedObject<jstring>, jstring>::name[] = "java/lang/String";
template<> const char ObjectBase<TypedObject<jclass>, jclass>::name[] = "java/lang/Class";
template<> const char ObjectBase<TypedObject<jthrowable>, jthrowable>::name[] = "java/lang/Throwable";
template<> const char ObjectBase<TypedObject<jbooleanArray>, jbooleanArray>::name[] = "[Z";
template<> const char ObjectBase<TypedObject<jbyteArray>, jbyteArray>::name[] = "[B";
template<> const char ObjectBase<TypedObject<jcharArray>, jcharArray>::name[] = "[C";
template<> const char ObjectBase<TypedObject<jshortArray>, jshortArray>::name[] = "[S";
template<> const char ObjectBase<TypedObject<jintArray>, jintArray>::name[] = "[I";
template<> const char ObjectBase<TypedObject<jlongArray>, jlongArray>::name[] = "[J";
template<> const char ObjectBase<TypedObject<jfloatArray>, jfloatArray>::name[] = "[F";
template<> const char ObjectBase<TypedObject<jdoubleArray>, jdoubleArray>::name[] = "[D";
template<> const char ObjectBase<TypedObject<jobjectArray>, jobjectArray>::name[] = "[Ljava/lang/Object;";
template<> const char ObjectBase<ByteBuffer, jobject>::name[] = "java/nio/ByteBuffer";
JNIEnv* sGeckoThreadEnv;
namespace {
JavaVM* sJavaVM;
pthread_key_t sThreadEnvKey;
jclass sOOMErrorClass;
jobject sClassLoader;
jmethodID sClassLoaderLoadClass;
bool sIsFennec;
void UnregisterThreadEnv(void* env)
{
if (!env) {
// We were never attached.
return;
}
// The thread may have already been detached. In that case, it's still
// okay to call DetachCurrentThread(); it'll simply return an error.
// However, we must not access | env | because it may be invalid.
MOZ_ASSERT(sJavaVM);
sJavaVM->DetachCurrentThread();
}
} // namespace
void SetGeckoThreadEnv(JNIEnv* aEnv)
{
MOZ_ASSERT(aEnv);
MOZ_ASSERT(!sGeckoThreadEnv || sGeckoThreadEnv == aEnv);
if (!sGeckoThreadEnv
&& pthread_key_create(&sThreadEnvKey, UnregisterThreadEnv)) {
MOZ_CRASH("Failed to initialize required TLS");
}
sGeckoThreadEnv = aEnv;
MOZ_ALWAYS_TRUE(!pthread_setspecific(sThreadEnvKey, aEnv));
MOZ_ALWAYS_TRUE(!aEnv->GetJavaVM(&sJavaVM));
MOZ_ASSERT(sJavaVM);
sOOMErrorClass = Class::GlobalRef(Class::LocalRef::Adopt(
aEnv->FindClass("java/lang/OutOfMemoryError"))).Forget();
aEnv->ExceptionClear();
sClassLoader = Object::GlobalRef(java::GeckoThread::ClsLoader()).Forget();
sClassLoaderLoadClass = aEnv->GetMethodID(
Class::LocalRef::Adopt(aEnv->GetObjectClass(sClassLoader)).Get(),
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
MOZ_ASSERT(sClassLoader && sClassLoaderLoadClass);
auto geckoAppClass = Class::LocalRef::Adopt(
aEnv->FindClass("org/mozilla/gecko/GeckoApp"));
aEnv->ExceptionClear();
sIsFennec = !!geckoAppClass;
}
JNIEnv* GetEnvForThread()
{
MOZ_ASSERT(sGeckoThreadEnv);
JNIEnv* env = static_cast<JNIEnv*>(pthread_getspecific(sThreadEnvKey));
if (env) {
return env;
}
// We don't have a saved JNIEnv, so try to get one.
// AttachCurrentThread() does the same thing as GetEnv() when a thread is
// already attached, so we don't have to call GetEnv() at all.
if (!sJavaVM->AttachCurrentThread(&env, nullptr)) {
MOZ_ASSERT(env);
MOZ_ALWAYS_TRUE(!pthread_setspecific(sThreadEnvKey, env));
return env;
}
MOZ_CRASH("Failed to get JNIEnv for thread");
return nullptr; // unreachable
}
bool ThrowException(JNIEnv *aEnv, const char *aClass,
const char *aMessage)
{
MOZ_ASSERT(aEnv, "Invalid thread JNI env");
Class::LocalRef cls = Class::LocalRef::Adopt(aEnv->FindClass(aClass));
MOZ_ASSERT(cls, "Cannot find exception class");
return !aEnv->ThrowNew(cls.Get(), aMessage);
}
bool HandleUncaughtException(JNIEnv* aEnv)
{
MOZ_ASSERT(aEnv, "Invalid thread JNI env");
if (!aEnv->ExceptionCheck()) {
return false;
}
#ifdef MOZ_CHECK_JNI
aEnv->ExceptionDescribe();
#endif
Throwable::LocalRef e =
Throwable::LocalRef::Adopt(aEnv, aEnv->ExceptionOccurred());
MOZ_ASSERT(e);
aEnv->ExceptionClear();
String::LocalRef stack = java::GeckoAppShell::GetExceptionStackTrace(e);
if (stack && ReportException(aEnv, e.Get(), stack.Get())) {
return true;
}
aEnv->ExceptionClear();
java::GeckoAppShell::HandleUncaughtException(e);
if (NS_WARN_IF(aEnv->ExceptionCheck())) {
aEnv->ExceptionDescribe();
aEnv->ExceptionClear();
}
return true;
}
bool ReportException(JNIEnv* aEnv, jthrowable aExc, jstring aStack)
{
bool result = true;
if (sOOMErrorClass && aEnv->IsInstanceOf(aExc, sOOMErrorClass)) {
NS_ABORT_OOM(0); // Unknown OOM size
}
return result;
}
namespace {
jclass sJNIObjectClass;
jfieldID sJNIObjectHandleField;
bool EnsureJNIObject(JNIEnv* env, jobject instance) {
if (!sJNIObjectClass) {
sJNIObjectClass = Class::GlobalRef(Class::LocalRef::Adopt(GetClassRef(
env, "org/mozilla/gecko/mozglue/JNIObject"))).Forget();
sJNIObjectHandleField = env->GetFieldID(
sJNIObjectClass, "mHandle", "J");
}
MOZ_ASSERT(env->IsInstanceOf(instance, sJNIObjectClass));
return true;
}
} // namespace
uintptr_t GetNativeHandle(JNIEnv* env, jobject instance)
{
if (!EnsureJNIObject(env, instance)) {
return 0;
}
return static_cast<uintptr_t>(
env->GetLongField(instance, sJNIObjectHandleField));
}
void SetNativeHandle(JNIEnv* env, jobject instance, uintptr_t handle)
{
if (!EnsureJNIObject(env, instance)) {
return;
}
env->SetLongField(instance, sJNIObjectHandleField,
static_cast<jlong>(handle));
}
jclass GetClassRef(JNIEnv* aEnv, const char* aClassName)
{
// First try the default class loader.
auto classRef = Class::LocalRef::Adopt(aEnv, aEnv->FindClass(aClassName));
if (!classRef && sClassLoader) {
// If the default class loader failed but we have an app class loader, try that.
// Clear the pending exception from failed FindClass call above.
aEnv->ExceptionClear();
classRef = Class::LocalRef::Adopt(aEnv, jclass(
aEnv->CallObjectMethod(sClassLoader, sClassLoaderLoadClass,
StringParam(aClassName, aEnv).Get())));
}
if (classRef) {
return classRef.Forget();
}
__android_log_print(
ANDROID_LOG_ERROR, "Gecko",
">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. "
"Did ProGuard optimize away something it shouldn't have?",
aClassName);
aEnv->ExceptionDescribe();
MOZ_CRASH("Cannot find JNI class");
return nullptr;
}
void DispatchToGeckoThread(UniquePtr<AbstractCall>&& aCall)
{
class AbstractCallEvent : public nsAppShell::Event
{
UniquePtr<AbstractCall> mCall;
public:
AbstractCallEvent(UniquePtr<AbstractCall>&& aCall)
: mCall(Move(aCall))
{}
void Run() override
{
(*mCall)();
}
};
nsAppShell::PostEvent(MakeUnique<AbstractCallEvent>(Move(aCall)));
}
bool IsFennec()
{
return sIsFennec;
}
} // jni
} // mozilla

View file

@ -1,147 +0,0 @@
#ifndef mozilla_jni_Utils_h__
#define mozilla_jni_Utils_h__
#include <jni.h>
#include "mozilla/UniquePtr.h"
#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
#define MOZ_CHECK_JNI
#endif
#ifdef MOZ_CHECK_JNI
#include <pthread.h>
#include "mozilla/Assertions.h"
#include "APKOpen.h"
#include "MainThreadUtils.h"
#endif
namespace mozilla {
namespace jni {
// 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,
};
// Thread that a particular JNI call is allowed on.
enum class CallingThread
{
// Can be called from any thread (default).
ANY,
// Can be called from the Gecko thread.
GECKO,
// Can be called from the Java UI thread.
UI,
};
// If and where a JNI call will be dispatched.
enum class DispatchTarget
{
// Call happens synchronously on the calling thread (default).
CURRENT,
// Call happens synchronously on the calling thread, but the call is
// wrapped in a function object and is passed thru UsesNativeCallProxy.
// Method must return void.
PROXY,
// Call is dispatched asynchronously on the Gecko thread. Method must
// return void.
GECKO,
};
extern JNIEnv* sGeckoThreadEnv;
inline bool IsAvailable()
{
return !!sGeckoThreadEnv;
}
inline JNIEnv* GetGeckoThreadEnv()
{
#ifdef MOZ_CHECK_JNI
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Must be on Gecko thread");
MOZ_RELEASE_ASSERT(sGeckoThreadEnv, "Must have a JNIEnv");
#endif
return sGeckoThreadEnv;
}
void SetGeckoThreadEnv(JNIEnv* aEnv);
JNIEnv* GetEnvForThread();
#ifdef MOZ_CHECK_JNI
#define MOZ_ASSERT_JNI_THREAD(thread) \
do { \
if ((thread) == mozilla::jni::CallingThread::GECKO) { \
MOZ_RELEASE_ASSERT(::NS_IsMainThread()); \
} else if ((thread) == mozilla::jni::CallingThread::UI) { \
const bool isOnUiThread = ::pthread_equal(::pthread_self(), \
::getJavaUiThread()); \
MOZ_RELEASE_ASSERT(isOnUiThread); \
} \
} while (0)
#else
#define MOZ_ASSERT_JNI_THREAD(thread) do {} while (0)
#endif
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);
}
inline bool ThrowException(const char *aClass, const char *aMessage)
{
return ThrowException(GetEnvForThread(), aClass, aMessage);
}
inline bool ThrowException(const char *aMessage)
{
return ThrowException(GetEnvForThread(), aMessage);
}
bool HandleUncaughtException(JNIEnv* aEnv);
bool ReportException(JNIEnv* aEnv, jthrowable aExc, jstring aStack);
#define MOZ_CATCH_JNI_EXCEPTION(env) \
do { \
if (mozilla::jni::HandleUncaughtException((env))) { \
MOZ_CRASH("JNI exception"); \
} \
} while (0)
uintptr_t GetNativeHandle(JNIEnv* env, jobject instance);
void SetNativeHandle(JNIEnv* env, jobject instance, uintptr_t handle);
jclass GetClassRef(JNIEnv* aEnv, const char* aClassName);
struct AbstractCall
{
virtual ~AbstractCall() {}
virtual void operator()() = 0;
};
void DispatchToGeckoThread(UniquePtr<AbstractCall>&& aCall);
/**
* Returns whether Gecko is running in a Fennec environment, as determined by
* the presence of the GeckoApp class.
*/
bool IsFennec();
} // jni
} // mozilla
#endif // mozilla_jni_Utils_h__

View file

@ -1,24 +0,0 @@
# -*- Mode: python; 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',
'Natives.h',
'Refs.h',
'Types.h',
'Utils.h',
]
UNIFIED_SOURCES += [
'Utils.cpp',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/widget',
'/widget/android',
]

View file

@ -1,73 +0,0 @@
# -*- Mode: python; 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',
'fennec',
'jni',
]
XPIDL_SOURCES += [
'nsIAndroidBridge.idl',
]
XPIDL_MODULE = 'widget_android'
EXPORTS += [
'AndroidBridge.h',
'AndroidJavaWrappers.h',
'AndroidJNIWrapper.h',
'GeneratedJNINatives.h',
'GeneratedJNIWrappers.h',
]
EXPORTS.mozilla.widget += [
'AndroidCompositorWidget.h',
]
UNIFIED_SOURCES += [
'AndroidAlerts.cpp',
'AndroidBridge.cpp',
'AndroidCompositorWidget.cpp',
'AndroidContentController.cpp',
'AndroidJavaWrappers.cpp',
'AndroidJNI.cpp',
'AndroidJNIWrapper.cpp',
'ANRReporter.cpp',
'GeneratedJNIWrappers.cpp',
'GfxInfo.cpp',
'NativeJSContainer.cpp',
'nsAndroidProtocolHandler.cpp',
'nsAppShell.cpp',
'nsClipboard.cpp',
'nsDeviceContextAndroid.cpp',
'nsIdleServiceAndroid.cpp',
'nsLookAndFeel.cpp',
'nsPrintOptionsAndroid.cpp',
'nsScreenManagerAndroid.cpp',
'nsWidgetFactory.cpp',
'nsWindow.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/docshell/base',
'/dom/base',
'/dom/system/android',
'/netwerk/base',
'/netwerk/cache',
'/widget',
]
CXXFLAGS += ['-Wno-error=shadow']
OS_LIBS += ['android']
#DEFINES['DEBUG_WIDGETS'] = True

View file

@ -1,183 +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 "nsIStandardURL.h"
#include "nsIURL.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 = java::GeckoAppShell::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;
SetURI(aURI);
auto type = java::GeckoAppShell::ConnectionGetMimeType(mConnection);
if (type) {
SetContentType(type->ToCString());
}
}
public:
static AndroidChannel* CreateChannel(nsIURI *aURI) {
nsCString spec;
aURI->GetSpec(spec);
auto connection = java::GeckoAppShell::GetConnection(spec);
return connection ? new AndroidChannel(aURI, connection) : nullptr;
}
virtual ~AndroidChannel() {
}
virtual nsresult OpenContentStream(bool async, nsIInputStream **result,
nsIChannel** channel) {
nsCOMPtr<nsIInputStream> 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<nsIStandardURL> 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<nsIURL> 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<nsIChannel> 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);
}

View file

@ -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___ */

View file

@ -1,683 +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 "nsISpeculativeConnect.h"
#include "nsIURIFixup.h"
#include "nsCategoryManagerUtils.h"
#include "nsCDefaultURIFixup.h"
#include "nsToolkitCompsCID.h"
#include "nsGeoPosition.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/Hal.h"
#include "prenv.h"
#include "AndroidBridge.h"
#include "AndroidBridgeUtilities.h"
#include "GeneratedJNINatives.h"
#include <android/log.h>
#include <pthread.h>
#include <wchar.h>
#include "GeckoProfiler.h"
#ifdef MOZ_ANDROID_HISTORY
#include "nsNetUtil.h"
#include "nsIURI.h"
#include "IHistory.h"
#endif
#ifdef MOZ_LOGGING
#include "mozilla/Logging.h"
#endif
#include "AndroidAlerts.h"
#include "ANRReporter.h"
#include "GeckoBatteryManager.h"
#include "GeckoNetworkManager.h"
#include "GeckoScreenOrientation.h"
#include "PrefsHelper.h"
#include "fennec/MemoryMonitor.h"
#include "fennec/Telemetry.h"
#include "fennec/ThumbnailHelper.h"
#ifdef DEBUG_ANDROID_EVENTS
#define EVLOG(args...) ALOG(args)
#else
#define EVLOG(args...) do { } while (0)
#endif
using namespace mozilla;
nsIGeolocationUpdate *gLocationCallback = nullptr;
nsAppShell* nsAppShell::sAppShell;
StaticAutoPtr<Mutex> nsAppShell::sAppShellLock;
NS_IMPL_ISUPPORTS_INHERITED(nsAppShell, nsBaseAppShell, nsIObserver)
class WakeLockListener final : public nsIDOMMozWakeLockListener {
private:
~WakeLockListener() {}
public:
NS_DECL_ISUPPORTS;
nsresult Callback(const nsAString& topic, const nsAString& state) override {
java::GeckoAppShell::NotifyWakeLockChanged(topic, state);
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(WakeLockListener, nsIDOMMozWakeLockListener)
nsCOMPtr<nsIPowerManagerService> sPowerManagerService = nullptr;
StaticRefPtr<WakeLockListener> sWakeLockListener;
class GeckoThreadSupport final
: public java::GeckoThread::Natives<GeckoThreadSupport>
{
// When this number goes above 0, the app is paused. When less than or
// equal to zero, the app is resumed.
static int32_t sPauseCount;
public:
static void SpeculativeConnect(jni::String::Param aUriStr)
{
if (!NS_IsMainThread()) {
// We will be on the main thread if the call was queued on the Java
// side during startup. Otherwise, the call was not queued, which
// means Gecko is already sufficiently loaded, and we don't really
// care about speculative connections at this point.
return;
}
nsCOMPtr<nsIIOService> ioServ = do_GetIOService();
nsCOMPtr<nsISpeculativeConnect> specConn = do_QueryInterface(ioServ);
if (!specConn) {
return;
}
nsCOMPtr<nsIURI> uri = nsAppShell::ResolveURI(aUriStr->ToCString());
if (!uri) {
return;
}
specConn->SpeculativeConnect(uri, nullptr);
}
static void WaitOnGecko()
{
struct NoOpEvent : nsAppShell::Event {
void Run() override {}
};
nsAppShell::SyncRunEvent(NoOpEvent());
}
static void OnPause()
{
MOZ_ASSERT(NS_IsMainThread());
sPauseCount++;
// If sPauseCount is now 1, we just crossed the threshold from "resumed"
// "paused". so we should notify observers and so on.
if (sPauseCount != 1) {
return;
}
nsCOMPtr<nsIObserverService> 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) {
prefs->SavePrefFile(nullptr);
}
}
static void OnResume()
{
MOZ_ASSERT(NS_IsMainThread());
sPauseCount--;
// If sPauseCount is now 0, we just crossed the threshold from "paused"
// to "resumed", so we should notify observers and so on.
if (sPauseCount != 0) {
return;
}
// 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<nsIObserverService> obsServ =
mozilla::services::GetObserverService();
obsServ->NotifyObservers(nullptr, "application-foreground", nullptr);
}
static void CreateServices(jni::String::Param aCategory, jni::String::Param aData)
{
MOZ_ASSERT(NS_IsMainThread());
nsCString category(aCategory->ToCString());
NS_CreateServicesFromCategory(
category.get(),
nullptr, // aOrigin
category.get(),
aData ? aData->ToString().get() : nullptr);
}
static int64_t RunUiThreadCallback()
{
if (!AndroidBridge::Bridge()) {
return -1;
}
return AndroidBridge::Bridge()->RunDelayedUiThreadTasks();
}
};
int32_t GeckoThreadSupport::sPauseCount;
class GeckoAppShellSupport final
: public java::GeckoAppShell::Natives<GeckoAppShellSupport>
{
public:
static void ReportJavaCrash(const jni::Class::LocalRef& aCls,
jni::Throwable::Param aException,
jni::String::Param aStack)
{
if (!jni::ReportException(aCls.Env(), aException.Get(), aStack.Get())) {
// Only crash below if crash reporter is initialized and annotation
// succeeded. Otherwise try other means of reporting the crash in
// Java.
return;
}
MOZ_CRASH("Uncaught Java exception");
}
static void SyncNotifyObservers(jni::String::Param aTopic,
jni::String::Param aData)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NotifyObservers(aTopic, aData);
}
static void NotifyObservers(jni::String::Param aTopic,
jni::String::Param aData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aTopic);
nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
if (!obsServ) {
return;
}
obsServ->NotifyObservers(nullptr, aTopic->ToCString().get(),
aData ? aData->ToString().get() : nullptr);
}
static void OnSensorChanged(int32_t aType, float aX, float aY, float aZ,
float aW, int32_t aAccuracy, int64_t aTime)
{
AutoTArray<float, 4> values;
switch (aType) {
// 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.0f - aX);
values.AppendElement(-aY);
values.AppendElement(-aZ);
break;
case hal::SENSOR_LINEAR_ACCELERATION:
case hal::SENSOR_ACCELERATION:
case hal::SENSOR_GYROSCOPE:
case hal::SENSOR_PROXIMITY:
values.AppendElement(aX);
values.AppendElement(aY);
values.AppendElement(aZ);
break;
case hal::SENSOR_LIGHT:
values.AppendElement(aX);
break;
case hal::SENSOR_ROTATION_VECTOR:
case hal::SENSOR_GAME_ROTATION_VECTOR:
values.AppendElement(aX);
values.AppendElement(aY);
values.AppendElement(aZ);
values.AppendElement(aW);
break;
default:
__android_log_print(ANDROID_LOG_ERROR, "Gecko",
"Unknown sensor type %d", aType);
}
hal::SensorData sdata(hal::SensorType(aType), aTime, values,
hal::SensorAccuracyType(aAccuracy));
hal::NotifySensorChange(sdata);
}
static void OnLocationChanged(double aLatitude, double aLongitude,
double aAltitude, float aAccuracy,
float aBearing, float aSpeed, int64_t aTime)
{
if (!gLocationCallback) {
return;
}
RefPtr<nsIDOMGeoPosition> geoPosition(
new nsGeoPosition(aLatitude, aLongitude, aAltitude, aAccuracy,
aAccuracy, aBearing, aSpeed, aTime));
gLocationCallback->Update(geoPosition);
}
static void NotifyUriVisited(jni::String::Param aUri)
{
#ifdef MOZ_ANDROID_HISTORY
nsCOMPtr<IHistory> history = services::GetHistoryService();
nsCOMPtr<nsIURI> visitedURI;
if (history &&
NS_SUCCEEDED(NS_NewURI(getter_AddRefs(visitedURI),
aUri->ToString()))) {
history->NotifyVisited(visitedURI);
}
#endif
}
static void NotifyAlertListener(jni::String::Param aName,
jni::String::Param aTopic,
jni::String::Param aCookie)
{
if (!aName || !aTopic || !aCookie) {
return;
}
AndroidAlerts::NotifyListener(
aName->ToString(), aTopic->ToCString().get(),
aCookie->ToString().get());
}
static void OnFullScreenPluginHidden(jni::Object::Param aView)
{
nsPluginInstanceOwner::ExitFullScreen(aView.Get());
}
};
nsAppShell::nsAppShell()
: mSyncRunFinished(*(sAppShellLock = new Mutex("nsAppShell")),
"nsAppShell.SyncRun")
, mSyncRunQuit(false)
{
{
MutexAutoLock lock(*sAppShellLock);
sAppShell = this;
}
if (!XRE_IsParentProcess()) {
return;
}
if (jni::IsAvailable()) {
// Initialize JNI and Set the corresponding state in GeckoThread.
AndroidBridge::ConstructBridge();
GeckoAppShellSupport::Init();
GeckoThreadSupport::Init();
mozilla::GeckoBatteryManager::Init();
mozilla::GeckoNetworkManager::Init();
mozilla::GeckoScreenOrientation::Init();
mozilla::PrefsHelper::Init();
nsWindow::InitNatives();
if (jni::IsFennec()) {
mozilla::ANRReporter::Init();
mozilla::MemoryMonitor::Init();
mozilla::widget::Telemetry::Init();
mozilla::ThumbnailHelper::Init();
}
java::GeckoThread::SetState(java::GeckoThread::State::JNI_READY());
}
sPowerManagerService = do_GetService(POWERMANAGERSERVICE_CONTRACTID);
if (sPowerManagerService) {
sWakeLockListener = new WakeLockListener();
} else {
NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!");
}
}
nsAppShell::~nsAppShell()
{
{
MutexAutoLock lock(*sAppShellLock);
sAppShell = nullptr;
}
while (mEventQueue.Pop(/* mayWait */ false)) {
NS_WARNING("Discarded event on shutdown");
}
if (sPowerManagerService) {
sPowerManagerService->RemoveWakeLockListener(sWakeLockListener);
sPowerManagerService = nullptr;
sWakeLockListener = nullptr;
}
if (jni::IsAvailable()) {
AndroidBridge::DeconstructBridge();
}
}
void
nsAppShell::NotifyNativeEvent()
{
mEventQueue.Signal();
}
#define PREFNAME_COALESCE_TOUCHES "dom.event.touch.coalescing.enabled"
static const char* kObservedPrefs[] = {
PREFNAME_COALESCE_TOUCHES,
nullptr
};
nsresult
nsAppShell::Init()
{
nsresult rv = nsBaseAppShell::Init();
nsCOMPtr<nsIObserverService> obsServ =
mozilla::services::GetObserverService();
if (obsServ) {
obsServ->AddObserver(this, "browser-delayed-startup-finished", false);
obsServ->AddObserver(this, "profile-after-change", false);
obsServ->AddObserver(this, "chrome-document-loaded", false);
obsServ->AddObserver(this, "quit-application-granted", false);
obsServ->AddObserver(this, "xpcom-shutdown", 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)
{
bool removeObserver = false;
if (!strcmp(aTopic, "xpcom-shutdown")) {
{
// Release any thread waiting for a sync call to finish.
mozilla::MutexAutoLock shellLock(*sAppShellLock);
mSyncRunQuit = true;
mSyncRunFinished.NotifyAll();
}
// 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");
} else if (!strcmp(aTopic, "profile-after-change")) {
if (jni::IsAvailable()) {
// See if we want to force 16-bit color before doing anything
if (Preferences::GetBool("gfx.android.rgb16.force", false)) {
java::GeckoAppShell::SetScreenDepthOverride(16);
}
java::GeckoThread::SetState(
java::GeckoThread::State::PROFILE_READY());
// Gecko on Android follows the Android app model where it never
// stops until it is killed by the system or told explicitly to
// quit. Therefore, we should *not* exit Gecko when there is no
// window or the last window is closed. nsIAppStartup::Quit will
// still force Gecko to exit.
nsCOMPtr<nsIAppStartup> appStartup =
do_GetService(NS_APPSTARTUP_CONTRACTID);
if (appStartup) {
appStartup->EnterLastWindowClosingSurvivalArea();
}
}
removeObserver = true;
} else if (!strcmp(aTopic, "chrome-document-loaded")) {
if (jni::IsAvailable()) {
// Our first window has loaded, assume any JS initialization has run.
java::GeckoThread::CheckAndSetState(
java::GeckoThread::State::PROFILE_READY(),
java::GeckoThread::State::RUNNING());
}
removeObserver = true;
} else if (!strcmp(aTopic, "quit-application-granted")) {
if (jni::IsAvailable()) {
java::GeckoThread::SetState(
java::GeckoThread::State::EXITING());
// We are told explicitly to quit, perhaps due to
// nsIAppStartup::Quit being called. We should release our hold on
// nsIAppStartup and let it continue to quit.
nsCOMPtr<nsIAppStartup> appStartup =
do_GetService(NS_APPSTARTUP_CONTRACTID);
if (appStartup) {
appStartup->ExitLastWindowClosingSurvivalArea();
}
}
removeObserver = true;
} else if (!strcmp(aTopic, "nsPref:changed")) {
if (jni::IsAvailable()) {
mozilla::PrefsHelper::OnPrefChange(aData);
}
}
if (removeObserver) {
nsCOMPtr<nsIObserverService> obsServ =
mozilla::services::GetObserverService();
if (obsServ) {
obsServ->RemoveObserver(this, aTopic);
}
}
return NS_OK;
}
bool
nsAppShell::ProcessNextNativeEvent(bool mayWait)
{
EVLOG("nsAppShell::ProcessNextNativeEvent %d", mayWait);
PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent",
js::ProfileEntry::Category::EVENTS);
mozilla::UniquePtr<Event> curEvent;
{
curEvent = mEventQueue.Pop(/* mayWait */ false);
if (!curEvent && mayWait) {
// This processes messages in the Android Looper. Note that we only
// get here if the normal Gecko event loop has been awoken
// (bug 750713). Looper messages effectively have the lowest
// priority because we only process them before we're about to
// wait for new events.
if (jni::IsAvailable() &&
AndroidBridge::Bridge()->PumpMessageLoop()) {
return true;
}
PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait",
js::ProfileEntry::Category::EVENTS);
mozilla::HangMonitor::Suspend();
curEvent = mEventQueue.Pop(/* mayWait */ true);
}
}
if (!curEvent)
return false;
mozilla::HangMonitor::NotifyActivity(curEvent->ActivityType());
curEvent->Run();
return true;
}
void
nsAppShell::SyncRunEvent(Event&& event,
UniquePtr<Event>(*eventFactory)(UniquePtr<Event>&&))
{
// Perform the call on the Gecko thread in a separate lambda, and wait
// on the monitor on the current thread.
MOZ_ASSERT(!NS_IsMainThread());
// This is the lock to check that app shell is still alive,
// and to wait on for the sync call to complete.
mozilla::MutexAutoLock shellLock(*sAppShellLock);
nsAppShell* const appShell = sAppShell;
if (MOZ_UNLIKELY(!appShell)) {
// Post-shutdown.
return;
}
bool finished = false;
auto runAndNotify = [&event, &finished] {
mozilla::MutexAutoLock shellLock(*sAppShellLock);
nsAppShell* const appShell = sAppShell;
if (MOZ_UNLIKELY(!appShell || appShell->mSyncRunQuit)) {
return;
}
event.Run();
finished = true;
appShell->mSyncRunFinished.NotifyAll();
};
UniquePtr<Event> runAndNotifyEvent = mozilla::MakeUnique<
LambdaEvent<decltype(runAndNotify)>>(mozilla::Move(runAndNotify));
if (eventFactory) {
runAndNotifyEvent = (*eventFactory)(mozilla::Move(runAndNotifyEvent));
}
appShell->mEventQueue.Post(mozilla::Move(runAndNotifyEvent));
while (!finished && MOZ_LIKELY(sAppShell && !sAppShell->mSyncRunQuit)) {
appShell->mSyncRunFinished.Wait();
}
}
already_AddRefed<nsIURI>
nsAppShell::ResolveURI(const nsCString& aUriStr)
{
nsCOMPtr<nsIIOService> ioServ = do_GetIOService();
nsCOMPtr<nsIURI> uri;
if (NS_SUCCEEDED(ioServ->NewURI(aUriStr, nullptr,
nullptr, getter_AddRefs(uri)))) {
return uri.forget();
}
nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
if (fixup && NS_SUCCEEDED(
fixup->CreateFixupURI(aUriStr, 0, nullptr, getter_AddRefs(uri)))) {
return uri.forget();
}
return nullptr;
}
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()
{
nsAppShell* const appShell = nsAppShell::Get();
if (!appShell) {
return false;
}
return appShell->ProcessNextNativeEvent(true) ? true : false;
}
void NotifyEvent()
{
nsAppShell* const appShell = nsAppShell::Get();
if (!appShell) {
return;
}
appShell->NotifyNativeEvent();
}
}

View file

@ -1,223 +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/HangMonitor.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Monitor.h"
#include "mozilla/Move.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/jni/Natives.h"
#include "nsBaseAppShell.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsInterfaceHashtable.h"
#include "nsIAndroidBridge.h"
namespace mozilla {
bool ProcessNextEvent();
void NotifyEvent();
}
class nsWindow;
class nsAppShell :
public nsBaseAppShell
{
public:
struct Event : mozilla::LinkedListElement<Event>
{
typedef mozilla::HangMonitor::ActivityType Type;
bool HasSameTypeAs(const Event* other) const
{
// Compare vtable addresses to determine same type.
return *reinterpret_cast<const uintptr_t*>(this)
== *reinterpret_cast<const uintptr_t*>(other);
}
virtual ~Event() {}
virtual void Run() = 0;
virtual void PostTo(mozilla::LinkedList<Event>& queue)
{
queue.insertBack(this);
}
virtual Type ActivityType() const
{
return Type::kGeneralActivity;
}
};
template<typename T>
class LambdaEvent : public Event
{
protected:
T lambda;
public:
LambdaEvent(T&& l) : lambda(mozilla::Move(l)) {}
void Run() override { return lambda(); }
};
class ProxyEvent : public Event
{
protected:
mozilla::UniquePtr<Event> baseEvent;
public:
ProxyEvent(mozilla::UniquePtr<Event>&& event)
: baseEvent(mozilla::Move(event))
{}
void PostTo(mozilla::LinkedList<Event>& queue) override
{
baseEvent->PostTo(queue);
}
void Run() override
{
baseEvent->Run();
}
};
static nsAppShell* Get()
{
MOZ_ASSERT(NS_IsMainThread());
return sAppShell;
}
nsAppShell();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
nsresult Init();
void NotifyNativeEvent();
bool ProcessNextNativeEvent(bool mayWait) override;
// Post a subclass of Event.
// e.g. PostEvent(mozilla::MakeUnique<MyEvent>());
template<typename T, typename D>
static void PostEvent(mozilla::UniquePtr<T, D>&& event)
{
mozilla::MutexAutoLock lock(*sAppShellLock);
if (!sAppShell) {
return;
}
sAppShell->mEventQueue.Post(mozilla::Move(event));
}
// Post a event that will call a lambda
// e.g. PostEvent([=] { /* do something */ });
template<typename T>
static void PostEvent(T&& lambda)
{
mozilla::MutexAutoLock lock(*sAppShellLock);
if (!sAppShell) {
return;
}
sAppShell->mEventQueue.Post(mozilla::MakeUnique<LambdaEvent<T>>(
mozilla::Move(lambda)));
}
// Post a event and wait for it to finish running on the Gecko thread.
static void SyncRunEvent(Event&& event,
mozilla::UniquePtr<Event>(*eventFactory)(
mozilla::UniquePtr<Event>&&) = nullptr);
static already_AddRefed<nsIURI> ResolveURI(const nsCString& aUriStr);
void SetBrowserApp(nsIAndroidBrowserApp* aBrowserApp) {
mBrowserApp = aBrowserApp;
}
nsIAndroidBrowserApp* GetBrowserApp() {
return mBrowserApp;
}
protected:
static nsAppShell* sAppShell;
static mozilla::StaticAutoPtr<mozilla::Mutex> sAppShellLock;
virtual ~nsAppShell();
nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver);
class NativeCallbackEvent : public Event
{
// Capturing the nsAppShell instance is safe because if the app
// shell is detroyed, this lambda will not be called either.
nsAppShell* const appShell;
public:
NativeCallbackEvent(nsAppShell* as) : appShell(as) {}
void Run() override { appShell->NativeEventCallback(); }
};
void ScheduleNativeEventCallback() override
{
mEventQueue.Post(mozilla::MakeUnique<NativeCallbackEvent>(this));
}
class Queue
{
private:
mozilla::Monitor mMonitor;
mozilla::LinkedList<Event> mQueue;
public:
Queue() : mMonitor("nsAppShell.Queue")
{}
void Signal()
{
mozilla::MonitorAutoLock lock(mMonitor);
lock.NotifyAll();
}
void Post(mozilla::UniquePtr<Event>&& event)
{
MOZ_ASSERT(event && !event->isInList());
mozilla::MonitorAutoLock lock(mMonitor);
event->PostTo(mQueue);
if (event->isInList()) {
// Ownership of event object transfers to the queue.
mozilla::Unused << event.release();
}
lock.NotifyAll();
}
mozilla::UniquePtr<Event> Pop(bool mayWait)
{
mozilla::MonitorAutoLock lock(mMonitor);
if (mayWait && mQueue.isEmpty()) {
lock.Wait();
}
// Ownership of event object transfers to the return value.
return mozilla::UniquePtr<Event>(mQueue.popFirst());
}
} mEventQueue;
mozilla::CondVar mSyncRunFinished;
bool mSyncRunQuit;
bool mAllowCoalescingTouches;
nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
nsInterfaceHashtable<nsStringHashKey, nsIObserver> mObserversHash;
};
#endif // nsAppShell_h__

View file

@ -1,123 +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<nsISupports> tmp;
uint32_t len;
nsresult rv = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp),
&len);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
// No support for non-text data
NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
nsAutoString buffer;
supportsString->GetData(buffer);
java::Clipboard::SetText(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<nsISupportsString> 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<nsISupports> 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;
java::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;
for (uint32_t k = 0; k < aLength; k++) {
if (strcmp(aFlavorList[k], kUnicodeMime) == 0) {
*aHasText = java::Clipboard::HasText();
break;
}
}
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;
}

View file

@ -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

View file

@ -1,84 +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 "mozilla/gfx/PrintTargetPDF.h"
#include "mozilla/RefPtr.h"
#include "nsString.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIPrintSettings.h"
#include "nsDirectoryServiceDefs.h"
using namespace mozilla;
using namespace mozilla::gfx;
NS_IMPL_ISUPPORTS(nsDeviceContextSpecAndroid, nsIDeviceContextSpec)
already_AddRefed<PrintTarget>
nsDeviceContextSpecAndroid::MakePrintTarget()
{
nsresult rv =
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mTempFile));
NS_ENSURE_SUCCESS(rv, nullptr);
nsAutoCString filename("tmp-printing.pdf");
mTempFile->AppendNative(filename);
rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0660);
NS_ENSURE_SUCCESS(rv, nullptr);
nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
rv = stream->Init(mTempFile, -1, -1, 0);
NS_ENSURE_SUCCESS(rv, nullptr);
// XXX: what should we do here for size? screen size?
IntSize size(480, 800);
return PrintTargetPDF::CreateOrNull(stream, size);
}
NS_IMETHODIMP
nsDeviceContextSpecAndroid::Init(nsIWidget* aWidget,
nsIPrintSettings* aPS,
bool aIsPrintPreview)
{
mPrintSettings = aPS;
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecAndroid::BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecAndroid::EndDocument()
{
nsXPIDLString targetPath;
nsCOMPtr<nsIFile> 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<nsIFile> 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;
}

View file

@ -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
virtual already_AddRefed<PrintTarget> MakePrintTarget() final;
NS_IMETHOD Init(nsIWidget* aWidget,
nsIPrintSettings* aPS,
bool aIsPrintPreview) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override { return NS_OK; }
NS_IMETHOD EndPage() override { return NS_OK; }
private:
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIFile> mTempFile;
};

View file

@ -1,42 +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"
interface mozIDOMWindowProxy;
[scriptable, uuid(e8420a7b-659b-4325-968b-a114a6a067aa)]
interface nsIBrowserTab : nsISupports {
readonly attribute mozIDOMWindowProxy window;
readonly attribute float scale;
};
[scriptable, uuid(08426a73-e70b-4680-9282-630932e2b2bb)]
interface nsIUITelemetryObserver : nsISupports {
void startSession(in wstring name,
in long long timestamp);
void stopSession(in wstring name,
in wstring reason,
in long long timestamp);
void addEvent(in wstring action,
in wstring method,
in long long timestamp,
in wstring extras);
};
[scriptable, uuid(0370450f-2e9c-4d16-b333-8ca6ce31a5ff)]
interface nsIAndroidBrowserApp : nsISupports {
readonly attribute nsIBrowserTab selectedTab;
nsIBrowserTab getBrowserTab(in int32_t tabId);
nsIUITelemetryObserver getUITelemetryObserver();
};
[scriptable, uuid(1beb70d3-70f3-4742-98cc-a3d301b26c0c)]
interface nsIAndroidBridge : nsISupports
{
[implicit_jscontext] void handleGeckoMessage(in jsval message);
attribute nsIAndroidBrowserApp browserApp;
void contentDocumentChanged(in mozIDOMWindowProxy window);
boolean isContentDocumentDisplayed(in mozIDOMWindowProxy window);
};

View file

@ -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;
}

View file

@ -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) override;
static already_AddRefed<nsIdleServiceAndroid> GetInstance()
{
RefPtr<nsIdleService> idleService = nsIdleService::GetInstance();
if (!idleService) {
idleService = new nsIdleServiceAndroid();
}
return idleService.forget().downcast<nsIdleServiceAndroid>();
}
protected:
nsIdleServiceAndroid() { }
virtual ~nsIdleServiceAndroid() { }
bool UsePollMode() override;
};
#endif // nsIdleServiceAndroid_h__

View file

@ -1,500 +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<uint32_t> 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_IsParentProcess())
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;
case eIntID_ContextMenuOffsetVertical:
case eIntID_ContextMenuOffsetHorizontal:
aResult = 2;
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_IsParentProcess()) {
mShowPassword = java::GeckoAppShell::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;
}

View file

@ -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

View file

@ -1,37 +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(u"PDF printer");
}
};
nsPrintOptionsAndroid::nsPrintOptionsAndroid()
{
}
nsPrintOptionsAndroid::~nsPrintOptionsAndroid()
{
}
nsresult
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;
}

View file

@ -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();
nsresult _CreatePrintSettings(nsIPrintSettings** _retval) override;
};
#endif /* nsPrintOptionsAndroid_h__ */

View file

@ -1,264 +0,0 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=4 expandtab:
* 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 "mozilla/SyncRunnable.h"
#include "nsScreenManagerAndroid.h"
#include "nsServiceManagerUtils.h"
#include "AndroidRect.h"
#include "FennecJNINatives.h"
#include "nsAppShell.h"
#include "nsThreadUtils.h"
#include <android/log.h>
#include <mozilla/jni/Refs.h>
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenManagerAndroid", ## args)
using namespace mozilla;
using namespace mozilla::java;
static uint32_t sScreenId = 0;
const uint32_t PRIMARY_SCREEN_ID = 0;
nsScreenAndroid::nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect)
: mId(sScreenId++)
, mDisplayType(aDisplayType)
, mRect(aRect)
, mDensity(0.0)
{
// ensure that the ID of the primary screen would be PRIMARY_SCREEN_ID.
if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
mId = PRIMARY_SCREEN_ID;
}
}
nsScreenAndroid::~nsScreenAndroid()
{
}
float
nsScreenAndroid::GetDensity() {
if (mDensity != 0.0) {
return mDensity;
}
if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
mDensity = mozilla::jni::IsAvailable() ? GeckoAppShell::GetDensity()
: 1.0; // xpcshell most likely
return mDensity;
}
return 1.0;
}
NS_IMETHODIMP
nsScreenAndroid::GetId(uint32_t *outId)
{
*outId = mId;
return NS_OK;
}
NS_IMETHODIMP
nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
{
if (mDisplayType != DisplayType::DISPLAY_PRIMARY) {
*outLeft = mRect.x;
*outTop = mRect.y;
*outWidth = mRect.width;
*outHeight = mRect.height;
return NS_OK;
}
if (!mozilla::jni::IsAvailable()) {
// xpcshell most likely
*outLeft = *outTop = *outWidth = *outHeight = 0;
return NS_ERROR_FAILURE;
}
java::sdk::Rect::LocalRef rect = java::GeckoAppShell::GetScreenSize();
rect->Left(outLeft);
rect->Top(outTop);
rect->Width(outWidth);
rect->Height(outHeight);
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)
{
if (!mozilla::jni::IsAvailable()) {
// xpcshell most likely
*aPixelDepth = 16;
return NS_ERROR_FAILURE;
}
*aPixelDepth = java::GeckoAppShell::GetScreenDepth();
return NS_OK;
}
NS_IMETHODIMP
nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
{
return GetPixelDepth(aColorDepth);
}
void
nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
{
if (mDisplayType == DisplayType::DISPLAY_PRIMARY &&
mozilla::jni::IsAvailable()) {
java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
}
}
class nsScreenManagerAndroid::ScreenManagerHelperSupport final
: public ScreenManagerHelper::Natives<ScreenManagerHelperSupport>
{
public:
typedef ScreenManagerHelper::Natives<ScreenManagerHelperSupport> Base;
static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) {
int32_t screenId = -1; // return value
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
[&aDisplayType, &aWidth, &aHeight, &aDensity, &screenId] {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIScreenManager> screenMgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
(nsScreenManagerAndroid*) screenMgr.get();
RefPtr<nsScreenAndroid> screen =
screenMgrAndroid->AddScreen(static_cast<DisplayType>(aDisplayType),
nsIntRect(0, 0, aWidth, aHeight));
MOZ_ASSERT(screen);
screen->SetDensity(aDensity);
screenId = static_cast<int32_t>(screen->GetId());
}).take());
return screenId;
}
static void RemoveDisplay(int32_t aScreenId) {
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
[&aScreenId] {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIScreenManager> screenMgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
(nsScreenManagerAndroid*) screenMgr.get();
screenMgrAndroid->RemoveScreen(aScreenId);
}).take());
}
};
NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager)
nsScreenManagerAndroid::nsScreenManagerAndroid()
{
if (mozilla::jni::IsAvailable()) {
ScreenManagerHelperSupport::Base::Init();
}
nsCOMPtr<nsIScreen> screen = AddScreen(DisplayType::DISPLAY_PRIMARY);
MOZ_ASSERT(screen);
}
nsScreenManagerAndroid::~nsScreenManagerAndroid()
{
}
NS_IMETHODIMP
nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen)
{
ScreenForId(PRIMARY_SCREEN_ID, outScreen);
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerAndroid::ScreenForId(uint32_t aId,
nsIScreen **outScreen)
{
for (size_t i = 0; i < mScreens.Length(); ++i) {
if (aId == mScreens[i]->GetId()) {
nsCOMPtr<nsIScreen> screen = (nsIScreen*) mScreens[i];
screen.forget(outScreen);
return NS_OK;
}
}
*outScreen = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerAndroid::ScreenForRect(int32_t inLeft,
int32_t inTop,
int32_t inWidth,
int32_t inHeight,
nsIScreen **outScreen)
{
// Not support to query non-primary screen with rect.
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
nsScreenManagerAndroid::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
{
// Not support to query non-primary screen with native widget.
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
nsScreenManagerAndroid::GetNumberOfScreens(uint32_t *aNumberOfScreens)
{
*aNumberOfScreens = mScreens.Length();
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerAndroid::GetSystemDefaultScale(float *aDefaultScale)
{
*aDefaultScale = 1.0f;
return NS_OK;
}
already_AddRefed<nsScreenAndroid>
nsScreenManagerAndroid::AddScreen(DisplayType aDisplayType, nsIntRect aRect)
{
ALOG("nsScreenManagerAndroid: add %s screen",
(aDisplayType == DisplayType::DISPLAY_PRIMARY ? "PRIMARY" :
(aDisplayType == DisplayType::DISPLAY_EXTERNAL ? "EXTERNAL" :
"VIRTUAL")));
RefPtr<nsScreenAndroid> screen = new nsScreenAndroid(aDisplayType, aRect);
mScreens.AppendElement(screen);
return screen.forget();
}
void
nsScreenManagerAndroid::RemoveScreen(uint32_t aScreenId)
{
for (size_t i = 0; i < mScreens.Length(); i++) {
if (aScreenId == mScreens[i]->GetId()) {
mScreens.RemoveElementAt(i);
}
}
}

View file

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: ts=4 sw=4 expandtab:
* 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 "nsRect.h"
#include "mozilla/WidgetUtils.h"
class nsScreenAndroid final : public nsBaseScreen
{
public:
nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect);
~nsScreenAndroid();
NS_IMETHOD GetId(uint32_t* aId) override;
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
uint32_t GetId() const { return mId; };
DisplayType GetDisplayType() const { return mDisplayType; }
void SetDensity(double aDensity) { mDensity = aDensity; }
float GetDensity();
protected:
virtual void ApplyMinimumBrightness(uint32_t aBrightness) override;
private:
uint32_t mId;
DisplayType mDisplayType;
nsIntRect mRect;
float mDensity;
};
class nsScreenManagerAndroid final : public nsIScreenManager
{
private:
~nsScreenManagerAndroid();
public:
class ScreenManagerHelperSupport;
nsScreenManagerAndroid();
NS_DECL_ISUPPORTS
NS_DECL_NSISCREENMANAGER
already_AddRefed<nsScreenAndroid> AddScreen(DisplayType aDisplayType,
nsIntRect aRect = nsIntRect());
void RemoveScreen(uint32_t aScreenId);
protected:
nsTArray<RefPtr<nsScreenAndroid>> mScreens;
};
#endif /* nsScreenManagerAndroid_h___ */

View file

@ -1,132 +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 "nsXULAppAPI.h"
#include "nsAndroidProtocolHandler.h"
#include "nsToolkitCompsCID.h"
#include "AndroidAlerts.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(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_GENERIC_FACTORY_CONSTRUCTOR(AndroidAlerts)
}
}
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_GFXINFO_CID);
NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID);
NS_DEFINE_NAMED_CID(NS_ANDROIDPROTOCOLHANDLER_CID);
NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_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_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor },
{ &kNS_ANDROIDBRIDGE_CID, false, nullptr, nsAndroidBridgeConstructor },
{ &kNS_ANDROIDPROTOCOLHANDLER_CID, false, nullptr, nsAndroidProtocolHandlerConstructor },
{ &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, mozilla::widget::AndroidAlertsConstructor },
{ 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/gfx/info;1", &kNS_GFXINFO_CID },
{ "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "android", &kNS_ANDROIDPROTOCOLHANDLER_CID },
{ NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_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;

File diff suppressed because it is too large Load diff

View file

@ -1,289 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* vim: set sw=4 ts=4 expandtab:
* 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/Mutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/TextRange.h"
#include "mozilla/UniquePtr.h"
struct ANPEvent;
namespace mozilla {
class TextComposition;
class WidgetTouchEvent;
namespace layers {
class CompositorBridgeParent;
class CompositorBridgeChild;
class LayerManager;
class APZCTreeManager;
}
}
class nsWindow : public nsBaseWidget
{
private:
virtual ~nsWindow();
public:
using nsBaseWidget::GetLayerManager;
nsWindow();
NS_DECL_ISUPPORTS_INHERITED
static void InitNatives();
void SetScreenId(uint32_t aScreenId) { mScreenId = aScreenId; }
private:
uint32_t mScreenId;
// An Event subclass that guards against stale events.
template<typename Lambda,
bool IsStatic = Lambda::isStatic,
typename InstanceType = typename Lambda::ThisArgType,
class Impl = typename Lambda::TargetClass>
class WindowEvent;
// Smart pointer for holding a pointer back to the nsWindow inside a native
// object class. The nsWindow pointer is automatically cleared when the
// nsWindow is destroyed, and a WindowPtr<Impl>::Locked class is provided
// for thread-safe access to the nsWindow pointer off of the Gecko thread.
template<class Impl> class WindowPtr;
// Smart pointer for holding a pointer to a native object class. The
// pointer is automatically cleared when the object is destroyed.
template<class Impl>
class NativePtr final
{
friend WindowPtr<Impl>;
static const char sName[];
WindowPtr<Impl>* mPtr;
Impl* mImpl;
mozilla::Mutex mImplLock;
public:
class Locked;
NativePtr() : mPtr(nullptr), mImpl(nullptr), mImplLock(sName) {}
~NativePtr() { MOZ_ASSERT(!mPtr); }
operator Impl*() const
{
MOZ_ASSERT(NS_IsMainThread());
return mImpl;
}
Impl* operator->() const { return operator Impl*(); }
template<class Instance, typename... Args>
void Attach(Instance aInstance, nsWindow* aWindow, Args&&... aArgs);
void Detach();
};
class LayerViewSupport;
// Object that implements native LayerView calls.
// Owned by the Java LayerView instance.
NativePtr<LayerViewSupport> mLayerViewSupport;
class NPZCSupport;
// Object that implements native NativePanZoomController calls.
// Owned by the Java NativePanZoomController instance.
NativePtr<NPZCSupport> mNPZCSupport;
class GeckoViewSupport;
// Object that implements native GeckoView calls and associated states.
// nullptr for nsWindows that were not opened from GeckoView.
// Because other objects get destroyed in the mGeckOViewSupport destructor,
// keep it last in the list, so its destructor is called first.
mozilla::UniquePtr<GeckoViewSupport> mGeckoViewSupport;
// Class that implements native PresentationMediaPlayerManager calls.
class PMPMSupport;
public:
static nsWindow* TopWindow();
void OnSizeChanged(const mozilla::gfx::IntSize& aSize);
void InitEvent(mozilla::WidgetGUIEvent& event,
LayoutDeviceIntPoint* aPoint = 0);
void UpdateOverscrollVelocity(const float aX, const float aY);
void UpdateOverscrollOffset(const float aX, const float aY);
void SetScrollingRootContent(const bool isRootContent);
//
// nsIWidget
//
using nsBaseWidget::Create; // for Create signature not overridden here
virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect,
nsWidgetInitData* aInitData) override;
virtual void Destroy() override;
NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&) override;
NS_IMETHOD SetParent(nsIWidget* aNewParent) override;
virtual nsIWidget *GetParent(void) override;
virtual float GetDPI() override;
virtual double GetDefaultScaleInternal() override;
NS_IMETHOD Show(bool aState) override;
virtual bool IsVisible() const override;
virtual void ConstrainPosition(bool aAllowSlop,
int32_t *aX,
int32_t *aY) override;
NS_IMETHOD Move(double aX,
double aY) override;
NS_IMETHOD Resize(double aWidth,
double aHeight,
bool aRepaint) override;
NS_IMETHOD Resize(double aX,
double aY,
double aWidth,
double aHeight,
bool aRepaint) override;
void SetZIndex(int32_t aZIndex) override;
virtual void SetSizeMode(nsSizeMode aMode) override;
NS_IMETHOD Enable(bool aState) override;
virtual bool IsEnabled() const override;
NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override;
NS_IMETHOD SetFocus(bool aRaise = false) override;
virtual LayoutDeviceIntRect GetScreenBounds() override;
virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus) override;
nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent);
virtual already_AddRefed<nsIScreen> GetWidgetScreen() override;
virtual nsresult MakeFullScreen(bool aFullScreen,
nsIScreen* aTargetScreen = nullptr)
override;
NS_IMETHOD SetCursor(nsCursor aCursor) override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD SetCursor(imgIContainer* aCursor,
uint32_t aHotspotX,
uint32_t aHotspotY) override { 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) override { return NS_ERROR_NOT_IMPLEMENTED; }
void* GetNativeData(uint32_t aDataType) override;
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
NS_IMETHOD SetTitle(const nsAString& aTitle) override { return NS_OK; }
NS_IMETHOD SetIcon(const nsAString& aIconSpec) override { return NS_OK; }
NS_IMETHOD GetAttention(int32_t aCycleCount) override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
int32_t aHorizontal,
int32_t aVertical) override
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) override;
NS_IMETHOD_(InputContext) GetInputContext() override;
virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
void SetSelectionDragState(bool aState);
LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
virtual bool NeedsPaint() override;
virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
virtual void DrawWindowUnderlay(mozilla::widget::WidgetRenderingContext* aContext,
LayoutDeviceIntRect aRect) override;
virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aContext,
LayoutDeviceIntRect aRect) override;
virtual bool WidgetPaintsBackground() override;
virtual uint32_t GetMaxTouchPoints() const override;
void UpdateZoomConstraints(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
TouchPointerState aPointerState,
LayoutDeviceIntPoint aPoint,
double aPointerPressure,
uint32_t aPointerOrientation,
nsIObserver* aObserver) override;
nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
uint32_t aModifierFlags,
nsIObserver* aObserver) override;
nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
nsIObserver* aObserver) override;
CompositorBridgeParent* GetCompositorBridgeParent() const;
mozilla::jni::DependentRef<mozilla::java::GeckoLayerClient> GetLayerClient();
protected:
void BringToFront();
nsWindow *FindTopLevel();
bool IsTopLevel();
RefPtr<mozilla::TextComposition> GetIMEComposition();
enum RemoveIMECompositionFlag {
CANCEL_IME_COMPOSITION,
COMMIT_IME_COMPOSITION
};
void RemoveIMEComposition(RemoveIMECompositionFlag aFlag = COMMIT_IME_COMPOSITION);
void ConfigureAPZControllerThread() override;
void DispatchHitTest(const mozilla::WidgetTouchEvent& aEvent);
already_AddRefed<GeckoContentController> 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<nsWindow*> mChildren;
nsWindow* mParent;
double mStartDist;
double mLastDist;
nsCOMPtr<nsIIdleServiceInternal> mIdleService;
bool mAwaitingFullScreen;
bool mIsFullScreen;
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) override;
bool UseExternalCompositingSurface() const override {
return true;
}
static void DumpWindows();
static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0);
static void LogWindow(nsWindow *win, int index, int indent);
private:
void CreateLayerManager(int aCompositorWidth, int aCompositorHeight);
void RedrawAll();
mozilla::java::LayerRenderer::Frame::GlobalRef mLayerRendererFrame;
};
#endif /* NSWINDOW_H_ */

View file

@ -6,9 +6,10 @@
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
if toolkit in ('cocoa', 'android', 'uikit'):
if toolkit in ('cocoa', 'uikit'):
DIRS += [toolkit]
if toolkit in ('android', 'gtk2', 'gtk3'):
if toolkit in ('gtk2', 'gtk3'):
EXPORTS += ['nsIPrintDialogService.h']
if toolkit == 'windows':
@ -41,8 +42,6 @@ elif toolkit == 'cocoa':
'nsIPrintDialogService.h',
]
TEST_DIRS += ['tests']
# Don't build the DSO under the 'build' directory as windows does.
#
# The DSOs get built in the toolkit dir itself. Do this so that
@ -221,20 +220,14 @@ if toolkit in ('cocoa', 'windows'):
'nsBaseClipboard.cpp',
]
if toolkit in {'gtk2', 'gtk3', 'cocoa', 'windows',
'android', 'uikit'}:
UNIFIED_SOURCES += [
'nsBaseFilePicker.cpp',
]
if toolkit in {'gtk2', 'gtk3', 'cocoa', 'windows', 'uikit'}:
UNIFIED_SOURCES += ['nsBaseFilePicker.cpp']
if toolkit in ('gtk2', 'gtk3', 'windows', 'cocoa'):
UNIFIED_SOURCES += [
'nsNativeTheme.cpp',
]
UNIFIED_SOURCES += ['nsNativeTheme.cpp']
if toolkit == 'gtk3':
XPIDL_SOURCES += [
'nsIApplicationChooser.idl',
]
XPIDL_SOURCES += ['nsIApplicationChooser.idl']
DEFINES['MOZ_CROSS_PROCESS_IME'] = True

View file

@ -134,11 +134,6 @@ typedef void* nsNativeWidget;
#define NS_NATIVE_COMPOSITOR_DISPLAY 105
#endif // MOZ_X11
#endif
#ifdef MOZ_WIDGET_ANDROID
#define NS_JAVA_SURFACE 100
#define NS_PRESENTATION_WINDOW 101
#define NS_PRESENTATION_SURFACE 102
#endif
#define NS_IWIDGET_IID \
{ 0x06396bf6, 0x2dd8, 0x45e5, \

View file

@ -21,10 +21,6 @@
#include "mozilla/Telemetry.h"
#include <algorithm>
#ifdef MOZ_WIDGET_ANDROID
#include <android/log.h>
#endif
using namespace mozilla;
// interval in milliseconds between internal idle time requests.
@ -53,7 +49,6 @@ using namespace mozilla;
static PRLogModuleInfo *sLog = nullptr;
#define LOG_TAG "GeckoIdleService"
#define LOG_LEVEL ANDROID_LOG_DEBUG
// Use this to find previously added observers in our array:
class IdleListenerComparator
@ -98,10 +93,6 @@ nsIdleServiceDaily::Observe(nsISupports *,
MOZ_LOG(sLog, LogLevel::Debug,
("nsIdleServiceDaily: Notifying idle-daily observers"));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Notifying idle-daily observers");
#endif
// Send the idle-daily observer event
nsCOMPtr<nsIObserverService> observerService =
@ -134,10 +125,6 @@ nsIdleServiceDaily::Observe(nsISupports *,
MOZ_LOG(sLog, LogLevel::Debug,
("nsIdleServiceDaily: Storing last idle time as %d sec.", nowSec));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Storing last idle time as %d", nowSec);
#endif
// Note the moment we expect to get the next timer callback
mExpectedTriggerTime = PR_Now() + ((PRTime)SECONDS_PER_DAY *
@ -202,10 +189,6 @@ nsIdleServiceDaily::Init()
} else {
MOZ_LOG(sLog, LogLevel::Debug,
("nsIdleServiceDaily: Setting timer a day from now"));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Setting timer a day from now");
#endif
// According to our last idle-daily pref, the last idle-daily was fired
// less then 24 hours ago. Set a wait for the amount of time remaining.
@ -255,10 +238,7 @@ nsIdleServiceDaily::StageIdleDaily(bool aHasBeenLongWait)
MOZ_LOG(sLog, LogLevel::Debug,
("nsIdleServiceDaily: Registering Idle observer callback "
"(short wait requested? %d)", aHasBeenLongWait));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Registering Idle observer callback");
#endif
mIdleDailyTriggerWait = (aHasBeenLongWait ?
DAILY_SHORTENED_IDLE_SERVICE_SEC :
DAILY_SIGNIFICANT_IDLE_SERVICE_SEC);
@ -271,15 +251,10 @@ nsIdleServiceDaily::DailyCallback(nsITimer* aTimer, void* aClosure)
{
MOZ_LOG(sLog, LogLevel::Debug,
("nsIdleServiceDaily: DailyCallback running"));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"DailyCallback running");
#endif
nsIdleServiceDaily* self = static_cast<nsIdleServiceDaily*>(aClosure);
// Check to be sure the timer didn't fire early. This currently only
// happens on android.
// Check to be sure the timer didn't fire early.
PRTime now = PR_Now();
if (self->mExpectedTriggerTime && now < self->mExpectedTriggerTime) {
// Timer returned early, reschedule to the appropriate time.
@ -290,11 +265,6 @@ nsIdleServiceDaily::DailyCallback(nsITimer* aTimer, void* aClosure)
MOZ_LOG(sLog, LogLevel::Debug, ("nsIdleServiceDaily: DailyCallback resetting timer to %lld msec",
delayTime / PR_USEC_PER_MSEC));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"DailyCallback resetting timer to %lld msec",
delayTime / PR_USEC_PER_MSEC);
#endif
(void)self->mTimer->InitWithFuncCallback(DailyCallback,
self,
@ -438,11 +408,6 @@ nsIdleService::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Register idle observer %p for %d seconds",
aObserver, aIdleTimeInS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Register idle observer %p for %d seconds",
aObserver, aIdleTimeInS);
#endif
// Put the time + observer in a struct we can keep:
IdleListener listener(aObserver, aIdleTimeInS);
@ -466,11 +431,6 @@ nsIdleService::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Register: adjusting next switch from %d to %d seconds",
mDeltaToNextIdleSwitchInS, aIdleTimeInS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Register: adjusting next switch from %d to %d seconds",
mDeltaToNextIdleSwitchInS, aIdleTimeInS);
#endif
mDeltaToNextIdleSwitchInS = aIdleTimeInS;
}
@ -508,11 +468,7 @@ nsIdleService::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aTimeInS)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Remove observer %p (%d seconds), %d remain idle",
aObserver, aTimeInS, mIdleObserverCount));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Remove observer %p (%d seconds), %d remain idle",
aObserver, aTimeInS, mIdleObserverCount);
#endif
return NS_OK;
}
@ -520,11 +476,7 @@ nsIdleService::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aTimeInS)
MOZ_LOG(sLog, LogLevel::Warning,
("idleService: Failed to remove idle observer %p (%d seconds)",
aObserver, aTimeInS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Failed to remove idle observer %p (%d seconds)",
aObserver, aTimeInS);
#endif
return NS_ERROR_FAILURE;
}
@ -591,11 +543,7 @@ nsIdleService::ResetIdleTimeOut(uint32_t idleDeltaInMS)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Reset idle timeout: tell observer %p user is back",
notifyList[numberOfPendingNotifications]));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Reset idle timeout: tell observer %p user is back",
notifyList[numberOfPendingNotifications]);
#endif
notifyList[numberOfPendingNotifications]->Observe(this,
OBSERVER_TOPIC_ACTIVE,
timeStr.get());
@ -627,11 +575,6 @@ nsIdleService::GetIdleTime(uint32_t* idleTime)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Get idle time: time since reset %u msec",
timeSinceResetInMS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Get idle time: time since reset %u msec",
timeSinceResetInMS);
#endif
// If we did't get pulled data, return the time since last idle reset.
if (!polledIdleTimeIsValid) {
@ -682,21 +625,13 @@ nsIdleService::IdleTimerCallback(void)
if (NS_FAILED(GetIdleTime(&currentIdleTimeInMS))) {
MOZ_LOG(sLog, LogLevel::Info,
("idleService: Idle timer callback: failed to get idle time"));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Idle timer callback: failed to get idle time");
#endif
return;
}
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: Idle timer callback: current idle time %u msec",
currentIdleTimeInMS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Idle timer callback: current idle time %u msec",
currentIdleTimeInMS);
#endif
// Check if we have had some user interaction we didn't handle previously
// we do the calculation in ms to lessen the chance for rounding errors to
@ -770,11 +705,7 @@ nsIdleService::IdleTimerCallback(void)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: **** Idle timer callback: tell observer %p user is idle",
notifyList[numberOfPendingNotifications]));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"Idle timer callback: tell observer %p user is idle",
notifyList[numberOfPendingNotifications]);
#endif
notifyList[numberOfPendingNotifications]->Observe(this,
OBSERVER_TOPIC_IDLE,
timeStr.get());
@ -790,12 +721,6 @@ nsIdleService::SetTimerExpiryIfBefore(TimeStamp aNextTimeout)
("idleService: SetTimerExpiryIfBefore: next timeout %0.f msec from now",
nextTimeoutDuration.ToMilliseconds()));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"SetTimerExpiryIfBefore: next timeout %0.f msec from now",
nextTimeoutDuration.ToMilliseconds());
#endif
// Bail if we don't have a timer service.
if (!mTimer) {
return;
@ -824,11 +749,6 @@ nsIdleService::SetTimerExpiryIfBefore(TimeStamp aNextTimeout)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: IdleService reset timer expiry to %0.f msec from now",
deltaTime.ToMilliseconds()));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"reset timer expiry to %0.f msec from now",
deltaTime.ToMilliseconds());
#endif
// Start the timer
mTimer->InitWithFuncCallback(StaticIdleTimerCallback,
@ -848,10 +768,7 @@ nsIdleService::ReconfigureTimer(void)
// And bail out.
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: ReconfigureTimer: no idle or waiting observers"));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"ReconfigureTimer: no idle or waiting observers");
#endif
return;
}
@ -870,12 +787,6 @@ nsIdleService::ReconfigureTimer(void)
("idleService: next timeout %0.f msec from now",
nextTimeoutDuration.ToMilliseconds()));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"next timeout %0.f msec from now",
nextTimeoutDuration.ToMilliseconds());
#endif
// Check if we should correct the timeout time because we should poll before.
if ((mIdleObserverCount > 0) && UsePollMode()) {
TimeStamp pollTimeout =
@ -885,11 +796,7 @@ nsIdleService::ReconfigureTimer(void)
MOZ_LOG(sLog, LogLevel::Debug,
("idleService: idle observers, reducing timeout to %lu msec from now",
MIN_IDLE_POLL_INTERVAL_MSEC));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(LOG_LEVEL, LOG_TAG,
"idle observers, reducing timeout to %lu msec from now",
MIN_IDLE_POLL_INTERVAL_MSEC);
#endif
nextTimeoutAt = pollTimeout;
}
}

View file

@ -1,503 +0,0 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "TestHarness.h"
#include "nsIAppShell.h"
#include "nsIAppShellService.h"
#include "nsIDocument.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMWindow.h"
#include "nsIDOMWindowUtils.h"
#include "nsIInterfaceRequestor.h"
#include "nsIRunnable.h"
#include "nsIURI.h"
#include "nsIWebBrowserChrome.h"
#include "nsIXULWindow.h"
#include "nsAppShellCID.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "mozilla/Attributes.h"
#ifdef XP_WIN
#include <windows.h>
#endif
using namespace mozilla;
typedef void (*TestFunc)(nsIAppShell*);
bool gStableStateEventHasRun = false;
class ExitAppShellRunnable : public Runnable
{
nsCOMPtr<nsIAppShell> mAppShell;
public:
explicit ExitAppShellRunnable(nsIAppShell* aAppShell)
: mAppShell(aAppShell)
{ }
NS_IMETHOD
Run() override
{
return mAppShell->Exit();
}
};
class StableStateRunnable : public Runnable
{
public:
NS_IMETHOD
Run() override
{
if (gStableStateEventHasRun) {
fail("StableStateRunnable already ran");
}
gStableStateEventHasRun = true;
return NS_OK;
}
};
class CheckStableStateRunnable : public Runnable
{
bool mShouldHaveRun;
public:
explicit CheckStableStateRunnable(bool aShouldHaveRun)
: mShouldHaveRun(aShouldHaveRun)
{ }
NS_IMETHOD
Run() override
{
if (mShouldHaveRun == gStableStateEventHasRun) {
passed("StableStateRunnable state correct (%s)",
mShouldHaveRun ? "true" : "false");
} else {
fail("StableStateRunnable ran at wrong time");
}
return NS_OK;
}
};
class ScheduleStableStateRunnable : public CheckStableStateRunnable
{
protected:
nsCOMPtr<nsIAppShell> mAppShell;
public:
explicit ScheduleStableStateRunnable(nsIAppShell* aAppShell)
: CheckStableStateRunnable(false), mAppShell(aAppShell)
{ }
NS_IMETHOD
Run() override
{
CheckStableStateRunnable::Run();
nsCOMPtr<nsIRunnable> runnable = new StableStateRunnable();
nsresult rv = mAppShell->RunBeforeNextEvent(runnable);
if (NS_FAILED(rv)) {
fail("RunBeforeNextEvent returned failure code %u", rv);
}
return rv;
}
};
class NextTestRunnable : public Runnable
{
nsCOMPtr<nsIAppShell> mAppShell;
public:
explicit NextTestRunnable(nsIAppShell* aAppShell)
: mAppShell(aAppShell)
{ }
NS_IMETHOD Run();
};
class ScheduleNestedStableStateRunnable : public ScheduleStableStateRunnable
{
public:
explicit ScheduleNestedStableStateRunnable(nsIAppShell* aAppShell)
: ScheduleStableStateRunnable(aAppShell)
{ }
NS_IMETHOD
Run() override
{
ScheduleStableStateRunnable::Run();
nsCOMPtr<nsIRunnable> runnable = new CheckStableStateRunnable(false);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch check runnable");
}
if (NS_FAILED(NS_ProcessPendingEvents(nullptr))) {
fail("Failed to process all pending events");
}
runnable = new CheckStableStateRunnable(true);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch check runnable");
}
runnable = new NextTestRunnable(mAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
}
return NS_OK;
}
};
class EventListener final : public nsIDOMEventListener
{
nsCOMPtr<nsIAppShell> mAppShell;
static nsIDOMWindowUtils* sWindowUtils;
static nsIAppShell* sAppShell;
~EventListener() {}
public:
NS_DECL_ISUPPORTS
explicit EventListener(nsIAppShell* aAppShell)
: mAppShell(aAppShell)
{ }
NS_IMETHOD
HandleEvent(nsIDOMEvent* aEvent) override
{
nsString type;
if (NS_FAILED(aEvent->GetType(type))) {
fail("Failed to get event type");
return NS_ERROR_FAILURE;
}
if (type.EqualsLiteral("load")) {
passed("Got load event");
nsCOMPtr<nsIDOMEventTarget> target;
if (NS_FAILED(aEvent->GetTarget(getter_AddRefs(target)))) {
fail("Failed to get event type");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocument> document = do_QueryInterface(target);
if (!document) {
fail("Failed to QI to nsIDocument!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsPIDOMWindow> window = document->GetWindow();
if (!window) {
fail("Failed to get window from document!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
if (!utils) {
fail("Failed to get DOMWindowUtils!");
return NS_ERROR_FAILURE;
}
if (!ScheduleTimer(utils)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
if (type.EqualsLiteral("keypress")) {
passed("Got keypress event");
nsCOMPtr<nsIRunnable> runnable = new StableStateRunnable();
nsresult rv = mAppShell->RunBeforeNextEvent(runnable);
if (NS_FAILED(rv)) {
fail("RunBeforeNextEvent returned failure code %u", rv);
return NS_ERROR_FAILURE;
}
return NS_OK;
}
fail("Got an unexpected event: %s", NS_ConvertUTF16toUTF8(type).get());
return NS_OK;
}
#ifdef XP_WIN
static VOID CALLBACK
TimerCallback(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
if (sWindowUtils) {
nsCOMPtr<nsIDOMWindowUtils> utils = dont_AddRef(sWindowUtils);
sWindowUtils = nullptr;
if (gStableStateEventHasRun) {
fail("StableStateRunnable ran at wrong time");
} else {
passed("StableStateRunnable state correct (false)");
}
int32_t layout = 0x409; // US
int32_t keyCode = 0x41; // VK_A
NS_NAMED_LITERAL_STRING(a, "a");
if (NS_FAILED(utils->SendNativeKeyEvent(layout, keyCode, 0, a, a, nullptr))) {
fail("Failed to synthesize native event");
}
return;
}
KillTimer(nullptr, idEvent);
nsCOMPtr<nsIAppShell> appShell = dont_AddRef(sAppShell);
if (!gStableStateEventHasRun) {
fail("StableStateRunnable didn't run yet");
} else {
passed("StableStateRunnable state correct (true)");
}
nsCOMPtr<nsIRunnable> runnable = new NextTestRunnable(appShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
}
}
#endif
bool
ScheduleTimer(nsIDOMWindowUtils* aWindowUtils)
{
#ifdef XP_WIN
UINT_PTR timerId = SetTimer(nullptr, 0, 1000, (TIMERPROC)TimerCallback);
if (!timerId) {
fail("SetTimer failed!");
return false;
}
nsCOMPtr<nsIDOMWindowUtils> utils = aWindowUtils;
utils.forget(&sWindowUtils);
nsCOMPtr<nsIAppShell> appShell = mAppShell;
appShell.forget(&sAppShell);
return true;
#else
return false;
#endif
}
};
nsIDOMWindowUtils* EventListener::sWindowUtils = nullptr;
nsIAppShell* EventListener::sAppShell = nullptr;
NS_IMPL_ISUPPORTS(EventListener, nsIDOMEventListener)
already_AddRefed<nsIAppShell>
GetAppShell()
{
static const char* platforms[] = {
"android", "mac", "gtk", "qt", "win"
};
NS_NAMED_LITERAL_CSTRING(contractPrefix, "@mozilla.org/widget/appshell/");
NS_NAMED_LITERAL_CSTRING(contractSuffix, ";1");
for (size_t index = 0; index < ArrayLength(platforms); index++) {
nsAutoCString contractID(contractPrefix);
contractID.AppendASCII(platforms[index]);
contractID.Append(contractSuffix);
nsCOMPtr<nsIAppShell> appShell = do_GetService(contractID.get());
if (appShell) {
return appShell.forget();
}
}
return nullptr;
}
void
Test1(nsIAppShell* aAppShell)
{
// Schedule stable state runnable to be run before next event.
nsCOMPtr<nsIRunnable> runnable = new StableStateRunnable();
if (NS_FAILED(aAppShell->RunBeforeNextEvent(runnable))) {
fail("RunBeforeNextEvent failed");
}
runnable = new CheckStableStateRunnable(true);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch check runnable");
}
runnable = new NextTestRunnable(aAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
}
}
void
Test2(nsIAppShell* aAppShell)
{
// Schedule stable state runnable to be run before next event from another
// runnable.
nsCOMPtr<nsIRunnable> runnable = new ScheduleStableStateRunnable(aAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch schedule runnable");
}
runnable = new CheckStableStateRunnable(true);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch check runnable");
}
runnable = new NextTestRunnable(aAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
}
}
void
Test3(nsIAppShell* aAppShell)
{
// Schedule steadystate runnable to be run before next event with nested loop.
nsCOMPtr<nsIRunnable> runnable =
new ScheduleNestedStableStateRunnable(aAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch schedule runnable");
}
}
bool
Test4Internal(nsIAppShell* aAppShell)
{
#ifndef XP_WIN
// Not sure how to test on other platforms.
return false;
#else
nsCOMPtr<nsIAppShellService> appService =
do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
if (!appService) {
fail("Failed to get appshell service!");
return false;
}
nsCOMPtr<nsIURI> uri;
if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), "about:", nullptr))) {
fail("Failed to create new uri");
return false;
}
uint32_t flags = nsIWebBrowserChrome::CHROME_DEFAULT;
nsCOMPtr<nsIXULWindow> xulWindow;
if (NS_FAILED(appService->CreateTopLevelWindow(nullptr, uri, flags, 100, 100, nullptr,
getter_AddRefs(xulWindow)))) {
fail("Failed to create new window");
return false;
}
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(xulWindow);
if (!window) {
fail("Can't get dom window!");
return false;
}
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(window);
if (!target) {
fail("Can't QI to nsIDOMEventTarget!");
return false;
}
nsCOMPtr<nsIDOMEventListener> listener = new EventListener(aAppShell);
if (NS_FAILED(target->AddEventListener(NS_LITERAL_STRING("keypress"),
listener, false, false)) ||
NS_FAILED(target->AddEventListener(NS_LITERAL_STRING("load"), listener,
false, false))) {
fail("Can't add event listeners!");
return false;
}
return true;
#endif
}
void
Test4(nsIAppShell* aAppShell)
{
if (!Test4Internal(aAppShell)) {
nsCOMPtr<nsIRunnable> runnable = new NextTestRunnable(aAppShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
}
}
}
const TestFunc gTests[] = {
Test1, Test2, Test3, Test4
};
size_t gTestIndex = 0;
NS_IMETHODIMP
NextTestRunnable::Run()
{
if (gTestIndex > 0) {
passed("Finished test %u", gTestIndex);
}
gStableStateEventHasRun = false;
if (gTestIndex < ArrayLength(gTests)) {
gTests[gTestIndex++](mAppShell);
}
else {
nsCOMPtr<nsIRunnable> exitRunnable = new ExitAppShellRunnable(mAppShell);
nsresult rv = NS_DispatchToCurrentThread(exitRunnable);
if (NS_FAILED(rv)) {
fail("Failed to dispatch exit runnable!");
}
}
return NS_OK;
}
int main(int argc, char** argv)
{
ScopedLogging log;
ScopedXPCOM xpcom("TestAppShellSteadyState");
if (!xpcom.failed()) {
nsCOMPtr<nsIAppShell> appShell = GetAppShell();
if (!appShell) {
fail("Couldn't get appshell!");
} else {
nsCOMPtr<nsIRunnable> runnable = new NextTestRunnable(appShell);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
fail("Failed to dispatch next test runnable");
} else if (NS_FAILED(appShell->Run())) {
fail("Failed to run appshell");
}
}
}
return gFailCount != 0;
}

View file

@ -1,155 +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/. */
/* This tests the margin parsing functionality in nsAttrValue.cpp, which
* is accessible via nsContentUtils, and is used in setting chromemargins
* to widget windows. It's located here due to linking issues in the
* content directory.
*/
/* This test no longer compiles now that we've removed nsIContentUtils (bug
* 647273). We need to be internal code in order to include nsContentUtils.h,
* but defining MOZILLA_INTERNAL_API is not enough to make us internal.
*/
#include "TestHarness.h"
#ifndef MOZILLA_INTERNAL_API
// some of the includes make use of internal string types
#define nsAString_h___
#define nsString_h___
#define nsStringFwd_h___
#define nsReadableUtils_h___
class nsACString;
class nsAString;
class nsAFlatString;
class nsAFlatCString;
class nsAdoptingString;
class nsAdoptingCString;
class nsXPIDLString;
template<class T> class nsReadingIterator;
#endif
#include "nscore.h"
#include "nsContentUtils.h"
#ifndef MOZILLA_INTERNAL_API
#undef nsString_h___
#undef nsAString_h___
#undef nsReadableUtils_h___
#endif
struct DATA {
bool shouldfail;
const char* margins;
int top;
int right;
int bottom;
int left;
};
const bool SHOULD_FAIL = true;
const int SHOULD_PASS = false;
const DATA Data[] = {
{ SHOULD_FAIL, "", 1, 2, 3, 4 },
{ SHOULD_FAIL, "1,0,0,0", 1, 2, 3, 4 },
{ SHOULD_FAIL, "1,2,0,0", 1, 2, 3, 4 },
{ SHOULD_FAIL, "1,2,3,0", 1, 2, 3, 4 },
{ SHOULD_FAIL, "4,3,2,1", 1, 2, 3, 4 },
{ SHOULD_FAIL, "azsasdasd", 0, 0, 0, 0 },
{ SHOULD_FAIL, ",azsasdasd", 0, 0, 0, 0 },
{ SHOULD_FAIL, " ", 1, 2, 3, 4 },
{ SHOULD_FAIL, "azsdfsdfsdfsdfsdfsasdasd,asdasdasdasdasdasd,asdadasdasd,asdasdasdasd", 0, 0, 0, 0 },
{ SHOULD_FAIL, "as,as,as,as", 0, 0, 0, 0 },
{ SHOULD_FAIL, "0,0,0", 0, 0, 0, 0 },
{ SHOULD_FAIL, "0,0", 0, 0, 0, 0 },
{ SHOULD_FAIL, "4.6,1,1,1", 0, 0, 0, 0 },
{ SHOULD_FAIL, ",,,,", 0, 0, 0, 0 },
{ SHOULD_FAIL, "1, , , ,", 0, 0, 0, 0 },
{ SHOULD_FAIL, "1, , ,", 0, 0, 0, 0 },
{ SHOULD_FAIL, "@!@%^&^*()", 1, 2, 3, 4 },
{ SHOULD_PASS, "4,3,2,1", 4, 3, 2, 1 },
{ SHOULD_PASS, "-4,-3,-2,-1", -4, -3, -2, -1 },
{ SHOULD_PASS, "10000,3,2,1", 10000, 3, 2, 1 },
{ SHOULD_PASS, "4 , 3 , 2 , 1", 4, 3, 2, 1 },
{ SHOULD_PASS, "4, 3 ,2,1", 4, 3, 2, 1 },
{ SHOULD_FAIL, "4,3,2,10000000000000 --", 4, 3, 2, 10000000000000 },
{ SHOULD_PASS, "4,3,2,1000", 4, 3, 2, 1000 },
{ SHOULD_PASS, "2147483647,3,2,1000", 2147483647, 3, 2, 1000 },
{ SHOULD_PASS, "2147483647,2147483647,2147483647,2147483647", 2147483647, 2147483647, 2147483647, 2147483647 },
{ SHOULD_PASS, "-2147483647,3,2,1000", -2147483647, 3, 2, 1000 },
{ SHOULD_FAIL, "2147483648,3,2,1000", 1, 3, 2, 1000 },
{ 0, nullptr, 0, 0, 0, 0 }
};
void DoAttrValueTest()
{
int idx = -1;
bool didFail = false;
while (Data[++idx].margins) {
nsAutoString str;
str.AssignLiteral(Data[idx].margins);
nsIntMargin values(99,99,99,99);
bool result = nsContentUtils::ParseIntMarginValue(str, values);
// if the parse fails
if (!result) {
if (Data[idx].shouldfail)
continue;
fail(Data[idx].margins);
didFail = true;
printf("*1\n");
continue;
}
if (Data[idx].shouldfail) {
if (Data[idx].top == values.top &&
Data[idx].right == values.right &&
Data[idx].bottom == values.bottom &&
Data[idx].left == values.left) {
// not likely
fail(Data[idx].margins);
didFail = true;
printf("*2\n");
continue;
}
// good failure, parse failed and that's what we expected.
continue;
}
#if 0
printf("%d==%d %d==%d %d==%d %d==%d\n",
Data[idx].top, values.top,
Data[idx].right, values.right,
Data[idx].bottom, values.bottom,
Data[idx].left, values.left);
#endif
if (Data[idx].top == values.top &&
Data[idx].right == values.right &&
Data[idx].bottom == values.bottom &&
Data[idx].left == values.left) {
// good parse results
continue;
}
else {
fail(Data[idx].margins);
didFail = true;
printf("*3\n");
continue;
}
}
if (!didFail)
passed("nsAttrValue margin parsing tests passed.");
}
int main(int argc, char** argv)
{
ScopedXPCOM xpcom("");
if (xpcom.failed())
return 1;
DoAttrValueTest();
return 0;
}

View file

@ -1,50 +0,0 @@
<?xml version="1.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/. -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="bug586713_window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="300"
height="300"
onload="onLoad();"
title="Bug 586713 Test">
<menubar id="nativemenubar">
<menu id="foo" label="Foo">
<menupopup>
<menuitem label="FooItem0"/>
</menupopup>
</menu>
</menubar>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function onTestsFinished() {
window.close();
window.opener.wrappedJSObject.SimpleTest.finish();
}
var fooCallCount = 0;
function foo() {
fooCallCount++;
let instruction = document.createProcessingInstruction("xml-stylesheet", 'href="chrome://foo.css" type="text/css"');
document.insertBefore(instruction, document.documentElement);
if (fooCallCount == 2) {
ok(true, "If we got here we didn't crash, excellent.");
onTestsFinished();
}
}
function onLoad() {
foo();
setTimeout(() => foo(), 0);
}
]]></script>
</window>

View file

@ -1,100 +0,0 @@
[DEFAULT]
skip-if = os == 'android'
support-files =
empty_window.xul
utils.js
[test_bug343416.xul]
skip-if = debug
[test_bug429954.xul]
support-files = window_bug429954.xul
[test_bug444800.xul]
subsuite = clipboard
[test_bug478536.xul]
skip-if = true # Bug 561929
support-files = window_bug478536.xul
[test_bug517396.xul]
[test_bug538242.xul]
support-files = window_bug538242.xul
[test_bug593307.xul]
support-files = window_bug593307_offscreen.xul window_bug593307_centerscreen.xul
[test_bug1151186.html]
skip-if = os == 'linux' && debug #Bug 1176038
[test_keycodes.xul]
[test_wheeltransaction.xul]
support-files = window_wheeltransaction.xul
[test_imestate.html]
support-files = window_imestate_iframes.html
[test_plugin_scroll_consistency.html]
[test_composition_text_querycontent.xul]
support-files = window_composition_text_querycontent.xul
[test_input_events_on_deactive_window.xul]
[test_position_on_resize.xul]
[test_sizemode_events.xul]
[test_taskbar_progress.xul]
skip-if = toolkit != "cocoa" && toolkit != "windows"
[test_bug760802.xul]
[test_clipboard.xul]
subsuite = clipboard
[test_panel_mouse_coords.xul]
skip-if = toolkit == "windows" # bug 1009955
# Cocoa
[test_native_menus.xul]
skip-if = toolkit != "cocoa"
support-files = native_menus_window.xul
[test_native_mouse_mac.xul]
skip-if = toolkit != "cocoa" || os_version == '10.10' # 10.10: bug 1137575
support-files = native_mouse_mac_window.xul
[test_bug413277.html]
skip-if = toolkit != "cocoa"
[test_bug428405.xul]
skip-if = toolkit != "cocoa"
[test_bug466599.xul]
subsuite = clipboard
skip-if = toolkit != "cocoa"
[test_bug485118.xul]
skip-if = toolkit != "cocoa"
[test_bug522217.xul]
tags = fullscreen
skip-if = toolkit != "cocoa"
support-files = window_bug522217.xul
[test_platform_colors.xul]
#skip-if = toolkit != "cocoa"
skip-if = true # Bug 1207190
[test_standalone_native_menu.xul]
skip-if = toolkit != "cocoa"
support-files = standalone_native_menu_window.xul
[test_bug586713.xul]
skip-if = toolkit != "cocoa"
support-files = bug586713_window.xul
[test_key_event_counts.xul]
skip-if = toolkit != "cocoa"
[test_bug596600.xul]
skip-if = toolkit != "cocoa"
[test_bug673301.xul]
subsuite = clipboard
skip-if = toolkit != "cocoa"
[test_secure_input.html]
skip-if = toolkit != "cocoa"
[test_native_key_bindings_mac.html]
skip-if = toolkit != "cocoa"
[test_system_status_bar.xul]
skip-if = toolkit != "cocoa"
# Windows
# taskbar_previews.xul
# window_state_windows.xul
[test_chrome_context_menus_win.xul]
skip-if = toolkit != "windows"
support-files = chrome_context_menus_win.xul
[test_plugin_input_event.html]
skip-if = toolkit != "windows"
[test_mouse_scroll.xul]
skip-if = toolkit != "windows"
support-files = window_mouse_scroll_win.html
# Privacy relevant
[test_bug1123480.xul]
subsuite = clipboard

View file

@ -1,101 +0,0 @@
<?xml version="1.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/. -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="ChromeContextMenuTest"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="300"
height="300"
title="Chrome Context Menu Test w/Plugin Focus">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<popupset>
<menupopup id="testmenu" onpopupshown="menuDisplayed()">
<menuitem label="One"/>
<menuitem label="Two"/>
<menuitem label="Three"/>
</menupopup>
</popupset>
<toolbox>
<toolbar id="nav-toolbar" style="height:30px" context="testmenu">
</toolbar>
</toolbox>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function onTestsFinished() {
window.close();
window.opener.wrappedJSObject.SimpleTest.finish();
}
function openContextMenuFor(element) {
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var tbX = (window.mozInnerScreenX + 10) * utils.screenPixelsPerCSSPixel;
var tbY = (window.mozInnerScreenY + 10) * utils.screenPixelsPerCSSPixel;
// See nsWidnow's SynthesizeNativeMouseEvent & SendInput on msdn
var MOUSEEVENTF_RIGHTDOWN = 0x0008;
var MOUSEEVENTF_RIGHTUP = 0x0010;
utils.sendNativeMouseEvent(tbX, tbY,
MOUSEEVENTF_RIGHTDOWN,
0, element);
utils.sendNativeMouseEvent(tbX, tbY,
MOUSEEVENTF_RIGHTUP,
0, element);
}
var tid = 0;
function onFocus() {
var _delayedOnLoad = function() {
var plugin = document.getElementById("plugin");
var toolbar = document.getElementById("nav-toolbar");
plugin.focus();
tid = setTimeout("menuTimeout()", 5000);
openContextMenuFor(toolbar);
}
setTimeout(_delayedOnLoad, 3000);
}
function menuTimeout() {
ok(false, "Right-click chrome menu did not display with focus on a plugin.");
onTestsFinished();
}
function menuDisplayed() {
clearTimeout(tid);
ok(true, "Right-click chrome menu displayed despite plugin having focus.");
onTestsFinished();
}
window.opener.wrappedJSObject.SimpleTest.waitForFocus(onFocus, window);
]]></script>
<body xmlns="http://www.w3.org/1999/xhtml">
<br/>
<embed id="plugin" type="application/x-test" width="50" height="50"></embed>
</body>
</window>

View file

@ -1,4 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window title="Empty window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>

View file

@ -1,12 +0,0 @@
[DEFAULT]
support-files = utils.js
[test_assign_event_data.html]
subsuite = clipboard
skip-if = toolkit == "cocoa" # Mac: Bug 933303
[test_bug565392.html]
subsuite = clipboard
skip-if = toolkit != "windows" || e10s # Bug 1267406
[test_picker_no_crash.html]
skip-if = toolkit != "windows" || e10s # Bug 1267491
support-files = window_picker_no_crash_child.html

View file

@ -1,15 +0,0 @@
# -*- Mode: python; 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/.
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
MOCHITEST_MANIFESTS += ['mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
# if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
#
# Test disabled because it requires the internal API. Re-enabling this test
# is bug 652123.
# CPP_UNIT_TESTS += ['TestChromeMargin']

View file

@ -1,285 +0,0 @@
<?xml version="1.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/. -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="NativeMenuWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="300"
height="300"
onload="onLoad();"
title="Native Menu Test">
<command id="cmd_FooItem0" oncommand="executedCommandID = 'cmd_FooItem0';"/>
<command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/>
<command id="cmd_BarItem0" oncommand="executedCommandID = 'cmd_BarItem0';"/>
<command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/>
<command id="cmd_NewItem0" oncommand="executedCommandID = 'cmd_NewItem0';"/>
<command id="cmd_NewItem1" oncommand="executedCommandID = 'cmd_NewItem1';"/>
<command id="cmd_NewItem2" oncommand="executedCommandID = 'cmd_NewItem2';"/>
<command id="cmd_NewItem3" oncommand="executedCommandID = 'cmd_NewItem3';"/>
<command id="cmd_NewItem4" oncommand="executedCommandID = 'cmd_NewItem4';"/>
<command id="cmd_NewItem5" oncommand="executedCommandID = 'cmd_NewItem5';"/>
<!-- We do not modify any menus or menu items defined here in testing. These
serve as a baseline structure for us to test after other modifications.
We add children to the menubar defined here and test by modifying those
children. -->
<menubar id="nativemenubar">
<menu id="foo" label="Foo">
<menupopup>
<menuitem label="FooItem0" command="cmd_FooItem0"/>
<menuitem label="FooItem1" command="cmd_FooItem1"/>
<menuseparator/>
<menu label="Bar">
<menupopup>
<menuitem label="BarItem0" command="cmd_BarItem0"/>
<menuitem label="BarItem1" command="cmd_BarItem1"/>
</menupopup>
</menu>
</menupopup>
</menu>
</menubar>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function onTestsFinished() {
window.close();
window.opener.wrappedJSObject.SimpleTest.finish();
}
// Force a menu to update itself. All of the menus parents will be updated
// as well. An empty string will force a complete menu system reload.
function forceUpdateNativeMenuAt(location) {
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
try {
utils.forceUpdateNativeMenuAt(location);
}
catch (e) {
dump(e + "\n");
}
}
var executedCommandID = "";
function testItem(location, targetID) {
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var correctCommandHandler = false;
try {
utils.activateNativeMenuItemAt(location);
correctCommandHandler = executedCommandID == targetID;
}
catch (e) {
dump(e + "\n");
}
finally {
executedCommandID = "";
return correctCommandHandler;
}
}
function createXULMenuPopup() {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var item = document.createElementNS(XUL_NS, "menupopup");
return item;
}
function createXULMenu(aLabel) {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var item = document.createElementNS(XUL_NS, "menu");
item.setAttribute("label", aLabel);
return item;
}
function createXULMenuItem(aLabel, aCommandId) {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var item = document.createElementNS(XUL_NS, "menuitem");
item.setAttribute("label", aLabel);
item.setAttribute("command", aCommandId);
return item;
}
function runBaseMenuTests() {
forceUpdateNativeMenuAt("0|3");
return testItem("0|0", "cmd_FooItem0") &&
testItem("0|1", "cmd_FooItem1") &&
testItem("0|3|0", "cmd_BarItem0") &&
testItem("0|3|1", "cmd_BarItem1");
}
function onLoad() {
var _delayedOnLoad = function() {
// First let's run the base menu tests.
ok(runBaseMenuTests());
// Set up some nodes that we'll use.
var menubarNode = document.getElementById("nativemenubar");
var newMenu0 = createXULMenu("NewMenu0");
var newMenu1 = createXULMenu("NewMenu1");
var newMenuPopup0 = createXULMenuPopup();
var newMenuPopup1 = createXULMenuPopup();
var newMenuItem0 = createXULMenuItem("NewMenuItem0", "cmd_NewItem0");
var newMenuItem1 = createXULMenuItem("NewMenuItem1", "cmd_NewItem1");
var newMenuItem2 = createXULMenuItem("NewMenuItem2", "cmd_NewItem2");
var newMenuItem3 = createXULMenuItem("NewMenuItem3", "cmd_NewItem3");
var newMenuItem4 = createXULMenuItem("NewMenuItem4", "cmd_NewItem4");
var newMenuItem5 = createXULMenuItem("NewMenuItem5", "cmd_NewItem5");
// Create another submenu with hierarchy via DOM manipulation.
// ******************
// * Foo * NewMenu0 * <- Menu bar
// ******************
// ****************
// * NewMenuItem0 * <- NewMenu0 submenu
// ****************
// * NewMenuItem1 *
// ****************
// * NewMenuItem2 *
// *******************************
// * NewMenu1 > * NewMenuItem3 * <- NewMenu1 submenu
// *******************************
// * NewMenuItem4 *
// ****************
// * NewMenuItem5 *
// ****************
newMenu0.appendChild(newMenuPopup0);
newMenuPopup0.appendChild(newMenuItem0);
newMenuPopup0.appendChild(newMenuItem1);
newMenuPopup0.appendChild(newMenuItem2);
newMenuPopup0.appendChild(newMenu1);
newMenu1.appendChild(newMenuPopup1);
newMenuPopup1.appendChild(newMenuItem3);
newMenuPopup1.appendChild(newMenuItem4);
newMenuPopup1.appendChild(newMenuItem5);
//XXX - we have to append the menu to the top-level of the menu bar
// only after constructing it. If we append before construction, it is
// invalid because it has no children and we don't validate it if we add
// children later.
menubarNode.appendChild(newMenu0);
forceUpdateNativeMenuAt("1|3");
// Run basic tests again.
ok(runBaseMenuTests());
// Error strings.
var sa = "Command handler(s) should have activated";
var sna = "Command handler(s) should not have activated";
// Test middle items.
ok(testItem("1|1", "cmd_NewItem1"), sa);
ok(testItem("1|3|1", "cmd_NewItem4"), sa);
// Hide newMenu0.
newMenu0.setAttribute("hidden", "true");
ok(runBaseMenuTests(), sa); // the base menu should still be unhidden
ok(!testItem("1|0", ""), sna);
ok(!testItem("1|1", ""), sna);
ok(!testItem("1|2", ""), sna);
ok(!testItem("1|3|0", ""), sna);
ok(!testItem("1|3|1", ""), sna);
ok(!testItem("1|3|2", ""), sna);
// Show newMenu0.
newMenu0.setAttribute("hidden", "false");
forceUpdateNativeMenuAt("1|3");
ok(runBaseMenuTests(), sa);
ok(testItem("1|0", "cmd_NewItem0"), sa);
ok(testItem("1|1", "cmd_NewItem1"), sa);
ok(testItem("1|2", "cmd_NewItem2"), sa);
ok(testItem("1|3|0", "cmd_NewItem3"), sa);
ok(testItem("1|3|1", "cmd_NewItem4"), sa);
ok(testItem("1|3|2", "cmd_NewItem5"), sa);
// Hide items.
newMenuItem1.setAttribute("hidden", "true");
newMenuItem4.setAttribute("hidden", "true");
forceUpdateNativeMenuAt("1|2");
ok(runBaseMenuTests(), sa);
ok(testItem("1|0", "cmd_NewItem0"), sa);
ok(testItem("1|1", "cmd_NewItem2"), sa);
ok(!testItem("1|2", ""), sna);
ok(testItem("1|2|0", "cmd_NewItem3"), sa);
ok(testItem("1|2|1", "cmd_NewItem5"), sa);
ok(!testItem("1|2|2", ""), sna);
// Show items.
newMenuItem1.setAttribute("hidden", "false");
newMenuItem4.setAttribute("hidden", "false");
forceUpdateNativeMenuAt("1|3");
ok(runBaseMenuTests(), sa);
ok(testItem("1|0", "cmd_NewItem0"), sa);
ok(testItem("1|1", "cmd_NewItem1"), sa);
ok(testItem("1|2", "cmd_NewItem2"), sa);
ok(testItem("1|3|0", "cmd_NewItem3"), sa);
ok(testItem("1|3|1", "cmd_NewItem4"), sa);
ok(testItem("1|3|2", "cmd_NewItem5"), sa);
// At this point in the tests the state of the menus has been returned
// to the originally diagramed state.
// Test command disabling
var cmd_NewItem0 = document.getElementById("cmd_NewItem0");
ok(testItem("1|0", "cmd_NewItem0"), sa);
cmd_NewItem0.setAttribute("disabled", "true");
ok(!testItem("1|0", "cmd_NewItem0"), sna);
cmd_NewItem0.removeAttribute("disabled");
ok(testItem("1|0", "cmd_NewItem0"), sa);
// Remove menu.
menubarNode.removeChild(newMenu0);
ok(runBaseMenuTests(), sa);
ok(!testItem("1|0", ""), sna);
ok(!testItem("1|1", ""), sna);
ok(!testItem("1|2", ""), sna);
ok(!testItem("1|3|0", ""), sna);
ok(!testItem("1|3|1", ""), sna);
ok(!testItem("1|3|2", ""), sna);
// return state to original diagramed state
menubarNode.appendChild(newMenu0);
// Test for bug 447042, make sure that adding a menu node with no children
// to the menu bar and then adding another menu node with children works.
// Menus with no children don't get their native menu items shown and that
// caused internal arrays to get out of sync and an append crashed.
var tmpMenu0 = createXULMenu("tmpMenu0");
menubarNode.removeChild(newMenu0);
menubarNode.appendChild(tmpMenu0);
menubarNode.appendChild(newMenu0);
forceUpdateNativeMenuAt("1|3");
ok(runBaseMenuTests());
ok(testItem("1|0", "cmd_NewItem0"), sa);
ok(testItem("1|1", "cmd_NewItem1"), sa);
ok(testItem("1|2", "cmd_NewItem2"), sa);
ok(testItem("1|3|0", "cmd_NewItem3"), sa);
ok(testItem("1|3|1", "cmd_NewItem4"), sa);
ok(testItem("1|3|2", "cmd_NewItem5"), sa);
// return state to original diagramed state
menubarNode.removeChild(tmpMenu0);
delete tmpMenu0;
// This test is basically a crash test for bug 433858.
newMenuItem1.setAttribute("hidden", "true");
newMenuItem2.setAttribute("hidden", "true");
newMenu1.setAttribute("hidden", "true");
forceUpdateNativeMenuAt("1");
newMenuItem1.setAttribute("hidden", "false");
newMenuItem2.setAttribute("hidden", "false");
newMenu1.setAttribute("hidden", "false");
forceUpdateNativeMenuAt("1");
onTestsFinished();
}
setTimeout(_delayedOnLoad, 1000);
}
]]></script>
</window>

View file

@ -1,773 +0,0 @@
<?xml version="1.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/. -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="NativeMenuWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
width="600"
height="600"
title="Native Mouse Event Test"
orient="vertical">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<box height="200" id="box"/>
<menupopup id="popup" width="250" height="50"/>
<panel id="panel" width="250" height="50" noautohide="true"/>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function is(a, b, message) {
window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
}
function todo(condition, message) {
window.opener.wrappedJSObject.SimpleTest.todo(condition, message);
}
function todo_is(a, b, message) {
window.opener.wrappedJSObject.SimpleTest.todo_is(a, b, message);
}
function onTestsFinished() {
clearTimeout(gAfterLoopExecution);
observe(window, eventMonitor, false);
observe(gRightWindow, eventMonitor, false);
observe(gPopup, eventMonitor, false);
gRightWindow.close();
var openerSimpleTest = window.opener.wrappedJSObject.SimpleTest;
window.close();
openerSimpleTest.finish();
}
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const xulWin = 'data:application/vnd.mozilla.xul+xml,<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin" type="text/css"?><window xmlns="' + XUL_NS + '"/>';
const NSLeftMouseDown = 1,
NSLeftMouseUp = 2,
NSRightMouseDown = 3,
NSRightMouseUp = 4,
NSMouseMoved = 5,
NSLeftMouseDragged = 6,
NSRightMouseDragged = 7,
NSMouseEntered = 8,
NSMouseExited = 9,
NSKeyDown = 10,
NSKeyUp = 11,
NSFlagsChanged = 12,
NSAppKitDefined = 13,
NSSystemDefined = 14,
NSApplicationDefined = 15,
NSPeriodic = 16,
NSCursorUpdate = 17,
NSScrollWheel = 22,
NSTabletPoint = 23,
NSTabletProximity = 24,
NSOtherMouseDown = 25,
NSOtherMouseUp = 26,
NSOtherMouseDragged = 27,
NSEventTypeGesture = 29,
NSEventTypeMagnify = 30,
NSEventTypeSwipe = 31,
NSEventTypeRotate = 18,
NSEventTypeBeginGesture = 19,
NSEventTypeEndGesture = 20;
const NSAlphaShiftKeyMask = 1 << 16,
NSShiftKeyMask = 1 << 17,
NSControlKeyMask = 1 << 18,
NSAlternateKeyMask = 1 << 19,
NSCommandKeyMask = 1 << 20,
NSNumericPadKeyMask = 1 << 21,
NSHelpKeyMask = 1 << 22,
NSFunctionKeyMask = 1 << 23;
const gDebug = false;
function printDebug(msg) { if (gDebug) dump(msg); }
var gExpectedEvents = [];
var gRightWindow = null, gPopup = null;
var gCurrentMouseX = 0, gCurrentMouseY = 0;
var gAfterLoopExecution = 0;
function testMouse(x, y, msg, elem, win, exp, flags, callback) {
clearExpectedEvents();
var syntheticEvent = null;
exp.forEach(function (expEv) {
expEv.screenX = x;
expEv.screenY = y;
if (expEv.synthetic) {
is(syntheticEvent, null,
"Can't handle two synthetic events in a single testMouse call");
syntheticEvent = expEv;
}
gExpectedEvents.push(expEv);
});
printDebug("sending event: " + x + ", " + y + " (" + msg + ")\n");
gCurrentMouseX = x;
gCurrentMouseY = y;
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var callbackFunc = function() {
clearExpectedEvents();
callback();
}
if (syntheticEvent) {
// Set up this listener before we sendNativeMouseEvent, just
// in case that synchronously calls us.
eventListenOnce(syntheticEvent.target, syntheticEvent.type,
// Trigger callbackFunc async, so we're not assuming
// anything about how our listener gets ordered with
// others.
function () { SimpleTest.executeSoon(callbackFunc) });
}
utils.sendNativeMouseEvent(x, y, msg, flags || 0, elem);
if (!syntheticEvent) {
gAfterLoopExecution = setTimeout(callbackFunc, 0);
}
}
function eventListenOnce(elem, name, callback) {
elem.addEventListener(name, function(e) {
elem.removeEventListener(name, arguments.callee, false);
callback(e);
}, false);
}
function focusAndThen(win, callback) {
eventListenOnce(win, "focus", callback);
printDebug("focusing a window\n");
win.focus();
}
function eventToString(e) {
return JSON.stringify({
type: e.type, target: e.target.nodeName, screenX: e.screenX, screenY: e.screenY
});
}
function clearExpectedEvents() {
while (gExpectedEvents.length > 0) {
var expectedEvent = gExpectedEvents.shift();
var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
}
}
var gEventNum = 0;
function eventMonitor(e) {
printDebug("got event: " + eventToString(e) + "\n");
processEvent(e);
}
function processEvent(e) {
if (e.screenX != gCurrentMouseX || e.screenY != gCurrentMouseY) {
todo(false, "Oh no! Received a stray event from a confused tracking area. Aborting test.");
onTestsFinished();
return;
}
var expectedEvent = gExpectedEvents.shift();
if (!expectedEvent) {
ok(false, "received event I didn't expect: " + eventToString(e));
return;
}
if (e.type != expectedEvent.type) {
// Didn't get expectedEvent.
var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
return processEvent(e);
}
gEventNum++;
is(e.screenX, expectedEvent.screenX, gEventNum + " | wrong X coord for event " + eventToString(e));
is(e.screenY, expectedEvent.screenY, gEventNum + " | wrong Y coord for event " + eventToString(e));
is(e.target, expectedEvent.target, gEventNum + " | wrong target for event " + eventToString(e));
if (expectedEvent.firesButShouldnt) {
todo(false, gEventNum + " | Got an event that should not have fired: " + eventToString(e));
}
}
function observe(elem, fun, add) {
var addOrRemove = add ? "addEventListener" : "removeEventListener";
elem[addOrRemove]("mousemove", fun, false);
elem[addOrRemove]("mouseover", fun, false);
elem[addOrRemove]("mouseout", fun, false);
elem[addOrRemove]("mousedown", fun, false);
elem[addOrRemove]("mouseup", fun, false);
elem[addOrRemove]("click", fun, false);
}
function start() {
window.resizeTo(200, 200);
window.moveTo(50, 50);
gRightWindow = open(xulWin, '', 'chrome,screenX=300,screenY=50,width=200,height=200');
eventListenOnce(gRightWindow, "focus", function () {
focusAndThen(window, runTests);
});
gPopup = document.getElementById("popup");
}
function runTests() {
observe(window, eventMonitor, true);
observe(gRightWindow, eventMonitor, true);
var left = window, right = gRightWindow;
var leftElem = document.getElementById("box");
var rightElem = gRightWindow.document.documentElement;
var panel = document.getElementById("panel");
var tooltip = (function createTooltipInRightWindow() {
var _tooltip = right.document.createElementNS(XUL_NS, "tooltip");
_tooltip.setAttribute("id", "tip");
_tooltip.setAttribute("width", "80");
_tooltip.setAttribute("height", "20");
right.document.documentElement.appendChild(_tooltip);
return _tooltip;
})();
var tests = [
// Part 1: Disallow click-through
function blockClickThrough(callback) {
document.documentElement.setAttribute("clickthrough", "never");
gRightWindow.document.documentElement.setAttribute("clickthrough", "never");
callback();
},
// Enter the left window, which is focused.
[150, 150, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem }
]],
// Test that moving inside the window fires mousemove events.
[170, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Leaving the window should fire a mouseout event...
[170, 20, NSMouseMoved, null, left, [
{ type: "mouseout", target: leftElem },
]],
// ... and entering a mouseover event.
[170, 120, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Move over the right window, which is inactive.
// Inactive windows shouldn't respond to mousemove events when clickthrough="never",
// so we should only get a mouseout event, no mouseover event.
[400, 150, NSMouseMoved, null, right, [
{ type: "mouseout", target: leftElem },
]],
// Left-clicking while holding Cmd and middle clicking should work even
// on inactive windows, but without making them active.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSOtherMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSOtherMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Clicking an inactive window should make it active and fire a mouseover
// event.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mouseover", target: rightElem, synthetic: true },
]],
[400, 150, NSLeftMouseUp, null, right, [
]],
// Now it's focused, so we should get a mousedown event when clicking.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
// Let's drag to the right without letting the button go.
[410, 150, NSLeftMouseDragged, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Let go of the mouse.
[410, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Move the mouse back over the left window, which is inactive.
[150, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: rightElem },
]],
// Now we're being sneaky. The left window is inactive, but *right*-clicks to it
// should still get through. Test that.
// Ideally we'd be bracketing that event with over and out events, too, but it
// probably doesn't matter too much.
[150, 170, NSRightMouseDown, null, left, [
{ type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
{ type: "mousedown", target: leftElem },
{ type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
]],
// Let go of the mouse.
[150, 170, NSRightMouseUp, null, left, [
{ type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
{ type: "mouseup", target: leftElem },
{ type: "click", target: leftElem },
{ type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
]],
// Right clicking hasn't focused it, so the window is still inactive.
// Let's focus it; this time without the mouse, for variaton's sake.
// Still, mouseout and mouseover events should fire.
function raiseLeftWindow(callback) {
clearExpectedEvents();
gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem });
// We have to be a bit careful here. The synthetic mouse event may
// not fire for a bit after we focus the left window.
eventListenOnce(leftElem, "mouseover", function() {
// Trigger callback async, so we're not assuming
// anything about how our listener gets ordered with others.
SimpleTest.executeSoon(callback);
});
printDebug("focusing left window");
left.focus();
},
// It's active, so it should respond to mousemove events now.
[150, 170, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// This was boring... let's introduce a popup. It will overlap both the left
// and the right window.
function openPopupInLeftWindow(callback) {
eventListenOnce(gPopup, "popupshown", callback);
gPopup.openPopupAtScreen(150, 50, true);
},
// Move the mouse over the popup.
[200, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// Move the mouse back over the left window outside the popup.
[160, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Back over the popup...
[190, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// ...and over into the right window.
// It's inactive, so it shouldn't get mouseover events yet.
[400, 170, NSMouseMoved, null, right, [
{ type: "mouseout", target: gPopup },
]],
// Again, no mouse events please, even though a popup is open. (bug 425556)
[400, 180, NSMouseMoved, null, right, [
]],
// Activate the right window with a click.
// This will close the popup and make the mouse enter the right window.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mouseover", target: rightElem, synthetic: true },
]],
[400, 180, NSLeftMouseUp, null, right, [
]],
function verifyPopupClosed2(callback) {
is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
callback();
},
// Now the right window is active; click it again, just for fun.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Time for our next trick: a tooltip!
// Install the tooltip, but don't show it yet.
function setTooltip(callback) {
rightElem.setAttribute("tooltip", "tip");
gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
eventListenOnce(rightElem, "popupshown", callback);
gCurrentMouseX = 410;
gCurrentMouseY = 180;
var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
},
// Now the tooltip is visible.
// Move the mouse a little to the right.
[411, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move another pixel.
[412, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move up and click to make the tooltip go away.
[412, 80, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[412, 80, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[412, 80, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// OK, next round. Open a panel in the left window, which is inactive.
function openPanel(callback) {
eventListenOnce(panel, "popupshown", callback);
panel.openPopupAtScreen(150, 150, false);
},
// The panel is parented, so it will be z-ordered over its parent but
// under the active window.
// Now we move the mouse over the part where the panel rect intersects the
// right window's rect. Since the panel is under the window, all the events
// should target the right window.
[390, 170, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[390, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[391, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Now move off the right window, so that the mouse is directly over the
// panel.
[260, 170, NSMouseMoved, panel, left, [
{ type: "mouseout", target: rightElem },
]],
[260, 171, NSMouseMoved, panel, left, [
]],
[261, 171, NSMouseMoved, panel, left, [
]],
// Let's be evil and click it.
[261, 171, NSLeftMouseDown, panel, left, [
]],
[261, 171, NSLeftMouseUp, panel, left, [
]],
// This didn't focus the window, unfortunately, so let's do it ourselves.
function raiseLeftWindowTakeTwo(callback) {
focusAndThen(left, callback);
},
// Now mouse events should get through to the panel (which is now over the
// right window).
[387, 170, NSMouseMoved, panel, left, [
{ type: "mouseover", target: panel },
{ type: "mousemove", target: panel },
]],
[387, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[388, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Click the panel.
[388, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel }
]],
[388, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// Last test for this part: Hit testing in the Canyon of Nowhere -
// the pixel row directly south of the panel, over the left window.
// Before bug 515003 we wrongly thought the mouse wasn't over any window.
[173, 200, NSMouseMoved, null, left, [
{ type: "mouseout", target: panel },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
[173, 201, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Part 2: Allow click-through
function hideThatPanel(callback) {
eventListenOnce(panel, "popuphidden", callback);
panel.hidePopup();
},
function unblockClickThrough(callback) {
document.documentElement.removeAttribute("clickthrough");
gRightWindow.document.documentElement.removeAttribute("clickthrough");
callback();
},
// Enter the left window, which is focused.
[150, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem }
]],
// Test that moving inside the window fires mousemove events.
[170, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Leaving the window should fire a mouseout event...
[170, 20, NSMouseMoved, null, left, [
{ type: "mouseout", target: leftElem },
]],
// ... and entering a mouseover event.
[170, 120, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Move over the right window, which is inactive but still accepts
// mouse events.
[400, 150, NSMouseMoved, null, right, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: rightElem },
{ type: "mousemove", target: rightElem },
]],
// Left-clicking while holding Cmd and middle clicking should work
// on inactive windows, but without making them active.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSOtherMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSOtherMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Clicking an inactive window should make it active
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Now it's focused.
[401, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
// Let's drag to the right without letting the button go.
[410, 150, NSLeftMouseDragged, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Let go of the mouse.
[410, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Move the mouse back over the left window, which is inactive.
[150, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: rightElem },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Right-click it.
[150, 170, NSRightMouseDown, null, left, [
{ type: "mousedown", target: leftElem },
]],
// Let go of the mouse.
[150, 170, NSRightMouseUp, null, left, [
{ type: "mouseup", target: leftElem },
{ type: "click", target: leftElem },
]],
// Right clicking hasn't focused it, so the window is still inactive.
// Let's focus it; this time without the mouse, for variaton's sake.
function raiseLeftWindow(callback) {
clearExpectedEvents();
focusAndThen(left, function () { SimpleTest.executeSoon(callback); });
},
// It's active and should still respond to mousemove events.
[150, 170, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// This was boring... let's introduce a popup. It will overlap both the left
// and the right window.
function openPopupInLeftWindow(callback) {
eventListenOnce(gPopup, "popupshown", callback);
gPopup.openPopupAtScreen(150, 50, true);
},
// Move the mouse over the popup.
[200, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// Move the mouse back over the left window outside the popup.
[160, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Back over the popup...
[190, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// ...and over into the right window.
[400, 170, NSMouseMoved, null, right, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: rightElem },
{ type: "mousemove", target: rightElem },
]],
[400, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Activate the right window with a click.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
function verifyPopupClosed2(callback) {
is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
callback();
},
// Now the right window is active; click it again, just for fun.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Time for our next trick: a tooltip!
// Install the tooltip, but don't show it yet.
function setTooltip2(callback) {
rightElem.setAttribute("tooltip", "tip");
gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
eventListenOnce(rightElem, "popupshown", callback);
gCurrentMouseX = 410;
gCurrentMouseY = 180;
var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
},
// Now the tooltip is visible.
// Move the mouse a little to the right.
[411, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move another pixel.
[412, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move up and click to make the tooltip go away.
[412, 80, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[412, 80, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[412, 80, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// OK, next round. Open a panel in the left window, which is inactive.
function openPanel2(callback) {
eventListenOnce(panel, "popupshown", callback);
panel.openPopupAtScreen(150, 150, false);
},
// The panel is parented, so it will be z-ordered over its parent but
// under the active window.
// Now we move the mouse over the part where the panel rect intersects the
// right window's rect. Since the panel is under the window, all the events
// should target the right window.
[390, 170, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[390, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[391, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Now move off the right window, so that the mouse is directly over the
// panel.
[260, 170, NSMouseMoved, panel, left, [
{ type: "mouseout", target: rightElem },
{ type: "mouseover", target: panel },
{ type: "mousemove", target: panel },
]],
[260, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[261, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Let's be evil and click it.
[261, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel },
]],
[261, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// This didn't focus the window, unfortunately, so let's do it ourselves.
function raiseLeftWindowTakeTwo(callback) {
focusAndThen(left, callback);
},
[387, 170, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[387, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[388, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Click the panel.
[388, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel }
]],
[388, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// Last test for today: Hit testing in the Canyon of Nowhere -
// the pixel row directly south of the panel, over the left window.
// Before bug 515003 we wrongly thought the mouse wasn't over any window.
[173, 200, NSMouseMoved, null, left, [
{ type: "mouseout", target: panel },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
[173, 201, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
];
function runNextTest() {
if (!tests.length)
return onTestsFinished();
var test = tests.shift();
if (typeof test == "function")
return test(runNextTest);
var [x, y, msg, elem, win, exp, flags] = test;
testMouse(x, y, msg, elem, win, exp, flags, runNextTest);
}
runNextTest();
}
SimpleTest.waitForFocus(start);
]]></script>
</window>

View file

@ -1,334 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="StandaloneNativeMenuWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="300"
height="300"
onload="onLoad();"
title="nsIStandaloneNativeMenu Test">
<command id="cmd_FooItem0" oncommand="executedCommandID = 'cmd_FooItem0';"/>
<command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/>
<command id="cmd_BarItem0" oncommand="executedCommandID = 'cmd_BarItem0';"/>
<command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/>
<command id="cmd_NewItem0" oncommand="executedCommandID = 'cmd_NewItem0';"/>
<command id="cmd_NewItem1" oncommand="executedCommandID = 'cmd_NewItem1';"/>
<command id="cmd_NewItem2" oncommand="executedCommandID = 'cmd_NewItem2';"/>
<command id="cmd_NewItem3" oncommand="executedCommandID = 'cmd_NewItem3';"/>
<command id="cmd_NewItem4" oncommand="executedCommandID = 'cmd_NewItem4';"/>
<command id="cmd_NewItem5" oncommand="executedCommandID = 'cmd_NewItem5';"/>
<!-- We do not modify any menus or menu items defined here in testing. These
serve as a baseline structure for us to test after other modifications.
We add children to the menubar defined here and test by modifying those
children. -->
<popupset>
<menupopup id="standalonenativemenu">
<menu id="foo" label="Foo">
<menupopup>
<menuitem label="FooItem0" command="cmd_FooItem0"/>
<menuitem label="FooItem1" command="cmd_FooItem1"/>
<menuseparator/>
<menu label="Bar">
<menupopup>
<menuitem label="BarItem0" command="cmd_BarItem0"/>
<menuitem label="BarItem1" command="cmd_BarItem1"/>
</menupopup>
</menu>
</menupopup>
</menu>
</menupopup>
</popupset>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function todo(condition, message) {
window.opener.wrappedJSObject.SimpleTest.todo(condition, message);
}
function onTestsFinished() {
window.close();
window.opener.wrappedJSObject.SimpleTest.finish();
}
var executedCommandID = "";
function testItem(menu, location, targetID) {
var correctCommandHandler = false;
try {
menu.menuWillOpen();
menu.activateNativeMenuItemAt(location);
correctCommandHandler = executedCommandID == targetID;
}
catch (e) {
dump(e + "\n");
}
finally {
executedCommandID = "";
return correctCommandHandler;
}
}
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
function createXULMenuPopup() {
return document.createElementNS(XUL_NS, "menupopup");
}
function createXULMenu(aLabel) {
var item = document.createElementNS(XUL_NS, "menu");
item.setAttribute("label", aLabel);
return item;
}
function createXULMenuItem(aLabel, aCommandId) {
var item = document.createElementNS(XUL_NS, "menuitem");
item.setAttribute("label", aLabel);
item.setAttribute("command", aCommandId);
return item;
}
function runBaseMenuTests(menu) {
menu.forceUpdateNativeMenuAt("0|3");
return testItem(menu, "0|0", "cmd_FooItem0") &&
testItem(menu, "0|1", "cmd_FooItem1") &&
testItem(menu, "0|3|0", "cmd_BarItem0") &&
testItem(menu, "0|3|1", "cmd_BarItem1");
}
function createStandaloneNativeMenu(menuNode) {
try {
let Cc = Components.classes;
let Ci = Components.interfaces;
let menu = Cc["@mozilla.org/widget/standalonenativemenu;1"].createInstance(Ci.nsIStandaloneNativeMenu);
menu.init(menuNode);
return menu;
} catch (e) {
ok(false, "Failed creating nsIStandaloneNativeMenu instance");
throw e;
}
}
function runDetachedMenuTests(addMenupopupBeforeCreatingSNM) {
let menu = createXULMenu("Detached menu");
menu.setAttribute("image", 'data:image/svg+xml,<svg%20xmlns="http://www.w3.org/2000/svg"%20width="32"%20height="32"><circle%20cx="16"%20cy="16"%20r="16"/></svg>');
let menupopup = createXULMenuPopup();
let popupShowingFired = false;
let itemActivated = false;
menupopup.addEventListener("popupshowing", function (e) {
popupShowingFired = true;
let menuitem = document.createElementNS(XUL_NS, "menuitem");
menuitem.setAttribute("label", "detached menu item");
menuitem.addEventListener("command", function (e) {
itemActivated = true;
})
menupopup.appendChild(menuitem);
})
// It shouldn't make a difference whether the menupopup is added to the
// menu element before or after we create the nsIStandaloneNativeMenu
// instance with it. We test both orders by calling this function twice
// with different values for addMenupopupBeforeCreatingSNM.
var menuSNM = null; // the nsIStandaloneNativeMenu object for "menu"
if (addMenupopupBeforeCreatingSNM) {
menu.appendChild(menupopup);
menuSNM = createStandaloneNativeMenu(menu);
} else {
menuSNM = createStandaloneNativeMenu(menu);
menu.appendChild(menupopup);
}
try {
ok(!popupShowingFired, "popupshowing shouldn't have fired before our call to menuWillOpen()");
menuSNM.menuWillOpen();
ok(popupShowingFired, "calling menuWillOpen() should have notified our popupshowing listener");
ok(!itemActivated, "our dynamically-added menuitem shouldn't have been activated yet");
menuSNM.activateNativeMenuItemAt("0");
ok(itemActivated, "the new menu item should have been activated now");
} catch (ex) {
ok(false, "dynamic menu test failed: " + ex);
}
}
function onLoad() {
var _delayedOnLoad = function() {
try {
var menuNode = document.getElementById("standalonenativemenu");
var menu = createStandaloneNativeMenu(menuNode);
// First let's run the base menu tests.
ok(runBaseMenuTests(menu), "base tests #1");
// Set up some nodes that we'll use.
var newMenu0 = createXULMenu("NewMenu0");
var newMenu1 = createXULMenu("NewMenu1");
var newMenuPopup0 = createXULMenuPopup();
var newMenuPopup1 = createXULMenuPopup();
var newMenuItem0 = createXULMenuItem("NewMenuItem0", "cmd_NewItem0");
var newMenuItem1 = createXULMenuItem("NewMenuItem1", "cmd_NewItem1");
var newMenuItem2 = createXULMenuItem("NewMenuItem2", "cmd_NewItem2");
var newMenuItem3 = createXULMenuItem("NewMenuItem3", "cmd_NewItem3");
var newMenuItem4 = createXULMenuItem("NewMenuItem4", "cmd_NewItem4");
var newMenuItem5 = createXULMenuItem("NewMenuItem5", "cmd_NewItem5");
// Create another submenu with hierarchy via DOM manipulation.
// ******************
// * Foo * NewMenu0 * <- Menu bar
// ******************
// ****************
// * NewMenuItem0 * <- NewMenu0 submenu
// ****************
// * NewMenuItem1 *
// ****************
// * NewMenuItem2 *
// *******************************
// * NewMenu1 > * NewMenuItem3 * <- NewMenu1 submenu
// *******************************
// * NewMenuItem4 *
// ****************
// * NewMenuItem5 *
// ****************
newMenu0.appendChild(newMenuPopup0);
newMenuPopup0.appendChild(newMenuItem0);
newMenuPopup0.appendChild(newMenuItem1);
newMenuPopup0.appendChild(newMenuItem2);
newMenuPopup0.appendChild(newMenu1);
newMenu1.appendChild(newMenuPopup1);
newMenuPopup1.appendChild(newMenuItem3);
newMenuPopup1.appendChild(newMenuItem4);
newMenuPopup1.appendChild(newMenuItem5);
//XXX - we have to append the menu to the top-level of the menu bar
// only after constructing it. If we append before construction, it is
// invalid because it has no children and we don't validate it if we add
// children later.
menuNode.appendChild(newMenu0);
menu.forceUpdateNativeMenuAt("1|3");
// Run basic tests again.
ok(runBaseMenuTests(menu), "base tests #2");
// Error strings.
var sa = "Command handler(s) should have activated";
var sna = "Command handler(s) should not have activated";
// Test middle items.
ok(testItem(menu, "1|1", "cmd_NewItem1"), "#1:" + sa);
ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#2:" + sa);
// Hide newMenu0.
newMenu0.setAttribute("hidden", "true");
ok(runBaseMenuTests(menu), "base tests #3: " + sa); // the base menu should still be unhidden
ok(!testItem(menu, "1|0", ""), "#3:" + sna);
ok(!testItem(menu, "1|1", ""), "#4:" + sna);
ok(!testItem(menu, "1|2", ""), "#5:" + sna);
ok(!testItem(menu, "1|3|0", ""), "#6:" + sna);
ok(!testItem(menu, "1|3|1", ""), "#7:" + sna);
ok(!testItem(menu, "1|3|2", ""), "#8:" + sna);
// Show newMenu0.
newMenu0.setAttribute("hidden", "false");
menu.forceUpdateNativeMenuAt("1|3");
ok(runBaseMenuTests(menu), "base tests #4:" + sa);
ok(testItem(menu, "1|0", "cmd_NewItem0"), "#9:" + sa);
ok(testItem(menu, "1|1", "cmd_NewItem1"), "#10:" + sa);
ok(testItem(menu, "1|2", "cmd_NewItem2"), "#11:" + sa);
ok(testItem(menu, "1|3|0", "cmd_NewItem3"), "#12:" + sa);
ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#13:" + sa);
ok(testItem(menu, "1|3|2", "cmd_NewItem5"), "#14:" + sa);
// Hide items.
newMenuItem1.setAttribute("hidden", "true");
newMenuItem4.setAttribute("hidden", "true");
menu.forceUpdateNativeMenuAt("1|2");
ok(runBaseMenuTests(menu), "base tests #5:" + sa);
ok(testItem(menu, "1|0", "cmd_NewItem0"), "#15:" + sa);
ok(testItem(menu, "1|1", "cmd_NewItem2"), "#16:" + sa);
ok(!testItem(menu, "1|2", ""), "#17:" + sna);
ok(testItem(menu, "1|2|0", "cmd_NewItem3"), "#18:" + sa);
ok(testItem(menu, "1|2|1", "cmd_NewItem5"), "#19:" + sa);
ok(!testItem(menu, "1|2|2", ""), "#20:" + sna);
// Show items.
newMenuItem1.setAttribute("hidden", "false");
newMenuItem4.setAttribute("hidden", "false");
//forceUpdateNativeMenuAt("1|3");
ok(runBaseMenuTests(menu), "base tests #6:" + sa);
ok(testItem(menu, "1|0", "cmd_NewItem0"), "#21:" + sa);
ok(testItem(menu, "1|1", "cmd_NewItem1"), "#22:" + sa);
ok(testItem(menu, "1|2", "cmd_NewItem2"), "#23:" + sa);
ok(testItem(menu, "1|3|0", "cmd_NewItem3"), "#24:" + sa);
ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#25:" + sa);
ok(testItem(menu, "1|3|2", "cmd_NewItem5"), "#26:" + sa);
// At this point in the tests the state of the menus has been returned
// to the originally diagramed state.
// Remove menu.
menuNode.removeChild(newMenu0);
ok(runBaseMenuTests(menu), "base tests #7:" + sa);
ok(!testItem(menu, "1|0", ""), "#27:" + sna);
ok(!testItem(menu, "1|1", ""), "#28:" + sna);
ok(!testItem(menu, "1|2", ""), "#29:" + sna);
ok(!testItem(menu, "1|3|0", ""), "#30:" + sna);
ok(!testItem(menu, "1|3|1", ""), "#31:" + sna);
ok(!testItem(menu, "1|3|2", ""), "#32:" + sna);
// return state to original diagramed state
menuNode.appendChild(newMenu0);
// Test for bug 447042, make sure that adding a menu node with no children
// to the menu bar and then adding another menu node with children works.
// Menus with no children don't get their native menu items shown and that
// caused internal arrays to get out of sync and an append crashed.
var tmpMenu0 = createXULMenu("tmpMenu0");
menuNode.removeChild(newMenu0);
menuNode.appendChild(tmpMenu0);
menuNode.appendChild(newMenu0);
menu.forceUpdateNativeMenuAt("1|3");
//todo(runBaseMenuTests(menu), "base tests #8");
todo(testItem(menu, "1|0", "cmd_NewItem0"), "#33:" +sa);
todo(testItem(menu, "1|1", "cmd_NewItem1"), "#34:" +sa);
todo(testItem(menu, "1|2", "cmd_NewItem2"), "#35:" +sa);
todo(testItem(menu, "1|3|0", "cmd_NewItem3"), "#36:" +sa);
todo(testItem(menu, "1|3|1", "cmd_NewItem4"), "#37:" +sa);
todo(testItem(menu, "1|3|2", "cmd_NewItem5"), "#38:" +sa);
// return state to original diagramed state
menuNode.removeChild(tmpMenu0);
delete tmpMenu0;
// This test is basically a crash test for bug 433858.
newMenuItem1.setAttribute("hidden", "true");
newMenuItem2.setAttribute("hidden", "true");
newMenu1.setAttribute("hidden", "true");
menu.forceUpdateNativeMenuAt("1");
newMenuItem1.setAttribute("hidden", "false");
newMenuItem2.setAttribute("hidden", "false");
newMenu1.setAttribute("hidden", "false");
menu.forceUpdateNativeMenuAt("1");
// Run tests where the menu nodes are not in the document's node tree.
runDetachedMenuTests(false);
runDetachedMenuTests(true);
} catch (e) {
ok(false, "Caught an exception: " + e);
} finally {
onTestsFinished();
}
}
setTimeout(_delayedOnLoad, 1000);
}
]]></script>
</window>

View file

@ -1,127 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Taskbar Previews Test"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="loaded();">
<title>Previews - yeah!</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script class="testbody" type="application/javascript">
<![CDATA[
let Cc = Components.classes;
let Ci = Components.interfaces;
let Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let taskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(Ci.nsIWinTaskbar);
function IsWin7OrHigher() {
try {
var sysInfo = Cc["@mozilla.org/system-info;1"].
getService(Ci.nsIPropertyBag2);
var ver = parseFloat(sysInfo.getProperty("version"));
if (ver >= 6.1)
return true;
} catch (ex) { }
return false;
}
isnot(taskbar, null, "Taskbar service is defined");
is(taskbar.available, IsWin7OrHigher(), "Expected availability of taskbar");
SimpleTest.waitForExplicitFinish();
function stdPreviewSuite(p) {
p.visible = !p.visible;
p.visible = !p.visible;
p.visible = true;
p.invalidate();
p.visible = false;
}
function loaded()
{
if (!taskbar.available)
SimpleTest.finish();
let controller = {
width: 400,
height: 400,
thumbnailAspectRatio: 1.0,
drawThumbnail: function () { return false; },
drawPreview: function () { return false; },
get wrappedJSObject() { return this; }
}
// HACK from mconnor:
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
let win = wm.getMostRecentWindow("navigator:browser");
let docShell = win.gBrowser.docShell;
let winPreview = taskbar.getTaskbarWindowPreview(docShell);
isnot(winPreview, null, "Window preview is not null");
winPreview.controller = controller;
let button = winPreview.getButton(0);
isnot(button, null, "Could get button at valid index");
try {
winPreview.getButton(-1);
ok(false, "Got button at negative index");
} catch (ex) {}
try {
winPreview.getButton(Ci.nsITaskbarWindowPreview.NUM_TOOLBAR_BUTTONS);
ok(false, "Got button at index that is too large");
} catch (ex) {}
button.image = null;
stdPreviewSuite(winPreview);
// Let's not perma-hide this window from the taskbar
winPreview.visible = true;
let tabP = taskbar.createTaskbarTabPreview(docShell, controller);
isnot(tabP, null, "Tab preview is not null");
is(tabP.controller.wrappedJSObject, controller, "Controllers match");
is(tabP.icon, null, "Default icon is null (windows default)");
tabP.icon = null;
tabP.move(null);
try {
tabP.move(tabP);
ok(false, "Moved a preview next to itself!");
} catch (ex) {}
stdPreviewSuite(tabP);
let tabP2 = taskbar.createTaskbarTabPreview(docShell, controller);
tabP.visible = true;
tabP2.visible = true;
isnot(tabP2, null, "2nd Tab preview is not null");
isnot(tabP,tabP2, "Tab previews are different");
tabP.active = true;
ok(tabP.active && !tabP2.active, "Only one tab is active (part 1)");
tabP2.active = true;
ok(!tabP.active && tabP2.active, "Only one tab is active (part 2)");
tabP.active = true;
ok(tabP.active && !tabP2.active, "Only one tab is active (part 3)");
tabP.active = false;
ok(!tabP.active && !tabP2.active, "Neither tab is active");
is(winPreview.active, false, "Window preview is not active");
tabP.active = true;
winPreview.active = true;
ok(winPreview.active && !tabP.active, "Tab preview takes activation from window");
tabP.active = true;
ok(tabP.active && !winPreview.active, "Tab preview takes activation from window");
tabP.visible = false;
tabP2.visible = false;
SimpleTest.finish();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</window>

View file

@ -1,748 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Testing ns*Event::Assign*EventData()</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/NativeKeyCodes.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
<style>
#a {
background-color: transparent;
transition: background-color 0.1s linear;
}
#a:focus {
background-color: red;
}
.slidin {
border: green 1px solid;
width: 10px;
height: 10px;
animation-name: slidein;
animation-duration: 1s;
}
@keyframes slidein {
from {
margin-left: 100%;
}
to {
margin-left: 0;
}
}
#pointer-target {
border: 1px dashed red;
background: yellow;
margin: 0px 10px;
padding: 0px 10px;
}
#scrollable-div {
background: green;
overflow: auto;
width: 30px;
height: 30px;
}
#scrolled-div {
background: magenta;
width: 10px;
height: 10px;
}
#form {
background: silver;
padding: 0px 10px;
}
#animated-div {
background: cyan;
padding: 0px 10px;
}
</style>
</head>
<body>
<div id="display">
<input id="input-text">
<button id="button">button</button>
<a id="a" href="about:blank">hyper link</a>
<span id="pointer-target">span</span>
<div id="scrollable-div"><div id="scrolled-div"></div></div>
<form id="form">form</form>
<div id="animated-div">&nbsp;</div>
</div>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(0, 34);
const kIsMac = (navigator.platform.indexOf("Mac") == 0);
const kIsWin = (navigator.platform.indexOf("Win") == 0);
var gEvent = null;
var gCopiedEvent = [];
var gCallback = null;
var gCallPreventDefault = false;
function onEvent(aEvent)
{
if (gCallPreventDefault) {
aEvent.preventDefault();
}
gEvent = aEvent;
for (var attr in aEvent) {
if (!attr.match(/^[A-Z0-9_]+$/) && // ignore const attributes
attr != "multipleActionsPrevented" && // multipleActionsPrevented isn't defined in any DOM event specs.
typeof(aEvent[attr]) != "function") {
gCopiedEvent.push({ name: attr, value: aEvent[attr]});
}
}
setTimeout(gCallback, 0);
}
const kTests = [
{ description: "InternalScrollPortEvent (overflow, vertical)",
targetID: "scrollable-div", eventType: "overflow",
dispatchEvent: function () {
document.getElementById("scrolled-div").style.height = "500px";
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalScrollPortEvent (overflow, horizontal)",
targetID: "scrollable-div", eventType: "overflow",
dispatchEvent: function () {
document.getElementById("scrolled-div").style.width = "500px";
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalScrollAreaEvent (MozScrolledAreaChanged, spreading)",
target: function () { return document; }, eventType: "MozScrolledAreaChanged",
dispatchEvent: function () {
document.getElementById("scrollable-div").style.width = "50000px";
document.getElementById("scrollable-div").style.height = "50000px";
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalScrollAreaEvent (MozScrolledAreaChanged, shrinking)",
target: function () { return document; }, eventType: "MozScrolledAreaChanged",
dispatchEvent: function () {
document.getElementById("scrollable-div").style.width = "30px";
document.getElementById("scrollable-div").style.height = "30px";
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "WidgetKeyboardEvent (keydown of 'a' key without modifiers)",
targetID: "input-text", eventType: "keydown",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_A : MAC_VK_ANSI_A,
{}, "a", "a");
},
canRun: function () {
return (kIsMac || kIsWin);
},
todoMismatch: [],
},
{ description: "WidgetKeyboardEvent (keyup of 'a' key without modifiers)",
targetID: "input-text", eventType: "keydown",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_A : MAC_VK_ANSI_A,
{}, "a", "a");
},
canRun: function () {
return (kIsMac || kIsWin);
},
todoMismatch: [],
},
{ description: "WidgetKeyboardEvent (keypress of 'b' key with Shift)",
targetID: "input-text", eventType: "keypress",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_B : MAC_VK_ANSI_B,
{ shiftKey: true }, "B", "B");
},
canRun: function () {
return (kIsMac || kIsWin);
},
todoMismatch: [],
},
{ description: "WidgetKeyboardEvent (keypress of 'c' key with Accel)",
targetID: "input-text", eventType: "keypress",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_C : MAC_VK_ANSI_C,
{ accelKey: true }, kIsWin ? "\u0003" : "c", "c");
},
canRun: function () {
return (kIsMac || kIsWin);
},
todoMismatch: [],
},
{ description: "WidgetKeyboardEvent (keyup during composition)",
targetID: "input-text", eventType: "keyup",
dispatchEvent: function () {
setAndObserveCompositionPref(true, () => {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeCompositionChange({ "composition":
{ "string": "\u306D",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 },
"key": { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A },
});
synthesizeComposition({ type: "compositioncommitasis" });
setAndObserveCompositionPref(null, runNextTest);
});
return true;
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetKeyboardEvent (keydown during composition)",
targetID: "input-text", eventType: "keydown",
dispatchEvent: function () {
setAndObserveCompositionPref(true, () => {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeCompositionChange({ "composition":
{ "string": "\u306D",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositioncommitasis",
key: { key: "KEY_Enter", code: "Enter" } });
setAndObserveCompositionPref(null, runNextTest);
});
return true;
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetMouseEvent (mousedown of left button without modifier)",
targetID: "button", eventType: "mousedown",
dispatchEvent: function () {
synthesizeMouseAtCenter(document.getElementById(this.targetID),
{ button: 0 });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "WidgetMouseEvent (click of middle button with Shift)",
// XXX I'm not sure why middle click event isn't fired on button element.
targetID: "input-text", eventType: "click",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeMouseAtCenter(document.getElementById(this.targetID),
{ button: 1, shiftKey: true, pressure: 0.5 });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "WidgetMouseEvent (mouseup of right button with Alt)",
targetID: "button", eventType: "mouseup",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeMouseAtCenter(document.getElementById(this.targetID),
{ button: 2, altKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "WidgetDragEvent",
targetID: "input-text", eventType: "dragstart",
dispatchEvent: function () {
return;
},
canRun: function () {
todo(false, "WidgetDragEvent isn't tested");
return false;
},
todoMismatch: [],
},
{ description: "WidgetTextEvent (text)",
targetID: "input-text", eventType: "text",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeComposition({ type: "compositioncommit", data: "\u306D" });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetCompositionEvent (compositionupdate)",
targetID: "input-text", eventType: "compositionupdate",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeComposition({ type: "compositioncommit", data: "\u30E9\u30FC\u30E1\u30F3" });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "InternalEditorInputEvent (input at key input)",
targetID: "input-text", eventType: "input",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_B : MAC_VK_ANSI_B,
{ shiftKey: true }, "B", "B");
},
canRun: function () {
return (kIsMac || kIsWin);
},
todoMismatch: [],
},
{ description: "InternalEditorInputEvent (input at composing)",
targetID: "input-text", eventType: "input",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
document.getElementById(this.targetID).focus();
synthesizeCompositionChange({ "composition":
{ "string": "\u30E9\u30FC\u30E1\u30F3",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "InternalEditorInputEvent (input at committing)",
targetID: "input-text", eventType: "input",
dispatchEvent: function () {
synthesizeComposition({ type: "compositioncommitasis" });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetMouseScrollEvent (DOMMouseScroll, vertical)",
targetID: "input-text", eventType: "DOMMouseScroll",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 3, 4,
{ deltaY: 30, lineOrPageDeltaY: 2 });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetMouseScrollEvent (DOMMouseScroll, horizontal)",
targetID: "input-text", eventType: "DOMMouseScroll",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 4, 5,
{ deltaX: 30, lineOrPageDeltaX: 2, shiftKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetMouseScrollEvent (MozMousePixelScroll, vertical)",
targetID: "input-text", eventType: "MozMousePixelScroll",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 3, 4,
{ deltaY: 20, lineOrPageDeltaY: 1, altKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetMouseScrollEvent (MozMousePixelScroll, horizontal)",
targetID: "input-text", eventType: "MozMousePixelScroll",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 4, 5,
{ deltaX: 20, lineOrPageDeltaX: 1, ctrlKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetWheelEvent (wheel, vertical)",
targetID: "input-text", eventType: "wheel",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 3, 4,
{ deltaY: 20, lineOrPageDeltaY: 1, altKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetWheelEvent (wheel, horizontal)",
targetID: "input-text", eventType: "wheel",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 4, 5,
{ deltaX: 20, lineOrPageDeltaX: 1, ctrlKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetWheelEvent (wheel, both)",
targetID: "input-text", eventType: "wheel",
dispatchEvent: function () {
document.getElementById(this.targetID).value = "";
synthesizeWheel(document.getElementById(this.targetID), 4, 5,
{ deltaX: 20, deltaY: 10,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetTouchEvent (touchstart)",
target: function () { return document; }, eventType: "touchstart",
dispatchEvent: function () {
synthesizeTouchAtPoint(1, 2, { id: 10, rx: 4, ry: 3, angle: 0, force: 1, shiftKey: true});
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetTouchEvent (touchend)",
target: function () { return document; }, eventType: "touchend",
dispatchEvent: function () {
synthesizeTouchAtPoint(4, 6, { id: 5, rx: 1, ry: 2, angle: 0.5, force: 0.8, ctrlKey: true});
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "InternalFormEvent (reset)",
targetID: "form", eventType: "reset",
dispatchEvent: function () {
document.getElementById("form").reset();
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "WidgetCommandEvent",
targetID: "input-text", eventType: "",
dispatchEvent: function () {
return;
},
canRun: function () {
todo(false, "WidgetCommandEvent isn't tested");
return false;
},
todoMismatch: [],
},
{ description: "InternalClipboardEvent (copy)",
targetID: "input-text", eventType: "copy",
dispatchEvent: function () {
document.getElementById("input-text").value = "go to clipboard!";
document.getElementById("input-text").focus();
document.getElementById("input-text").select();
synthesizeKey("c", { accelKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [ ],
},
{ description: "InternalUIEvent (DOMActivate)",
targetID: "button", eventType: "DOMActivate",
dispatchEvent: function () {
synthesizeMouseAtCenter(document.getElementById(this.targetID),
{ button: 0, shiftKey: true });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalFocusEvent (focus)",
targetID: "input-text", eventType: "focus",
dispatchEvent: function () {
document.getElementById(this.targetID).focus();
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalFocusEvent (blur)",
targetID: "input-text", eventType: "blur",
dispatchEvent: function () {
document.getElementById(this.targetID).blur();
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "WidgetSimpleGestureEvent",
targetID: "", eventType: "",
dispatchEvent: function () {
return;
},
canRun: function () {
// Simple gesture event may be handled before it comes content.
// So, we cannot test it in this test.
todo(false, "WidgetSimpleGestureEvent isn't tested");
return false;
},
todoMismatch: [],
},
{ description: "InternalTransitionEvent (transitionend)",
targetID: "a", eventType: "transitionend",
dispatchEvent: function () {
document.getElementById(this.targetID).focus();
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalAnimationEvent (animationend)",
targetID: "animated-div", eventType: "animationend",
dispatchEvent: function () {
document.getElementById(this.targetID).className = "slidin";
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalMutationEvent (DOMAttrModified)",
targetID: "animated-div", eventType: "DOMAttrModified",
dispatchEvent: function () {
document.getElementById(this.targetID).setAttribute("x-data", "foo");
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalMutationEvent (DOMNodeInserted)",
targetID: "animated-div", eventType: "DOMNodeInserted",
dispatchEvent: function () {
var div = document.createElement("div");
div.id = "inserted-div";
document.getElementById("animated-div").appendChild(div);
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "InternalMutationEvent (DOMNodeRemoved)",
targetID: "animated-div", eventType: "DOMNodeRemoved",
dispatchEvent: function () {
document.getElementById("animated-div").removeChild(document.getElementById("inserted-div"));
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "PointerEvent (pointerdown)",
targetID: "pointer-target", eventType: "pointerdown",
dispatchEvent: function () {
var elem = document.getElementById(this.targetID);
var rect = elem.getBoundingClientRect();
synthesizePointer(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: 1, clickCount: 1, inputSource: 2, pressure: 0.25, isPrimary: true });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
{ description: "PointerEvent (pointerup)",
targetID: "pointer-target", eventType: "pointerup",
dispatchEvent: function () {
var elem = document.getElementById(this.targetID);
var rect = elem.getBoundingClientRect();
synthesizePointer(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: -1, ctrlKey: true, shiftKey: true, altKey: true, isSynthesized: false });
},
canRun: function () {
return true;
},
todoMismatch: [],
},
];
/**
* Sets or clears dom.keyboardevent.dispatch_during_composition and calls the
* given callback when the change is observed.
*
* @param aValue
* Pass null to clear the pref. Otherwise pass a bool.
* @param aCallback
* Called when the pref change is observed.
*/
function setAndObserveCompositionPref(aValue, aCallback) {
let pref = "dom.keyboardevent.dispatch_during_composition";
let branch = SpecialPowers.Cc["@mozilla.org/preferences-service;1"].
getService(SpecialPowers.Ci.nsIPrefService).
getBranch(pref);
let obs = SpecialPowers.wrapCallback(function () {
branch.removeObserver("", obs);
// Make sure the code under test sees the change first, so executeSoon().
SimpleTest.executeSoon(aCallback);
});
branch.addObserver("", obs, false);
if (aValue === null) {
SpecialPowers.clearUserPref(pref);
} else {
SpecialPowers.setBoolPref(pref, aValue);
}
}
function doTest(aTest)
{
if (!aTest.canRun()) {
SimpleTest.executeSoon(runNextTest);
return;
}
gEvent = null;
gCopiedEvent = [];
var target = aTest.target ? aTest.target() : document.getElementById(aTest.targetID);
target.addEventListener(aTest.eventType, onEvent, true);
gCallback = function () {
var description = aTest.description + " (gCallPreventDefault=" + gCallPreventDefault + ")";
target.removeEventListener(aTest.eventType, onEvent, true);
ok(gEvent !== null, description + ": failed to get duplicated event");
ok(gCopiedEvent.length > 0, description + ": count of attribute of the event must be larger than 0");
for (var i = 0; i < gCopiedEvent.length; ++i) {
var name = gCopiedEvent[i].name;
if (name == "rangeOffset") {
todo(false, description + ": " + name + " attribute value is never reset (" + gEvent[name] + ")");
} else if (name == "eventPhase") {
is(gEvent[name], 0, description + ": mismatch with fixed value (" + name + ")");
} else if (name == "rangeParent" || name == "currentTarget") {
is(gEvent[name], null, description + ": mismatch with fixed value (" + name + ")");
} else if (aTest.todoMismatch.indexOf(name) >= 0) {
todo_is(gEvent[name], gCopiedEvent[i].value, description + ": mismatch (" + name + ")");
} else if (name == "offsetX" || name == "offsetY") {
// do nothing; these are defined to return different values during event dispatch
// vs not during event dispatch
} else {
is(gEvent[name], gCopiedEvent[i].value, description + ": mismatch (" + name + ")");
}
}
if (!testWillCallRunNextTest) {
runNextTest();
}
};
var testWillCallRunNextTest = aTest.dispatchEvent();
}
var gIndex = -1;
function runNextTest()
{
if (++gIndex == kTests.length) {
if (gCallPreventDefault) {
finish();
return;
}
// Test with a call of preventDefault() of the events.
gCallPreventDefault = true;
gIndex = -1;
// Restoring the initial state of all elements.
document.getElementById("scrollable-div").style.height = "30px";
document.getElementById("scrollable-div").style.width = "30px";
document.getElementById("scrolled-div").style.height = "10px";
document.getElementById("scrolled-div").style.width = "10px";
document.getElementById("input-text").value = "";
document.getElementById("animated-div").className = "";
document.getElementById("animated-div").removeAttribute("x-data");
if (document.activeElement) {
document.activeElement.blur();
}
window.requestAnimationFrame(function () {
setTimeout(runNextTest, 0);
});
return;
}
doTest(kTests[gIndex]);
}
function init()
{
SpecialPowers.pushPrefEnv({"set":[["middlemouse.contentLoadURL", false],
["middlemouse.paste", false],
["general.autoScroll", false],
["mousewheel.default.action", 0],
["mousewheel.default.action.override_x", -1],
["mousewheel.with_shift.action", 0],
["mousewheel.with_shift.action.override_x", -1],
["mousewheel.with_control.action", 0],
["mousewheel.with_control.action.override_x", -1],
["mousewheel.with_alt.action", 0],
["mousewheel.with_alt.action.override_x", -1],
["mousewheel.with_meta.action", 0],
["mousewheel.with_meta.action.override_x", -1]]}, runNextTest);
}
function finish()
{
SimpleTest.finish();
}
SimpleTest.waitForFocus(init);
</script>
</body>

View file

@ -1,79 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480
-->
<window title="Mozilla Bug 1123480"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="RunTest();">
<title>nsTransferable PBM Overflow Selection Test</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript">
<![CDATA[
// Boilerplate constructs
var SmallDataset = 100000; // Hundred thousand bytes
// Create 1 Mo of sample garbage text
var Ipsum = ""; // Select text from this
for (var Iter = 0; Iter < SmallDataset; Iter++) {
Ipsum += Math.random().toString(36) + ' ';
}
function RunTest() {
// Construct a nsIFile object for access to file methods
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var clipboardFile = FileUtils.getFile("TmpD", ["clipboardcache"]);
// Sanitize environment
if (clipboardFile.exists()) {
clipboardFile.remove(false);
}
ok(!clipboardFile.exists(), "failed to presanitize the environment");
// Overflow a nsTransferable region by using the clipboard helper
const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
gClipboardHelper.copyString(Ipsum);
// Disabled private browsing mode should cache large selections to disk
ok(clipboardFile.exists(), "correctly saved memory by caching to disk");
// Sanitize environment again
if (clipboardFile.exists()) {
clipboardFile.remove(false);
}
ok(!clipboardFile.exists(), "failed to postsanitize the environment");
// Repeat procedure of plain text selection with private browsing enabled
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
var Winpriv = window.open("about:blank", "_blank", "chrome, width=500, height=200, private");
ok(Winpriv, "failed to open private window");
ok(PrivateBrowsingUtils.isContentWindowPrivate(Winpriv), "correctly used a private window context");
// Select plaintext in private channel
Components.utils.import('resource://gre/modules/Services.jsm');
const nsTransferable = Components.Constructor("@mozilla.org/widget/transferable;1", "nsITransferable");
const nsSupportsString = Components.Constructor("@mozilla.org/supports-string;1", "nsISupportsString");
var Loadctx = PrivateBrowsingUtils.privacyContextFromWindow(Winpriv);
var Transfer = nsTransferable();
var Suppstr = nsSupportsString();
Suppstr.data = Ipsum;
Transfer.init(Loadctx);
Transfer.addDataFlavor("text/plain");
Transfer.setTransferData("text/plain", Suppstr, Ipsum.length);
Services.clipboard.setData(Transfer, null, Services.clipboard.kGlobalClipboard);
// Enabled private browsing mode should not cache any selection to disk
ok(!clipboardFile.exists(), "did not violate private browsing mode");
}
]]>
</script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1123480"
target="_blank">Mozilla Bug 1123480</a>
</body>
</window>

View file

@ -1,43 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1151186
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1151186</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1151186 **/
SimpleTest.waitForExplicitFinish();
document.addEventListener("focus", () => {
document.getElementById("editor").focus();
SimpleTest.executeSoon(runTests);
});
function runTests()
{
is(document.activeElement, document.getElementById("editor"),
"The div element should be focused");
var utils = SpecialPowers.getDOMWindowUtils(window);
is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
"IME should be enabled");
SimpleTest.finish();
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151186">Mozilla Bug 1151186</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<div id="editor" contenteditable="true"></div>
<pre id="test">
</pre>
</body>
</html>

View file

@ -1,202 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=343416
-->
<window title="Mozilla Bug 343416"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=343416">Mozilla Bug 343416</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
/** Test for Bug 343416 **/
SimpleTest.waitForExplicitFinish();
// Observer:
var idleObserver =
{
QueryInterface: function _qi(iid)
{
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIObserver))
{
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
},
observe: function _observe(subject, topic, data)
{
if (topic != "idle")
return;
var diff = Math.abs(data - newIdleSeconds * 1000);
// ok (diff < 5000, "The idle time should have increased by roughly 6 seconds, " +
// "as that's when we told this listener to fire.");
// if (diff >= 5000)
// alert(data + " " + newIdleSeconds);
// Attempt to get to the nsIIdleService
var subjectOK = false;
try {
var idleService = subject.QueryInterface(nsIIdleService);
subjectOK = true;
}
catch (ex)
{}
ok(subjectOK, "The subject of the notification should be the " +
"nsIIdleService.");
// Attempt to remove ourselves.
var removedObserver = false;
try {
idleService.removeIdleObserver(this, newIdleSeconds);
removedObserver = true;
}
catch (ex)
{}
ok(removedObserver, "We should be able to remove our observer here.");
finishedListenerOK = true;
if (finishedTimeoutOK)
{
clearTimeout(testBailout);
finishThisTest();
}
}
};
const nsIIdleService = Components.interfaces.nsIIdleService;
const nsIISCID = "@mozilla.org/widget/idleservice;1";
var idleService = null;
try
{
idleService = Components.classes[nsIISCID].getService(nsIIdleService);
}
catch (ex)
{}
ok(idleService, "nsIIdleService should exist and be implemented on all tier 1 platforms.");
var idleTime = null;
var gotIdleTime = false;
try
{
idleTime = idleService.idleTime;
gotIdleTime = true;
}
catch (ex)
{}
ok (gotIdleTime, "Getting the idle time should not fail " +
"in normal circumstances on any tier 1 platform.");
// Now we set up a timeout to sanity-test the idleTime after 5 seconds
setTimeout(testIdleTime, 5000);
var startTimeStamp = Date.now();
// Now we add the listener:
var newIdleSeconds = Math.floor(idleTime / 1000) + 6;
var addedObserver = false;
try
{
idleService.addIdleObserver(idleObserver, newIdleSeconds);
addedObserver = true;
}
catch (ex)
{}
ok(addedObserver, "The nsIIdleService should allow us to add an observer.");
addedObserver = false;
try
{
idleService.addIdleObserver(idleObserver, newIdleSeconds);
addedObserver = true;
}
catch (ex)
{}
ok(addedObserver, "The nsIIdleService should allow us to add the same observer again.");
var removedObserver = false;
try
{
idleService.removeIdleObserver(idleObserver, newIdleSeconds);
removedObserver = true;
}
catch (ex)
{}
ok(removedObserver, "The nsIIdleService should allow us to remove the observer just once.");
function testIdleTime()
{
var gotIdleTime = false
try
{
var newIdleTime = idleService.idleTime;
gotIdleTime = true
}
catch (ex)
{}
ok(gotIdleTime, "Getting the idle time should not fail " +
"in normal circumstances on any tier 1 platform.");
// Get the time difference, remove the approx. 5 seconds that we've waited,
// should be very close to 0 left.
var timeDiff = Math.abs((newIdleTime - idleTime) -
(Date.now() - startTimeStamp));
var timePassed = Date.now() - startTimeStamp;
var idleTimeDiff = newIdleTime - idleTime;
// 1.5 second leniency.
ok(timeDiff < 1500, "The idle time should have increased by roughly the " +
"amount of time it took for the timeout to fire. " +
"You didn't touch the mouse or keyboard during the " +
"test did you?");
finishedTimeoutOK = true;
}
// make sure we still exit when the listener and/or setTimeout don't fire:
var testBailout = setTimeout(finishThisTest, 12000);
var finishedTimeoutOK = false, finishedListenerOK = false;
function finishThisTest()
{
ok(finishedTimeoutOK, "We set a timeout and it should have fired by now.");
ok(finishedListenerOK, "We added a listener and it should have been called by now.");
if (!finishedListenerOK)
{
var removedListener = false;
try
{
idleService.removeIdleObserver(idleObserver, newIdleSeconds);
removedListener = true;
}
catch (ex)
{}
ok(removedListener, "We added a listener and we should be able to remove it.");
}
// Done:
SimpleTest.finish();
}
]]>
</script>
</window>

View file

@ -1,36 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=413277
-->
<head>
<title>Test for Bug 413277</title>
<script type="text/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=413277">Mozilla Bug 413277</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript">
var atts='width=100, height=100, top=100, screenY=100';
atts += ', left=100, screenX=100, toolbar=no';
atts += ', location=no, directories=no, status=no';
atts += ', menubar=no, scrollbars=no, resizable=no';
var newWindow = window.open('_blank', 'win_name', atts);
newWindow.resizeBy(1000000, 1000000);
SimpleTest.is(newWindow.outerWidth, newWindow.screen.availWidth, true);
SimpleTest.is(newWindow.outerHeight, newWindow.screen.availHeight, true);
SimpleTest.is(newWindow.screenY, newWindow.screen.availTop, true);
SimpleTest.is(newWindow.screenX, newWindow.screen.availLeft, true);
newWindow.close();
</script>
</pre>
</body>

Some files were not shown because too many files have changed in this diff Show more