Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "TelephonyCallGroup.h"
8 #include "mozilla/dom/TelephonyCallGroupBinding.h"
10 #include "CallEvent.h"
11 #include "CallsList.h"
12 #include "mozilla/dom/CallGroupErrorEvent.h"
13 #include "Telephony.h"
15 using namespace mozilla::dom;
16 using mozilla::ErrorResult;
18 TelephonyCallGroup::TelephonyCallGroup(nsPIDOMWindow* aOwner)
19 : DOMEventTargetHelper(aOwner)
20 , mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN)
21 {
22 }
24 TelephonyCallGroup::~TelephonyCallGroup()
25 {
26 }
28 // static
29 already_AddRefed<TelephonyCallGroup>
30 TelephonyCallGroup::Create(Telephony* aTelephony)
31 {
32 NS_ASSERTION(aTelephony, "Null telephony!");
34 nsRefPtr<TelephonyCallGroup> group =
35 new TelephonyCallGroup(aTelephony->GetOwner());
37 group->mTelephony = aTelephony;
38 group->mCallsList = new CallsList(aTelephony, group);
40 return group.forget();
41 }
43 JSObject*
44 TelephonyCallGroup::WrapObject(JSContext* aCx)
45 {
46 return TelephonyCallGroupBinding::Wrap(aCx, this);
47 }
49 void
50 TelephonyCallGroup::AddCall(TelephonyCall* aCall)
51 {
52 NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!");
53 mCalls.AppendElement(aCall);
54 aCall->ChangeGroup(this);
55 NotifyCallsChanged(aCall);
56 }
58 void
59 TelephonyCallGroup::RemoveCall(TelephonyCall* aCall)
60 {
61 NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!");
62 mCalls.RemoveElement(aCall);
63 aCall->ChangeGroup(nullptr);
64 NotifyCallsChanged(aCall);
65 }
67 nsresult
68 TelephonyCallGroup::NotifyError(const nsAString& aName, const nsAString& aMessage)
69 {
70 CallGroupErrorEventInit init;
71 init.mBubbles = false;
72 init.mCancelable = false;
73 init.mName = aName;
74 init.mMessage = aMessage;
76 nsRefPtr<CallGroupErrorEvent> event =
77 CallGroupErrorEvent::Constructor(this, NS_LITERAL_STRING("error"), init);
79 return DispatchTrustedEvent(event);
80 }
82 void
83 TelephonyCallGroup::ChangeState(uint16_t aCallState)
84 {
85 if (mCallState == aCallState) {
86 return;
87 }
89 nsString stateString;
90 switch (aCallState) {
91 case nsITelephonyProvider::CALL_STATE_UNKNOWN:
92 break;
93 case nsITelephonyProvider::CALL_STATE_CONNECTED:
94 stateString.AssignLiteral("connected");
95 break;
96 case nsITelephonyProvider::CALL_STATE_HOLDING:
97 stateString.AssignLiteral("holding");
98 break;
99 case nsITelephonyProvider::CALL_STATE_HELD:
100 stateString.AssignLiteral("held");
101 break;
102 case nsITelephonyProvider::CALL_STATE_RESUMING:
103 stateString.AssignLiteral("resuming");
104 break;
105 default:
106 NS_NOTREACHED("Unknown state!");
107 }
109 mState = stateString;
110 mCallState = aCallState;
112 nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
113 if (NS_FAILED(rv)) {
114 NS_WARNING("Failed to dispatch specific event!");
115 }
116 if (!stateString.IsEmpty()) {
117 // This can change if the statechange handler called back here... Need to
118 // figure out something smarter.
119 if (mCallState == aCallState) {
120 rv = DispatchCallEvent(stateString, nullptr);
121 if (NS_FAILED(rv)) {
122 NS_WARNING("Failed to dispatch specific event!");
123 }
124 }
125 }
127 for (uint32_t index = 0; index < mCalls.Length(); index++) {
128 nsRefPtr<TelephonyCall> call = mCalls[index];
129 call->ChangeState(aCallState);
131 MOZ_ASSERT(call->CallState() == aCallState);
132 }
133 }
135 nsresult
136 TelephonyCallGroup::NotifyCallsChanged(TelephonyCall* aCall)
137 {
138 return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall);
139 }
141 nsresult
142 TelephonyCallGroup::DispatchCallEvent(const nsAString& aType,
143 TelephonyCall* aCall)
144 {
145 nsRefPtr<CallEvent> event = CallEvent::Create(this, aType, aCall, false, false);
146 return DispatchTrustedEvent(event);
147 }
149 bool
150 TelephonyCallGroup::CanConference(const TelephonyCall& aCall,
151 TelephonyCall* aSecondCall)
152 {
153 if (!aCall.Mergeable()) {
154 return false;
155 }
157 if (!aSecondCall) {
158 MOZ_ASSERT(!mCalls.IsEmpty());
160 return (mCallState == nsITelephonyProvider::CALL_STATE_CONNECTED &&
161 aCall.CallState() == nsITelephonyProvider::CALL_STATE_HELD) ||
162 (mCallState == nsITelephonyProvider::CALL_STATE_HELD &&
163 aCall.CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED);
164 }
166 MOZ_ASSERT(mCallState == nsITelephonyProvider::CALL_STATE_UNKNOWN);
168 if (aCall.ServiceId() != aSecondCall->ServiceId()) {
169 return false;
170 }
172 if (!aSecondCall->Mergeable()) {
173 return false;
174 }
176 return (aCall.CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED &&
177 aSecondCall->CallState() == nsITelephonyProvider::CALL_STATE_HELD) ||
178 (aCall.CallState() == nsITelephonyProvider::CALL_STATE_HELD &&
179 aSecondCall->CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED);
180 }
182 already_AddRefed<TelephonyCall>
183 TelephonyCallGroup::GetCall(uint32_t aServiceId, uint32_t aCallIndex)
184 {
185 nsRefPtr<TelephonyCall> call;
187 for (uint32_t index = 0; index < mCalls.Length(); index++) {
188 nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
189 if (tempCall->ServiceId() == aServiceId &&
190 tempCall->CallIndex() == aCallIndex) {
191 call = tempCall;
192 break;
193 }
194 }
196 return call.forget();
197 }
199 NS_IMPL_CYCLE_COLLECTION_CLASS(TelephonyCallGroup)
201 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCallGroup,
202 DOMEventTargetHelper)
203 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCalls)
204 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallsList)
205 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
206 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
208 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCallGroup,
209 DOMEventTargetHelper)
210 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCalls)
211 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallsList)
212 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTelephony)
213 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
215 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCallGroup)
216 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
218 NS_IMPL_ADDREF_INHERITED(TelephonyCallGroup, DOMEventTargetHelper)
219 NS_IMPL_RELEASE_INHERITED(TelephonyCallGroup, DOMEventTargetHelper)
221 // WebIDL
222 already_AddRefed<CallsList>
223 TelephonyCallGroup::Calls() const
224 {
225 nsRefPtr<CallsList> list = mCallsList;
226 return list.forget();
227 }
229 void
230 TelephonyCallGroup::Add(TelephonyCall& aCall,
231 ErrorResult& aRv)
232 {
233 if (!CanConference(aCall, nullptr)) {
234 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
235 return;
236 }
238 aRv = mTelephony->Provider()->ConferenceCall(aCall.ServiceId());
239 }
241 void
242 TelephonyCallGroup::Add(TelephonyCall& aCall,
243 TelephonyCall& aSecondCall,
244 ErrorResult& aRv)
245 {
246 if (!CanConference(aCall, &aSecondCall)) {
247 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
248 return;
249 }
251 aRv = mTelephony->Provider()->ConferenceCall(aCall.ServiceId());
252 }
254 void
255 TelephonyCallGroup::Remove(TelephonyCall& aCall, ErrorResult& aRv)
256 {
257 if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
258 NS_WARNING("Remove call from a non-connected call group. Ignore!");
259 return;
260 }
262 uint32_t serviceId = aCall.ServiceId();
263 uint32_t callIndex = aCall.CallIndex();
265 nsRefPtr<TelephonyCall> call;
267 call = GetCall(serviceId, callIndex);
268 if (call) {
269 aRv = mTelephony->Provider()->SeparateCall(serviceId, callIndex);
270 } else {
271 NS_WARNING("Didn't have this call. Ignore!");
272 }
273 }
275 void
276 TelephonyCallGroup::Hold(ErrorResult& aRv)
277 {
278 if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
279 NS_WARNING("Hold non-connected call ignored!");
280 return;
281 }
283 MOZ_ASSERT(!mCalls.IsEmpty());
285 nsresult rv = mTelephony->Provider()->HoldConference(mCalls[0]->ServiceId());
286 if (NS_FAILED(rv)) {
287 aRv.Throw(rv);
288 return;
289 }
291 ChangeState(nsITelephonyProvider::CALL_STATE_HOLDING);
292 }
294 void
295 TelephonyCallGroup::Resume(ErrorResult& aRv)
296 {
297 if (mCallState != nsITelephonyProvider::CALL_STATE_HELD) {
298 NS_WARNING("Resume non-held call ignored!");
299 return;
300 }
302 MOZ_ASSERT(!mCalls.IsEmpty());
304 nsresult rv = mTelephony->Provider()->ResumeConference(mCalls[0]->ServiceId());
305 if (NS_FAILED(rv)) {
306 aRv.Throw(rv);
307 return;
308 }
310 ChangeState(nsITelephonyProvider::CALL_STATE_RESUMING);
311 }