зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
d53e4a6316
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "eff18c4265f0d8e49e5a2f2d7c9fdb01c87bd42e",
|
||||
"revision": "097d333ddd568576aa933f9259b7f6ee1f62d41f",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="01d86c8cc615658694b114ca5711763efc4ef205"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -812,7 +812,6 @@ pref("plugin.state.f5 sam inspection host plugin", 2);
|
|||
// display door hanger if flash not installed
|
||||
pref("plugins.notifyMissingFlash", true);
|
||||
|
||||
pref("browser.preferences.instantApply", true);
|
||||
#ifdef XP_MACOSX
|
||||
pref("browser.preferences.animateFadeIn", true);
|
||||
#else
|
||||
|
@ -820,7 +819,17 @@ pref("browser.preferences.animateFadeIn", false);
|
|||
#endif
|
||||
|
||||
// Toggles between the two Preferences implementations, pop-up window and in-content
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("browser.preferences.inContent", true);
|
||||
pref("browser.preferences.instantApply", true);
|
||||
#else
|
||||
pref("browser.preferences.inContent", false);
|
||||
#ifdef XP_WIN
|
||||
pref("browser.preferences.instantApply", false);
|
||||
#else
|
||||
pref("browser.preferences.instantApply", true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
pref("browser.download.show_plugins_in_list", true);
|
||||
pref("browser.download.hide_plugins_without_extensions", true);
|
||||
|
|
|
@ -975,6 +975,10 @@ GK_ATOM(rp, "rp")
|
|||
GK_ATOM(rt, "rt")
|
||||
GK_ATOM(rtl, "rtl")
|
||||
GK_ATOM(ruby, "ruby")
|
||||
GK_ATOM(rubyBase, "ruby-base")
|
||||
GK_ATOM(rubyBaseContainer, "ruby-base-container")
|
||||
GK_ATOM(rubyText, "ruby-text")
|
||||
GK_ATOM(rubyTextContainer, "ruby-text-container")
|
||||
GK_ATOM(rule, "rule")
|
||||
GK_ATOM(rules, "rules")
|
||||
GK_ATOM(s, "s")
|
||||
|
@ -1876,6 +1880,11 @@ GK_ATOM(popupSetFrame, "PopupSetFrame")
|
|||
GK_ATOM(canvasFrame, "CanvasFrame")
|
||||
GK_ATOM(rangeFrame, "RangeFrame")
|
||||
GK_ATOM(rootFrame, "RootFrame")
|
||||
GK_ATOM(rubyBaseContainerFrame, "RubyBaseContainerFrame")
|
||||
GK_ATOM(rubyBaseFrame, "RubyBaseFrame")
|
||||
GK_ATOM(rubyFrame, "RubyFrame")
|
||||
GK_ATOM(rubyTextContainerFrame, "RubyTextContainerFrame")
|
||||
GK_ATOM(rubyTextFrame, "RubyTextFrame")
|
||||
GK_ATOM(scrollFrame, "ScrollFrame")
|
||||
GK_ATOM(scrollbarFrame, "ScrollbarFrame")
|
||||
GK_ATOM(sequenceFrame, "SequenceFrame")
|
||||
|
|
|
@ -169,7 +169,7 @@ public:
|
|||
}
|
||||
|
||||
NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK);
|
||||
sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs);
|
||||
sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs, nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -492,6 +492,75 @@ static btrc_callbacks_t sBtAvrcpCallbacks = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION > 17
|
||||
class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
|
||||
{
|
||||
public:
|
||||
InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothAvrcpInterface::Init failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() MOZ_OVERRIDE
|
||||
{
|
||||
if (mRes) {
|
||||
mRes->Init();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
#endif
|
||||
|
||||
class InitA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
|
||||
{
|
||||
public:
|
||||
InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothA2dpInterface::Init failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() MOZ_OVERRIDE
|
||||
{
|
||||
#if ANDROID_VERSION > 17
|
||||
/* Also init AVRCP if it's available, ... */
|
||||
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
|
||||
NS_ENSURE_TRUE_VOID(btInf);
|
||||
|
||||
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
|
||||
NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
|
||||
|
||||
sBtAvrcpInterface->Init(&sBtAvrcpCallbacks,
|
||||
new InitAvrcpResultHandler(mRes));
|
||||
#else
|
||||
/* ...or signal success otherwise. */
|
||||
if (mRes) {
|
||||
mRes->Init();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function will be only called when Bluetooth is turning on.
|
||||
* It is important to register a2dp callbacks before enable() gets called.
|
||||
|
@ -508,24 +577,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
|||
sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
|
||||
NS_ENSURE_TRUE_VOID(sBtA2dpInterface);
|
||||
|
||||
int ret = sBtA2dpInterface->Init(&sBtA2dpCallbacks);
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
BT_LOGR("Warning: failed to init a2dp module");
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION > 17
|
||||
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
|
||||
NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
|
||||
|
||||
ret = sBtAvrcpInterface->Init(&sBtAvrcpCallbacks);
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
BT_LOGR("Warning: failed to init avrcp module");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
aRes->Init();
|
||||
}
|
||||
sBtA2dpInterface->Init(&sBtA2dpCallbacks, new InitA2dpResultHandler(aRes));
|
||||
}
|
||||
|
||||
BluetoothA2dpManager::~BluetoothA2dpManager()
|
||||
|
@ -599,6 +651,99 @@ BluetoothA2dpManager::Get()
|
|||
return sBluetoothA2dpManager;
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION > 17
|
||||
class CleanupAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
|
||||
{
|
||||
public:
|
||||
CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup() MOZ_OVERRIDE
|
||||
{
|
||||
sBtAvrcpInterface = nullptr;
|
||||
if (mRes) {
|
||||
mRes->Deinit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
#endif
|
||||
|
||||
class CleanupA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
|
||||
{
|
||||
public:
|
||||
CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup() MOZ_OVERRIDE
|
||||
{
|
||||
sBtA2dpInterface = nullptr;
|
||||
#if ANDROID_VERSION > 17
|
||||
/* Cleanup AVRCP if it's available and initialized, ...*/
|
||||
if (sBtAvrcpInterface) {
|
||||
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
|
||||
} else
|
||||
#endif
|
||||
if (mRes) {
|
||||
/* ...or simply signal success from here. */
|
||||
mRes->Deinit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
CleanupA2dpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
sBtA2dpInterface = nullptr;
|
||||
#if ANDROID_VERSION > 17
|
||||
/* Cleanup AVRCP if it's available and initialized, ...*/
|
||||
if (sBtAvrcpInterface) {
|
||||
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
|
||||
} else
|
||||
#endif
|
||||
if (mRes) {
|
||||
/* ...or simply signal success from here. */
|
||||
mRes->Deinit();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
// static
|
||||
void
|
||||
BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||
|
@ -606,17 +751,14 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sBtA2dpInterface) {
|
||||
sBtA2dpInterface->Cleanup();
|
||||
sBtA2dpInterface = nullptr;
|
||||
}
|
||||
#if ANDROID_VERSION > 17
|
||||
if (sBtAvrcpInterface) {
|
||||
sBtAvrcpInterface->Cleanup();
|
||||
sBtAvrcpInterface = nullptr;
|
||||
}
|
||||
#endif
|
||||
if (aRes) {
|
||||
aRes->Deinit();
|
||||
sBtA2dpInterface->Cleanup(new CleanupA2dpResultHandler(aRes));
|
||||
} else if (aRes) {
|
||||
// We dispatch a runnable here to make the profile resource handler
|
||||
// behave as if A2DP was initialized.
|
||||
nsRefPtr<nsRunnable> r = new CleanupA2dpResultHandlerRunnable(aRes);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -629,6 +771,29 @@ BluetoothA2dpManager::HandleShutdown()
|
|||
sBluetoothA2dpManager = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::OnConnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
|
||||
|
||||
mController = nullptr;
|
||||
mDeviceAddress.Truncate();
|
||||
}
|
||||
|
||||
class ConnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
|
||||
{
|
||||
public:
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_LOGR("BluetoothA2dpInterface::Connect failed: %d", (int)aStatus);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
|
||||
sBluetoothA2dpManager->OnConnectError();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress,
|
||||
BluetoothProfileController* aController)
|
||||
|
@ -660,14 +825,29 @@ BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress,
|
|||
bt_bdaddr_t remoteAddress;
|
||||
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||
|
||||
bt_status_t result = sBtA2dpInterface->Connect(&remoteAddress);
|
||||
if (BT_STATUS_SUCCESS != result) {
|
||||
BT_LOGR("Failed to connect: %x", result);
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
|
||||
return;
|
||||
}
|
||||
sBtA2dpInterface->Connect(&remoteAddress, new ConnectResultHandler());
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::OnDisconnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
|
||||
}
|
||||
|
||||
class DisconnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
|
||||
{
|
||||
public:
|
||||
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_LOGR("BluetoothA2dpInterface::Disconnect failed: %d", (int)aStatus);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
|
||||
sBluetoothA2dpManager->OnDisconnectError();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
|
||||
{
|
||||
|
@ -702,12 +882,7 @@ BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
|
|||
bt_bdaddr_t remoteAddress;
|
||||
StringToBdAddressType(mDeviceAddress, &remoteAddress);
|
||||
|
||||
bt_status_t result = sBtA2dpInterface->Disconnect(&remoteAddress);
|
||||
if (BT_STATUS_SUCCESS != result) {
|
||||
BT_LOGR("Failed to disconnect: %x", result);
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
|
||||
return;
|
||||
}
|
||||
sBtA2dpInterface->Disconnect(&remoteAddress, new DisconnectResultHandler());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -939,7 +1114,7 @@ BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
|
|||
mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
|
||||
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_TRACK_CHANGE,
|
||||
BTRC_NOTIFICATION_TYPE_CHANGED,
|
||||
¶m);
|
||||
¶m, nullptr);
|
||||
if (mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
|
||||
param.song_pos = mPosition;
|
||||
// EVENT_PLAYBACK_POS_CHANGED shall be notified if changed current track
|
||||
|
@ -947,7 +1122,7 @@ BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
|
|||
sBtAvrcpInterface->RegisterNotificationRsp(
|
||||
BTRC_EVT_PLAY_POS_CHANGED,
|
||||
BTRC_NOTIFICATION_TYPE_CHANGED,
|
||||
¶m);
|
||||
¶m, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,7 +1150,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
|
|||
NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
|
||||
// always update playstatus first
|
||||
sBtAvrcpInterface->GetPlayStatusRsp((btrc_play_status_t)aPlayStatus,
|
||||
aDuration, aPosition);
|
||||
aDuration, aPosition, nullptr);
|
||||
// when play status changed, send both play status and position
|
||||
if (mPlayStatus != aPlayStatus &&
|
||||
mPlayStatusChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
|
||||
|
@ -984,7 +1159,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
|
|||
mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
|
||||
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_STATUS_CHANGED,
|
||||
BTRC_NOTIFICATION_TYPE_CHANGED,
|
||||
¶m);
|
||||
¶m, nullptr);
|
||||
}
|
||||
|
||||
if (mPosition != aPosition &&
|
||||
|
@ -994,7 +1169,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
|
|||
mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
|
||||
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_POS_CHANGED,
|
||||
BTRC_NOTIFICATION_TYPE_CHANGED,
|
||||
¶m);
|
||||
¶m, nullptr);
|
||||
}
|
||||
|
||||
mDuration = aDuration;
|
||||
|
@ -1062,7 +1237,7 @@ BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam)
|
|||
|
||||
sBtAvrcpInterface->RegisterNotificationRsp((btrc_event_id_t)aEventId,
|
||||
BTRC_NOTIFICATION_TYPE_INTERIM,
|
||||
¶m);
|
||||
¶m, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ public:
|
|||
static void DeinitA2dpInterface(BluetoothProfileResultHandler* aRes);
|
||||
virtual ~BluetoothA2dpManager();
|
||||
|
||||
void OnConnectError();
|
||||
void OnDisconnectError();
|
||||
|
||||
// A2DP-specific functions
|
||||
void HandleSinkPropertyChanged(const BluetoothSignal& aSignal);
|
||||
|
||||
|
|
|
@ -847,6 +847,37 @@ struct interface_traits<BluetoothA2dpInterface>
|
|||
}
|
||||
};
|
||||
|
||||
typedef
|
||||
BluetoothInterfaceRunnable0<BluetoothA2dpResultHandler, void>
|
||||
BluetoothA2dpResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void, bt_status_t>
|
||||
BluetoothA2dpErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothA2dpResult(
|
||||
BluetoothA2dpResultHandler* aRes,
|
||||
void (BluetoothA2dpResultHandler::*aMethod)(),
|
||||
bt_status_t aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRunnable* runnable;
|
||||
|
||||
if (aStatus == BT_STATUS_SUCCESS) {
|
||||
runnable = new BluetoothA2dpResultRunnable(aRes, aMethod);
|
||||
} else {
|
||||
runnable = new BluetoothA2dpErrorRunnable(aRes,
|
||||
&BluetoothA2dpResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
BluetoothA2dpInterface::BluetoothA2dpInterface(
|
||||
const btav_interface_t* aInterface)
|
||||
: mInterface(aInterface)
|
||||
|
@ -857,28 +888,51 @@ BluetoothA2dpInterface::BluetoothA2dpInterface(
|
|||
BluetoothA2dpInterface::~BluetoothA2dpInterface()
|
||||
{ }
|
||||
|
||||
bt_status_t
|
||||
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks)
|
||||
void
|
||||
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->init(aCallbacks);
|
||||
bt_status_t status = mInterface->init(aCallbacks);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init,
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpInterface::Cleanup()
|
||||
BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
mInterface->cleanup();
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
|
||||
BT_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr)
|
||||
void
|
||||
BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->connect(aBdAddr);
|
||||
bt_status_t status = mInterface->connect(aBdAddr);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Connect,
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr)
|
||||
void
|
||||
BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->disconnect(aBdAddr);
|
||||
bt_status_t status = mInterface->disconnect(aBdAddr);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Disconnect,
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -897,6 +951,37 @@ struct interface_traits<BluetoothAvrcpInterface>
|
|||
}
|
||||
};
|
||||
|
||||
typedef
|
||||
BluetoothInterfaceRunnable0<BluetoothAvrcpResultHandler, void>
|
||||
BluetoothAvrcpResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void, bt_status_t>
|
||||
BluetoothAvrcpErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothAvrcpResult(
|
||||
BluetoothAvrcpResultHandler* aRes,
|
||||
void (BluetoothAvrcpResultHandler::*aMethod)(),
|
||||
bt_status_t aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRunnable* runnable;
|
||||
|
||||
if (aStatus == BT_STATUS_SUCCESS) {
|
||||
runnable = new BluetoothAvrcpResultRunnable(aRes, aMethod);
|
||||
} else {
|
||||
runnable = new BluetoothAvrcpErrorRunnable(aRes,
|
||||
&BluetoothAvrcpResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
BluetoothAvrcpInterface::BluetoothAvrcpInterface(
|
||||
const btrc_interface_t* aInterface)
|
||||
: mInterface(aInterface)
|
||||
|
@ -907,86 +992,157 @@ BluetoothAvrcpInterface::BluetoothAvrcpInterface(
|
|||
BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
|
||||
{ }
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks)
|
||||
void
|
||||
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->init(aCallbacks);
|
||||
bt_status_t status = mInterface->init(aCallbacks);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init,
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpInterface::Cleanup()
|
||||
BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
mInterface->cleanup();
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
|
||||
BT_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
void
|
||||
BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
|
||||
uint32_t aSongLen, uint32_t aSongPos)
|
||||
uint32_t aSongLen, uint32_t aSongPos,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->get_play_status_rsp(aPlayStatus, aSongLen, aSongPos);
|
||||
bt_status_t status = mInterface->get_play_status_rsp(aPlayStatus, aSongLen,
|
||||
aSongPos);
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::ListPlayerAppAttrRsp(int aNumAttr,
|
||||
btrc_player_attr_t* aPAttrs)
|
||||
void
|
||||
BluetoothAvrcpInterface::ListPlayerAppAttrRsp(
|
||||
int aNumAttr, btrc_player_attr_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
|
||||
bt_status_t status = mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals)
|
||||
void
|
||||
BluetoothAvrcpInterface::ListPlayerAppValueRsp(
|
||||
int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->list_player_app_value_rsp(aNumVal, aPVals);
|
||||
bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::GetPlayerAppValueRsp(btrc_player_settings_t* aPVals)
|
||||
void
|
||||
BluetoothAvrcpInterface::GetPlayerAppValueRsp(
|
||||
btrc_player_settings_t* aPVals, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->get_player_app_value_rsp(aPVals);
|
||||
bt_status_t status = mInterface->get_player_app_value_rsp(aPVals);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(int aNumAttr,
|
||||
btrc_player_setting_text_t* aPAttrs)
|
||||
void
|
||||
BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(
|
||||
int aNumAttr, btrc_player_setting_text_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs);
|
||||
bt_status_t status = mInterface->get_player_app_attr_text_rsp(aNumAttr,
|
||||
aPAttrs);
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(int aNumVal,
|
||||
btrc_player_setting_text_t* aPVals)
|
||||
void
|
||||
BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(
|
||||
int aNumVal, btrc_player_setting_text_t* aPVals,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->get_player_app_value_text_rsp(aNumVal, aPVals);
|
||||
bt_status_t status = mInterface->get_player_app_value_text_rsp(aNumVal,
|
||||
aPVals);
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::GetElementAttrRsp(uint8_t aNumAttr,
|
||||
btrc_element_attr_val_t* aPAttrs)
|
||||
void
|
||||
BluetoothAvrcpInterface::GetElementAttrRsp(
|
||||
uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
|
||||
bt_status_t status = mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::SetPlayerAppValueRsp(btrc_status_t aRspStatus)
|
||||
void
|
||||
BluetoothAvrcpInterface::SetPlayerAppValueRsp(
|
||||
btrc_status_t aRspStatus, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->set_player_app_value_rsp(aRspStatus);
|
||||
bt_status_t status = mInterface->set_player_app_value_rsp(aRspStatus);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::RegisterNotificationRsp(btrc_event_id_t aEventId,
|
||||
btrc_notification_type_t aType, btrc_register_notification_t* aPParam)
|
||||
void
|
||||
BluetoothAvrcpInterface::RegisterNotificationRsp(
|
||||
btrc_event_id_t aEventId, btrc_notification_type_t aType,
|
||||
btrc_register_notification_t* aPParam, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
return mInterface->register_notification_rsp(aEventId, aType, aPParam);
|
||||
bt_status_t status = mInterface->register_notification_rsp(aEventId, aType,
|
||||
aPParam);
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, status);
|
||||
}
|
||||
}
|
||||
|
||||
bt_status_t
|
||||
BluetoothAvrcpInterface::SetVolume(uint8_t aVolume)
|
||||
void
|
||||
BluetoothAvrcpInterface::SetVolume(uint8_t aVolume,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
#if ANDROID_VERSION >= 19
|
||||
return mInterface->set_volume(aVolume);
|
||||
bt_status_t status = mInterface->set_volume(aVolume);
|
||||
#else
|
||||
return BT_STATUS_UNSUPPORTED;
|
||||
bt_status_t status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::SetVolume, status);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -181,16 +181,37 @@ private:
|
|||
// Bluetooth Advanced Audio Interface
|
||||
//
|
||||
|
||||
class BluetoothA2dpResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothA2dpResultHandler)
|
||||
|
||||
virtual ~BluetoothA2dpResultHandler() { }
|
||||
|
||||
virtual void OnError(bt_status_t aStatus)
|
||||
{
|
||||
BT_WARNING("received error code %d", (int)aStatus);
|
||||
}
|
||||
|
||||
virtual void Init() { }
|
||||
virtual void Cleanup() { }
|
||||
virtual void Connect() { }
|
||||
virtual void Disconnect() { }
|
||||
};
|
||||
|
||||
class BluetoothA2dpInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothInterface;
|
||||
|
||||
bt_status_t Init(btav_callbacks_t *aCallbacks);
|
||||
void Cleanup();
|
||||
void Init(btav_callbacks_t *aCallbacks,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
void Cleanup(BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
bt_status_t Connect(bt_bdaddr_t *aBdAddr);
|
||||
bt_status_t Disconnect(bt_bdaddr_t *aBdAddr);
|
||||
void Connect(bt_bdaddr_t *aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
void Disconnect(bt_bdaddr_t *aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothA2dpInterface(const btav_interface_t* aInterface);
|
||||
|
@ -204,37 +225,79 @@ private:
|
|||
// Bluetooth AVRCP Interface
|
||||
//
|
||||
|
||||
class BluetoothAvrcpResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothAvrcpResultHandler)
|
||||
|
||||
virtual ~BluetoothAvrcpResultHandler() { }
|
||||
|
||||
virtual void OnError(bt_status_t aStatus)
|
||||
{
|
||||
BT_WARNING("received error code %d", (int)aStatus);
|
||||
}
|
||||
|
||||
virtual void Init() { }
|
||||
virtual void Cleanup() { }
|
||||
|
||||
virtual void GetPlayStatusRsp() { }
|
||||
|
||||
virtual void ListPlayerAppAttrRsp() { }
|
||||
virtual void ListPlayerAppValueRsp() { }
|
||||
|
||||
virtual void GetPlayerAppValueRsp() { }
|
||||
virtual void GetPlayerAppAttrTextRsp() { }
|
||||
virtual void GetPlayerAppValueTextRsp() { }
|
||||
|
||||
virtual void GetElementAttrRsp() { }
|
||||
|
||||
virtual void SetPlayerAppValueRsp() { }
|
||||
|
||||
virtual void RegisterNotificationRsp() { }
|
||||
|
||||
virtual void SetVolume() { }
|
||||
};
|
||||
|
||||
class BluetoothAvrcpInterface
|
||||
{
|
||||
#if ANDROID_VERSION >= 18
|
||||
public:
|
||||
friend class BluetoothInterface;
|
||||
|
||||
bt_status_t Init(btrc_callbacks_t* aCallbacks);
|
||||
void Cleanup();
|
||||
void Init(btrc_callbacks_t* aCallbacks,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void Cleanup(BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
|
||||
uint32_t aSongLen, uint32_t aSongPos);
|
||||
void GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
|
||||
uint32_t aSongLen, uint32_t aSongPos,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs);
|
||||
bt_status_t ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals);
|
||||
void ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t GetPlayerAppValueRsp(btrc_player_settings_t* aPVals);
|
||||
bt_status_t GetPlayerAppAttrTextRsp(int aNumAttr,
|
||||
btrc_player_setting_text_t* aPAttrs);
|
||||
bt_status_t GetPlayerAppValueTextRsp(int aNumVal,
|
||||
btrc_player_setting_text_t* aPVals);
|
||||
void GetPlayerAppValueRsp(btrc_player_settings_t* aPVals,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void GetPlayerAppAttrTextRsp(int aNumAttr,
|
||||
btrc_player_setting_text_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void GetPlayerAppValueTextRsp(int aNumVal,
|
||||
btrc_player_setting_text_t* aPVals,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t GetElementAttrRsp(uint8_t aNumAttr,
|
||||
btrc_element_attr_val_t* aPAttrs);
|
||||
void GetElementAttrRsp(uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t SetPlayerAppValueRsp(btrc_status_t aRspStatus);
|
||||
void SetPlayerAppValueRsp(btrc_status_t aRspStatus,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t RegisterNotificationRsp(btrc_event_id_t aEventId,
|
||||
btrc_notification_type_t aType,
|
||||
btrc_register_notification_t* aPParam);
|
||||
void RegisterNotificationRsp(btrc_event_id_t aEventId,
|
||||
btrc_notification_type_t aType,
|
||||
btrc_register_notification_t* aPParam,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
bt_status_t SetVolume(uint8_t aVolume);
|
||||
void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothAvrcpInterface(const btrc_interface_t* aInterface);
|
||||
|
|
|
@ -62,6 +62,11 @@
|
|||
#include "nsBoxLayout.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
#include "nsGridContainerFrame.h"
|
||||
#include "nsRubyFrame.h"
|
||||
#include "nsRubyBaseFrame.h"
|
||||
#include "nsRubyBaseContainerFrame.h"
|
||||
#include "nsRubyTextFrame.h"
|
||||
#include "nsRubyTextContainerFrame.h"
|
||||
#include "nsImageFrame.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -1877,6 +1882,15 @@ nsCSSFrameConstructor::GetParentType(nsIAtom* aFrameType)
|
|||
if (aFrameType == nsGkAtoms::tableColGroupFrame) {
|
||||
return eTypeColGroup;
|
||||
}
|
||||
if (aFrameType == nsGkAtoms::rubyBaseContainerFrame) {
|
||||
return eTypeRubyBaseContainer;
|
||||
}
|
||||
if (aFrameType == nsGkAtoms::rubyTextContainerFrame) {
|
||||
return eTypeRubyTextContainer;
|
||||
}
|
||||
if (aFrameType == nsGkAtoms::rubyFrame) {
|
||||
return eTypeRuby;
|
||||
}
|
||||
|
||||
return eTypeBlock;
|
||||
}
|
||||
|
@ -2251,7 +2265,7 @@ NeedFrameFor(const nsFrameConstructorState& aState,
|
|||
// should be considered ignorable just because they evaluate to
|
||||
// whitespace.
|
||||
|
||||
// We could handle all this in CreateNeededTablePseudos or some other place
|
||||
// We could handle all this in CreateNeededPseudos or some other place
|
||||
// after we build our frame construction items, but that would involve
|
||||
// creating frame construction items for whitespace kids of
|
||||
// eExcludesIgnorableWhitespace frames, where we know we'll be dropping them
|
||||
|
@ -4529,6 +4543,21 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
|
|||
FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
|
||||
{ NS_STYLE_DISPLAY_INLINE_GRID,
|
||||
FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
|
||||
{ NS_STYLE_DISPLAY_RUBY,
|
||||
FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT,
|
||||
NS_NewRubyFrame) },
|
||||
{ NS_STYLE_DISPLAY_RUBY_BASE,
|
||||
FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer),
|
||||
NS_NewRubyBaseFrame) },
|
||||
{ NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER,
|
||||
FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
|
||||
NS_NewRubyBaseContainerFrame) },
|
||||
{ NS_STYLE_DISPLAY_RUBY_TEXT,
|
||||
FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer),
|
||||
NS_NewRubyTextFrame) },
|
||||
{ NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER,
|
||||
FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
|
||||
NS_NewRubyTextContainerFrame) },
|
||||
{ NS_STYLE_DISPLAY_TABLE,
|
||||
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
|
||||
{ NS_STYLE_DISPLAY_INLINE_TABLE,
|
||||
|
@ -8315,6 +8344,12 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
|
|||
} else if (nsGkAtoms::flexContainerFrame == frameType) {
|
||||
newFrame = NS_NewFlexContainerFrame(shell, styleContext);
|
||||
newFrame->Init(content, aParentFrame, aFrame);
|
||||
//TODO: Add conditionals for rubyFrame and rubyBaseContainerFrame
|
||||
// once their reflow methods are advanced enough to return
|
||||
// non-complete statuses
|
||||
} else if (nsGkAtoms::rubyTextContainerFrame == frameType) {
|
||||
newFrame = NS_NewRubyTextContainerFrame(shell, styleContext);
|
||||
newFrame->Init(content, aParentFrame, aFrame);
|
||||
} else {
|
||||
NS_RUNTIMEABORT("unexpected frame type");
|
||||
}
|
||||
|
@ -8983,6 +9018,41 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
|
|||
FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
|
||||
&nsCSSFrameConstructor::ConstructTable),
|
||||
&nsCSSAnonBoxes::table
|
||||
},
|
||||
{ // Ruby
|
||||
FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
|
||||
FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_SKIP_FRAMESET,
|
||||
NS_NewRubyFrame),
|
||||
&nsCSSAnonBoxes::ruby
|
||||
},
|
||||
{ // Ruby Base
|
||||
FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer) |
|
||||
FCDATA_SKIP_FRAMESET,
|
||||
NS_NewRubyBaseFrame),
|
||||
&nsCSSAnonBoxes::rubyBase
|
||||
},
|
||||
{ // Ruby Base Container
|
||||
FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
|
||||
FCDATA_SKIP_FRAMESET,
|
||||
NS_NewRubyBaseContainerFrame),
|
||||
&nsCSSAnonBoxes::rubyBaseContainer
|
||||
},
|
||||
{ // Ruby Text
|
||||
FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer) |
|
||||
FCDATA_SKIP_FRAMESET,
|
||||
NS_NewRubyTextFrame),
|
||||
&nsCSSAnonBoxes::rubyText
|
||||
},
|
||||
{ // Ruby Text Container
|
||||
FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
|
||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
|
||||
FCDATA_SKIP_FRAMESET,
|
||||
NS_NewRubyTextContainerFrame),
|
||||
&nsCSSAnonBoxes::rubyTextContainer
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9115,9 +9185,9 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
|
|||
* contain only items for frames that can be direct kids of aParentFrame.
|
||||
*/
|
||||
void
|
||||
nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
||||
FrameConstructionItemList& aItems,
|
||||
nsIFrame* aParentFrame)
|
||||
nsCSSFrameConstructor::CreateNeededPseudos(nsFrameConstructorState& aState,
|
||||
FrameConstructionItemList& aItems,
|
||||
nsIFrame* aParentFrame)
|
||||
{
|
||||
ParentType ourParentType = GetParentType(aParentFrame);
|
||||
if (aItems.AllWantParentType(ourParentType)) {
|
||||
|
@ -9178,6 +9248,7 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
|||
if ((trailingSpaces && ourParentType != eTypeBlock) ||
|
||||
(!trailingSpaces && spaceEndIter.item().DesiredParentType() !=
|
||||
eTypeBlock)) {
|
||||
//TODO: Add whitespace handling for ruby
|
||||
bool updateStart = (iter == endIter);
|
||||
endIter.DeleteItemsTo(spaceEndIter);
|
||||
NS_ASSERTION(trailingSpaces == endIter.IsDone(), "These should match");
|
||||
|
@ -9217,6 +9288,13 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
|||
break;
|
||||
}
|
||||
|
||||
// Don't group ruby base boxes and ruby annotation boxes together
|
||||
if (ourParentType == eTypeRuby &&
|
||||
(prevParentType == eTypeRubyTextContainer) !=
|
||||
(groupingParentType == eTypeRubyTextContainer)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Include the whitespace we didn't drop (if any) in the group, since
|
||||
// this is not the end of the group. Note that this doesn't change
|
||||
// prevParentType, since if we didn't drop the whitespace then we ended
|
||||
|
@ -9236,9 +9314,6 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
|||
// parent type to use depends on ourParentType.
|
||||
ParentType wrapperType;
|
||||
switch (ourParentType) {
|
||||
case eTypeBlock:
|
||||
wrapperType = eTypeTable;
|
||||
break;
|
||||
case eTypeRow:
|
||||
// The parent type for a cell is eTypeBlock, since that's what a cell
|
||||
// looks like to its kids.
|
||||
|
@ -9252,8 +9327,30 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
|||
wrapperType = groupingParentType == eTypeColGroup ?
|
||||
eTypeColGroup : eTypeRowGroup;
|
||||
break;
|
||||
default:
|
||||
case eTypeColGroup:
|
||||
MOZ_CRASH("Colgroups should be suppresing non-col child items");
|
||||
case eTypeRuby:
|
||||
if (groupingParentType == eTypeRubyTextContainer) {
|
||||
wrapperType = eTypeRubyTextContainer;
|
||||
} else {
|
||||
wrapperType = eTypeRubyBaseContainer;
|
||||
}
|
||||
break;
|
||||
case eTypeRubyBaseContainer:
|
||||
wrapperType = eTypeRubyBase;
|
||||
break;
|
||||
case eTypeRubyTextContainer:
|
||||
wrapperType = eTypeRubyText;
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(ourParentType == eTypeBlock, "Unrecognized parent type");
|
||||
if (IsRubyParentType(groupingParentType)) {
|
||||
wrapperType = eTypeRuby;
|
||||
} else {
|
||||
NS_ASSERTION(IsTableParentType(groupingParentType),
|
||||
"groupingParentType should be either Ruby or table");
|
||||
wrapperType = eTypeTable;
|
||||
}
|
||||
}
|
||||
|
||||
const PseudoParentData& pseudoData = sPseudoParentData[wrapperType];
|
||||
|
@ -9262,7 +9359,10 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
|||
nsIContent* parentContent = aParentFrame->GetContent();
|
||||
|
||||
if (pseudoType == nsCSSAnonBoxes::table &&
|
||||
parentStyle->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE) {
|
||||
(parentStyle->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE ||
|
||||
IsRubyParentType(ourParentType) ||
|
||||
parentStyle->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE ||
|
||||
parentStyle->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_RUBY_TEXT)) {
|
||||
pseudoType = nsCSSAnonBoxes::inlineTable;
|
||||
}
|
||||
|
||||
|
@ -9318,7 +9418,7 @@ nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aSta
|
|||
nsContainerFrame* aParentFrame,
|
||||
nsFrameItems& aFrameItems)
|
||||
{
|
||||
CreateNeededTablePseudos(aState, aItems, aParentFrame);
|
||||
CreateNeededPseudos(aState, aItems, aParentFrame);
|
||||
CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
|
||||
|
||||
aItems.SetTriedConstructingFrames();
|
||||
|
|
|
@ -415,18 +415,24 @@ private:
|
|||
nsFrameItems& aFrameItems);
|
||||
|
||||
private:
|
||||
/* An enum of possible parent types for anonymous table object construction */
|
||||
/* An enum of possible parent types for anonymous table or ruby object
|
||||
construction */
|
||||
enum ParentType {
|
||||
eTypeBlock = 0, /* This includes all non-table-related frames */
|
||||
eTypeRow,
|
||||
eTypeRowGroup,
|
||||
eTypeColGroup,
|
||||
eTypeTable,
|
||||
eTypeRuby,
|
||||
eTypeRubyBase,
|
||||
eTypeRubyBaseContainer,
|
||||
eTypeRubyText,
|
||||
eTypeRubyTextContainer,
|
||||
eParentTypeCount
|
||||
};
|
||||
|
||||
/* 3 bits is enough to handle our ParentType values */
|
||||
#define FCDATA_PARENT_TYPE_OFFSET 29
|
||||
/* 4 bits is enough to handle our ParentType values */
|
||||
#define FCDATA_PARENT_TYPE_OFFSET 28
|
||||
/* Macro to get the desired parent type out of an mBits member of
|
||||
FrameConstructionData */
|
||||
#define FCDATA_DESIRED_PARENT_TYPE(_bits) \
|
||||
|
@ -443,6 +449,21 @@ private:
|
|||
/* Get the parent type for the given nsIFrame type atom */
|
||||
static ParentType GetParentType(nsIAtom* aFrameType);
|
||||
|
||||
static bool IsRubyParentType(ParentType aParentType) {
|
||||
return (aParentType == eTypeRuby ||
|
||||
aParentType == eTypeRubyBase ||
|
||||
aParentType == eTypeRubyBaseContainer ||
|
||||
aParentType == eTypeRubyText ||
|
||||
aParentType == eTypeRubyTextContainer);
|
||||
}
|
||||
|
||||
static bool IsTableParentType(ParentType aParentType) {
|
||||
return (aParentType == eTypeTable ||
|
||||
aParentType == eTypeRow ||
|
||||
aParentType == eTypeRowGroup ||
|
||||
aParentType == eTypeColGroup);
|
||||
}
|
||||
|
||||
/* A constructor function that just creates an nsIFrame object. The caller
|
||||
is responsible for initializing the object, adding it to frame lists,
|
||||
constructing frames for the children, etc.
|
||||
|
@ -1041,9 +1062,9 @@ private:
|
|||
* @param aItems the child frame construction items before pseudo creation
|
||||
* @param aParentFrame the parent frame we're creating pseudos for
|
||||
*/
|
||||
inline void CreateNeededTablePseudos(nsFrameConstructorState& aState,
|
||||
FrameConstructionItemList& aItems,
|
||||
nsIFrame* aParentFrame);
|
||||
inline void CreateNeededPseudos(nsFrameConstructorState& aState,
|
||||
FrameConstructionItemList& aItems,
|
||||
nsIFrame* aParentFrame);
|
||||
|
||||
/**
|
||||
* Function to adjust aParentFrame to deal with captions.
|
||||
|
|
|
@ -109,6 +109,7 @@ using mozilla::image::ImageOps;
|
|||
using mozilla::image::Orientation;
|
||||
|
||||
#define GRID_ENABLED_PREF_NAME "layout.css.grid.enabled"
|
||||
#define RUBY_ENABLED_PREF_NAME "layout.css.ruby.enabled"
|
||||
#define STICKY_ENABLED_PREF_NAME "layout.css.sticky.enabled"
|
||||
#define TEXT_ALIGN_TRUE_ENABLED_PREF_NAME "layout.css.text-align-true-value.enabled"
|
||||
|
||||
|
@ -186,6 +187,78 @@ GridEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RubyEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
MOZ_ASSERT(strncmp(aPrefName, RUBY_ENABLED_PREF_NAME,
|
||||
ArrayLength(RUBY_ENABLED_PREF_NAME)) == 0,
|
||||
"We only registered this callback for a single pref, so it "
|
||||
"should only be called for that pref");
|
||||
|
||||
static int32_t sIndexOfRubyInDisplayTable;
|
||||
static int32_t sIndexOfRubyBaseInDisplayTable;
|
||||
static int32_t sIndexOfRubyBaseContainerInDisplayTable;
|
||||
static int32_t sIndexOfRubyTextInDisplayTable;
|
||||
static int32_t sIndexOfRubyTextContainerInDisplayTable;
|
||||
static bool sAreRubyKeywordIndicesInitialized; // initialized to false
|
||||
|
||||
bool isRubyEnabled =
|
||||
Preferences::GetBool(RUBY_ENABLED_PREF_NAME, false);
|
||||
if (!sAreRubyKeywordIndicesInitialized) {
|
||||
// First run: find the position of the ruby display values in
|
||||
// kDisplayKTable.
|
||||
sIndexOfRubyInDisplayTable =
|
||||
nsCSSProps::FindIndexOfKeyword(eCSSKeyword_ruby,
|
||||
nsCSSProps::kDisplayKTable);
|
||||
MOZ_ASSERT(sIndexOfRubyInDisplayTable >= 0,
|
||||
"Couldn't find ruby in kDisplayKTable");
|
||||
sIndexOfRubyBaseInDisplayTable =
|
||||
nsCSSProps::FindIndexOfKeyword(eCSSKeyword_ruby_base,
|
||||
nsCSSProps::kDisplayKTable);
|
||||
MOZ_ASSERT(sIndexOfRubyBaseInDisplayTable >= 0,
|
||||
"Couldn't find ruby-base in kDisplayKTable");
|
||||
sIndexOfRubyBaseContainerInDisplayTable =
|
||||
nsCSSProps::FindIndexOfKeyword(eCSSKeyword_ruby_base_container,
|
||||
nsCSSProps::kDisplayKTable);
|
||||
MOZ_ASSERT(sIndexOfRubyBaseContainerInDisplayTable >= 0,
|
||||
"Couldn't find ruby-base-container in kDisplayKTable");
|
||||
sIndexOfRubyTextInDisplayTable =
|
||||
nsCSSProps::FindIndexOfKeyword(eCSSKeyword_ruby_text,
|
||||
nsCSSProps::kDisplayKTable);
|
||||
MOZ_ASSERT(sIndexOfRubyTextInDisplayTable >= 0,
|
||||
"Couldn't find ruby-text in kDisplayKTable");
|
||||
sIndexOfRubyTextContainerInDisplayTable =
|
||||
nsCSSProps::FindIndexOfKeyword(eCSSKeyword_ruby_text_container,
|
||||
nsCSSProps::kDisplayKTable);
|
||||
MOZ_ASSERT(sIndexOfRubyTextContainerInDisplayTable >= 0,
|
||||
"Couldn't find ruby-text-container in kDisplayKTable");
|
||||
sAreRubyKeywordIndicesInitialized = true;
|
||||
}
|
||||
|
||||
// OK -- now, stomp on or restore the "ruby" entries in kDisplayKTable,
|
||||
// depending on whether the ruby pref is enabled vs. disabled.
|
||||
if (sIndexOfRubyInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyInDisplayTable] =
|
||||
isRubyEnabled ? eCSSKeyword_ruby : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyBaseInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseInDisplayTable] =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_base : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyBaseContainerInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseContainerInDisplayTable] =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_base_container : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyTextInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextInDisplayTable] =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_text : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyTextContainerInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextContainerInDisplayTable] =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_text_container : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// When the pref "layout.css.sticky.enabled" changes, this function is invoked
|
||||
// to let us update kPositionKTable, to selectively disable or restore the
|
||||
// entry for "sticky" in that table.
|
||||
|
@ -6069,6 +6142,9 @@ nsLayoutUtils::Initialize()
|
|||
Preferences::RegisterCallback(GridEnabledPrefChangeCallback,
|
||||
GRID_ENABLED_PREF_NAME);
|
||||
GridEnabledPrefChangeCallback(GRID_ENABLED_PREF_NAME, nullptr);
|
||||
Preferences::RegisterCallback(RubyEnabledPrefChangeCallback,
|
||||
RUBY_ENABLED_PREF_NAME);
|
||||
RubyEnabledPrefChangeCallback(RUBY_ENABLED_PREF_NAME, nullptr);
|
||||
Preferences::RegisterCallback(StickyEnabledPrefChangeCallback,
|
||||
STICKY_ENABLED_PREF_NAME);
|
||||
StickyEnabledPrefChangeCallback(STICKY_ENABLED_PREF_NAME, nullptr);
|
||||
|
@ -6091,6 +6167,8 @@ nsLayoutUtils::Shutdown()
|
|||
|
||||
Preferences::UnregisterCallback(GridEnabledPrefChangeCallback,
|
||||
GRID_ENABLED_PREF_NAME);
|
||||
Preferences::UnregisterCallback(RubyEnabledPrefChangeCallback,
|
||||
RUBY_ENABLED_PREF_NAME);
|
||||
Preferences::UnregisterCallback(StickyEnabledPrefChangeCallback,
|
||||
STICKY_ENABLED_PREF_NAME);
|
||||
|
||||
|
|
|
@ -81,6 +81,11 @@ UNIFIED_SOURCES += [
|
|||
'nsPageContentFrame.cpp',
|
||||
'nsPageFrame.cpp',
|
||||
'nsPlaceholderFrame.cpp',
|
||||
'nsRubyBaseContainerFrame.cpp',
|
||||
'nsRubyBaseFrame.cpp',
|
||||
'nsRubyFrame.cpp',
|
||||
'nsRubyTextContainerFrame.cpp',
|
||||
'nsRubyTextFrame.cpp',
|
||||
'nsSelection.cpp',
|
||||
'nsSimplePageSequenceFrame.cpp',
|
||||
'nsSplittableFrame.cpp',
|
||||
|
|
|
@ -466,7 +466,12 @@ IsFontSizeInflationContainer(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
nsIContent *content = aFrame->GetContent();
|
||||
// Ruby text containers are excluded here because they inherit from block
|
||||
// (should not be considered inline).
|
||||
bool isInline = (aFrame->GetDisplay() == NS_STYLE_DISPLAY_INLINE ||
|
||||
(aFrame->StyleDisplay()->IsRubyDisplayType() &&
|
||||
aFrame->GetDisplay() !=
|
||||
NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) ||
|
||||
(aFrame->IsFloating() &&
|
||||
aFrame->GetType() == nsGkAtoms::letterFrame) ||
|
||||
// Given multiple frames for the same node, only the
|
||||
|
|
|
@ -115,6 +115,11 @@ FRAME_ID(nsProgressMeterFrame)
|
|||
FRAME_ID(nsRangeFrame)
|
||||
FRAME_ID(nsResizerFrame)
|
||||
FRAME_ID(nsRootBoxFrame)
|
||||
FRAME_ID(nsRubyBaseContainerFrame)
|
||||
FRAME_ID(nsRubyBaseFrame)
|
||||
FRAME_ID(nsRubyFrame)
|
||||
FRAME_ID(nsRubyTextContainerFrame)
|
||||
FRAME_ID(nsRubyTextFrame)
|
||||
FRAME_ID(nsScrollbarButtonFrame)
|
||||
FRAME_ID(nsScrollbarFrame)
|
||||
FRAME_ID(nsSelectsAreaFrame)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-base-container" */
|
||||
|
||||
#include "nsRubyBaseContainerFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Frame class boilerplate
|
||||
// =======================
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsRubyBaseContainerFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsRubyBaseContainerFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsRubyBaseContainerFrame)
|
||||
|
||||
nsContainerFrame*
|
||||
NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsRubyBaseContainerFrame(aContext);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// nsRubyBaseContainerFrame Method Implementations
|
||||
// ===============================================
|
||||
|
||||
nsIAtom*
|
||||
nsRubyBaseContainerFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::rubyBaseContainerFrame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult
|
||||
nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("RubyBaseContainer"), aResult);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-base-container" */
|
||||
|
||||
#ifndef nsRubyBaseContainerFrame_h___
|
||||
#define nsRubyBaseContainerFrame_h___
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyBaseContainerFrame (infallible)
|
||||
*/
|
||||
nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
class nsRubyBaseContainerFrame MOZ_FINAL : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsRubyBaseContainerFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend nsContainerFrame*
|
||||
NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
};
|
||||
|
||||
#endif /* nsRubyBaseContainerFrame_h___ */
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-base" */
|
||||
|
||||
#include "nsRubyBaseFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Frame class boilerplate
|
||||
// =======================
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsRubyBaseFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsRubyBaseFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsRubyBaseFrame)
|
||||
|
||||
nsContainerFrame*
|
||||
NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsRubyBaseFrame(aContext);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// nsRubyBaseFrame Method Implementations
|
||||
// ======================================
|
||||
|
||||
nsIAtom*
|
||||
nsRubyBaseFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::rubyBaseFrame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult
|
||||
nsRubyBaseFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("RubyBase"), aResult);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-base" */
|
||||
|
||||
#ifndef nsRubyBaseFrame_h___
|
||||
#define nsRubyBaseFrame_h___
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyBaseFrame (infallible)
|
||||
*/
|
||||
nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
class nsRubyBaseFrame MOZ_FINAL : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsRubyBaseFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
nsRubyBaseFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
};
|
||||
|
||||
#endif /* nsRubyBaseFrame_h___ */
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby" */
|
||||
#include "nsRubyFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Frame class boilerplate
|
||||
// =======================
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsRubyFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsRubyFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsRubyFrame)
|
||||
|
||||
nsContainerFrame*
|
||||
NS_NewRubyFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsRubyFrame(aContext);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// nsRubyFrame Method Implementations
|
||||
// ==================================
|
||||
|
||||
nsIAtom*
|
||||
nsRubyFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::rubyFrame;
|
||||
}
|
||||
|
||||
bool
|
||||
nsRubyFrame::IsFrameOfType(uint32_t aFlags) const
|
||||
{
|
||||
return nsContainerFrame::IsFrameOfType(aFlags &
|
||||
~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult
|
||||
nsRubyFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("Ruby"), aResult);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby" */
|
||||
|
||||
#ifndef nsRubyFrame_h___
|
||||
#define nsRubyFrame_h___
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyFrame (infallible)
|
||||
*/
|
||||
nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
class nsRubyFrame MOZ_FINAL : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsRubyFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||
virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
nsRubyFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
};
|
||||
|
||||
#endif /* nsRubyFrame_h___ */
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-text-container" */
|
||||
|
||||
#include "nsRubyTextContainerFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Frame class boilerplate
|
||||
// =======================
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsRubyTextContainerFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsRubyTextContainerFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextContainerFrame)
|
||||
|
||||
nsContainerFrame*
|
||||
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsRubyTextContainerFrame(aContext);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// nsRubyTextContainerFrame Method Implementations
|
||||
// ===============================================
|
||||
|
||||
nsIAtom*
|
||||
nsRubyTextContainerFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::rubyTextContainerFrame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult
|
||||
nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("RubyTextContainer"), aResult);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-text-container" */
|
||||
|
||||
#ifndef nsRubyTextContainerFrame_h___
|
||||
#define nsRubyTextContainerFrame_h___
|
||||
|
||||
#include "nsBlockFrame.h"
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyTextContainerFrame (infallible)
|
||||
*/
|
||||
nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
// If this is ever changed to be inline again, the code in
|
||||
// nsFrame::IsFontSizeInflationContainer should be updated to stop excluding
|
||||
// this from being considered inline.
|
||||
class nsRubyTextContainerFrame MOZ_FINAL : public nsBlockFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsRubyTextContainerFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend nsContainerFrame*
|
||||
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
nsRubyTextContainerFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) {}
|
||||
};
|
||||
|
||||
#endif /* nsRubyTextContainerFrame_h___ */
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-text" */
|
||||
|
||||
#include "nsRubyTextFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Frame class boilerplate
|
||||
// =======================
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsRubyTextFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsRubyTextFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextFrame)
|
||||
|
||||
nsContainerFrame*
|
||||
NS_NewRubyTextFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsRubyTextFrame(aContext);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// nsRubyTextFrame Method Implementations
|
||||
// ======================================
|
||||
|
||||
nsIAtom*
|
||||
nsRubyTextFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::rubyTextFrame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
nsresult
|
||||
nsRubyTextFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("RubyText"), aResult);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code is subject to the terms of the Mozilla Public License
|
||||
* version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
* http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* rendering object for CSS "display: ruby-text" */
|
||||
|
||||
#ifndef nsRubyTextFrame_h___
|
||||
#define nsRubyTextFrame_h___
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyTextFrame (infallible)
|
||||
*/
|
||||
nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
class nsRubyTextFrame MOZ_FINAL : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
NS_DECL_QUERYFRAME_TARGET(nsRubyTextFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
nsRubyTextFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
};
|
||||
|
||||
#endif /* nsRubyTextFrame_h___ */
|
|
@ -164,7 +164,9 @@ function do_test() {
|
|||
"table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row",
|
||||
"table-column-group", "table-column", "table-cell", "table-caption", "-moz-box", "-moz-inline-box",
|
||||
"-moz-grid", "-moz-inline-grid", "-moz-grid-group", "-moz-grid-line", "-moz-stack", "-moz-inline-stack",
|
||||
"-moz-deck", "-moz-popup", "-moz-groupbox", "flex", "inline-flex", "grid", "inline-grid" ];
|
||||
"-moz-deck", "-moz-popup", "-moz-groupbox", "flex", "inline-flex", "grid",
|
||||
"inline-grid", "ruby", "ruby-base", "ruby-base-container", "ruby-text",
|
||||
"ruby-text-container" ];
|
||||
ok(testValues(values, expected), "property display's values.");
|
||||
|
||||
// test property
|
||||
|
|
|
@ -70,6 +70,12 @@ CSS_ANON_BOX(anonymousFlexItem, ":-moz-anonymous-flex-item")
|
|||
// an anonymous block, which is then treated as a grid item.
|
||||
CSS_ANON_BOX(anonymousGridItem, ":-moz-anonymous-grid-item")
|
||||
|
||||
CSS_ANON_BOX(ruby, ":-moz-ruby")
|
||||
CSS_ANON_BOX(rubyBase, ":-moz-ruby-base")
|
||||
CSS_ANON_BOX(rubyBaseContainer, ":-moz-ruby-base-container")
|
||||
CSS_ANON_BOX(rubyText, ":-moz-ruby-text")
|
||||
CSS_ANON_BOX(rubyTextContainer, ":-moz-ruby-text-container")
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
CSS_ANON_BOX(moztreecolumn, ":-moz-tree-column")
|
||||
CSS_ANON_BOX(moztreerow, ":-moz-tree-row")
|
||||
|
|
|
@ -430,6 +430,10 @@ CSS_KEY(row-resize, row_resize)
|
|||
CSS_KEY(row-reverse, row_reverse)
|
||||
CSS_KEY(rtl, rtl)
|
||||
CSS_KEY(ruby, ruby)
|
||||
CSS_KEY(ruby-base, ruby_base)
|
||||
CSS_KEY(ruby-base-container, ruby_base_container)
|
||||
CSS_KEY(ruby-text, ruby_text)
|
||||
CSS_KEY(ruby-text-container, ruby_text_container)
|
||||
CSS_KEY(running, running)
|
||||
CSS_KEY(s, s)
|
||||
CSS_KEY(s-resize, s_resize)
|
||||
|
|
|
@ -1044,41 +1044,47 @@ const KTableValue nsCSSProps::kDirectionKTable[] = {
|
|||
};
|
||||
|
||||
KTableValue nsCSSProps::kDisplayKTable[] = {
|
||||
eCSSKeyword_none, NS_STYLE_DISPLAY_NONE,
|
||||
eCSSKeyword_inline, NS_STYLE_DISPLAY_INLINE,
|
||||
eCSSKeyword_block, NS_STYLE_DISPLAY_BLOCK,
|
||||
eCSSKeyword_inline_block, NS_STYLE_DISPLAY_INLINE_BLOCK,
|
||||
eCSSKeyword_list_item, NS_STYLE_DISPLAY_LIST_ITEM,
|
||||
eCSSKeyword_table, NS_STYLE_DISPLAY_TABLE,
|
||||
eCSSKeyword_inline_table, NS_STYLE_DISPLAY_INLINE_TABLE,
|
||||
eCSSKeyword_table_row_group, NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
|
||||
eCSSKeyword_table_header_group, NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
|
||||
eCSSKeyword_table_footer_group, NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
|
||||
eCSSKeyword_table_row, NS_STYLE_DISPLAY_TABLE_ROW,
|
||||
eCSSKeyword_table_column_group, NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
|
||||
eCSSKeyword_table_column, NS_STYLE_DISPLAY_TABLE_COLUMN,
|
||||
eCSSKeyword_table_cell, NS_STYLE_DISPLAY_TABLE_CELL,
|
||||
eCSSKeyword_table_caption, NS_STYLE_DISPLAY_TABLE_CAPTION,
|
||||
eCSSKeyword_none, NS_STYLE_DISPLAY_NONE,
|
||||
eCSSKeyword_inline, NS_STYLE_DISPLAY_INLINE,
|
||||
eCSSKeyword_block, NS_STYLE_DISPLAY_BLOCK,
|
||||
eCSSKeyword_inline_block, NS_STYLE_DISPLAY_INLINE_BLOCK,
|
||||
eCSSKeyword_list_item, NS_STYLE_DISPLAY_LIST_ITEM,
|
||||
eCSSKeyword_table, NS_STYLE_DISPLAY_TABLE,
|
||||
eCSSKeyword_inline_table, NS_STYLE_DISPLAY_INLINE_TABLE,
|
||||
eCSSKeyword_table_row_group, NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
|
||||
eCSSKeyword_table_header_group, NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
|
||||
eCSSKeyword_table_footer_group, NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
|
||||
eCSSKeyword_table_row, NS_STYLE_DISPLAY_TABLE_ROW,
|
||||
eCSSKeyword_table_column_group, NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
|
||||
eCSSKeyword_table_column, NS_STYLE_DISPLAY_TABLE_COLUMN,
|
||||
eCSSKeyword_table_cell, NS_STYLE_DISPLAY_TABLE_CELL,
|
||||
eCSSKeyword_table_caption, NS_STYLE_DISPLAY_TABLE_CAPTION,
|
||||
// Make sure this is kept in sync with the code in
|
||||
// nsCSSFrameConstructor::ConstructXULFrame
|
||||
eCSSKeyword__moz_box, NS_STYLE_DISPLAY_BOX,
|
||||
eCSSKeyword__moz_inline_box, NS_STYLE_DISPLAY_INLINE_BOX,
|
||||
eCSSKeyword__moz_box, NS_STYLE_DISPLAY_BOX,
|
||||
eCSSKeyword__moz_inline_box, NS_STYLE_DISPLAY_INLINE_BOX,
|
||||
#ifdef MOZ_XUL
|
||||
eCSSKeyword__moz_grid, NS_STYLE_DISPLAY_XUL_GRID,
|
||||
eCSSKeyword__moz_inline_grid, NS_STYLE_DISPLAY_INLINE_XUL_GRID,
|
||||
eCSSKeyword__moz_grid_group, NS_STYLE_DISPLAY_XUL_GRID_GROUP,
|
||||
eCSSKeyword__moz_grid_line, NS_STYLE_DISPLAY_XUL_GRID_LINE,
|
||||
eCSSKeyword__moz_stack, NS_STYLE_DISPLAY_STACK,
|
||||
eCSSKeyword__moz_inline_stack, NS_STYLE_DISPLAY_INLINE_STACK,
|
||||
eCSSKeyword__moz_deck, NS_STYLE_DISPLAY_DECK,
|
||||
eCSSKeyword__moz_popup, NS_STYLE_DISPLAY_POPUP,
|
||||
eCSSKeyword__moz_groupbox, NS_STYLE_DISPLAY_GROUPBOX,
|
||||
eCSSKeyword__moz_grid, NS_STYLE_DISPLAY_XUL_GRID,
|
||||
eCSSKeyword__moz_inline_grid, NS_STYLE_DISPLAY_INLINE_XUL_GRID,
|
||||
eCSSKeyword__moz_grid_group, NS_STYLE_DISPLAY_XUL_GRID_GROUP,
|
||||
eCSSKeyword__moz_grid_line, NS_STYLE_DISPLAY_XUL_GRID_LINE,
|
||||
eCSSKeyword__moz_stack, NS_STYLE_DISPLAY_STACK,
|
||||
eCSSKeyword__moz_inline_stack, NS_STYLE_DISPLAY_INLINE_STACK,
|
||||
eCSSKeyword__moz_deck, NS_STYLE_DISPLAY_DECK,
|
||||
eCSSKeyword__moz_popup, NS_STYLE_DISPLAY_POPUP,
|
||||
eCSSKeyword__moz_groupbox, NS_STYLE_DISPLAY_GROUPBOX,
|
||||
#endif
|
||||
eCSSKeyword_flex, NS_STYLE_DISPLAY_FLEX,
|
||||
eCSSKeyword_inline_flex, NS_STYLE_DISPLAY_INLINE_FLEX,
|
||||
eCSSKeyword_flex, NS_STYLE_DISPLAY_FLEX,
|
||||
eCSSKeyword_inline_flex, NS_STYLE_DISPLAY_INLINE_FLEX,
|
||||
// The next two entries are controlled by the layout.css.grid.enabled pref.
|
||||
eCSSKeyword_grid, NS_STYLE_DISPLAY_GRID,
|
||||
eCSSKeyword_inline_grid, NS_STYLE_DISPLAY_INLINE_GRID,
|
||||
eCSSKeyword_grid, NS_STYLE_DISPLAY_GRID,
|
||||
eCSSKeyword_inline_grid, NS_STYLE_DISPLAY_INLINE_GRID,
|
||||
// The next five entries are controlled by the layout.css.ruby.enabled pref.
|
||||
eCSSKeyword_ruby, NS_STYLE_DISPLAY_RUBY,
|
||||
eCSSKeyword_ruby_base, NS_STYLE_DISPLAY_RUBY_BASE,
|
||||
eCSSKeyword_ruby_base_container, NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER,
|
||||
eCSSKeyword_ruby_text, NS_STYLE_DISPLAY_RUBY_TEXT,
|
||||
eCSSKeyword_ruby_text_container, NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
};
|
||||
|
||||
|
|
|
@ -181,6 +181,36 @@ nsRuleNode::EnsureBlockDisplay(uint8_t& display,
|
|||
}
|
||||
}
|
||||
|
||||
// EnsureInlineDisplay:
|
||||
// - if the display value (argument) is not an inline type
|
||||
// then we set it to a valid inline display value
|
||||
/* static */
|
||||
void
|
||||
nsRuleNode::EnsureInlineDisplay(uint8_t& display)
|
||||
{
|
||||
// see if the display value is already inline
|
||||
switch (display) {
|
||||
case NS_STYLE_DISPLAY_BLOCK :
|
||||
display = NS_STYLE_DISPLAY_INLINE_BLOCK;
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_TABLE :
|
||||
display = NS_STYLE_DISPLAY_INLINE_TABLE;
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_FLEX :
|
||||
display = NS_STYLE_DISPLAY_INLINE_FLEX;
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_GRID :
|
||||
display = NS_STYLE_DISPLAY_INLINE_GRID;
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_BOX:
|
||||
display = NS_STYLE_DISPLAY_INLINE_BOX;
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_STACK:
|
||||
display = NS_STYLE_DISPLAY_INLINE_STACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
||||
nscoord aFontSize,
|
||||
const nsStyleFont* aStyleFont,
|
||||
|
|
|
@ -674,6 +674,7 @@ public:
|
|||
|
||||
static void EnsureBlockDisplay(uint8_t& display,
|
||||
bool aConvertListItem = false);
|
||||
static void EnsureInlineDisplay(uint8_t& display);
|
||||
|
||||
// Transition never returns null; on out of memory it'll just return |this|.
|
||||
nsRuleNode* Transition(nsIStyleRule* aRule, uint8_t aLevel,
|
||||
|
|
|
@ -416,6 +416,11 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
|||
#define NS_STYLE_DISPLAY_INLINE_FLEX 30
|
||||
#define NS_STYLE_DISPLAY_GRID 31
|
||||
#define NS_STYLE_DISPLAY_INLINE_GRID 32
|
||||
#define NS_STYLE_DISPLAY_RUBY 33
|
||||
#define NS_STYLE_DISPLAY_RUBY_BASE 34
|
||||
#define NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER 35
|
||||
#define NS_STYLE_DISPLAY_RUBY_TEXT 36
|
||||
#define NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER 37
|
||||
|
||||
// See nsStylePosition
|
||||
#define NS_STYLE_ALIGN_CONTENT_FLEX_START 0
|
||||
|
|
|
@ -356,12 +356,11 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
|
|||
// # The computed 'display' of a flex item is determined
|
||||
// # by applying the table in CSS 2.1 Chapter 9.7.
|
||||
// ...which converts inline-level elements to their block-level equivalents.
|
||||
// Any direct children of elements with Ruby display values which are
|
||||
// block-level are converted to their inline-level equivalents.
|
||||
if (!aSkipParentDisplayBasedStyleFixup && mParent) {
|
||||
const nsStyleDisplay* parentDisp = mParent->StyleDisplay();
|
||||
if ((parentDisp->mDisplay == NS_STYLE_DISPLAY_FLEX ||
|
||||
parentDisp->mDisplay == NS_STYLE_DISPLAY_INLINE_FLEX ||
|
||||
parentDisp->mDisplay == NS_STYLE_DISPLAY_GRID ||
|
||||
parentDisp->mDisplay == NS_STYLE_DISPLAY_INLINE_GRID) &&
|
||||
if (parentDisp->IsFlexOrGridDisplayType() &&
|
||||
GetPseudo() != nsCSSAnonBoxes::mozNonElement) {
|
||||
uint8_t displayVal = disp->mDisplay;
|
||||
// Skip table parts.
|
||||
|
@ -394,6 +393,16 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
|
|||
static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display));
|
||||
mutable_display->mDisplay = displayVal;
|
||||
}
|
||||
}
|
||||
} else if (parentDisp->IsRubyDisplayType()) {
|
||||
uint8_t displayVal = disp->mDisplay;
|
||||
nsRuleNode::EnsureInlineDisplay(displayVal);
|
||||
// The display change should only occur for "in-flow" children
|
||||
if (displayVal != disp->mDisplay &&
|
||||
!disp->IsOutOfFlowStyle()) {
|
||||
nsStyleDisplay *mutable_display =
|
||||
static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display));
|
||||
mutable_display->mDisplay = displayVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2061,7 +2061,12 @@ struct nsStyleDisplay {
|
|||
NS_STYLE_DISPLAY_INLINE_FLEX == aDisplay ||
|
||||
NS_STYLE_DISPLAY_INLINE_GRID == aDisplay ||
|
||||
NS_STYLE_DISPLAY_INLINE_XUL_GRID == aDisplay ||
|
||||
NS_STYLE_DISPLAY_INLINE_STACK == aDisplay;
|
||||
NS_STYLE_DISPLAY_INLINE_STACK == aDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY == aDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_BASE == aDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER == aDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_TEXT == aDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER == aDisplay;
|
||||
}
|
||||
|
||||
bool IsInlineOutsideStyle() const {
|
||||
|
@ -2097,6 +2102,25 @@ struct nsStyleDisplay {
|
|||
NS_STYLE_POSITION_STICKY == mPosition;
|
||||
}
|
||||
|
||||
bool IsRubyDisplayType() const {
|
||||
return NS_STYLE_DISPLAY_RUBY == mDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_BASE == mDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER == mDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_TEXT == mDisplay ||
|
||||
NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER == mDisplay;
|
||||
}
|
||||
|
||||
bool IsFlexOrGridDisplayType() const {
|
||||
return NS_STYLE_DISPLAY_FLEX == mDisplay ||
|
||||
NS_STYLE_DISPLAY_INLINE_FLEX == mDisplay ||
|
||||
NS_STYLE_DISPLAY_GRID == mDisplay ||
|
||||
NS_STYLE_DISPLAY_INLINE_GRID == mDisplay;
|
||||
}
|
||||
|
||||
bool IsOutOfFlowStyle() const {
|
||||
return (IsAbsolutelyPositionedStyle() || IsFloatingStyle());
|
||||
}
|
||||
|
||||
bool IsScrollableOverflow() const {
|
||||
// mOverflowX and mOverflowY always match when one of them is
|
||||
// NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
|
||||
|
|
|
@ -4799,6 +4799,17 @@ if (SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
|
|||
};
|
||||
}
|
||||
|
||||
if (SpecialPowers.getBoolPref("layout.css.ruby.enabled")) {
|
||||
// Using unshift to add these values at the beginning.
|
||||
// Adding them to the end would trigger bug 1038905. The "unshift" should be
|
||||
// changed to a "push" when this bug is resolved.
|
||||
gCSSProperties["display"].other_values.unshift("ruby",
|
||||
"ruby-base",
|
||||
"ruby-base-container",
|
||||
"ruby-text",
|
||||
"ruby-text-container");
|
||||
}
|
||||
|
||||
if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
|
||||
gCSSProperties["display"].other_values.push("grid", "inline-grid");
|
||||
gCSSProperties["grid-auto-flow"] = {
|
||||
|
|
|
@ -72,6 +72,23 @@
|
|||
white-space: inherit;
|
||||
}
|
||||
|
||||
/* Ruby */
|
||||
*|*::-moz-ruby {
|
||||
display: ruby;
|
||||
}
|
||||
*|*::-moz-ruby-base {
|
||||
display: ruby-base;
|
||||
}
|
||||
*|*::-moz-ruby-text {
|
||||
display: ruby-text;
|
||||
}
|
||||
*|*::-moz-ruby-base-container {
|
||||
display: ruby-base-container;
|
||||
}
|
||||
*|*::-moz-ruby-text-container {
|
||||
display: ruby-text-container;
|
||||
}
|
||||
|
||||
/* Lists */
|
||||
|
||||
*|*::-moz-list-bullet, *|*::-moz-list-number {
|
||||
|
|
|
@ -748,7 +748,7 @@ public class BrowserApp extends GeckoApp
|
|||
String title = tab.getDisplayTitle();
|
||||
Bitmap favicon = tab.getFavicon();
|
||||
if (url != null && title != null) {
|
||||
GeckoAppShell.createShortcut(title, url, url, favicon, "");
|
||||
GeckoAppShell.createShortcut(title, url, favicon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -597,13 +597,6 @@ public abstract class GeckoApp
|
|||
// Context: Sharing via chrome list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
|
||||
|
||||
} else if ("Shortcut:Remove".equals(event)) {
|
||||
final String url = message.getString("url");
|
||||
final String origin = message.getString("origin");
|
||||
final String title = message.getString("title");
|
||||
final String type = message.getString("shortcutType");
|
||||
GeckoAppShell.removeShortcut(title, url, origin, type);
|
||||
|
||||
} else if ("SystemUI:Visibility".equals(event)) {
|
||||
setSystemUiVisible(message.getBoolean("visible"));
|
||||
|
||||
|
@ -1515,7 +1508,6 @@ public abstract class GeckoApp
|
|||
"Sanitize:ClearHistory",
|
||||
"Session:StatePurged",
|
||||
"Share:Text",
|
||||
"Shortcut:Remove",
|
||||
"SystemUI:Visibility",
|
||||
"Toast:Show",
|
||||
"ToggleChrome:Focus",
|
||||
|
@ -2050,7 +2042,6 @@ public abstract class GeckoApp
|
|||
"Sanitize:ClearHistory",
|
||||
"Session:StatePurged",
|
||||
"Share:Text",
|
||||
"Shortcut:Remove",
|
||||
"SystemUI:Visibility",
|
||||
"Toast:Show",
|
||||
"ToggleChrome:Focus",
|
||||
|
|
|
@ -135,9 +135,6 @@ public class GeckoAppShell
|
|||
// See also HardwareUtils.LOW_MEMORY_THRESHOLD_MB.
|
||||
private static final int HIGH_MEMORY_DEVICE_THRESHOLD_MB = 768;
|
||||
|
||||
public static final String SHORTCUT_TYPE_WEBAPP = "webapp";
|
||||
public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark";
|
||||
|
||||
static private int sDensityDpi = 0;
|
||||
static private int sScreenDepth = 0;
|
||||
|
||||
|
@ -254,7 +251,7 @@ public class GeckoAppShell
|
|||
|
||||
@Override
|
||||
public void onFaviconLoaded(String pageUrl, String faviconURL, Bitmap favicon) {
|
||||
GeckoAppShell.createShortcut(title, url, url, favicon, "");
|
||||
GeckoAppShell.createShortcut(title, url, favicon);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,59 +778,25 @@ public class GeckoAppShell
|
|||
restartScheduled = true;
|
||||
}
|
||||
|
||||
public static Intent getWebappIntent(String aURI, String aOrigin, String aTitle, Bitmap aIcon) {
|
||||
Intent intent;
|
||||
|
||||
Allocator slots = Allocator.getInstance(getContext());
|
||||
int index = slots.getIndexForOrigin(aOrigin);
|
||||
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String packageName = slots.getAppForIndex(index);
|
||||
intent = getContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (aURI != null) {
|
||||
intent.setData(Uri.parse(aURI));
|
||||
}
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
// "Installs" an application by creating a shortcut
|
||||
// This is the entry point from AndroidBridge.h
|
||||
// Creates a homescreen shortcut for a web page.
|
||||
// This is the entry point from nsIShellService.
|
||||
@WrapElementForJNI
|
||||
static void createShortcut(String aTitle, String aURI, String aIconData, String aType) {
|
||||
if ("webapp".equals(aType)) {
|
||||
Log.w(LOGTAG, "createShortcut with no unique URI should not be used for aType = webapp!");
|
||||
}
|
||||
|
||||
createShortcut(aTitle, aURI, aURI, aIconData, aType);
|
||||
}
|
||||
|
||||
// For non-webapps.
|
||||
public static void createShortcut(String aTitle, String aURI, Bitmap aBitmap, String aType) {
|
||||
createShortcut(aTitle, aURI, aURI, aBitmap, aType);
|
||||
}
|
||||
|
||||
// Internal, for webapps.
|
||||
static void createShortcut(final String aTitle, final String aURI, final String aUniqueURI, final String aIconData, final String aType) {
|
||||
static void createShortcut(final String aTitle, final String aURI, final String aIconData) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: use the cache. Bug 961600.
|
||||
Bitmap icon = FaviconDecoder.getMostSuitableBitmapFromDataURI(aIconData, getPreferredIconSize());
|
||||
GeckoAppShell.doCreateShortcut(aTitle, aURI, aURI, icon, aType);
|
||||
GeckoAppShell.doCreateShortcut(aTitle, aURI, icon);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void createShortcut(final String aTitle, final String aURI, final String aUniqueURI,
|
||||
final Bitmap aIcon, final String aType) {
|
||||
public static void createShortcut(final String aTitle, final String aURI, final Bitmap aBitmap) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GeckoAppShell.doCreateShortcut(aTitle, aURI, aUniqueURI, aIcon, aType);
|
||||
GeckoAppShell.doCreateShortcut(aTitle, aURI, aBitmap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -841,23 +804,17 @@ public class GeckoAppShell
|
|||
/**
|
||||
* Call this method only on the background thread.
|
||||
*/
|
||||
private static void doCreateShortcut(final String aTitle, final String aURI, final String aUniqueURI,
|
||||
final Bitmap aIcon, final String aType) {
|
||||
private static void doCreateShortcut(final String aTitle, final String aURI, final Bitmap aIcon) {
|
||||
// The intent to be launched by the shortcut.
|
||||
Intent shortcutIntent;
|
||||
if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
|
||||
shortcutIntent = getWebappIntent(aURI, aUniqueURI, aTitle, aIcon);
|
||||
} else {
|
||||
shortcutIntent = new Intent();
|
||||
shortcutIntent.setAction(GeckoApp.ACTION_HOMESCREEN_SHORTCUT);
|
||||
shortcutIntent.setData(Uri.parse(aURI));
|
||||
shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.BROWSER_INTENT_CLASS_NAME);
|
||||
}
|
||||
Intent shortcutIntent = new Intent();
|
||||
shortcutIntent.setAction(GeckoApp.ACTION_HOMESCREEN_SHORTCUT);
|
||||
shortcutIntent.setData(Uri.parse(aURI));
|
||||
shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.BROWSER_INTENT_CLASS_NAME);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, getLauncherIcon(aIcon, aType));
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, getLauncherIcon(aIcon));
|
||||
|
||||
if (aTitle != null) {
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aTitle);
|
||||
|
@ -872,41 +829,6 @@ public class GeckoAppShell
|
|||
getContext().sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public static void removeShortcut(final String aTitle, final String aURI, final String aType) {
|
||||
removeShortcut(aTitle, aURI, null, aType);
|
||||
}
|
||||
|
||||
public static void removeShortcut(final String aTitle, final String aURI, final String aUniqueURI, final String aType) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// the intent to be launched by the shortcut
|
||||
Intent shortcutIntent;
|
||||
if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
|
||||
shortcutIntent = getWebappIntent(aURI, aUniqueURI, "", null);
|
||||
if (shortcutIntent == null)
|
||||
return;
|
||||
} else {
|
||||
shortcutIntent = new Intent();
|
||||
shortcutIntent.setAction(GeckoApp.ACTION_HOMESCREEN_SHORTCUT);
|
||||
shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.BROWSER_INTENT_CLASS_NAME);
|
||||
shortcutIntent.setData(Uri.parse(aURI));
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
if (aTitle != null)
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aTitle);
|
||||
else
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aURI);
|
||||
|
||||
intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
|
||||
getContext().sendBroadcast(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@JNITarget
|
||||
static public int getPreferredIconSize() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
|
@ -925,7 +847,7 @@ public class GeckoAppShell
|
|||
}
|
||||
}
|
||||
|
||||
static private Bitmap getLauncherIcon(Bitmap aSource, String aType) {
|
||||
static private Bitmap getLauncherIcon(Bitmap aSource) {
|
||||
final int kOffset = 6;
|
||||
final int kRadius = 5;
|
||||
int size = getPreferredIconSize();
|
||||
|
@ -941,8 +863,8 @@ public class GeckoAppShell
|
|||
// If we aren't drawing a favicon, just use an orange color.
|
||||
paint.setColor(Color.HSVToColor(DEFAULT_LAUNCHER_ICON_HSV));
|
||||
canvas.drawRoundRect(new RectF(kOffset, kOffset, size - kOffset, size - kOffset), kRadius, kRadius, paint);
|
||||
} else if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP) || aSource.getWidth() >= insetSize || aSource.getHeight() >= insetSize) {
|
||||
// otherwise, if this is a webapp or if the icons is lare enough, just draw it
|
||||
} else if (aSource.getWidth() >= insetSize || aSource.getHeight() >= insetSize) {
|
||||
// Otherwise, if the icon is large enough, just draw it.
|
||||
Rect iconBounds = new Rect(0, 0, size, size);
|
||||
canvas.drawBitmap(aSource, null, iconBounds, null);
|
||||
return bitmap;
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.util.Log;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class GeckoThread extends Thread implements GeckoEventListener {
|
||||
private static final String LOGTAG = "GeckoThread";
|
||||
|
@ -34,9 +35,10 @@ public class GeckoThread extends Thread implements GeckoEventListener {
|
|||
GeckoRunning,
|
||||
GeckoExiting,
|
||||
GeckoExited
|
||||
};
|
||||
}
|
||||
|
||||
private static LaunchState sLaunchState = LaunchState.Launching;
|
||||
private static AtomicReference<LaunchState> sLaunchState =
|
||||
new AtomicReference<LaunchState>(LaunchState.Launching);
|
||||
|
||||
private static GeckoThread sGeckoThread;
|
||||
|
||||
|
@ -176,8 +178,6 @@ public class GeckoThread extends Thread implements GeckoEventListener {
|
|||
GeckoAppShell.runGecko(path, args, mUri, type);
|
||||
}
|
||||
|
||||
private static Object sLock = new Object();
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
if ("Gecko:Ready".equals(event)) {
|
||||
|
@ -189,15 +189,11 @@ public class GeckoThread extends Thread implements GeckoEventListener {
|
|||
|
||||
@RobocopTarget
|
||||
public static boolean checkLaunchState(LaunchState checkState) {
|
||||
synchronized (sLock) {
|
||||
return sLaunchState == checkState;
|
||||
}
|
||||
return sLaunchState.get() == checkState;
|
||||
}
|
||||
|
||||
static void setLaunchState(LaunchState setState) {
|
||||
synchronized (sLock) {
|
||||
sLaunchState = setState;
|
||||
}
|
||||
sLaunchState.set(setState);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,11 +201,6 @@ public class GeckoThread extends Thread implements GeckoEventListener {
|
|||
* state is <code>checkState</code>; otherwise do nothing and return false.
|
||||
*/
|
||||
static boolean checkAndSetLaunchState(LaunchState checkState, LaunchState setState) {
|
||||
synchronized (sLock) {
|
||||
if (sLaunchState != checkState)
|
||||
return false;
|
||||
sLaunchState = setState;
|
||||
return true;
|
||||
}
|
||||
return sLaunchState.compareAndSet(checkState, setState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ skip-if = android_version == "10"
|
|||
[testJNI]
|
||||
# [testMozPay] # see bug 945675
|
||||
[testOrderedBroadcast]
|
||||
[testResourceSubstitutions]
|
||||
[testSharedPreferences]
|
||||
[testSimpleDiscovery]
|
||||
[testUITelemetry]
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.mozilla.gecko.tests;
|
||||
|
||||
|
||||
|
||||
public class testResourceSubstitutions extends JavascriptTest {
|
||||
public testResourceSubstitutions() {
|
||||
super("testResourceSubstitutions.js");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// -*- indent-tabs-mode: nil; js-indent-level: 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm"); /*global Promise */
|
||||
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm"); /*global NetUtil */
|
||||
|
||||
function readChannel(url) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let channel = NetUtil.newChannel(url);
|
||||
channel.contentType = "text/plain";
|
||||
|
||||
NetUtil.asyncFetch(channel, function(inputStream, status) {
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
deferred.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
let content = NetUtil.readInputStreamToString(inputStream, inputStream.available());
|
||||
deferred.resolve(content);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
add_task(function test_Android() {
|
||||
let protocolHandler = Services.io
|
||||
.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
|
||||
do_check_true(protocolHandler.hasSubstitution("android"));
|
||||
|
||||
// This can be any file that we know exists in the root of every APK.
|
||||
let packageName = yield readChannel("resource://android/package-name.txt");
|
||||
|
||||
// It's difficult to fish ANDROID_PACKAGE_NAME from JavaScript, so we test the
|
||||
// following weaker condition.
|
||||
let expectedPrefix = "org.mozilla.";
|
||||
do_check_eq(packageName.substring(0, expectedPrefix.length), expectedPrefix);
|
||||
});
|
||||
|
||||
run_next_test();
|
|
@ -110,10 +110,6 @@ public class Allocator {
|
|||
return findSlotForPrefix(PREFIX_PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
public synchronized int getIndexForOrigin(String origin) {
|
||||
return findSlotForPrefix(PREFIX_ORIGIN, origin);
|
||||
}
|
||||
|
||||
protected int findSlotForPrefix(String prefix, String value) {
|
||||
for (int i = 0; i < MAX_WEB_APPS; ++i) {
|
||||
if (mPrefs.getString(prefix + i, "").equals(value)) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public class EventListener implements NativeEventListener {
|
|||
"Webapps:InstallApk",
|
||||
"Webapps:UninstallApk",
|
||||
"Webapps:Postinstall",
|
||||
"Webapps:Open",
|
||||
"Webapps:Launch",
|
||||
"Webapps:Uninstall",
|
||||
"Webapps:GetApkVersions");
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public class EventListener implements NativeEventListener {
|
|||
"Webapps:InstallApk",
|
||||
"Webapps:UninstallApk",
|
||||
"Webapps:Postinstall",
|
||||
"Webapps:Open",
|
||||
"Webapps:Launch",
|
||||
"Webapps:Uninstall",
|
||||
"Webapps:GetApkVersions");
|
||||
}
|
||||
|
@ -70,14 +70,8 @@ public class EventListener implements NativeEventListener {
|
|||
uninstallApk(GeckoAppShell.getGeckoInterface().getActivity(), message);
|
||||
} else if (event.equals("Webapps:Postinstall")) {
|
||||
postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
|
||||
} else if (event.equals("Webapps:Open")) {
|
||||
Intent intent = GeckoAppShell.getWebappIntent(message.getString("manifestURL"),
|
||||
message.getString("origin"),
|
||||
"", null);
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
GeckoAppShell.getGeckoInterface().getActivity().startActivity(intent);
|
||||
} else if (event.equals("Webapps:Launch")) {
|
||||
launchWebapp(message.getString("packageName"));
|
||||
} else if (event.equals("Webapps:GetApkVersions")) {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
|
||||
|
@ -95,6 +89,11 @@ public class EventListener implements NativeEventListener {
|
|||
allocator.putOrigin(index, aOrigin);
|
||||
}
|
||||
|
||||
private void launchWebapp(String aPackageName) {
|
||||
Intent intent = GeckoAppShell.getContext().getPackageManager().getLaunchIntentForPackage(aPackageName);
|
||||
GeckoAppShell.getGeckoInterface().getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
public static void uninstallWebapp(final String packageName) {
|
||||
// On uninstall, we need to do a couple of things:
|
||||
// 1. nuke the running app process.
|
||||
|
|
|
@ -110,8 +110,7 @@ function addApplication(aApp) {
|
|||
let container = document.createElement("div");
|
||||
container.className = "app list-item";
|
||||
container.setAttribute("contextmenu", "appmenu");
|
||||
container.setAttribute("id", "app-" + aApp.origin);
|
||||
container.setAttribute("mozApp", aApp.origin);
|
||||
container.setAttribute("id", "app-" + aApp.manifestURL);
|
||||
container.setAttribute("title", manifest.name);
|
||||
|
||||
let img = document.createElement("img");
|
||||
|
@ -140,7 +139,7 @@ function addApplication(aApp) {
|
|||
}
|
||||
|
||||
function onInstall(aEvent) {
|
||||
let node = document.getElementById("app-" + aEvent.application.origin);
|
||||
let node = document.getElementById("app-" + aEvent.application.manifestURL);
|
||||
if (node)
|
||||
return;
|
||||
|
||||
|
@ -149,7 +148,7 @@ function onInstall(aEvent) {
|
|||
}
|
||||
|
||||
function onUninstall(aEvent) {
|
||||
let node = document.getElementById("app-" + aEvent.application.origin);
|
||||
let node = document.getElementById("app-" + aEvent.application.manifestURL);
|
||||
if (node) {
|
||||
let parent = node.parentNode;
|
||||
parent.removeChild(node);
|
||||
|
|
|
@ -119,8 +119,33 @@ BrowserCLH.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Register resource://android as the APK root.
|
||||
*
|
||||
* Consumers can access Android assets using resource://android/assets/FILENAME.
|
||||
*/
|
||||
setResourceSubstitutions: function () {
|
||||
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci["nsIChromeRegistry"]);
|
||||
// Like jar:jar:file:///data/app/org.mozilla.fennec-2.apk!/assets/omni.ja!/chrome/chrome/content/aboutHome.xhtml
|
||||
let url = registry.convertChromeURL(Services.io.newURI("chrome://browser/content/aboutHome.xhtml", null, null)).spec;
|
||||
// Like jar:file:///data/app/org.mozilla.fennec-2.apk!/
|
||||
url = url.substring(4, url.indexOf("!/") + 2);
|
||||
|
||||
let protocolHandler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
|
||||
protocolHandler.setSubstitution("android", Services.io.newURI(url, null, null));
|
||||
},
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "app-startup":
|
||||
this.setResourceSubstitutions();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// QI
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
// XPCOMUtils factory
|
||||
classID: Components.ID("{be623d20-d305-11de-8a39-0800200c9a66}")
|
||||
|
|
|
@ -66,6 +66,7 @@ category wakeup-request PromptService @mozilla.org/embedcomp/prompt-service;1,ns
|
|||
component {be623d20-d305-11de-8a39-0800200c9a66} BrowserCLH.js application={aa3c5121-dab2-40e2-81ca-7ea25febc110}
|
||||
contract @mozilla.org/browser/browser-clh;1 {be623d20-d305-11de-8a39-0800200c9a66}
|
||||
category command-line-handler x-browser @mozilla.org/browser/browser-clh;1
|
||||
category app-startup BrowserCLH @mozilla.org/browser/browser-clh;1
|
||||
|
||||
# ContentDispatchChooser.js
|
||||
component {5a072a22-1e66-4100-afc1-07aed8b62fc5} ContentDispatchChooser.js
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIShellService : nsISupports
|
|||
* @param aTitle the user-friendly name of the shortcut.
|
||||
* @param aURI the URI to open.
|
||||
* @param aIconData a base64-encoded data: URI representation of the shortcut's icon, as accepted by the favicon decoder.
|
||||
* @param aIntent how the URI should be opened. Examples: "default", "bookmark" and "webapp"
|
||||
* @param aIntent obsolete and ignored, but remains for backward compatibility; pass an empty string
|
||||
*/
|
||||
void createShortcut(in AString aTitle, in AString aURI, in AString aIconData, in AString aIntent);
|
||||
};
|
||||
|
|
|
@ -25,6 +25,6 @@ nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI,
|
|||
if (!aTitle.Length() || !aURI.Length() || !aIconData.Length())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mozilla::widget::android::GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData, aIntent);
|
||||
mozilla::widget::android::GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -198,13 +198,12 @@ this.WebappManager = {
|
|||
this.writeDefaultPrefs(file, localeManifest);
|
||||
},
|
||||
|
||||
launch: function({ manifestURL, origin }) {
|
||||
debug("launchWebapp: " + manifestURL);
|
||||
launch: function({ apkPackageName }) {
|
||||
debug("launch: " + apkPackageName);
|
||||
|
||||
sendMessageToJava({
|
||||
type: "Webapps:Open",
|
||||
manifestURL: manifestURL,
|
||||
origin: origin
|
||||
type: "Webapps:Launch",
|
||||
packageName: apkPackageName,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.view.View;
|
|||
|
||||
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
|
||||
import org.mozilla.search.autocomplete.AcceptsSearchQuery;
|
||||
import org.mozilla.search.autocomplete.SearchFragment;
|
||||
|
||||
/**
|
||||
* The main entrance for the Android search intent.
|
||||
|
@ -58,8 +59,12 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery
|
|||
public void onSearch(String query) {
|
||||
startPostsearch();
|
||||
storeQuery(query);
|
||||
|
||||
((PostSearchFragment) getSupportFragmentManager().findFragmentById(R.id.postsearch))
|
||||
.setUrl("https://search.yahoo.com/search?p=" + Uri.encode(query));
|
||||
|
||||
((SearchFragment) getSupportFragmentManager().findFragmentById(R.id.search_fragment))
|
||||
.setSearchTerm(query);
|
||||
}
|
||||
|
||||
private void startPresearch() {
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/* 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/. */
|
||||
|
||||
package org.mozilla.search.autocomplete;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mozilla.search.R;
|
||||
|
||||
public class ClearableEditText extends FrameLayout {
|
||||
|
||||
private EditText editText;
|
||||
private Button clearButton;
|
||||
private InputMethodManager inputMethodManager;
|
||||
|
||||
private TextListener listener;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public interface TextListener {
|
||||
public void onChange(String text);
|
||||
public void onSubmit(String text);
|
||||
}
|
||||
|
||||
public ClearableEditText(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.clearable_edit_text, this);
|
||||
|
||||
editText = (EditText) findViewById(R.id.edit_text);
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (listener != null) {
|
||||
listener.onChange(s.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Attach a listener for the "search" key on the keyboard.
|
||||
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (listener != null && actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
listener.onSubmit(v.getText().toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
clearButton = (Button) findViewById(R.id.clear_button);
|
||||
clearButton.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
editText.setText("");
|
||||
}
|
||||
});
|
||||
|
||||
inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
editText.setText(text);
|
||||
|
||||
// Move cursor to end of search input.
|
||||
editText.setSelection(text.length());
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
if (this.active == active) {
|
||||
return;
|
||||
}
|
||||
this.active = active;
|
||||
|
||||
clearButton.setVisibility(active ? View.VISIBLE : View.GONE);
|
||||
|
||||
editText.setFocusable(active);
|
||||
editText.setFocusableInTouchMode(active);
|
||||
|
||||
if (active) {
|
||||
editText.requestFocus();
|
||||
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
|
||||
} else {
|
||||
editText.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextListener(TextListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent e) {
|
||||
// When the view is active, pass touch events to child views.
|
||||
// Otherwise, intercept touch events to allow click listeners on the view to
|
||||
// fire no matter where the user clicks.
|
||||
return !active;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
package org.mozilla.search.autocomplete;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
@ -12,21 +11,13 @@ import android.support.v4.app.Fragment;
|
|||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mozilla.search.R;
|
||||
|
||||
|
@ -39,8 +30,7 @@ import java.util.List;
|
|||
* <p/>
|
||||
* TODO: Add more search providers (other than the dictionary)
|
||||
*/
|
||||
public class SearchFragment extends Fragment
|
||||
implements TextView.OnEditorActionListener, AcceptsJumpTaps {
|
||||
public class SearchFragment extends Fragment implements AcceptsJumpTaps {
|
||||
|
||||
private static final int LOADER_ID_SUGGESTION = 0;
|
||||
private static final String KEY_SEARCH_TERM = "search_term";
|
||||
|
@ -54,16 +44,14 @@ public class SearchFragment extends Fragment
|
|||
// Color of search term match in search suggestion
|
||||
private static final int SUGGESTION_HIGHLIGHT_COLOR = 0xFF999999;
|
||||
|
||||
private AcceptsSearchQuery searchListener;
|
||||
private SuggestClient suggestClient;
|
||||
private SuggestionLoaderCallbacks suggestionLoaderCallbacks;
|
||||
|
||||
private InputMethodManager inputMethodManager;
|
||||
private AutoCompleteAdapter autoCompleteAdapter;
|
||||
|
||||
private View mainView;
|
||||
private View searchBar;
|
||||
private EditText editText;
|
||||
private Button clearButton;
|
||||
private ClearableEditText editText;
|
||||
private ListView suggestionDropdown;
|
||||
|
||||
private State state = State.WAITING;
|
||||
|
@ -81,6 +69,12 @@ public class SearchFragment extends Fragment
|
|||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
if (activity instanceof AcceptsSearchQuery) {
|
||||
searchListener = (AcceptsSearchQuery) activity;
|
||||
} else {
|
||||
throw new ClassCastException(activity.toString() + " must implement AcceptsSearchQuery.");
|
||||
}
|
||||
|
||||
// TODO: Don't hard-code this template string (bug 1039758)
|
||||
final String template = "https://search.yahoo.com/sugg/ff?" +
|
||||
"output=fxjson&appid=ffm&command=__searchTerms__&nresults=" + SUGGESTION_MAX;
|
||||
|
@ -88,7 +82,6 @@ public class SearchFragment extends Fragment
|
|||
suggestClient = new SuggestClient(activity, template, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
suggestionLoaderCallbacks = new SuggestionLoaderCallbacks();
|
||||
|
||||
inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
autoCompleteAdapter = new AutoCompleteAdapter(activity, this);
|
||||
}
|
||||
|
||||
|
@ -96,9 +89,9 @@ public class SearchFragment extends Fragment
|
|||
public void onDetach() {
|
||||
super.onDetach();
|
||||
|
||||
searchListener = null;
|
||||
suggestClient = null;
|
||||
suggestionLoaderCallbacks = null;
|
||||
inputMethodManager = null;
|
||||
autoCompleteAdapter = null;
|
||||
}
|
||||
|
||||
|
@ -115,42 +108,33 @@ public class SearchFragment extends Fragment
|
|||
}
|
||||
});
|
||||
|
||||
searchBar = mainView.findViewById(R.id.search_bar);
|
||||
editText = (EditText) mainView.findViewById(R.id.search_bar_edit_text);
|
||||
// Disable the click listener while the fragment is State.WAITING.
|
||||
// We can't do this in the layout file because the setOnClickListener
|
||||
// implementation calls setClickable(true).
|
||||
mainView.setClickable(false);
|
||||
|
||||
final View.OnClickListener transitionToRunningListener = new View.OnClickListener() {
|
||||
editText = (ClearableEditText) mainView.findViewById(R.id.auto_complete_edit_text);
|
||||
editText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
transitionToRunning();
|
||||
}
|
||||
};
|
||||
searchBar.setOnClickListener(transitionToRunningListener);
|
||||
editText.setOnClickListener(transitionToRunningListener);
|
||||
|
||||
// Attach a listener for the "search" key on the keyboard.
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(KEY_SEARCH_TERM, s.toString());
|
||||
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
|
||||
}
|
||||
});
|
||||
editText.setOnEditorActionListener(this);
|
||||
|
||||
clearButton = (Button) mainView.findViewById(R.id.search_bar_clear_button);
|
||||
clearButton.setOnClickListener(new View.OnClickListener(){
|
||||
editText.setTextListener(new ClearableEditText.TextListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
editText.setText("");
|
||||
public void onChange(String text) {
|
||||
if (state == State.RUNNING) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(KEY_SEARCH_TERM, text);
|
||||
getLoaderManager().restartLoader(LOADER_ID_SUGGESTION, args, suggestionLoaderCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubmit(String text) {
|
||||
transitionToWaiting();
|
||||
searchListener.onSearch(text);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -162,7 +146,9 @@ public class SearchFragment extends Fragment
|
|||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Suggestion suggestion = (Suggestion) suggestionDropdown.getItemAtPosition(position);
|
||||
startSearch(suggestion.value);
|
||||
|
||||
transitionToWaiting();
|
||||
searchListener.onSearch(suggestion.value);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -173,9 +159,7 @@ public class SearchFragment extends Fragment
|
|||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
searchBar = null;
|
||||
editText = null;
|
||||
clearButton = null;
|
||||
|
||||
if (null != suggestionDropdown) {
|
||||
suggestionDropdown.setOnItemClickListener(null);
|
||||
|
@ -184,78 +168,41 @@ public class SearchFragment extends Fragment
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for the "search" button on the keyboard.
|
||||
*/
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
startSearch(v.getText().toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public void onJumpTap(String suggestion) {
|
||||
setSearchTerm(suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a search intent and put the widget into waiting.
|
||||
* Sets the search term in the search bar. If the SearchFragment is
|
||||
* in State.RUNNING, this will also update the search suggestions.
|
||||
*
|
||||
* @param searchTerm
|
||||
*/
|
||||
private void startSearch(String queryString) {
|
||||
if (getActivity() instanceof AcceptsSearchQuery) {
|
||||
editText.setText(queryString);
|
||||
editText.setSelection(queryString.length());
|
||||
transitionToWaiting();
|
||||
((AcceptsSearchQuery) getActivity()).onSearch(queryString);
|
||||
} else {
|
||||
throw new RuntimeException("Parent activity does not implement AcceptsSearchQuery.");
|
||||
}
|
||||
public void setSearchTerm(String searchTerm) {
|
||||
editText.setText(searchTerm);
|
||||
}
|
||||
|
||||
private void transitionToWaiting() {
|
||||
if (state == State.WAITING) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEditTextFocusable(false);
|
||||
mainView.setClickable(false);
|
||||
|
||||
suggestionDropdown.setVisibility(View.GONE);
|
||||
clearButton.setVisibility(View.GONE);
|
||||
|
||||
state = State.WAITING;
|
||||
|
||||
mainView.setClickable(false);
|
||||
editText.setActive(false);
|
||||
suggestionDropdown.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void transitionToRunning() {
|
||||
if (state == State.RUNNING) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEditTextFocusable(true);
|
||||
mainView.setClickable(true);
|
||||
|
||||
suggestionDropdown.setVisibility(View.VISIBLE);
|
||||
clearButton.setVisibility(View.VISIBLE);
|
||||
|
||||
state = State.RUNNING;
|
||||
}
|
||||
|
||||
private void setEditTextFocusable(boolean focusable) {
|
||||
editText.setFocusable(focusable);
|
||||
editText.setFocusableInTouchMode(focusable);
|
||||
|
||||
if (focusable) {
|
||||
editText.requestFocus();
|
||||
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
|
||||
} else {
|
||||
editText.clearFocus();
|
||||
inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJumpTap(String suggestion) {
|
||||
editText.setText(suggestion);
|
||||
// Move cursor to end of search input.
|
||||
editText.setSelection(suggestion.length());
|
||||
mainView.setClickable(true);
|
||||
editText.setActive(true);
|
||||
suggestionDropdown.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public static class Suggestion {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="textNoSuggestions|textVisiblePassword"
|
||||
android:drawableLeft="@drawable/search_icon"
|
||||
android:drawablePadding="10dp"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:hint="@string/search_bar_hint"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/clear_button"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/search_clear"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</merge>
|
|
@ -8,37 +8,13 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:clickable="false"
|
||||
tools:context=".autocomplete.AutoCompleteFragment">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_bar"
|
||||
<org.mozilla.search.autocomplete.ClearableEditText
|
||||
android:id="@+id/auto_complete_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_bar_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="textNoSuggestions|textVisiblePassword"
|
||||
android:drawableLeft="@drawable/search_icon"
|
||||
android:drawablePadding="10dp"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:hint="@string/search_bar_hint"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/search_bar_clear_button"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/search_clear"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
android:padding="10dp"/>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/auto_complete_dropdown"
|
||||
|
|
|
@ -8,6 +8,7 @@ search_activity_sources = [
|
|||
'java/org/mozilla/search/autocomplete/AcceptsJumpTaps.java',
|
||||
'java/org/mozilla/search/autocomplete/AcceptsSearchQuery.java',
|
||||
'java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java',
|
||||
'java/org/mozilla/search/autocomplete/ClearableEditText.java',
|
||||
'java/org/mozilla/search/autocomplete/SearchFragment.java',
|
||||
'java/org/mozilla/search/autocomplete/SuggestClient.java',
|
||||
'java/org/mozilla/search/Constants.java',
|
||||
|
|
|
@ -2000,6 +2000,9 @@ pref("layout.css.overflow-clip-box.enabled", false);
|
|||
// Is support for CSS grid enabled?
|
||||
pref("layout.css.grid.enabled", false);
|
||||
|
||||
// Is support for CSS Ruby enabled?
|
||||
pref("layout.css.ruby.enabled", false);
|
||||
|
||||
// Is support for CSS box-decoration-break enabled?
|
||||
pref("layout.css.box-decoration-break.enabled", true);
|
||||
|
||||
|
|
|
@ -136,6 +136,9 @@ user_pref("layout.css.report_errors", true);
|
|||
// Enable CSS Grid for testing
|
||||
user_pref("layout.css.grid.enabled", true);
|
||||
|
||||
// Enable CSS Ruby for testing
|
||||
user_pref("layout.css.ruby.enabled", true);
|
||||
|
||||
// Enable mozContacts
|
||||
user_pref("dom.mozContacts.enabled", true);
|
||||
user_pref("dom.navigator-property.disable.mozContacts", false);
|
||||
|
|
|
@ -108,7 +108,7 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) {
|
|||
jConnectionGetMimeType = getStaticMethod("connectionGetMimeType", "(Ljava/net/URLConnection;)Ljava/lang/String;");
|
||||
jCreateInputStream = getStaticMethod("createInputStream", "(Ljava/net/URLConnection;)Ljava/io/InputStream;");
|
||||
jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;IIZI)V");
|
||||
jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
jDeleteMessageWrapper = getStaticMethod("deleteMessage", "(II)V");
|
||||
jDisableBatteryNotifications = getStaticMethod("disableBatteryNotifications", "()V");
|
||||
jDisableNetworkNotifications = getStaticMethod("disableNetworkNotifications", "()V");
|
||||
|
@ -348,18 +348,17 @@ void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArra
|
|||
env->PopLocalFrame(nullptr);
|
||||
}
|
||||
|
||||
void GeckoAppShell::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) {
|
||||
void GeckoAppShell::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2) {
|
||||
JNIEnv *env = AndroidBridge::GetJNIEnv();
|
||||
if (env->PushLocalFrame(4) != 0) {
|
||||
if (env->PushLocalFrame(3) != 0) {
|
||||
AndroidBridge::HandleUncaughtException(env);
|
||||
MOZ_CRASH("Exception should have caused crash.");
|
||||
}
|
||||
|
||||
jvalue args[4];
|
||||
jvalue args[3];
|
||||
args[0].l = AndroidBridge::NewJavaString(env, a0);
|
||||
args[1].l = AndroidBridge::NewJavaString(env, a1);
|
||||
args[2].l = AndroidBridge::NewJavaString(env, a2);
|
||||
args[3].l = AndroidBridge::NewJavaString(env, a3);
|
||||
|
||||
env->CallStaticVoidMethodA(mGeckoAppShellClass, jCreateShortcut, args);
|
||||
AndroidBridge::HandleUncaughtException(env);
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
static jstring ConnectionGetMimeType(jobject a0);
|
||||
static jobject CreateInputStream(jobject a0);
|
||||
static void CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6);
|
||||
static void CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3);
|
||||
static void CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2);
|
||||
static void DeleteMessageWrapper(int32_t a0, int32_t a1);
|
||||
static void DisableBatteryNotifications();
|
||||
static void DisableNetworkNotifications();
|
||||
|
|
Загрузка…
Ссылка в новой задаче