diff -r 000000000000 -r 89d6a7a84779 Symbian3/SDK/Source/GUID-A8130D83-E684-5B6C-BDFE-EB6EE3CD49E8.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/SDK/Source/GUID-A8130D83-E684-5B6C-BDFE-EB6EE3CD49E8.dita Thu Jan 21 18:18:20 2010 +0000 @@ -0,0 +1,509 @@ + + + + + +Writing +a UPS Dialog Creator +
Introduction

Dialog creators are EComplug-ins that +device creators can write to generate the dialogs containing prompts for phone +users.

The plug-in has an API that consists of two asynchronous functions:

    +
  • The PrepareDialog() function. +This function is called first by the UPS server. It enables the dialog creator +to query other system servers such as AppArc or the SIS registry to retrieve +additional information to display in the dialog. For example it might query +the SIS registry using the client application’s secure id.

  • +
  • The DisplayDialog() function. +This function is called second by the UPS server. It displays the prompt, +most commonly through the notification framework. This function also returns +the option selected by the user and, if applicable, the fingerprint for a +new decision record.

  • +

The UPS displays only one prompt at a time so it is possible for +there to be a delay between calling the function to prepare the dialog and +the function to display the dialog. It is also possible for other dialogs +to be displayed between the dialog being prepared and its being displayed.

Both PrepareDialog() and DisplayDialog() are asynchronous and must support cancellation through CActive::Cancel. +If either function is cancelled, the dialog creator instance is destroyed +without calling further methods.

The work split between PrepareDialog() and DisplayDialog() described +above is a recommendation, and some of the functionality could be implemented +directly in the notifier implementation.

In the example given in this +document, the functionality for dialogs is implemented separately from the +functionality for policy evaluators. This allows multiple policy evaluators +to share common UI code. However, it is possible to deliver policy evaluator +and dialog creator plug-ins in the same DLL.

+
Procedure

Dialog creators implement the CDialogCreator interface. +This section shows how to implement the functions that prepare and display +the user prompt.

    +
  1. Prepare a dialog using +the PrepareDialog() function.

  2. +
  3. Display the dialog using +the DisplayDialog() function.

  4. +

The Dialog Creator plug-in creates a dialog prompt in cases where +no previous decision is found in the decision database.

Preparing +the dialog

The parameters to PrepareDialog() are +mostly const pointers and references to the data that has +already been generated by the UPS or policy evaluator.

The following +table describes the parameters for the PrepareDialog() function:

+ + + +Parameter +Description + + + + +

aRequest

+

Data that the system server provides to the UPS, including the ClientSid, +ServerSid and ServiceId.

+
+ +

aPolicy

+

Details of the policy for the service.

+
+ +

aFingerprints

+

A pointer to the fingerprints array generated by the policy evaluator. +(If the user selects "Always" or “Never”, the dialog creator returns a pointer +to an existing fingerprint object instead of re-generating the fingerprint.)

+
+ +

aClientEntity

+

Details of client entity (will be null if the client process is +not an execution host or the policy evaluator does not support client entities).

+
+ +

aEvalPrivateData

+

Opaque data, which can be any other information for use in the fingerprint +or to be displayed in the dialog.

+
+ +

aStatus

+

The request status used to contain completion information for the +function.

+
+ + +

The UPS does not allow any responses to be returned +to the system server except those defined in the UPS policy file. If the dialog +creator returns an option that was not specified in the policy, the request +is rejected and EUpsDecNo is returned.

Your implementation +can assume that the pointers remain valid until after DisplayDialog() has +been called.

The PrepareDialog() function sets values.

The DoPrepareDialogL() function +prepares the data for the prompt. The DoPrepareDialogL() function is called +through a switch statement, which can be seen in the full code sample at the +end of this.

Displaying the dialog

