|         |      1 /* | 
|         |      2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). | 
|         |      3 * All rights reserved. | 
|         |      4 * This component and the accompanying materials are made available | 
|         |      5 * under the terms of "Eclipse Public License v1.0" | 
|         |      6 * which accompanies this distribution, and is available | 
|         |      7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". | 
|         |      8 * | 
|         |      9 * Initial Contributors: | 
|         |     10 * Nokia Corporation - initial contribution. | 
|         |     11 * | 
|         |     12 * Contributors: | 
|         |     13 * | 
|         |     14 * Description:   Implements class | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18  | 
|         |     19  | 
|         |     20 // INCLUDE FILES | 
|         |     21  | 
|         |     22 #include "coutboxsendoperation.h"   // header | 
|         |     23  | 
|         |     24 #include <SendUiConsts.h>           // MTM Uids | 
|         |     25 #include <msvids.h>                  // Entry Ids | 
|         |     26 #include <gsmerror.h>                // SMS sending failure error codes | 
|         |     27 #include <smutset.h> | 
|         |     28 #include "debugtraces.h" | 
|         |     29  | 
|         |     30 // ================= MEMBER FUNCTIONS ======================= | 
|         |     31  | 
|         |     32 // Two-phased constructor. | 
|         |     33 COutboxSendOperation* COutboxSendOperation::NewL( | 
|         |     34     CMsvSession& aMsvSession, | 
|         |     35     TRequestStatus& aObserverRequestStatus ) | 
|         |     36     { | 
|         |     37     // Create the instance of sending operation | 
|         |     38     COutboxSendOperation* self = | 
|         |     39         new (ELeave) COutboxSendOperation( | 
|         |     40             aMsvSession, aObserverRequestStatus ); | 
|         |     41  | 
|         |     42     // Push self into cleanup stack during construction | 
|         |     43     CleanupStack::PushL(self); | 
|         |     44     self->ConstructL(); | 
|         |     45     CleanupStack::Pop(); | 
|         |     46  | 
|         |     47     // Return the object | 
|         |     48     return self; | 
|         |     49     } | 
|         |     50  | 
|         |     51 // C++ default constructor can NOT contain any code that | 
|         |     52 // might leave. | 
|         |     53 // | 
|         |     54 COutboxSendOperation::COutboxSendOperation( | 
|         |     55     CMsvSession& aMsvSession, | 
|         |     56     TRequestStatus& aObserverRequestStatus ) | 
|         |     57     : | 
|         |     58     CMsvOperation( aMsvSession, CActive::EPriorityStandard, aObserverRequestStatus ), | 
|         |     59     iSelections( 4 ), | 
|         |     60     iServices(), | 
|         |     61     iSupportedMsgs( COutboxSendOperation::ESupportsSmsSending ) | 
|         |     62     { | 
|         |     63     // Start scheduler | 
|         |     64     CActiveScheduler::Add(this); | 
|         |     65     } | 
|         |     66  | 
|         |     67 //destructor | 
|         |     68 COutboxSendOperation::~COutboxSendOperation() | 
|         |     69     { | 
|         |     70     // Cancel sending | 
|         |     71     Cancel(); | 
|         |     72  | 
|         |     73     // Delete sending operation | 
|         |     74     delete iOperation; | 
|         |     75     iOperation = NULL; | 
|         |     76  | 
|         |     77     // Delete entry | 
|         |     78     delete iEntry; | 
|         |     79     iEntry = NULL; | 
|         |     80  | 
|         |     81     // Remove services from queue and destroy message selections | 
|         |     82     iServices.Reset(); | 
|         |     83     iSelections.ResetAndDestroy(); | 
|         |     84     } | 
|         |     85  | 
|         |     86 // ---------------------------------------------------- | 
|         |     87 // COutboxSendOperation::ConstructL | 
|         |     88 // ---------------------------------------------------- | 
|         |     89 // | 
|         |     90 void COutboxSendOperation::ConstructL() | 
|         |     91     { | 
|         |     92     // Get rootindex entry | 
|         |     93     iEntry = iMsvSession.GetEntryL( KMsvRootIndexEntryId ); | 
|         |     94     iEntry->SetSortTypeL( | 
|         |     95         TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByNone, ETrue ) ); | 
|         |     96  | 
|         |     97     // Set sending flags | 
|         |     98     iSupportedMsgs |= ESendSms; | 
|         |     99  | 
|         |    100     // Start sending | 
|         |    101     StartSendingL(); | 
|         |    102     } | 
|         |    103  | 
|         |    104 // ---------------------------------------------------- | 
|         |    105 // COutboxSendOperation::RunL | 
|         |    106 // ---------------------------------------------------- | 
|         |    107 // | 
|         |    108 void COutboxSendOperation::RunL() | 
|         |    109     { | 
|         |    110     QDEBUG_WRITE("COutboxSendOperation::RunL"); | 
|         |    111     User::LeaveIfError( iStatus.Int() ); | 
|         |    112  | 
|         |    113     // Check and start sending, if needed | 
|         |    114     TUid sendMtm; | 
|         |    115  | 
|         |    116     // Check if messages needs to be sent | 
|         |    117     if( IsSendingNeeded( sendMtm ) ) | 
|         |    118         { | 
|         |    119         StartSendingL(); | 
|         |    120         } | 
|         |    121     // Nothing to send, complete operation | 
|         |    122     else | 
|         |    123         { | 
|         |    124         CompleteObserver( iStatus.Int() ); | 
|         |    125         } | 
|         |    126     } | 
|         |    127  | 
|         |    128 // ---------------------------------------------------- | 
|         |    129 // COutboxSendOperation::RunError | 
|         |    130 // ---------------------------------------------------- | 
|         |    131 // | 
|         |    132 TInt COutboxSendOperation::RunError( TInt aError ) | 
|         |    133     {    | 
|         |    134     CompleteObserver( aError ); | 
|         |    135     return aError; | 
|         |    136     } | 
|         |    137  | 
|         |    138 // ---------------------------------------------------- | 
|         |    139 // COutboxSendOperation::DoCancel | 
|         |    140 // ---------------------------------------------------- | 
|         |    141 // | 
|         |    142 void COutboxSendOperation::DoCancel() | 
|         |    143     { | 
|         |    144     // Check if sending operation is running | 
|         |    145     if( iOperation ) | 
|         |    146         { | 
|         |    147         // Cancel it | 
|         |    148         iOperation->Cancel(); | 
|         |    149         } | 
|         |    150  | 
|         |    151     // Complete operation with current status | 
|         |    152     CompleteObserver( iStatus.Int() ); | 
|         |    153     } | 
|         |    154  | 
|         |    155 // ---------------------------------------------------- | 
|         |    156 // COutboxSendOperation::ProgressL | 
|         |    157 // ---------------------------------------------------- | 
|         |    158 // | 
|         |    159 const TDesC8& COutboxSendOperation::ProgressL() | 
|         |    160     { | 
|         |    161     // Check if operation exists | 
|         |    162     if( iOperation ) | 
|         |    163         { | 
|         |    164         // Return the operation | 
|         |    165         return iOperation->ProgressL(); | 
|         |    166         } | 
|         |    167  | 
|         |    168     // If no operation, return blank information | 
|         |    169     return KNullDesC8(); | 
|         |    170     } | 
|         |    171  | 
|         |    172 // --------------------------------------------------------- | 
|         |    173 // COutboxSendOperation::CompleteOperation | 
|         |    174 // --------------------------------------------------------- | 
|         |    175 // | 
|         |    176 void COutboxSendOperation::CompleteObserver( TInt aStatus ) | 
|         |    177     { | 
|         |    178     // Get the observer status | 
|         |    179     TRequestStatus* status = &iObserverRequestStatus; | 
|         |    180     User::RequestComplete( status, aStatus ); | 
|         |    181     } | 
|         |    182  | 
|         |    183 // ---------------------------------------------------- | 
|         |    184 // COutboxSendOperation::StartSendingL | 
|         |    185 // ---------------------------------------------------- | 
|         |    186 // | 
|         |    187 void COutboxSendOperation::StartSendingL() | 
|         |    188     { | 
|         |    189     // Remove any sending operation that currently may be running | 
|         |    190     delete iOperation; | 
|         |    191     iOperation = NULL; | 
|         |    192  | 
|         |    193  | 
|         |    194     // Check if there was errors with creating selection | 
|         |    195     if  ( CheckAndCreateSelectionL() ) | 
|         |    196         { | 
|         |    197         // Create new operation and trap any errors | 
|         |    198         SendWaitingSMSMessages(); | 
|         |    199         RemoveSelection(); | 
|         |    200         } | 
|         |    201     else | 
|         |    202         { | 
|         |    203         CompleteSelf( KErrNone ); | 
|         |    204         } | 
|         |    205     } | 
|         |    206  | 
|         |    207     // if error, then complete this pass with the error code | 
|         |    208 void COutboxSendOperation::SendWaitingSMSMessages() | 
|         |    209     { | 
|         |    210     TRAPD( err, SendWaitingSMSMessagesL() ); | 
|         |    211     if  ( err != KErrNone ) | 
|         |    212         { | 
|         |    213         ASSERT( !IsActive() ); | 
|         |    214         CompleteSelf( err ); | 
|         |    215         } | 
|         |    216     } | 
|         |    217  | 
|         |    218 // ---------------------------------------------------- | 
|         |    219 // COutboxSendOperation::SendWaitingSMSMessagesL | 
|         |    220 // ---------------------------------------------------- | 
|         |    221 // | 
|         |    222 void COutboxSendOperation::SendWaitingSMSMessagesL() | 
|         |    223     { | 
|         |    224     // Get first selection from queue | 
|         |    225     CMsvEntrySelection& selection = ( *iSelections[0] ); | 
|         |    226  | 
|         |    227     // Get count of messages in queue | 
|         |    228     TInt count = selection.Count(); | 
|         |    229  | 
|         |    230     // Go through all messages | 
|         |    231     while( count-- ) | 
|         |    232         { | 
|         |    233         // Select message | 
|         |    234         iEntry->SetEntryL( selection[count] ); | 
|         |    235         TMsvEntry entry( iEntry->Entry() ); | 
|         |    236  | 
|         |    237         // Check if the message is tried to send when in offline | 
|         |    238         if( ( entry.SendingState() == KMsvSendStateSuspended || | 
|         |    239               entry.SendingState() == KMsvSendStateFailed) && | 
|         |    240             ( entry.iError == KErrGsmOfflineOpNotAllowed || | 
|         |    241               entry.iError == KErrGsmOfflineSimOpNotAllowed) ) | 
|         |    242             { | 
|         |    243             // Set message to wait sending | 
|         |    244             entry.SetSendingState( KMsvSendStateWaiting ); | 
|         |    245             iEntry->ChangeL( entry ); | 
|         |    246             } | 
|         |    247 		else | 
|         |    248 			{ | 
|         |    249 			selection.Delete( count ); | 
|         |    250 			} | 
|         |    251         } | 
|         |    252     selection.Compress(); | 
|         |    253  | 
|         |    254     // Set entry to outbox | 
|         |    255     iMtm = iEntry->Entry().iMtm; | 
|         |    256     iEntry->SetEntryL( KMsvGlobalOutBoxIndexEntryId ); | 
|         |    257 	if ( selection.Count() ) | 
|         |    258 		{ | 
|         |    259 		iOperation = iEntry->CopyL( selection, iServices[0], iStatus ); | 
|         |    260         SetActive(); | 
|         |    261 		} | 
|         |    262     else | 
|         |    263         { | 
|         |    264         // Nothing to send, but we must complete the observer via our RunL callback | 
|         |    265         CompleteSelf( KErrNone ); | 
|         |    266         } | 
|         |    267     } | 
|         |    268  | 
|         |    269  | 
|         |    270 // ---------------------------------------------------- | 
|         |    271 // COutboxSendOperation::RemoveSelection | 
|         |    272 // ---------------------------------------------------- | 
|         |    273 // | 
|         |    274 void COutboxSendOperation::RemoveSelection() | 
|         |    275     { | 
|         |    276     // Clear the the current selection. | 
|         |    277     iServices.Delete(0); | 
|         |    278  | 
|         |    279     // Delete selection object and index | 
|         |    280     delete iSelections[0]; | 
|         |    281     iSelections.Delete(0); | 
|         |    282     } | 
|         |    283  | 
|         |    284 // ---------------------------------------------------- | 
|         |    285 // COutboxSendOperation::CreateSelectionL | 
|         |    286 // ---------------------------------------------------- | 
|         |    287 // | 
|         |    288 void COutboxSendOperation::CreateSelectionL( | 
|         |    289     const TUid &aUidForSel, | 
|         |    290     const TMsvId& aServiceId, | 
|         |    291     CMsvEntrySelection*& aSelection ) | 
|         |    292     { | 
|         |    293     // Set entry to outbox and get messages from outbox | 
|         |    294     iEntry->SetEntryL( KMsvGlobalOutBoxIndexEntryId ); | 
|         |    295     aSelection = iEntry->ChildrenWithMtmL( *&aUidForSel ); | 
|         |    296  | 
|         |    297     // Check if there is anything to put into array | 
|         |    298     if( aSelection->Count() ) | 
|         |    299         { | 
|         |    300         // Put selection to queue | 
|         |    301         CleanupStack::PushL( aSelection ); | 
|         |    302         iSelections.AppendL( aSelection ); | 
|         |    303         CleanupStack::Pop( aSelection ); | 
|         |    304  | 
|         |    305         // Put service to queue | 
|         |    306         iServices.AppendL( aServiceId ); | 
|         |    307         } | 
|         |    308     else | 
|         |    309         { | 
|         |    310         // Remove selection | 
|         |    311         delete aSelection; | 
|         |    312         aSelection = NULL; | 
|         |    313         } | 
|         |    314     } | 
|         |    315  | 
|         |    316 // ---------------------------------------------------- | 
|         |    317 // COutboxSendOperation::CheckAndCreateSelectionL | 
|         |    318 // ---------------------------------------------------- | 
|         |    319 // | 
|         |    320 TBool COutboxSendOperation::CheckAndCreateSelectionL() | 
|         |    321     { | 
|         |    322     // Get root index | 
|         |    323     iEntry->SetEntryL( KMsvRootIndexEntryId ); | 
|         |    324  | 
|         |    325     // MTM, for which the selection is collected | 
|         |    326     TUid sendMtm; | 
|         |    327  | 
|         |    328     // Selection of messages for sending | 
|         |    329     CMsvEntrySelection* smsSelection = NULL; | 
|         |    330  | 
|         |    331     // While MTM's available for sending | 
|         |    332     while( smsSelection == NULL && IsSendingNeeded( sendMtm ) ) | 
|         |    333         { | 
|         |    334         // Find default SMS service | 
|         |    335         TMsvId serviceId =0; | 
|         |    336         TSmsUtilities::ServiceIdL(*iEntry, serviceId); | 
|         |    337         QDEBUG_WRITE_FORMAT("COutboxSendOperation::CheckAndCreateSelectionL ",serviceId ); | 
|         |    338         // Check if the service ID is found | 
|         |    339         if( serviceId != KMsvNullIndexEntryId ) | 
|         |    340             { | 
|         |    341             // Create selection of messages of specified MTM | 
|         |    342             CreateSelectionL( sendMtm, serviceId, smsSelection ); | 
|         |    343             } | 
|         |    344         // Selection has been created, remove the flag | 
|         |    345         RemoveSendingFlag( *&sendMtm ); | 
|         |    346         } | 
|         |    347  | 
|         |    348     const TBool selectionAvailable = ( smsSelection != NULL ); | 
|         |    349     return selectionAvailable; | 
|         |    350     } | 
|         |    351  | 
|         |    352 // ---------------------------------------------------- | 
|         |    353 // COutboxSendOperation::RemoveSendingFlag | 
|         |    354 // ---------------------------------------------------- | 
|         |    355 // | 
|         |    356 void COutboxSendOperation::RemoveSendingFlag( const TUid& aMtm ) | 
|         |    357     { | 
|         |    358     // Decide actions by mtm | 
|         |    359     switch( aMtm.iUid ) | 
|         |    360         { | 
|         |    361         // SMS-messages | 
|         |    362         case KSenduiMtmSmsUidValue: | 
|         |    363             iSupportedMsgs &= ~ESendSms; | 
|         |    364             break;         | 
|         |    365         default: | 
|         |    366             break; | 
|         |    367         } | 
|         |    368     } | 
|         |    369  | 
|         |    370 // ---------------------------------------------------- | 
|         |    371 // COutboxSendOperation::IsSendingNeeded | 
|         |    372 // ---------------------------------------------------- | 
|         |    373 // | 
|         |    374 TBool COutboxSendOperation::IsSendingNeeded( | 
|         |    375     TUid& aMtm ) const | 
|         |    376     { | 
|         |    377     // Set starting condition | 
|         |    378     TBool needSending = EFalse; | 
|         |    379  | 
|         |    380     // Check if sms-sending is supported and messages need to be sent | 
|         |    381     if( iSupportedMsgs & ESupportsSmsSending && | 
|         |    382         iSupportedMsgs & ESendSms ) | 
|         |    383         { | 
|         |    384         aMtm = KSenduiMtmSmsUid; | 
|         |    385         needSending = ETrue; | 
|         |    386         } | 
|         |    387     // Otherwise nothing needs to be done | 
|         |    388     else | 
|         |    389         { | 
|         |    390         aMtm.iUid = 0; | 
|         |    391         needSending = EFalse; | 
|         |    392         } | 
|         |    393  | 
|         |    394     // Return the result | 
|         |    395     return needSending; | 
|         |    396     } | 
|         |    397  | 
|         |    398 // ---------------------------------------------------- | 
|         |    399 // COutboxSendOperation::CompleteSelf | 
|         |    400 // ---------------------------------------------------- | 
|         |    401 // | 
|         |    402 void COutboxSendOperation::CompleteSelf( TInt aValue ) | 
|         |    403     { | 
|         |    404     TRequestStatus* status = &iStatus; | 
|         |    405     User::RequestComplete( status, aValue ); | 
|         |    406     SetActive(); | 
|         |    407     } | 
|         |    408      | 
|         |    409 // End of file |