src/hbcore/devicedialogbase/hbdevicedialogsymbian.cpp
changeset 0 16d8024aca5e
child 2 06ff229162e9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include <QVariant>
       
    27 
       
    28 #include "hbdevicedialogserverdefs_p.h"
       
    29 #include "hbdevicedialogerrors_p.h"
       
    30 #include "hbdevicedialogclientsession_p.h"
       
    31 #include <e32cmn.h>
       
    32 
       
    33 #include "hbdevicedialogsymbian.h"
       
    34 #include "hbsymbianvariant.h"
       
    35 #include "hbsymbianvariantconverter_p.h"
       
    36 #include "hbdeleteguardsymbian_p.h"
       
    37 
       
    38 /*!
       
    39  \class CHbDeviceDialogSymbian
       
    40  \brief CHbDeviceDialog displays dialogs on top of applications. It is a client interface for Symbian applications to Hb
       
    41     device dialogs.
       
    42  \sa HbDeviceDialog
       
    43 
       
    44  Data given to this API in symbian format is packed to QVariantMap. See
       
    45  CHbSymbianVariant to see which Qt datatypes are supported.
       
    46  \sa CHbSymbianVariant
       
    47  \sa CHbSymbianVariantMap
       
    48 
       
    49  When plugin returns data in Qt format, the data is converted, if possible,
       
    50  to CHbSymbianVariantMap.
       
    51 
       
    52  \proto
       
    53 
       
    54  \hbcore
       
    55  */
       
    56 
       
    57 /*!
       
    58     \enum CHbDeviceDialogSymbian::TDeviceDialogError
       
    59     Defines device dialog error codes and ranges.
       
    60 */
       
    61 /*!
       
    62     \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EFrameworkErrors
       
    63     Start of an error range for errors originating from device dialog framework (client or server).
       
    64 */
       
    65 /*!
       
    66     \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EPluginErrors
       
    67     Start of an error range for errors originating from device dialog plugins. The framework passes
       
    68     these from the plugin unmodified.
       
    69 */
       
    70 /*!
       
    71     \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EErrorTypeMask
       
    72     Mask for error type part of the error code.
       
    73 */
       
    74 /*!
       
    75     \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::ECancelledError
       
    76     Operation was cancelled by Cancel().
       
    77 */
       
    78 /*!
       
    79     \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::ESystemCancelledError
       
    80     Operation was cancelled by device dialog framework.
       
    81 */
       
    82 
       
    83 /*!
       
    84    \fn void MHbDeviceDialogObserver::DataReceived(CHbSymbianVariantMap& aData)
       
    85 
       
    86     This callback is called when data is received from a device dialog.
       
    87     \a aData contains data from the dialog plugin.
       
    88     The structure and meaning of the data is a contract between the dialog and
       
    89     a client. Structure should be aligned with the data types supported by
       
    90 	CHbSymbianVariantMap.
       
    91 
       
    92     \sa CHbSymbianVariantMap.
       
    93 */
       
    94 
       
    95 /*!
       
    96     \fn void MHbDeviceDialogObserver::DeviceDialogClosed(TInt aCompletionCode)
       
    97 
       
    98     This callback is called when a device dialog is closed. Any data sent by
       
    99     the dialog is indicated by the dataReceived() callback. If no observer is
       
   100     set in CHbDeviceDialogSymbian::Show the latest data can be retrieved with
       
   101     CHbDeviceDialogSymbian::receivedData()
       
   102 
       
   103     \a aCompletionCode gives the result of the dialog completion. Code can be
       
   104     either Symbian error code or device dialog error code.
       
   105 
       
   106     \sa DataReceived() ReceivedData()
       
   107 */
       
   108 
       
   109 // Device dialogs are implemented only for Symbian/S60 OS.
       
   110 
       
   111 class CHbDeviceDialogSymbianPrivate : public CActive
       
   112 {
       
   113 public:
       
   114         CHbDeviceDialogSymbianPrivate();
       
   115         ~CHbDeviceDialogSymbianPrivate();
       
   116         TInt Show( const QByteArray& aArray );
       
   117         TInt Update( const QByteArray& aArray );
       
   118         void CancelDialog();
       
   119         TInt Error() const;
       
   120         void SetObserver( MHbDeviceDialogObserver* aObserver );
       
   121 
       
   122         // CActive
       
   123         void RunL();
       
   124         void DoCancel();
       
   125         TInt RunError( TInt aError );
       
   126 
       
   127         void Start();
       
   128         TInt SymToDeviceDialogError( TInt errorCode );
       
   129         void SetError(TInt aError);
       
   130         bool CallDialogClosedObserver(TInt aCompletionCode);
       
   131         bool CallDataReceivedObserver(CHbSymbianVariantMap& aData);
       
   132 
       
   133 public:
       
   134     TInt iFlags;
       
   135     RHbDeviceDialogClientSession iHbSession;
       
   136     TInt iLastError;
       
   137     TPckgBuf<THbDeviceDialogSrvUpdateInfo> iUpdateInfo;
       
   138     TPckgBuf<int> iDeviceDialogId;
       
   139     HBufC8* iBuffer;
       
   140     TPtr8 iDataPtr;
       
   141     TBool iRequesting;
       
   142     QVariantMap iDataReceived;
       
   143     CActiveSchedulerWait* iWait;
       
   144     MHbDeviceDialogObserver* iObserver;
       
   145     bool *iDeleted;
       
   146 };
       
   147 
       
   148 CHbDeviceDialogSymbianPrivate::CHbDeviceDialogSymbianPrivate():
       
   149 CActive( EPriorityStandard ),
       
   150 iFlags(0),
       
   151 iLastError(0),
       
   152 iDeviceDialogId(0),
       
   153 iBuffer(NULL),
       
   154 iDataPtr(NULL, 0, 0),
       
   155 iRequesting(EFalse),
       
   156 iObserver(NULL)
       
   157 {
       
   158     if (!iBuffer) {
       
   159         iBuffer = HBufC8::NewL(64);
       
   160         if (iBuffer) {
       
   161             iDataPtr.Set(iBuffer->Des());
       
   162         }
       
   163     }
       
   164 }
       
   165 
       
   166 CHbDeviceDialogSymbianPrivate::~CHbDeviceDialogSymbianPrivate()
       
   167 {
       
   168     // Inform the server to finish the dialog session and not to cancel it
       
   169     if(!iObserver) {
       
   170         iHbSession.SendSyncRequest(EHbSrvClientClosing);
       
   171     }
       
   172 
       
   173     Cancel();
       
   174     iHbSession.Close();
       
   175 
       
   176     delete iBuffer;
       
   177     iBuffer = NULL;
       
   178 
       
   179     iObserver= NULL;
       
   180     // Set object deleted flag
       
   181     if (iDeleted) {
       
   182         // Mark the object as deleted.
       
   183         *iDeleted = true;
       
   184         iDeleted = 0;
       
   185     }
       
   186 }
       
   187 
       
   188 TInt CHbDeviceDialogSymbianPrivate::Show(const QByteArray& aArray )
       
   189 {
       
   190     TInt error = iLastError = KErrNone;
       
   191 
       
   192     TPtrC8 ptr( reinterpret_cast<const TUint8*>(aArray.data()), aArray.size() );
       
   193     // Synchronous call to server to show dialog.
       
   194     error = iHbSession.SendSyncRequest( EHbSrvShowDeviceDialog, ptr, &iDeviceDialogId );
       
   195     //error = SymToDeviceDialogError(error);
       
   196 
       
   197     if (error == KErrNone) {
       
   198         // Start listening for server updates. Device dialog update and closing is
       
   199         // received via this channel. Error status received in RunL method.
       
   200         Start();
       
   201     }
       
   202     // Error, just return the error code
       
   203     else {
       
   204         SetError(error);
       
   205     }
       
   206     return error;
       
   207 }
       
   208 
       
   209 /*!
       
   210     \internal
       
   211 
       
   212     Send device dialog update.
       
   213 */
       
   214 TInt CHbDeviceDialogSymbianPrivate::Update( const QByteArray& aArray )
       
   215 {
       
   216     TInt error = iLastError = KErrNone;
       
   217     if (iRequesting) {
       
   218 
       
   219         TPtrC8 ptr( reinterpret_cast<const TUint8*>(aArray.data()), aArray.size() );
       
   220 
       
   221         error = iHbSession.SendSyncRequest( EHbSrvUpdateDeviceDialog, ptr );
       
   222         //error = SymToDeviceDialogError(error);
       
   223         if (error != KErrNone) {
       
   224             SetError(error);
       
   225         }
       
   226     }
       
   227     else {
       
   228         SetError(KErrBadHandle);
       
   229         error = KErrBadHandle;
       
   230     }
       
   231     return error;
       
   232 }
       
   233 
       
   234 /*!
       
   235     \internal
       
   236 
       
   237     Cancel a scheduled popup on HbDeviceDialogManager. Event buffer is cleared
       
   238     at server.
       
   239 */
       
   240 void CHbDeviceDialogSymbianPrivate::CancelDialog()
       
   241 {
       
   242     iLastError = KErrNone;
       
   243     int error = KErrNotFound;
       
   244 
       
   245     if (iRequesting) {
       
   246         // Ignore other than server errors.
       
   247         error = iHbSession.SendSyncRequest(EHbSrvCancelDeviceDialog, iDeviceDialogId());
       
   248         // error = SymToDeviceDialogError(error);
       
   249     }
       
   250     if (error != KErrNone) {
       
   251         SetError(error);
       
   252     }
       
   253 }
       
   254 
       
   255 /*!
       
   256     \internal
       
   257 
       
   258     Return last error.
       
   259 */
       
   260 TInt CHbDeviceDialogSymbianPrivate::Error() const
       
   261 {
       
   262     return iLastError;
       
   263 }
       
   264 
       
   265 void CHbDeviceDialogSymbianPrivate::SetObserver( MHbDeviceDialogObserver* aObserver )
       
   266 {
       
   267     iObserver = aObserver;
       
   268 }
       
   269 /*!
       
   270     \internal
       
   271     RunL from CActive.
       
   272 */
       
   273 void CHbDeviceDialogSymbianPrivate::RunL()
       
   274 {
       
   275     TInt completionCode = iStatus.Int();
       
   276     //int errorCode = SymToDeviceDialogError(completionCode);
       
   277 
       
   278     if (completionCode < KErrNone) {
       
   279         // Any Symbian error, stop requesting, sycnhoronous requests are stopped
       
   280         // in the end of the RunL
       
   281         iRequesting = EFalse;
       
   282         SetError(completionCode);
       
   283         if (CallDialogClosedObserver(completionCode)) {
       
   284             return; // observed deleted this object, do not touch it
       
   285         }
       
   286     }
       
   287     else {
       
   288         // Check that event is for latest device dialog. iDeviceDialogId was updated by server
       
   289         // during show()
       
   290         THbDeviceDialogSrvUpdateInfo &updateInfo = iUpdateInfo();
       
   291         if (updateInfo.iDeviceDialogId == iDeviceDialogId()) {
       
   292             switch(updateInfo.iUpdateType) {
       
   293             case EHbDeviceDialogUpdateData: {
       
   294                 if (completionCode == KErrNone &&
       
   295                     updateInfo.iInfo.iDataInfo.iDataSize > 0) {
       
   296                     // Resize buffer and get new data synchronously
       
   297                     delete iBuffer;
       
   298                     iBuffer = NULL;
       
   299                     iBuffer = HBufC8::NewL(updateInfo.iInfo.iDataInfo.iDataSize);
       
   300                     iDataPtr.Set(iBuffer->Des());
       
   301                     completionCode = iHbSession.SendSyncRequest(EHbSrvUpdateData, iDataPtr);
       
   302                     //errorCode = SymToDeviceDialogError(completionCode);
       
   303 
       
   304                     // data request failed
       
   305                     if (completionCode < KErrNone) {
       
   306                         iRequesting = EFalse;
       
   307                         SetError(completionCode);
       
   308                         if (CallDialogClosedObserver(completionCode)) {
       
   309                             return; // observed deleted this object, do not touch it
       
   310                         }
       
   311                     }
       
   312                 }
       
   313                 if (completionCode == KErrNone) {
       
   314                     // Signal data if there are connections. Otherwise keep a copy.
       
   315                     QByteArray resArray((const char*)iDataPtr.Ptr(), iDataPtr.Size());
       
   316                     QDataStream stream(&resArray, QIODevice::ReadOnly);
       
   317 
       
   318                     iDataReceived.clear();
       
   319 
       
   320                     QVariant var;
       
   321                     stream >> var;
       
   322                     QVariantMap varMap = var.toMap();
       
   323 
       
   324                     if (iObserver) {
       
   325                         CHbSymbianVariantMap* symbianMap =
       
   326                             HbSymbianVariantConverter::fromQVariantMapL(varMap);
       
   327                         bool thisIsDeleted = CallDataReceivedObserver(*symbianMap);
       
   328                         delete symbianMap;
       
   329                         symbianMap = 0;
       
   330                         if (thisIsDeleted) { // observer deleted this, do not touch anymore
       
   331                             return;
       
   332                         }
       
   333                     }
       
   334                     else {
       
   335                         iDataReceived = varMap;
       
   336                     }
       
   337                 }
       
   338                 break;
       
   339             }
       
   340             case EHbDeviceDialogUpdateClosed:
       
   341                 // Signal possible cancelled error
       
   342                 if (completionCode != KErrNone) {
       
   343                     SetError(completionCode);
       
   344                 }
       
   345                 iRequesting = EFalse;
       
   346                 if (CallDialogClosedObserver(completionCode)) {
       
   347                     return; // observed deleted this object, do not touch it
       
   348                 }
       
   349                 break;
       
   350             default:
       
   351                 break;
       
   352             }
       
   353         }
       
   354     }
       
   355     // Make a new request if there was no errors and device dialog wasn't closed
       
   356     if (iRequesting) {
       
   357         Start();
       
   358     }
       
   359 }
       
   360 
       
   361 /*!
       
   362     \internal
       
   363     DoCancel from CActive.
       
   364 */
       
   365 void CHbDeviceDialogSymbianPrivate::DoCancel()
       
   366 {
       
   367     SetError(KErrCancel);
       
   368     iRequesting = EFalse;
       
   369     iHbSession.SendSyncRequest(EHbSrvCancelUpdateChannel);
       
   370 }
       
   371 
       
   372 /*!
       
   373     \internal
       
   374     RunError from CActive.
       
   375 */
       
   376 TInt CHbDeviceDialogSymbianPrivate::RunError( TInt /*aError*/ )
       
   377 {
       
   378     SetError( KErrGeneral );
       
   379     return KErrNone;
       
   380 }
       
   381 
       
   382 /*!
       
   383     \internal
       
   384     Starts asynchronous message to receive update and close events from session.
       
   385 */
       
   386 void CHbDeviceDialogSymbianPrivate::Start()
       
   387 {
       
   388     iDataPtr.Zero();
       
   389 
       
   390     if ( !IsActive() ) {
       
   391         iHbSession.SendASyncRequest( EHbSrvOpenUpdateChannel, iDataPtr, iUpdateInfo, iStatus );
       
   392         SetActive();
       
   393         iRequesting = ETrue;
       
   394     }
       
   395 }
       
   396 
       
   397 // Convert symbian error code into HbDeviceDialog error code
       
   398 int CHbDeviceDialogSymbianPrivate::SymToDeviceDialogError( TInt errorCode )
       
   399 {
       
   400     if (errorCode != HbDeviceDialogNoError) {
       
   401         // Any Symbian error, close session handle. It will be reopened on next show()
       
   402         if (errorCode < KErrNone) {
       
   403             iHbSession.Close();
       
   404         }
       
   405         // All Symbian errors are connected to HbDeviceDialogConnectError
       
   406         if (errorCode < KErrNone) {
       
   407             errorCode = HbDeviceDialogConnectError;
       
   408         }
       
   409     }
       
   410     return errorCode;
       
   411 }
       
   412 
       
   413 void CHbDeviceDialogSymbianPrivate::SetError( TInt aError )
       
   414 {
       
   415     iLastError = aError;
       
   416 }
       
   417 
       
   418 // Call device dialog closed observer. Return true if observer deleted this object.
       
   419 bool CHbDeviceDialogSymbianPrivate::CallDialogClosedObserver(TInt aCompletionCode)
       
   420 {
       
   421     if (iObserver) {
       
   422         RHbDeleteGuardSymbian guard;
       
   423         guard.OpenAndPushL(&iDeleted);
       
   424         iObserver->DeviceDialogClosed(aCompletionCode);
       
   425         return guard.PopAndClose();
       
   426     } else {
       
   427         return false;
       
   428     }
       
   429 }
       
   430 
       
   431 // Call device dialog data received observer. Return true if observer deleted this object.
       
   432 bool CHbDeviceDialogSymbianPrivate::CallDataReceivedObserver(CHbSymbianVariantMap& aData)
       
   433 {
       
   434     if (iObserver) {
       
   435         RHbDeleteGuardSymbian guard;
       
   436         guard.OpenAndPushL(&iDeleted);
       
   437         iObserver->DataReceived(aData);
       
   438         return guard.PopAndClose();
       
   439     } else {
       
   440         return false;
       
   441     }
       
   442 }
       
   443 
       
   444 /*!
       
   445     Constructs CHbDeviceDialogSymbian object. \a f contains construct flags. Device
       
   446     dialog service will clean all dialogs launched when the instance is deleted.
       
   447 */
       
   448 
       
   449 EXPORT_C CHbDeviceDialogSymbian* CHbDeviceDialogSymbian::NewL( TInt aFlags )
       
   450 {
       
   451      CHbDeviceDialogSymbian* deviceDialog = new (ELeave) CHbDeviceDialogSymbian(aFlags);
       
   452      int error = KErrNone;
       
   453      if(deviceDialog->d) {
       
   454          error = deviceDialog->d->iHbSession.Connect();
       
   455      }
       
   456      if(error != KErrNone) {
       
   457          CleanupStack::PushL(deviceDialog);
       
   458          User::Leave(error);
       
   459          delete deviceDialog;
       
   460          deviceDialog = 0;
       
   461      }
       
   462      return deviceDialog;
       
   463 }
       
   464 
       
   465 EXPORT_C CHbDeviceDialogSymbian::~CHbDeviceDialogSymbian()
       
   466 {
       
   467     delete d;
       
   468 }
       
   469 
       
   470 /*!
       
   471   Show of device dialog. Each time a Show() is called a new dialog is launched.
       
   472   aParameter data is sent to device dialog in Qt's QVariantMap object.
       
   473   The function is asynchronous and returns immediately. Closing and data events from the
       
   474   dialog can be received by observer interface. Deleting CHbDeviceDialogSymbian object
       
   475   closes and deletes the device dialog at server if observer is set. If observer is null
       
   476   the dialog is left executing at the server and it's assumed it closes itself by a timeout.
       
   477   Cancel() to closes the device dialog.
       
   478 
       
   479   \a aDeviceDialogType is name of the device dialog. Identifies the device
       
   480   dialog plugin. \a aParameters is a buffer containing data for the device dialog.
       
   481 
       
   482   \a aObserver is used to observe the session.
       
   483 
       
   484   Return value informs if the call was successful.
       
   485 
       
   486   \sa Update() Cancel()
       
   487  */
       
   488 EXPORT_C TInt CHbDeviceDialogSymbian::Show(const TDesC& aDeviceDialogType, const CHbSymbianVariantMap& aParameters, MHbDeviceDialogObserver* aObserver)
       
   489 {
       
   490     d->SetObserver(aObserver);
       
   491 
       
   492     QString deviceDialogType = QString::fromUtf16(aDeviceDialogType.Ptr(), aDeviceDialogType.Length());
       
   493 
       
   494     QVariantMap parameters;
       
   495     HbSymbianVariantConverter::toQtVariantMap(aParameters, parameters);
       
   496 
       
   497     QByteArray array;
       
   498     QDataStream stream( &array, QIODevice::WriteOnly );
       
   499 
       
   500     QVariant var( parameters );
       
   501     stream << deviceDialogType;
       
   502     stream << var;
       
   503 
       
   504     return d->Show(array);
       
   505 }
       
   506 
       
   507 /*!
       
   508     Updates device dialog parameters by a set of new values. Show() must be called before an
       
   509     Update() can be called. Returns true on success and false
       
   510     if error occurred.
       
   511 
       
   512     \sa Show()
       
   513 */
       
   514 EXPORT_C TInt CHbDeviceDialogSymbian::Update(const CHbSymbianVariantMap& aParameters)
       
   515 {
       
   516     if(!d) {
       
   517         return KErrNotReady;
       
   518     }
       
   519     QVariantMap parameters;
       
   520 
       
   521     HbSymbianVariantConverter::toQtVariantMap(aParameters, parameters);
       
   522 
       
   523     QByteArray array;
       
   524     QDataStream stream( &array, QIODevice::WriteOnly );
       
   525 
       
   526     QVariant var( parameters );
       
   527     stream << var;
       
   528 
       
   529     return d->Update(array);
       
   530 }
       
   531 
       
   532 /*!
       
   533     Get the data received from device dialog if using synchronous Show
       
   534     in s60 data types. Caller gets the ownership.
       
   535 */
       
   536 EXPORT_C CHbSymbianVariantMap* CHbDeviceDialogSymbian::ReceivedDataL() const
       
   537 {
       
   538     CHbSymbianVariantMap* map = HbSymbianVariantConverter::fromQVariantMapL(d->iDataReceived);
       
   539     return map;
       
   540 }
       
   541 
       
   542 /*!
       
   543     Cancel device dialog session. Visible dialog is removed from the screen.
       
   544     Waiting dialogs are canceled and no effect if dialog already dismissed
       
   545 */
       
   546 EXPORT_C void CHbDeviceDialogSymbian::Cancel()
       
   547 {
       
   548     d->CancelDialog();
       
   549 }
       
   550 
       
   551 /*!
       
   552     Set observer for device dialog events. \aObserver is pointer to the
       
   553     observer. Null disables observing.
       
   554 */
       
   555 EXPORT_C void CHbDeviceDialogSymbian::SetObserver(MHbDeviceDialogObserver* aObserver)
       
   556 {
       
   557     d->SetObserver(aObserver);
       
   558 }
       
   559 
       
   560 CHbDeviceDialogSymbian::CHbDeviceDialogSymbian(TInt aFlags) : d(NULL)
       
   561 {
       
   562   d = new CHbDeviceDialogSymbianPrivate;
       
   563   d->iFlags = aFlags;
       
   564   CActiveScheduler::Add(d);
       
   565 
       
   566   // Is needed to implement?
       
   567   //if (mDeviceDialogFlags & HbDeviceDialog::ImmediateResourceReservationFlag)
       
   568 }