The DisplayDialog() function +displays the dialog created by PrepareDialog(). On completion, +it sets the option selected by the user and the fingerprint value if “Always” +or “Never” was selected. Usually, dialogs are displayed using the notifier +framework, but device creators are free to use other mechanisms.

On +completion iOptionSelected must be set to the option selected +by the user: Yes, No, Session, Always or Never.

    +
  • If the user selects +“Always” or “Never”, iFingerprint must be set to point to +the fingerprint to use for the new decision record. Usually, this would just +point to one of the fingerprints passed to PrepareDialog(), +but generating a new fingerprint is also permitted.

  • +
  • If the decision record +already exists and DisplayDialog() modifies the value of aEvaluatorInfo, +the record is updated with the new value.

  • +

In the example at the end of this section, the DisplayDialog() function +sets values. The DoDisplayDialogL() function calls the notifier +framework to display the dialogs. The DoDisplayDialogL() function +is called through a switch statement, which can be seen in +the full code sample at the end of this section:

+
Example

The following code shows an example of +a full implementation of the dialog creator file:

// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. + +// refdialogcreator.cpp + + +#include "refdialogcreator.h" +#include <ecom/implementationproxy.h> +#include <apaid.h> +#include <apgcli.h> +#include <ups/promptrequest.h> +#include <swi/sisregistrypackage.h> +#include <swi/sisregistrysession.h> +#include <scs/nullstream.h> +#include <s32mem.h> + +static const TUint KRefDialogCreatorImplementationId = 0x10283694; + +static const TUint KRefNotifierImplementationId = 0x1028369B; + +CDialogCreator* CRefDialogCreator::CreateDialogCreatorL() +/** +Factory method that instantiates a new dialog creator EComplug-in. + +@return A pointer to the new reference dialog creator object. +*/ + { + CRefDialogCreator* self = new (ELeave)CRefDialogCreator(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +static const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY(KRefDialogCreatorImplementationId, CRefDialogCreator::CreateDialogCreatorL) + }; + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +/** +Standard EComfactory +*/ + { + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; + } + + +CRefDialogCreator::CRefDialogCreator() +/** +Constructor +*/ + : CDialogCreator(), iPromptResult(), iPromptResultPckg(iPromptResult), iState(EIdle) + { + CActiveScheduler::Add(this); + } + +CRefDialogCreator::~CRefDialogCreator() +/** +Destructor +*/ + { + Deque(); + delete iPromptData; + iPromptDataDes.Close(); + iNotifier.Close(); + } + +void CRefDialogCreator::ConstructL() +/** +Second phase constructor +*/ + { + User::LeaveIfError(iNotifier.Connect()); + } + +void CRefDialogCreator::DoCancel() + { + if (iState == EProcessResult) + { + iNotifier.CancelNotifier(TUid::Uid(KRefNotifierImplementationId)); + } + if (iClientStatus) + { + User::RequestComplete(iClientStatus, KErrCancel); + } + } + +TInt CRefDialogCreator::RunError(TInt aError) + { + if (iClientStatus) + { + User::RequestComplete(iClientStatus, aError); + } + return KErrNone; + } + +void CRefDialogCreator::RunL() + { + User::LeaveIfError(iStatus.Int()); + switch (iState) + { + case EPrepareDialog: + DoPrepareDialogL(); + break; + case EDisplayDialog: + DoDisplayDialogL(); + break; + case EProcessResult: + DoProcessResultL(); + break; + default: + ASSERT(EFalse); + } + } + +void CRefDialogCreator::DoPrepareDialogL() + { + iPromptData = CPromptData::NewL(); + + // Only one state at the moment but more should be + // added for long running operators e.g. querying the SIS registry + // or resolving the client entity. + ResolveClientNameL(iRequest->ClientSid()); + + // Get the vendor name for the client process + ResolveVendorNameL(iRequest->ClientVid()); + + // Server / Service localized names generated in notifier plug-in. + iPromptData->iServerSid = iRequest->ServerSid(); + iPromptData->iServiceId = iRequest->ServiceId(); + + // Different dialog text is displayed depending on whether the client application + // is signed. + // N.B. Protected SID is assumed to be signed or included at ROM build. + if (iRequest->IsClientSidProtected()) iPromptData->iFlags |= ETrustedClient; + + // Use the options specified by the policy + iPromptData->iOptions = iPolicy->Options(); + + // Add the descriptions of the fingerprints. This could be used + // to allow the user to grant access to all destinations + // or a single destination. + TInt count = iFingerprints->Count(); + for (TInt i = 0; i < count; ++i) + { + HBufC* description = (*iFingerprints)[i]->Description().AllocLC(); + iPromptData->iDescriptions.AppendL(description); + CleanupStack::Pop(description); + } + + User::RequestComplete(iClientStatus, KErrNone); + // DisplayDialog is invoked by the UPS, this just verifies + // that PrepareDialog was called first. + iState = EDisplayDialog; + } + +void CRefDialogCreator::DoDisplayDialogL() +/** +Uses the notifier framework to display the dialog. +*/ + { + // Externalize the prompt data to a descriptor + RNullWriteStream ns; + ns << *iPromptData; + ns.CommitL(); + iPromptDataDes.CreateL(ns.BytesWritten()); + RDesWriteStream ws; + ws.Open(iPromptDataDes); + ws << *iPromptData; + ws.CommitL(); + iNotifier.StartNotifierAndGetResponse(iStatus, TUid::Uid(KRefNotifierImplementationId), + iPromptDataDes, iPromptResultPckg); + SetActive(); + iState = EProcessResult; + } + +void CRefDialogCreator::DoProcessResultL() +/** +Processes the result returned by the notifier. +*/ + { + if (iPromptResult.iSelected == CPolicy::EAlways || + iPromptResult.iSelected == CPolicy::ENever) + { + // The Always or Never option was selected so return the fingerprint + // for the new decision record. + // + // In this implementation a copy of the original fingerprint is returned. However, + // it is permitted to return a different fingerprint e.g. a modifier description. + if (iPromptResult.iDestination >= 0 && iPromptResult.iDestination < iFingerprints->Count()) + { + *iFingerprint = (*iFingerprints)[iPromptResult.iDestination]; + } + else + { + ASSERT(EFalse); // should never happen, unless the notifier has errors. + } + } + *iOptionSelected = iPromptResult.iSelected; + iState = EIdle; + User::RequestComplete(iClientStatus, KErrNone); + } + +void CRefDialogCreator::ResolveVendorNameL(const TVendorId& aVid) +/** +Looks up the localized vendor name for the client process and writes +this to iPromptData->iVendorName. + +Typically, this would be resolved from the SIS registry or a lookup table. + +@param aVid The vendor id of the client process. +*/ + { + if (iPromptData->iVendorName.Length() != 0) + { + // already obtained vendor name from SIS registry + return; + } + + if (aVid.iId == 0x70000001) + { + _LIT(KSymbian, "Symbian Foundation"); + iPromptData->iVendorName.Create(KSymbian); + } + else + { + _LIT(KUnknown, "Unknown vendor"); + iPromptData->iVendorName.Create(KUnknown); + } + } + +void CRefDialogCreator::ResolveClientNameL(const TSecureId& aSid) +/** +Generates a human readable name for the client process. In order of +preference the following data is returned + +- The AppArc caption name. +- The localized package name that owns this SID. +- A value from a lookup table. +- The filename for the client process executable. + +@param aSid The secure id of the client process. +*/ + { + TBool found = EFalse; + + // Although the client name from AppArc takes precedance the SIS + // registry is always invoked in order to retrieve the vendor name + found |= ResolveClientNameFromSisRegistryL(aSid); + found |= ResolveClientNameFromAppArcL(aSid); + + // A lookup that maps secure-ids to application names could + // be used here. + + // Fall back to the filename of the client process + // The original thread may have exited so the process handle is used instead. + // because the client-side object e.g. RSocket may be shared between threads. + + // If the process has exited then it's o.k. to leave. + if (! found) + { + RProcess clientProcess; + User::LeaveIfError(clientProcess.Open(iRequest->ClientProcessId())); + CleanupClosePushL(clientProcess); + iPromptData->iClientName.Create(clientProcess.FileName()); + CleanupStack::PopAndDestroy(&clientProcess); + } + } + +TBool CRefDialogCreator::ResolveClientNameFromAppArcL(const TSecureId& aSid) +/** +Gets the caption name for the application from AppArc (if available). + +@param aSid The secure id of the client process. +@return ETrue if a match was found in apparc; otherwise, EFalse is returned. +*/ + { + TBool found(EFalse); + + RApaLsSession apa; + CleanupClosePushL(apa); + TInt err = apa.Connect(); + if (err == KErrNone) + { + TApaAppInfo* info = new(ELeave) TApaAppInfo(); + CleanupStack::PushL(info); + + err = apa.GetAppInfo(*info, TUid::Uid(aSid)); + if (err == KErrNone) + { + iPromptData->iClientName.Close(); + iPromptData->iClientName.Create(info->iCaption); + found = ETrue; + } + else if (err != KErrNotFound) + { + User::Leave(err); + } + CleanupStack::PopAndDestroy(info); + } + else if (err != KErrNotFound) + { + // If the connection to apparc failed with KErrNotFound + // then the error is ignored becase we assume the dialog + // creator was invoked from text-shell + User::Leave(err); + } + CleanupStack::PopAndDestroy(&apa); + return found; + } + +TBool CRefDialogCreator::ResolveClientNameFromSisRegistryL(const TSecureId& aSid) +/** +Retrieves the client and vendor information from the SIS registry. +@param aSid The secure-id of the client application to lookup in the registry. +@return ETrue, if the lookup was successful; otherwise, EFalse is returned. +*/ + { + TBool found(EFalse); + Swi::RSisRegistrySession r; + User::LeaveIfError(r.Connect()); + CleanupClosePushL(r); + + Swi::CSisRegistryPackage* p(0); + TRAPD(err, p = r.SidToPackageL(TUid::Uid(aSid.iId))); + if (err == KErrNone) + { + iPromptData->iClientName.Create(p->Name()); + iPromptData->iVendorName.Create(p->Vendor()); + found = ETrue; + delete p; + } + CleanupStack::PopAndDestroy(&r); + return found; + } + +// From CDialogCreator +void CRefDialogCreator::PrepareDialog( + const UserPromptService::CPromptRequest& aRequest, const CPolicy& aPolicy, + const RPointerArray<CFingerprint>& aFingerprints, const CClientEntity* aClientEntity, + const TAny* aEvalPrivateData, TRequestStatus& aStatus) + { + aStatus = KRequestPending; + iClientStatus = &aStatus; + + iRequest = &aRequest; + iPolicy = &aPolicy; + iFingerprints = &aFingerprints; + iEvalPrivateData = aEvalPrivateData; + (void) aClientEntity; + + // Kick off dialog creator state machine + iState = EPrepareDialog; + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete(status, KErrNone); + } + +void CRefDialogCreator::DisplayDialog(CPolicy::TOptions& aOptions, const CFingerprint*& aFingerprint, + TUint& aEvaluatorInfo, TRequestStatus& aStatus) + { + aStatus = KRequestPending; + iClientStatus = &aStatus; + + iOptionSelected = &aOptions; + iFingerprint = &aFingerprint; + aFingerprint = 0; + iEvaluatorInfo = &aEvaluatorInfo; + iClientStatus = &aStatus; + + // Start state machine + ASSERT(iState == EDisplayDialog); // PrepareDialog should have been called first + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete(status, KErrNone); + } +
+
\ No newline at end of file