|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // csendassender.cpp |
|
15 // |
|
16 |
|
17 #include "csendassender.h" |
|
18 |
|
19 #include <msvids.h> |
|
20 #include <mtclbase.h> |
|
21 #include <tmsvpackednotifierrequest.h> |
|
22 #include <s32mem.h> |
|
23 |
|
24 #include "msendassenderobserver.h" |
|
25 #include "tsendasserverpanic.h" |
|
26 |
|
27 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
28 #include "msvconsts.h" |
|
29 #endif |
|
30 |
|
31 // Buffer for IPC messages to notifier |
|
32 const TInt KNotifierBufferLength = 60; |
|
33 const TInt KNotifierBufferIncrement = 20; |
|
34 |
|
35 CSendAsSender* CSendAsSender::NewL(MSendAsSenderObserver& aObserver) |
|
36 { |
|
37 CSendAsSender* self = new (ELeave) CSendAsSender(aObserver); |
|
38 CleanupStack::PushL(self); |
|
39 self->ConstructL(); |
|
40 CleanupStack::Pop(self); |
|
41 return self; |
|
42 } |
|
43 |
|
44 CSendAsSender::~CSendAsSender() |
|
45 { |
|
46 // do not notify observer during deletion. |
|
47 iObserver = NULL; |
|
48 Cancel(); |
|
49 |
|
50 iNotifier.Close(); |
|
51 delete iClientMtm; |
|
52 delete iOperation; |
|
53 delete iBuffer; |
|
54 delete iSelection; |
|
55 // Close UPS session |
|
56 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
57 iUpsSubsession.Close(); |
|
58 iUpsSession.Close(); |
|
59 #endif |
|
60 } |
|
61 |
|
62 CSendAsSender::CSendAsSender(MSendAsSenderObserver& aObserver) |
|
63 : CActive(CActive::EPriorityStandard), iObserver(&aObserver) |
|
64 { |
|
65 CActiveScheduler::Add(this); |
|
66 } |
|
67 |
|
68 void CSendAsSender::ConstructL() |
|
69 { |
|
70 iBuffer = HBufC8::NewL(KNotifierBufferLength); |
|
71 User::LeaveIfError(iNotifier.Connect()); |
|
72 iSelection = new (ELeave) CMsvEntrySelection(); |
|
73 } |
|
74 |
|
75 /** |
|
76 Sets the client MTM to use for move and send operations. |
|
77 |
|
78 @param aClientMtm |
|
79 The client MTM. |
|
80 */ |
|
81 void CSendAsSender::SetClientMtm(CBaseMtm& aClientMtm) |
|
82 { |
|
83 __ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() ); |
|
84 __ASSERT_ALWAYS( iClientMtm == NULL, User::Invariant() ); |
|
85 __ASSERT_ALWAYS( iSelection != NULL, User::Invariant() ); |
|
86 |
|
87 iClientMtm = &aClientMtm; |
|
88 } |
|
89 |
|
90 /** |
|
91 Populates the entry selection from the client MTM's entry. |
|
92 */ |
|
93 void CSendAsSender::SetEntrySelectionL() |
|
94 { |
|
95 iSelection->Reset(); |
|
96 iSelection->AppendL(iClientMtm->Entry().EntryId()); |
|
97 } |
|
98 |
|
99 /** |
|
100 Initiates an confirmed / unconfirmed message send operation. |
|
101 */ |
|
102 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
103 void CSendAsSender::SendMessageL(const RMessage2 aMessage, TBool aHasCapability) |
|
104 { |
|
105 __ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() ); |
|
106 __ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() ); |
|
107 |
|
108 iState = ESenderAuthoriseSend; |
|
109 // Serialise the recipient list |
|
110 const CMsvRecipientList& rcptList = iClientMtm->AddresseeList(); |
|
111 const MDesC16Array& recipient = rcptList.RecipientList(); |
|
112 |
|
113 TInt rcptCount = recipient.MdcaCount(); |
|
114 TInt size = 0; |
|
115 for(TInt i=0;i<rcptCount; ++i) |
|
116 { |
|
117 size += recipient.MdcaPoint(i).Length(); |
|
118 } |
|
119 |
|
120 _LIT16(KComma, ","); |
|
121 |
|
122 RBuf16 buffer; |
|
123 buffer.Create(size+ rcptCount); |
|
124 CleanupClosePushL(buffer); |
|
125 if(rcptCount > 0) |
|
126 { |
|
127 buffer.Append(recipient.MdcaPoint(0)); |
|
128 } |
|
129 |
|
130 for(TInt i=1;i<rcptCount; ++i) |
|
131 { |
|
132 buffer.Append(KComma); |
|
133 buffer.Append(recipient.MdcaPoint(i)); |
|
134 } |
|
135 |
|
136 RThread clientThread; |
|
137 aMessage.Client(clientThread); |
|
138 |
|
139 // Connect to UPS service..... |
|
140 User::LeaveIfError(iUpsSession.Connect()); |
|
141 |
|
142 User::LeaveIfError(iUpsSubsession.Initialise(iUpsSession, clientThread)); |
|
143 |
|
144 iDecision = EUpsDecNo; |
|
145 iUpsSubsession.Authorise(aHasCapability, KUidSendAs2Service, buffer, iDecision, iStatus); |
|
146 SetActive(); |
|
147 CleanupStack::PopAndDestroy(&buffer); |
|
148 } |
|
149 #endif |
|
150 |
|
151 /** |
|
152 Initiates an unconfirmed message send operation. |
|
153 */ |
|
154 void CSendAsSender::SendMessage() |
|
155 { |
|
156 __ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() ); |
|
157 __ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() ); |
|
158 |
|
159 // update state and auto-complete - send process started by RunL() |
|
160 iState = ESenderStartingUnconfirmedSend; |
|
161 TRequestStatus* status=&iStatus; |
|
162 User::RequestComplete(status, KErrNone); |
|
163 SetActive(); |
|
164 } |
|
165 |
|
166 /** |
|
167 Initiates a confirmed message send operation. |
|
168 |
|
169 @param aSecurityInfo |
|
170 The security info associated with the message. |
|
171 |
|
172 @param aNotifierUid |
|
173 The UID of the notifier plugin. |
|
174 */ |
|
175 void CSendAsSender::SendMessage(const TSecurityInfo& aSecurityInfo, const TUid& aNotifierUid) |
|
176 { |
|
177 __ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() ); |
|
178 __ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() ); |
|
179 |
|
180 // confirmed send - use notifier to prompt the user for confirmation. |
|
181 iSecurityInfo = aSecurityInfo; |
|
182 iNotifierUid = aNotifierUid; |
|
183 |
|
184 // update state and auto-complete |
|
185 iState = ESenderStartingConfirmedSend; |
|
186 TRequestStatus* status=&iStatus; |
|
187 User::RequestComplete(status, KErrNone); |
|
188 SetActive(); |
|
189 } |
|
190 |
|
191 /** |
|
192 Provides progress information for the send operation. |
|
193 |
|
194 @param aProgress |
|
195 The operation progerss object. |
|
196 */ |
|
197 void CSendAsSender::ProgressL(TMsvSendOperationProgress& aProgress) |
|
198 { |
|
199 switch( iState ) |
|
200 { |
|
201 case ESenderStartingUnconfirmedSend: |
|
202 case ESenderStartingConfirmedSend: |
|
203 case ESenderIdle: |
|
204 case ESenderConfirming: |
|
205 case ESenderMoving: |
|
206 case ESenderAuthoriseSend: |
|
207 { |
|
208 aProgress().iState = CMsvSendOperation::ESendStateWaitingToSend; |
|
209 } break; |
|
210 case ESenderSending: |
|
211 { |
|
212 // when sending, operation returns a CMsvSendOperation which returns the |
|
213 // correct progress. |
|
214 const TDesC8& opProgress = iOperation->ProgressL(); |
|
215 __ASSERT_ALWAYS(opProgress.Size() == sizeof(CMsvSendOperation::TSendOperationProgress), |
|
216 TSendAsServerPanic::Panic(TSendAsServerPanic::ESendAsBadDescriptor)); |
|
217 TMsvSendOperationProgress& progress = (TMsvSendOperationProgress&) opProgress; |
|
218 aProgress = progress; |
|
219 } break; |
|
220 case ESenderDone: |
|
221 { |
|
222 FinalProgress(aProgress); |
|
223 } break; |
|
224 default: |
|
225 User::Invariant(); |
|
226 break; |
|
227 } |
|
228 } |
|
229 |
|
230 void CSendAsSender::FinalProgress(TMsvSendOperationProgress& aProgress) |
|
231 { |
|
232 __ASSERT_ALWAYS( iState == ESenderDone, User::Invariant() ); |
|
233 |
|
234 aProgress = iFinalProgress; |
|
235 } |
|
236 |
|
237 /** |
|
238 Deletes the current operation |
|
239 */ |
|
240 void CSendAsSender::DeleteOperation() |
|
241 { |
|
242 delete iOperation; |
|
243 iOperation = NULL; |
|
244 } |
|
245 |
|
246 /** |
|
247 Invokes an asynchronous move operation. |
|
248 Moves the message from current location (drafts folder) to the outbox. |
|
249 */ |
|
250 void CSendAsSender::InvokeMoveOperationL() |
|
251 { |
|
252 iEntry = iClientMtm->Entry().Entry(); |
|
253 iClientMtm->Entry().SetEntryL(iEntry.Parent()); |
|
254 |
|
255 DeleteOperation(); |
|
256 iOperation = iClientMtm->Entry().MoveL(iEntry.Id(), KMsvGlobalOutBoxIndexEntryId, iStatus); |
|
257 SetActive(); |
|
258 |
|
259 iState = ESenderMoving; |
|
260 } |
|
261 |
|
262 /** |
|
263 Invokes an asychronous send operation. |
|
264 */ |
|
265 void CSendAsSender::InvokeSendOperationL() |
|
266 { |
|
267 // Buffer required for call to InvokeAsyncFunction, unused. |
|
268 TBuf8<1> buf; |
|
269 iClientMtm->Entry().SetEntryL(iEntry.Id()); |
|
270 DeleteOperation(); |
|
271 // Note: This operation must be a CMsvSendOperation as TMsvSendOperationProgress is needed |
|
272 iOperation = iClientMtm->InvokeAsyncFunctionL(KMTMStandardFunctionsSendMessage, *iSelection, buf, iStatus); |
|
273 SetActive(); |
|
274 |
|
275 iState = ESenderSending; |
|
276 } |
|
277 |
|
278 /** |
|
279 Invokes an asynchronous notification request. |
|
280 */ |
|
281 void CSendAsSender::InvokeConfirmOperationL() |
|
282 { |
|
283 // Use plugin notifier to get the send confirmation. |
|
284 TMsvPackedNotifierRequest packedInfo(iBuffer); |
|
285 while(packedInfo.Pack(*iSelection, iSecurityInfo) != KErrNone) |
|
286 { |
|
287 // increase the size of the buffer and try again |
|
288 iBuffer->Des().Zero(); // to avoid copying contents |
|
289 iBuffer = iBuffer->ReAllocL(iBuffer->Des().MaxSize() + KNotifierBufferIncrement); |
|
290 } |
|
291 |
|
292 iNotifier.StartNotifierAndGetResponse(iStatus, iNotifierUid, *iBuffer, iNotifierResult); |
|
293 SetActive(); |
|
294 |
|
295 iState = ESenderConfirming; |
|
296 } |
|
297 |
|
298 /** |
|
299 Notifies the observer that the operation has completed. |
|
300 @param aError The error code. |
|
301 */ |
|
302 void CSendAsSender::Complete(TInt aError) |
|
303 { |
|
304 iState = ESenderDone; // This must be set before notifying observer |
|
305 if( iObserver != NULL ) |
|
306 { |
|
307 // notify observer that the send has completed. |
|
308 iObserver->SenderComplete(aError); |
|
309 } |
|
310 } |
|
311 |
|
312 /** |
|
313 Methods from CActive |
|
314 Handles a request completion event. |
|
315 Implements the CSendAsSender state machine. |
|
316 |
|
317 @see CActive::RunL() |
|
318 */ |
|
319 void CSendAsSender::RunL() |
|
320 { |
|
321 User::LeaveIfError(iStatus.Int()); |
|
322 |
|
323 switch( iState ) |
|
324 { |
|
325 case ESenderStartingConfirmedSend: |
|
326 { |
|
327 SetEntrySelectionL(); |
|
328 InvokeConfirmOperationL(); |
|
329 }break; |
|
330 case ESenderStartingUnconfirmedSend: |
|
331 { |
|
332 SetEntrySelectionL(); |
|
333 } // fall through |
|
334 case ESenderConfirming: |
|
335 { |
|
336 InvokeMoveOperationL(); |
|
337 } break; |
|
338 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
339 case ESenderAuthoriseSend: |
|
340 { |
|
341 if(iDecision != EUpsDecYes) |
|
342 { |
|
343 Complete(KErrPermissionDenied); |
|
344 } |
|
345 else |
|
346 { |
|
347 SetEntrySelectionL(); |
|
348 InvokeMoveOperationL(); |
|
349 } |
|
350 |
|
351 }break; |
|
352 #endif |
|
353 case ESenderMoving: |
|
354 { |
|
355 InvokeSendOperationL(); |
|
356 } break; |
|
357 case ESenderSending: |
|
358 { |
|
359 TMsvSendOperationProgress& progress = (TMsvSendOperationProgress&)iOperation->FinalProgress(); |
|
360 iFinalProgress = progress; |
|
361 Complete(KErrNone); |
|
362 } break; |
|
363 case ESenderIdle: |
|
364 case ESenderDone: |
|
365 default: |
|
366 User::Invariant(); |
|
367 } |
|
368 } |
|
369 |
|
370 /** |
|
371 Implements cancellation of an outstanding request. |
|
372 @see CActive::DoCancel() |
|
373 */ |
|
374 void CSendAsSender::DoCancel() |
|
375 { |
|
376 switch( iState ) |
|
377 { |
|
378 case ESenderConfirming: |
|
379 { |
|
380 iNotifier.NotifyCancel(); |
|
381 }break; |
|
382 case ESenderMoving: |
|
383 case ESenderSending: |
|
384 { |
|
385 __ASSERT_ALWAYS( iOperation != NULL, User::Invariant() ); |
|
386 iOperation->Cancel(); |
|
387 } break; |
|
388 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
389 case ESenderAuthoriseSend: |
|
390 { |
|
391 iUpsSubsession.Close(); |
|
392 }break; |
|
393 #endif |
|
394 case ESenderStartingConfirmedSend: |
|
395 case ESenderStartingUnconfirmedSend: |
|
396 case ESenderIdle: |
|
397 case ESenderDone: |
|
398 default: |
|
399 // do nothing... |
|
400 break; |
|
401 } |
|
402 Complete(KErrCancel); |
|
403 } |
|
404 |
|
405 /** |
|
406 Handles leaves from the RunL method. |
|
407 @see CActive::RunL() |
|
408 */ |
|
409 TInt CSendAsSender::RunError(TInt aError) |
|
410 { |
|
411 Complete(aError); |
|
412 return KErrNone; |
|
413 } |