Merge b2ginbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-10-07 11:04:26 -07:00
commit 3879aa4f85
34 changed files with 586 additions and 334 deletions

View File

@ -125,7 +125,7 @@ textarea,
border-style: solid;
border-color: #7d7d7d;
color: #414141;
background: white linear-gradient(rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);
background-color: white;
}
/* Selects are handled by the form helper, see bug 685197 */
@ -147,11 +147,11 @@ button {
}
input[type="checkbox"] {
background: white linear-gradient(rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
background-color: white;
}
input[type="radio"] {
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
background-color: white;
}
select {
@ -226,7 +226,7 @@ input[type="file"]:focus > input[type="text"],
outline: 0px !important;
border-style: solid;
border-color: rgb(94,128,153);
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
background-color: white;
}
select:not([size]):not([multiple]):focus,
@ -247,14 +247,6 @@ input[type="radio"]:focus {
border-color: #99c6e0 !important;
}
input[type="checkbox"]:focus {
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
}
input[type="radio"]:focus {
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
}
/* we need to be specific for selects because the above rules are specific too */
textarea[disabled],
select[size][disabled],
@ -269,13 +261,13 @@ button[disabled],
border-color: rgba(125,125,125,0.4);
border-style: solid;
border-width: 1px;
background: transparent linear-gradient(rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
background-color: #f5f5f5;
}
select:not([size]):not([multiple])[disabled],
select[size="0"][disabled],
select[size="1"][disabled] {
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
background-color: #f5f5f5;
}
input[type="button"][disabled],
@ -286,7 +278,7 @@ button[disabled] {
-moz-padding-end: 7px;
padding-block-start: 0;
padding-block-end: 0;
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
background-color: #f5f5f5;
}
input[type="radio"][disabled],

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>

View File

@ -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="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -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="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "77d463a009a1425e413edaae92b237e116708560",
"git_revision": "b99837aa2294348317bcae68acabe71d9a83d774",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "c00c454a571f087579b93184b878363351844ae2",
"revision": "cd2549520049a8532b966d3edda167f7bc444fba",
"repo_path": "integration/gaia-central"
}

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>

View File

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77d463a009a1425e413edaae92b237e116708560"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>

View File

@ -120,10 +120,10 @@ public:
{
if (aName.EqualsLiteral("appId")) {
nsresult rv;
mOriginAttributes->mAppId = aValue.ToInteger(&rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
int64_t val = aValue.ToInteger64(&rv);
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_TRUE(val <= UINT32_MAX, false);
mOriginAttributes->mAppId = static_cast<uint32_t>(val);
return true;
}
@ -145,10 +145,10 @@ public:
if (aName.EqualsLiteral("userContextId")) {
nsresult rv;
mOriginAttributes->mUserContextId = aValue.ToInteger(&rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
int64_t val = aValue.ToInteger64(&rv);
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_TRUE(val <= UINT32_MAX, false);
mOriginAttributes->mUserContextId = static_cast<uint32_t>(val);
return true;
}

View File

@ -49,6 +49,9 @@ LOCAL_INCLUDES += [
'/js/xpconnect/src',
]
if CONFIG['ENABLE_TESTS']:
DIRS += ['tests/gtest']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/BasePrincipal.h"
using mozilla::OriginAttributes;
static void
TestSuffix(const OriginAttributes& attrs)
{
nsAutoCString suffix;
attrs.CreateSuffix(suffix);
OriginAttributes attrsFromSuffix;
attrsFromSuffix.PopulateFromSuffix(suffix);
EXPECT_EQ(attrs, attrsFromSuffix);
}
TEST(OriginAttributes, Suffix_default)
{
OriginAttributes attrs;
TestSuffix(attrs);
}
TEST(OriginAttributes, Suffix_appId_inBrowser)
{
OriginAttributes attrs(1, true);
TestSuffix(attrs);
}
TEST(OriginAttributes, Suffix_maxAppId_inBrowser)
{
OriginAttributes attrs(4294967295, true);
TestSuffix(attrs);
}

View File

@ -0,0 +1,13 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestOriginAttributes.cpp'
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'

View File

@ -166,14 +166,6 @@ Telephony::IsValidServiceId(uint32_t aServiceId)
return aServiceId < GetNumServices();
}
// static
bool
Telephony::IsActiveState(uint16_t aCallState) {
return aCallState == nsITelephonyService::CALL_STATE_DIALING ||
aCallState == nsITelephonyService::CALL_STATE_ALERTING ||
aCallState == nsITelephonyService::CALL_STATE_CONNECTED;
}
uint32_t
Telephony::GetServiceId(const Optional<uint32_t>& aServiceId,
bool aGetIfActiveCall)
@ -182,11 +174,11 @@ Telephony::GetServiceId(const Optional<uint32_t>& aServiceId,
return aServiceId.Value();
} else if (aGetIfActiveCall) {
nsTArray<nsRefPtr<TelephonyCall> > &calls = mCalls;
if (mGroup->CallState() == nsITelephonyService::CALL_STATE_CONNECTED) {
if (mGroup->IsActive()) {
calls = mGroup->CallsArray();
}
for (uint32_t i = 0; i < calls.Length(); i++) {
if (IsActiveState(calls[i]->CallState())) {
if (calls[i]->IsActive()) {
return calls[i]->mServiceId;
}
}
@ -257,17 +249,17 @@ Telephony::CreateCallId(const nsAString& aNumber, uint16_t aNumberPresentation,
already_AddRefed<TelephonyCall>
Telephony::CreateCall(TelephonyCallId* aId, uint32_t aServiceId,
uint32_t aCallIndex, uint16_t aCallState,
uint32_t aCallIndex, TelephonyCallState aState,
bool aEmergency, bool aConference,
bool aSwitchable, bool aMergeable)
{
// We don't have to create an already ended call.
if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
if (aState == TelephonyCallState::Disconnected) {
return nullptr;
}
nsRefPtr<TelephonyCall> call =
TelephonyCall::Create(this, aId, aServiceId, aCallIndex, aCallState,
TelephonyCall::Create(this, aId, aServiceId, aCallIndex, aState,
aEmergency, aConference, aSwitchable, aMergeable);
NS_ASSERTION(call, "This should never fail!");
@ -338,61 +330,66 @@ Telephony::HandleCallInfo(nsITelephonyCallInfo* aInfo)
aInfo->GetIsSwitchable(&isSwitchable);
aInfo->GetIsMergeable(&isMergeable);
nsRefPtr<TelephonyCall> call = GetCallFromEverywhere(serviceId, callIndex);
TelephonyCallState state = TelephonyCall::ConvertToTelephonyCallState(callState);
nsRefPtr<TelephonyCall> call = GetCallFromEverywhere(serviceId, callIndex);
// Handle a newly created call.
if (!call) {
nsRefPtr<TelephonyCallId> id = CreateCallId(aInfo);
call = CreateCall(id, serviceId, callIndex, callState, isEmergency,
call = CreateCall(id, serviceId, callIndex, state, isEmergency,
isConference, isSwitchable, isMergeable);
if (call && callState == nsITelephonyService::CALL_STATE_INCOMING) {
// The newly created call is an incoming call.
if (call &&
state == TelephonyCallState::Incoming) {
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call);
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
call->UpdateEmergency(isEmergency);
call->UpdateSwitchable(isSwitchable);
call->UpdateMergeable(isMergeable);
return NS_OK;
}
nsAutoString number;
aInfo->GetNumber(number);
nsRefPtr<TelephonyCallId> id = call->Id();
id->UpdateNumber(number);
// Update an existing call
call->UpdateEmergency(isEmergency);
call->UpdateSwitchable(isSwitchable);
call->UpdateMergeable(isMergeable);
nsAutoString disconnectedReason;
aInfo->GetDisconnectedReason(disconnectedReason);
nsAutoString number;
aInfo->GetNumber(number);
nsRefPtr<TelephonyCallId> id = call->Id();
id->UpdateNumber(number);
// State changed.
if (call->CallState() != callState) {
if (callState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
call->UpdateDisconnectedReason(disconnectedReason);
call->ChangeState(nsITelephonyService::CALL_STATE_DISCONNECTED);
return NS_OK;
}
nsAutoString disconnectedReason;
aInfo->GetDisconnectedReason(disconnectedReason);
// We don't fire the statechange event on a call in conference here.
// Instead, the event will be fired later in
// TelephonyCallGroup::ChangeState(). Thus the sequence of firing the
// statechange events is guaranteed: first on TelephonyCallGroup then on
// individual TelephonyCall objects.
bool fireEvent = !isConference;
call->ChangeStateInternal(callState, fireEvent);
// State changed.
if (call->State() != state) {
if (state == TelephonyCallState::Disconnected) {
call->UpdateDisconnectedReason(disconnectedReason);
call->ChangeState(TelephonyCallState::Disconnected);
return NS_OK;
}
// Group changed.
nsRefPtr<TelephonyCallGroup> group = call->GetGroup();
// We don't fire the statechange event on a call in conference here.
// Instead, the event will be fired later in
// TelephonyCallGroup::ChangeState(). Thus the sequence of firing the
// statechange events is guaranteed: first on TelephonyCallGroup then on
// individual TelephonyCall objects.
bool fireEvent = !isConference;
call->ChangeStateInternal(state, fireEvent);
}
if (!group && isConference) {
// Add to conference.
NS_ASSERTION(mCalls.Contains(call), "Should in mCalls");
mGroup->AddCall(call);
RemoveCall(call);
} else if (group && !isConference) {
// Remove from conference.
NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup");
mGroup->RemoveCall(call);
AddCall(call);
}
// Group changed.
nsRefPtr<TelephonyCallGroup> group = call->GetGroup();
if (!group && isConference) {
// Add to conference.
NS_ASSERTION(mCalls.Contains(call), "Should in mCalls");
mGroup->AddCall(call);
RemoveCall(call);
} else if (group && !isConference) {
// Remove from conference.
NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup");
mGroup->RemoveCall(call);
AddCall(call);
}
return NS_OK;
@ -623,18 +620,21 @@ Telephony::SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv)
void
Telephony::GetActive(Nullable<OwningTelephonyCallOrTelephonyCallGroup>& aValue)
{
if (mGroup->CallState() == nsITelephonyService::CALL_STATE_CONNECTED) {
if (mGroup->IsActive()) {
aValue.SetValue().SetAsTelephonyCallGroup() = mGroup;
} else {
// Search the first active call.
for (uint32_t i = 0; i < mCalls.Length(); i++) {
if (IsActiveState(mCalls[i]->CallState())) {
aValue.SetValue().SetAsTelephonyCall() = mCalls[i];
return;
}
}
aValue.SetNull();
return;
}
// Search for the active call.
for (uint32_t i = 0; i < mCalls.Length(); i++) {
if (mCalls[i]->IsActive()) {
aValue.SetValue().SetAsTelephonyCall() = mCalls[i];
return;
}
}
// Nothing active found.
aValue.SetNull();
}
already_AddRefed<CallsList>
@ -747,7 +747,11 @@ Telephony::EnumerateCallState(nsITelephonyCallInfo* aInfo)
NS_IMETHODIMP
Telephony::ConferenceCallStateChanged(uint16_t aCallState)
{
mGroup->ChangeState(aCallState);
// The current design of Telephony Stack gaurantees that the calls within a
// call group are updated before this method being called, so we can let a
// call update its state by its own, and we can discard |aCallState| here.
// Anyway, this method is going to be deprecated in Bug 1155072.
mGroup->ChangeState();
return NS_OK;
}
@ -755,19 +759,7 @@ NS_IMETHODIMP
Telephony::EnumerateCallStateComplete()
{
// Set conference state.
if (mGroup->CallsArray().Length() >= 2) {
const nsTArray<nsRefPtr<TelephonyCall> > &calls = mGroup->CallsArray();
uint16_t callState = calls[0]->CallState();
for (uint32_t i = 1; i < calls.Length(); i++) {
if (calls[i]->CallState() != callState) {
callState = nsITelephonyService::CALL_STATE_UNKNOWN;
break;
}
}
mGroup->ChangeState(callState);
}
mGroup->ChangeState();
HandleAudioAgentState();
if (mReadyPromise) {

View File

@ -190,9 +190,6 @@ private:
static bool
IsValidServiceId(uint32_t aServiceId);
static bool
IsActiveState(uint16_t aCallState);
uint32_t
GetServiceId(const Optional<uint32_t>& aServiceId,
bool aGetIfActiveCall = false);
@ -212,9 +209,13 @@ private:
already_AddRefed<TelephonyCall>
CreateCall(TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex, uint16_t aCallState,
bool aEmergency = false, bool aConference = false,
bool aSwitchable = true, bool aMergeable = true);
uint32_t aServiceId,
uint32_t aCallIndex,
TelephonyCallState aState,
bool aEmergency = false,
bool aConference = false,
bool aSwitchable = true,
bool aMergeable = true);
nsresult
NotifyEvent(const nsAString& aType);

View File

@ -34,16 +34,51 @@
} \
}
#ifdef TELEPHONY_CALL_STATE
#undef TELEPHONY_CALL_STATE
#endif
#define TELEPHONY_CALL_STATE(_state) \
(TelephonyCallStateValues::strings[static_cast<int32_t>(_state)].value)
using namespace mozilla::dom;
using namespace mozilla::dom::telephony;
using mozilla::ErrorResult;
// static
TelephonyCallState
TelephonyCall::ConvertToTelephonyCallState(uint32_t aCallState)
{
switch (aCallState) {
case nsITelephonyService::CALL_STATE_DIALING:
return TelephonyCallState::Dialing;
case nsITelephonyService::CALL_STATE_ALERTING:
return TelephonyCallState::Alerting;
case nsITelephonyService::CALL_STATE_CONNECTED:
return TelephonyCallState::Connected;
case nsITelephonyService::CALL_STATE_HELD:
return TelephonyCallState::Held;
case nsITelephonyService::CALL_STATE_DISCONNECTED:
return TelephonyCallState::Disconnected;
case nsITelephonyService::CALL_STATE_INCOMING:
return TelephonyCallState::Incoming;
}
NS_NOTREACHED("Unknown state!");
return TelephonyCallState::Disconnected;
}
// static
already_AddRefed<TelephonyCall>
TelephonyCall::Create(Telephony* aTelephony, TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex,
uint16_t aCallState, bool aEmergency, bool aConference,
bool aSwitchable, bool aMergeable)
TelephonyCall::Create(Telephony* aTelephony,
TelephonyCallId* aId,
uint32_t aServiceId,
uint32_t aCallIndex,
TelephonyCallState aState,
bool aEmergency,
bool aConference,
bool aSwitchable,
bool aMergeable)
{
NS_ASSERTION(aTelephony, "Null aTelephony pointer!");
NS_ASSERTION(aId, "Null aId pointer!");
@ -61,8 +96,7 @@ TelephonyCall::Create(Telephony* aTelephony, TelephonyCallId* aId,
call->mMergeable = aMergeable;
call->mError = nullptr;
call->ChangeStateInternal(aCallState, false);
call->ChangeStateInternal(aState, false);
return call.forget();
}
@ -83,35 +117,15 @@ TelephonyCall::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
void
TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
TelephonyCall::ChangeStateInternal(TelephonyCallState aState, bool aFireEvents)
{
nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
mCallState = aCallState;
switch (aCallState) {
case nsITelephonyService::CALL_STATE_DIALING:
mState.AssignLiteral("dialing");
break;
case nsITelephonyService::CALL_STATE_ALERTING:
mState.AssignLiteral("alerting");
break;
case nsITelephonyService::CALL_STATE_CONNECTED:
mState.AssignLiteral("connected");
break;
case nsITelephonyService::CALL_STATE_HELD:
mState.AssignLiteral("held");
break;
case nsITelephonyService::CALL_STATE_DISCONNECTED:
mState.AssignLiteral("disconnected");
break;
case nsITelephonyService::CALL_STATE_INCOMING:
mState.AssignLiteral("incoming");
break;
default:
NS_NOTREACHED("Unknown state!");
}
// Update current state
mState = aState;
if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
// Handle disconnected calls
if (mState == TelephonyCallState::Disconnected) {
NS_ASSERTION(mLive, "Should be live!");
mLive = false;
if (mGroup) {
@ -119,7 +133,7 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
} else {
mTelephony->RemoveCall(this);
}
} else if (!mLive) {
} else if (!mLive) { // Handle newly added calls
mLive = true;
if (mGroup) {
mGroup->AddCall(this);
@ -128,23 +142,39 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
}
}
// Dispatch call state changed and call state event
if (aFireEvents) {
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
// This can change if the statechange handler called back here... Need to
// figure out something smarter.
if (mCallState == aCallState) {
rv = DispatchCallEvent(mState, this);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
}
NotifyStateChanged();
}
}
nsresult
TelephonyCall::NotifyStateChanged()
{
// Since |mState| can be changed after statechange handler called back here,
// we must save current state. Maybe we should figure out something smarter.
TelephonyCallState prevState = mState;
nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
// Check whether |mState| remains the same after the statechange handler.
if (mState != prevState) {
NS_WARNING("Call State has changed by statechange handler!");
return res;
}
res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_CALL_STATE(mState)),
this);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch a specific event!");
}
return res;
}
nsresult
TelephonyCall::DispatchCallEvent(const nsAString& aType,
TelephonyCall* aCall)
@ -278,9 +308,10 @@ TelephonyCall::Answer(ErrorResult& aRv)
return nullptr;
}
if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
if (mState != TelephonyCallState::Incoming) {
NS_WARNING(nsPrintfCString("Answer on non-incoming call is rejected!"
" (State: %u)", mCallState).get());
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
@ -300,15 +331,16 @@ TelephonyCall::HangUp(ErrorResult& aRv)
return nullptr;
}
if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
NS_WARNING(nsPrintfCString("HangUp on previously disconnected call"
" is rejected! (State: %u)", mCallState).get());
if (mState == TelephonyCallState::Disconnected) {
NS_WARNING(nsPrintfCString("HangUp on a disconnected call is rejected!"
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
aRv = mState == TelephonyCallState::Incoming ?
mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) :
mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
@ -334,30 +366,13 @@ TelephonyCall::Hold(ErrorResult& aRv)
return promise.forget();
}
already_AddRefed<Promise>
TelephonyCall::Resume(ErrorResult& aRv)
{
nsRefPtr<Promise> promise = CreatePromise(aRv);
if (!promise) {
return nullptr;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = Resume(callback);
if (NS_WARN_IF(aRv.Failed() &&
!aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) {
return nullptr;
}
return promise.forget();
}
nsresult
TelephonyCall::Hold(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
if (mState != TelephonyCallState::Connected) {
NS_WARNING(nsPrintfCString("Hold non-connected call is rejected!"
" (State: %u)", mCallState).get());
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
@ -389,11 +404,31 @@ TelephonyCall::Hold(nsITelephonyCallback* aCallback)
return NS_OK;
}
already_AddRefed<Promise>
TelephonyCall::Resume(ErrorResult& aRv)
{
nsRefPtr<Promise> promise = CreatePromise(aRv);
if (!promise) {
return nullptr;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = Resume(callback);
if (NS_WARN_IF(aRv.Failed() &&
!aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) {
return nullptr;
}
return promise.forget();
}
nsresult
TelephonyCall::Resume(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
NS_WARNING("Resume non-held call is rejected!");
if (mState != TelephonyCallState::Held) {
NS_WARNING(nsPrintfCString("Resume non-held call is rejected!"
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}

View File

@ -29,7 +29,7 @@ class TelephonyCall final : public DOMEventTargetHelper
nsRefPtr<TelephonyCallId> mSecondId;
uint32_t mServiceId;
nsString mState;
TelephonyCallState mState;
bool mEmergency;
nsRefPtr<DOMError> mError;
Nullable<TelephonyCallDisconnectedReason> mDisconnectedReason;
@ -38,7 +38,6 @@ class TelephonyCall final : public DOMEventTargetHelper
bool mMergeable;
uint32_t mCallIndex;
uint16_t mCallState;
bool mLive;
public:
@ -65,10 +64,10 @@ public:
already_AddRefed<TelephonyCallId>
GetSecondId() const;
void
GetState(nsString& aState) const
TelephonyCallState
State() const
{
aState.Assign(mState);
return mState;
}
bool
@ -89,6 +88,14 @@ public:
return mMergeable;
}
bool
IsActive() const
{
return mState == TelephonyCallState::Dialing ||
mState == TelephonyCallState::Alerting ||
mState == TelephonyCallState::Connected;
}
already_AddRefed<DOMError>
GetError() const;
@ -122,18 +129,24 @@ public:
IMPL_EVENT_HANDLER(error)
IMPL_EVENT_HANDLER(groupchange)
static TelephonyCallState
ConvertToTelephonyCallState(uint32_t aCallState);
static already_AddRefed<TelephonyCall>
Create(Telephony* aTelephony, TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex, uint16_t aCallState,
uint32_t aServiceId, uint32_t aCallIndex, TelephonyCallState aState,
bool aEmergency = false, bool aConference = false,
bool aSwitchable = true, bool aMergeable = true);
void
ChangeState(uint16_t aCallState)
ChangeState(TelephonyCallState aState)
{
ChangeStateInternal(aCallState, true);
ChangeStateInternal(aState, true);
}
nsresult
NotifyStateChanged();
uint32_t
ServiceId() const
{
@ -146,12 +159,6 @@ public:
return mCallIndex;
}
uint16_t
CallState() const
{
return mCallState;
}
void
UpdateEmergency(bool aEmergency)
{
@ -194,7 +201,7 @@ private:
Resume(nsITelephonyCallback* aCallback);
void
ChangeStateInternal(uint16_t aCallState, bool aFireEvents);
ChangeStateInternal(TelephonyCallState aState, bool aFireEvents);
nsresult
DispatchCallEvent(const nsAString& aType,

View File

@ -10,16 +10,23 @@
#include "Telephony.h"
#include "mozilla/dom/CallEvent.h"
#include "mozilla/dom/CallGroupErrorEvent.h"
#include "mozilla/dom/TelephonyCallGroupBinding.h"
#include "mozilla/dom/telephony/TelephonyCallback.h"
#include "nsPrintfCString.h"
#ifdef TELEPHONY_GROUP_STATE
#undef TELEPHONY_GROUP_STATE
#endif
#define TELEPHONY_GROUP_STATE(_state) \
(TelephonyCallGroupStateValues::strings[static_cast<int32_t>(_state)].value)
using namespace mozilla::dom;
using namespace mozilla::dom::telephony;
using mozilla::ErrorResult;
TelephonyCallGroup::TelephonyCallGroup(nsPIDOMWindow* aOwner)
: DOMEventTargetHelper(aOwner)
, mCallState(nsITelephonyService::CALL_STATE_UNKNOWN)
{
}
@ -37,6 +44,7 @@ TelephonyCallGroup::Create(Telephony* aTelephony)
new TelephonyCallGroup(aTelephony->GetOwner());
group->mTelephony = aTelephony;
group->mState = TelephonyCallGroupState::_empty;
group->mCallsList = new CallsList(aTelephony, group);
return group.forget();
@ -82,48 +90,84 @@ TelephonyCallGroup::NotifyError(const nsAString& aName, const nsAString& aMessag
}
void
TelephonyCallGroup::ChangeState(uint16_t aCallState)
TelephonyCallGroup::ChangeState()
{
if (mCallState == aCallState) {
MOZ_ASSERT(mCalls.Length() != 1);
if (mCalls.Length() == 0) {
ChangeStateInternal(TelephonyCallGroupState::_empty);
return;
}
mCallState = aCallState;
switch (aCallState) {
case nsITelephonyService::CALL_STATE_UNKNOWN:
mState.AssignLiteral("");
break;
case nsITelephonyService::CALL_STATE_CONNECTED:
mState.AssignLiteral("connected");
break;
case nsITelephonyService::CALL_STATE_HELD:
mState.AssignLiteral("held");
break;
default:
NS_NOTREACHED("Unknown state!");
}
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
if (!mState.IsEmpty()) {
// This can change if the statechange handler called back here... Need to
// figure out something smarter.
if (mCallState == aCallState) {
rv = DispatchCallEvent(mState, nullptr);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
TelephonyCallState state = mCalls[0]->State();
for (uint32_t i = 1; i < mCalls.Length(); i++) {
if (mCalls[i]->State() != state) {
MOZ_ASSERT(false, "Various call states are found in a call group!");
ChangeStateInternal(TelephonyCallGroupState::_empty);
return;
}
}
for (uint32_t index = 0; index < mCalls.Length(); index++) {
nsRefPtr<TelephonyCall> call = mCalls[index];
call->ChangeState(aCallState);
MOZ_ASSERT(call->CallState() == aCallState);
TelephonyCallGroupState groupState = TelephonyCallGroupState::_empty;
switch (state) {
case TelephonyCallState::Connected:
groupState = TelephonyCallGroupState::Connected;
break;
case TelephonyCallState::Held:
groupState = TelephonyCallGroupState::Held;
break;
default:
NS_NOTREACHED(nsPrintfCString("Invavild call state for a call group(%s)!",
TELEPHONY_CALL_STATE(state)).get());
}
ChangeStateInternal(groupState);
}
void
TelephonyCallGroup::ChangeStateInternal(TelephonyCallGroupState aState)
{
if (mState == aState) {
return;
}
// Update Current State
mState = aState;
// Dispatch related events
NotifyStateChanged();
}
nsresult
TelephonyCallGroup::NotifyStateChanged()
{
// Since |mState| can be changed after statechange handler called back here,
// we must save current state. Maybe we should figure out something smarter.
TelephonyCallGroupState prevState = mState;
nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
// Check whether |mState| remains the same after the statechange handler.
// Besides, If there is no conference call at all, then we dont't have to
// dispatch the state evnet.
if (mState == prevState) {
res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_GROUP_STATE(mState)),
nullptr);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
}
// Notify each call within to dispatch call state change event
for (uint32_t index = 0; index < mCalls.Length(); index++) {
if (NS_FAILED(mCalls[index]->NotifyStateChanged())){
res = NS_ERROR_FAILURE;
}
}
return res;
}
nsresult
@ -172,14 +216,13 @@ TelephonyCallGroup::CanConference(const TelephonyCall& aCall,
if (!aSecondCall) {
MOZ_ASSERT(!mCalls.IsEmpty());
return (mCallState == nsITelephonyService::CALL_STATE_CONNECTED &&
aCall.CallState() == nsITelephonyService::CALL_STATE_HELD) ||
(mCallState == nsITelephonyService::CALL_STATE_HELD &&
aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
return (mState == TelephonyCallGroupState::Connected &&
aCall.State() == TelephonyCallState::Held) ||
(mState == TelephonyCallGroupState::Held &&
aCall.State() == TelephonyCallState::Connected);
}
MOZ_ASSERT(mCallState == nsITelephonyService::CALL_STATE_UNKNOWN);
MOZ_ASSERT(mState != TelephonyCallGroupState::_empty);
if (aCall.ServiceId() != aSecondCall->ServiceId()) {
return false;
@ -189,10 +232,10 @@ TelephonyCallGroup::CanConference(const TelephonyCall& aCall,
return false;
}
return (aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED &&
aSecondCall->CallState() == nsITelephonyService::CALL_STATE_HELD) ||
(aCall.CallState() == nsITelephonyService::CALL_STATE_HELD &&
aSecondCall->CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
return (aCall.State() == TelephonyCallState::Connected &&
aSecondCall->State() == TelephonyCallState::Held) ||
(aCall.State() == TelephonyCallState::Held &&
aSecondCall->State() == TelephonyCallState::Connected);
}
already_AddRefed<TelephonyCall>
@ -297,7 +340,7 @@ TelephonyCallGroup::Remove(TelephonyCall& aCall, ErrorResult& aRv)
return nullptr;
}
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
if (mState != TelephonyCallGroupState::Connected) {
NS_WARNING("Remove call from a non-connected call group. Ignore!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
@ -330,6 +373,14 @@ TelephonyCallGroup::HangUp(ErrorResult& aRv)
return nullptr;
}
if (mState == TelephonyCallGroupState::_empty) {
NS_WARNING(nsPrintfCString("We don't have a call group now!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mTelephony->Service()->HangUpConference(mCalls[0]->ServiceId(),
callback);
@ -357,6 +408,26 @@ TelephonyCallGroup::Hold(ErrorResult& aRv)
return promise.forget();
}
nsresult
TelephonyCallGroup::Hold(nsITelephonyCallback* aCallback)
{
if (mState != TelephonyCallGroupState::Connected) {
NS_WARNING(nsPrintfCString("Resume non-connected call group is rejected!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(),
aCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
already_AddRefed<Promise>
TelephonyCallGroup::Resume(ErrorResult& aRv)
{
@ -377,29 +448,13 @@ TelephonyCallGroup::Resume(ErrorResult& aRv)
return promise.forget();
}
nsresult
TelephonyCallGroup::Hold(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
NS_WARNING("Holding a non-connected call is rejected!");
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(),
aCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
TelephonyCallGroup::Resume(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
NS_WARNING("Resuming a non-held call is rejected!");
if (mState != TelephonyCallGroupState::Held) {
NS_WARNING(nsPrintfCString("Resume non-held call group is rejected!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}

View File

@ -8,6 +8,7 @@
#define mozilla_dom_telephony_telephonycallgroup_h__
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/TelephonyCallGroupBinding.h"
#include "mozilla/dom/telephony/TelephonyCommon.h"
namespace mozilla {
@ -21,9 +22,7 @@ class TelephonyCallGroup final : public DOMEventTargetHelper
nsRefPtr<CallsList> mCallsList;
nsString mState;
uint16_t mCallState;
TelephonyCallGroupState mState;
public:
NS_DECL_ISUPPORTS_INHERITED
@ -64,10 +63,15 @@ public:
already_AddRefed<Promise>
Resume(ErrorResult& aRv);
void
GetState(nsString& aState) const
TelephonyCallGroupState
State() const
{
aState = mState;
return mState;
}
bool
IsActive() {
return mState == TelephonyCallGroupState::Connected;
}
IMPL_EVENT_HANDLER(statechange)
@ -94,14 +98,9 @@ public:
return mCalls;
}
// Update its call state according to the calls wihtin itself.
void
ChangeState(uint16_t aCallState);
uint16_t
CallState() const
{
return mCallState;
}
ChangeState();
nsresult
NotifyError(const nsAString& aName, const nsAString& aMessage);
@ -116,9 +115,15 @@ private:
nsresult
Resume(nsITelephonyCallback* aCallback);
nsresult
NotifyStateChanged();
nsresult
NotifyCallsChanged(TelephonyCall* aCall);
void
ChangeStateInternal(TelephonyCallGroupState aState);
nsresult
DispatchCallEvent(const nsAString& aType,
TelephonyCall* aCall);

View File

@ -59,7 +59,7 @@ TelephonyDialCallback::NotifyDialCallSuccess(uint32_t aClientId,
nsRefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
nsRefPtr<TelephonyCall> call =
mTelephony->CreateCall(id, aClientId, aCallIndex,
nsITelephonyService::CALL_STATE_DIALING);
TelephonyCallState::Dialing);
mPromise->MaybeResolve(call);
return NS_OK;

View File

@ -1070,14 +1070,22 @@ TelephonyService.prototype = {
// Handle unknown MMI code as USSD.
default:
this._sendUSSDInternal(aClientId, aMmi.fullMMI, aResponse => {
if (aResponse.errorMsg) {
aCallback.notifyDialMMIError(aResponse.errorMsg);
return;
}
aCallback.notifyDialMMISuccess("");
});
if (this._ussdSessions[aClientId]) {
// Cancel the previous ussd session first.
this._cancelUSSDInternal(aClientId, aResponse => {
// Fail to cancel ussd session, report error instead of sending ussd
// request.
if (aResponse.errorMsg) {
aCallback.notifyDialMMIError(aResponse.errorMsg);
return;
}
this._sendUSSDInternal(aClientId, aMmi.fullMMI,
this._defaultMMICallbackHandler.bind(this, aCallback));
});
return;
}
this._sendUSSDInternal(aClientId, aMmi.fullMMI,
this._defaultMMICallbackHandler.bind(this, aCallback));
break;
}
},
@ -1684,6 +1692,14 @@ TelephonyService.prototype = {
}
},
_defaultMMICallbackHandler: function(aCallback, aResponse) {
if (aResponse.errorMsg) {
aCallback.notifyDialMMIError(aResponse.errorMsg);
} else {
aCallback.notifyDialMMISuccess("");
}
},
_getCallsWithState: function(aClientId, aState) {
let calls = [];
for (let i in this._currentCalls[aClientId]) {
@ -2138,24 +2154,9 @@ TelephonyService.prototype = {
},
_sendUSSDInternal: function(aClientId, aUssd, aCallback) {
if (!this._ussdSessions[aClientId]) {
this._sendToRilWorker(aClientId, "sendUSSD", { ussd: aUssd }, aResponse => {
this._ussdSessions[aClientId] = !aResponse.errorMsg;
aCallback(aResponse);
});
return;
}
// Cancel the previous ussd session first.
this._cancelUSSDInternal(aClientId, aResponse => {
// Fail to cancel ussd session, report error instead of sending ussd
// request.
if (aResponse.errorMsg) {
aCallback(aResponse);
return;
}
this._sendUSSDInternal(aClientId, aUssd, aCallback);
this._sendToRilWorker(aClientId, "sendUSSD", { ussd: aUssd }, aResponse => {
this._ussdSessions[aClientId] = !aResponse.errorMsg;
aCallback(aResponse);
});
},

View File

@ -4,7 +4,7 @@
"use strict";
function debug(aMsg) {
//dump("[TVSimulatorService] " + aMsg + "\n");
//dump("[TVSimulatorService] " + aMsg + "\n");
}
const Cc = Components.classes;
@ -14,6 +14,18 @@ const Cr = Components.returnCode;
const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy";
const TV_SIMULATOR_DUMMY_FILE = "settings.json";
// See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVSourceType
const TV_SOURCE_TYPES = ["dvb-t","dvb-t2","dvb-c","dvb-c2","dvb-s",
"dvb-s2","dvb-h","dvb-sh","atsc","atsc-m/h",
"isdb-t","isdb-tb","isdb-s","isdb-c","1seg",
"dtmb","cmmb","t-dmb","s-dmb"];
function containInvalidSourceType(aElement, aIndex, aArray) {
return !TV_SOURCE_TYPES.includes(aElement);
}
// See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVChannelType
const TV_CHANNEL_TYPES = ["tv","radio","data"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function TVSimulatorService() {
@ -66,7 +78,7 @@ TVSimulatorService.prototype = {
cstream.close();
}
let settingObj;
let settingsObj;
try {
/*
*
@ -109,18 +121,24 @@ TVSimulatorService.prototype = {
* },]
* }
*/
settingObj = JSON.parse(settingStr);
settingsObj = JSON.parse(settingStr);
} catch(e) {
debug("File load error: " + e);
return;
}
// validation
if (!this._validateSettings(settingsObj)) {
debug("Failed to validate settings.");
return;
}
// Key is as follow
// {'tunerId':tunerId, 'sourceType':sourceType}
this._internalTuners = new Map();
// TVTunerData
for each (let tunerData in settingObj.tuners) {
for each (let tunerData in settingsObj.tuners) {
let tuner = Cc["@mozilla.org/tv/tvtunerdata;1"]
.createInstance(Ci.nsITVTunerData);
tuner.id = tunerData.id;
@ -403,7 +421,7 @@ TVSimulatorService.prototype = {
}
let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
if (!wrapChannelData) {
if (!wrapChannelData || !wrapChannelData.videoFilePath) {
return "";
}
@ -433,6 +451,84 @@ TVSimulatorService.prototype = {
return dsFile.path;
},
_validateSettings: function TVSimValidateSettings(aSettingsObject) {
return this._validateTuners(aSettingsObject.tuners);
},
_validateTuners: function TVSimValidateTuners(aTunersObject) {
let tunerIds = new Array();
for each (let tuner in aTunersObject) {
if (!tuner.id ||
!tuner.supportedType ||
!tuner.supportedType.length ||
tuner.supportedType.some(containInvalidSourceType) ||
tunerIds.includes(tuner.id)) {
debug("invalid tuner data.");
return false;
}
tunerIds.push(tuner.id);
if (!this._validateSources(tuner.sources)) {
return false;
}
}
return true;
},
_validateSources: function TVSimValidateSources(aSourcesObject) {
for each (let source in aSourcesObject) {
if (!source.type ||
!TV_SOURCE_TYPES.includes(source.type)) {
debug("invalid source data.");
return false;
}
if (!this._validateChannels(source.channels)) {
return false;
}
}
return true;
},
_validateChannels: function TVSimValidateChannels(aChannelsObject) {
let channelNumbers = new Array();
for each (let channel in aChannelsObject) {
if (!channel.networkId ||
!channel.transportStreamId ||
!channel.serviceId ||
!channel.type ||
!TV_CHANNEL_TYPES.includes(channel.type) ||
!channel.number ||
channelNumbers.includes(channel.number) ||
!channel.name) {
debug("invalid channel data.");
return false;
}
channelNumbers.push(channel.number);
if (!this._validatePrograms(channel.programs)) {
return false;
}
}
return true;
},
_validatePrograms: function TVSimValidatePrograms(aProgramsObject) {
let eventIds = new Array();
for each (let program in aProgramsObject) {
if (!program.eventId ||
eventIds.includes(program.eventId) ||
!program.title ||
!program.startTime ||
!program.duration) {
debug("invalid program data.");
return false;
}
eventIds.push(program.eventId);
}
return true;
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TVSimulatorService]);

View File

@ -285,7 +285,7 @@ TVTuner::CreateSimulatedMediaStream()
currentChannelNumber,
domWin,
currentVideoBlobUrl);
if (NS_WARN_IF(NS_FAILED(rv))) {
if (NS_WARN_IF(NS_FAILED(rv) || currentVideoBlobUrl.IsEmpty())) {
return nullptr;
}

View File

@ -15,7 +15,7 @@ interface TelephonyCall : EventTarget {
// call. We need an additional attribute for the CDMA waiting call.
readonly attribute TelephonyCallId? secondId;
readonly attribute DOMString state;
readonly attribute TelephonyCallState state;
// The property "emergency" indicates whether the call number is an emergency
// number. Only the outgoing call could have a value with true and it is
@ -56,6 +56,15 @@ interface TelephonyCall : EventTarget {
attribute EventHandler ongroupchange;
};
enum TelephonyCallState {
"dialing",
"alerting",
"connected",
"held",
"disconnected",
"incoming",
};
enum TelephonyCallDisconnectedReason {
"BadNumber",
"NoRouteToDestination",

View File

@ -26,7 +26,7 @@ interface TelephonyCallGroup : EventTarget {
[NewObject, Throws]
Promise<void> resume();
readonly attribute DOMString state;
readonly attribute TelephonyCallGroupState state;
attribute EventHandler onstatechange;
attribute EventHandler onconnected;
@ -34,3 +34,9 @@ interface TelephonyCallGroup : EventTarget {
attribute EventHandler oncallschanged;
attribute EventHandler onerror;
};
enum TelephonyCallGroupState {
"",
"connected",
"held",
};

View File

@ -1,7 +1,7 @@
== textarea-valid.html textarea-ref.html
== textarea-customerror.html textarea-ref.html
fails-if(B2G||Mulet) == textarea-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(B2G||Mulet) == textarea-dyn-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== textarea-disabled.html textarea-ref.html
== textarea-dyn-disabled.html textarea-ref.html
== textarea-dyn-not-disabled.html textarea-ref.html
== textarea-readonly.html textarea-ref.html
== textarea-dyn-readonly.html textarea-ref.html

View File

@ -1,7 +1,7 @@
== textarea-valid.html textarea-ref.html
== textarea-customerror.html textarea-ref.html
skip-if(B2G||Mulet) == textarea-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(B2G||Mulet) == textarea-dyn-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== textarea-disabled.html textarea-ref.html
== textarea-dyn-disabled.html textarea-ref.html
== textarea-dyn-not-disabled.html textarea-ref.html
== textarea-readonly.html textarea-ref.html
== textarea-dyn-readonly.html textarea-ref.html

View File

@ -1,7 +1,7 @@
== textarea-valid.html textarea-ref.html
== textarea-customerror.html textarea-ref.html
fails-if(B2G||Mulet) == textarea-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
random-if(B2G||Mulet) == textarea-dyn-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== textarea-disabled.html textarea-ref.html
== textarea-dyn-disabled.html textarea-ref.html
== textarea-dyn-not-disabled.html textarea-ref.html
== textarea-dyn-not-disabled-changed.html textarea-ref.html
== textarea-readonly.html textarea-ref.html

View File

@ -1,7 +1,7 @@
== textarea-valid.html textarea-ref.html
== textarea-customerror.html textarea-ref.html
fails-if(B2G||Mulet) == textarea-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(B2G||Mulet) == textarea-dyn-disabled.html textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== textarea-disabled.html textarea-ref.html
== textarea-dyn-disabled.html textarea-ref.html
== textarea-dyn-not-disabled.html textarea-ref.html
== textarea-readonly.html textarea-ref.html
== textarea-dyn-readonly.html textarea-ref.html

View File

@ -17,11 +17,11 @@
== value-prop.html 75pct-common-ref.html
== valueAsNumber-prop-unthemed.html 75pct-unthemed-common-ref.html
== valueAsNumber-prop.html 75pct-common-ref.html
fuzzy-if(B2G,1,1) == stepDown-unthemed.html 75pct-unthemed-common-ref.html
fuzzy-if(B2G,1,1) == stepDown.html 75pct-common-ref.html
fuzzy-if(B2G,2,1) == stepDown-unthemed.html 75pct-unthemed-common-ref.html
fuzzy-if(B2G,2,1) == stepDown.html 75pct-common-ref.html
== stepUp-unthemed.html 75pct-unthemed-common-ref.html
== stepUp.html 75pct-common-ref.html
fuzzy-if(B2G,1,1) == max-prop.html 100pct-common-ref.html
fuzzy-if(B2G,2,1) == max-prop.html 100pct-common-ref.html
== reset-value.html reset-value-ref.html
# 'direction' property: