|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-A8130D83-E684-5B6C-BDFE-EB6EE3CD49E8" xml:lang="en"><title>Writing |
|
13 a UPS Dialog Creator</title><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <section><title>Introduction</title> <p>Dialog creators are EComplug-ins that |
|
15 device creators can write to generate the dialogs containing prompts for phone |
|
16 users. </p> <p>The plug-in has an API that consists of two asynchronous functions: </p> <ul> |
|
17 <li id="GUID-96CBCE79-4F5D-5F87-AC6B-C366346447AB"><p>The <codeph>PrepareDialog()</codeph> function. |
|
18 This function is called first by the UPS server. It enables the dialog creator |
|
19 to query other system servers such as AppArc or the SIS registry to retrieve |
|
20 additional information to display in the dialog. For example it might query |
|
21 the SIS registry using the client application’s secure id. </p> </li> |
|
22 <li id="GUID-A439E217-B95B-5B68-8893-BDBD61D694D1"><p>The <codeph>DisplayDialog()</codeph> function. |
|
23 This function is called second by the UPS server. It displays the prompt, |
|
24 most commonly through the notification framework. This function also returns |
|
25 the option selected by the user and, if applicable, the fingerprint for a |
|
26 new decision record. </p> </li> |
|
27 </ul> <p>The UPS displays only one prompt at a time so it is possible for |
|
28 there to be a delay between calling the function to prepare the dialog and |
|
29 the function to display the dialog. It is also possible for other dialogs |
|
30 to be displayed between the dialog being prepared and its being displayed. </p> <p>Both <codeph>PrepareDialog()</codeph> and <codeph>DisplayDialog()</codeph> are asynchronous and must support cancellation through <codeph>CActive::Cancel</codeph>. |
|
31 If either function is cancelled, the dialog creator instance is destroyed |
|
32 without calling further methods. </p> <p>The work split between <codeph>PrepareDialog()</codeph> and <codeph>DisplayDialog()</codeph> described |
|
33 above is a recommendation, and some of the functionality could be implemented |
|
34 directly in the notifier implementation. </p> <p>In the example given in this |
|
35 document, the functionality for dialogs is implemented separately from the |
|
36 functionality for policy evaluators. This allows multiple policy evaluators |
|
37 to share common UI code. However, it is possible to deliver policy evaluator |
|
38 and dialog creator plug-ins in the same DLL. </p> </section> |
|
39 <section><title>Procedure</title> <p>Dialog creators implement the <codeph>CDialogCreator</codeph> interface. |
|
40 This section shows how to implement the functions that prepare and display |
|
41 the user prompt. </p> <ol id="GUID-0F29F8B7-F303-5D42-BB95-A32B1FE13A9A"> |
|
42 <li id="GUID-9FDDAD1F-4B9A-516A-8A00-0C331F38C4CA"><p>Prepare a dialog using |
|
43 the <xref href="GUID-2308E2F4-A878-3B0A-951B-EFC4908AD9BB.dita"><apiname>PrepareDialog()</apiname></xref> function. </p> </li> |
|
44 <li id="GUID-45C16A52-A05E-545A-AB3A-967CCA35BB15"><p>Display the dialog using |
|
45 the <xref href="GUID-E6C3B0F0-43A7-3656-946B-5CFE97DCFC80.dita"><apiname>DisplayDialog()</apiname></xref> function. </p> </li> |
|
46 </ol> <p>The Dialog Creator plug-in creates a dialog prompt in cases where |
|
47 no previous decision is found in the decision database. </p> <p><b> Preparing |
|
48 the dialog</b> </p> <p>The parameters to <codeph>PrepareDialog()</codeph> are |
|
49 mostly <codeph>const</codeph> pointers and references to the data that has |
|
50 already been generated by the UPS or policy evaluator. </p> <p>The following |
|
51 table describes the parameters for the <codeph>PrepareDialog()</codeph> function: </p> <table id="GUID-6D139216-B6A8-55A1-8D9B-C15134198198"> |
|
52 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/> |
|
53 <thead> |
|
54 <row> |
|
55 <entry>Parameter</entry> |
|
56 <entry>Description</entry> |
|
57 </row> |
|
58 </thead> |
|
59 <tbody> |
|
60 <row> |
|
61 <entry><p> <codeph>aRequest</codeph> </p> </entry> |
|
62 <entry><p>Data that the system server provides to the UPS, including the ClientSid, |
|
63 ServerSid and ServiceId. </p> </entry> |
|
64 </row> |
|
65 <row> |
|
66 <entry><p> <codeph>aPolicy</codeph> </p> </entry> |
|
67 <entry><p>Details of the policy for the service. </p> </entry> |
|
68 </row> |
|
69 <row> |
|
70 <entry><p> <codeph>aFingerprints</codeph> </p> </entry> |
|
71 <entry><p>A pointer to the fingerprints array generated by the policy evaluator. |
|
72 (If the user selects "Always" or “Never”, the dialog creator returns a pointer |
|
73 to an existing fingerprint object instead of re-generating the fingerprint.) </p> </entry> |
|
74 </row> |
|
75 <row> |
|
76 <entry><p> <codeph>aClientEntity</codeph> </p> </entry> |
|
77 <entry><p>Details of client entity (will be null if the client process is |
|
78 not an execution host or the policy evaluator does not support client entities). </p> </entry> |
|
79 </row> |
|
80 <row> |
|
81 <entry><p> <codeph>aEvalPrivateData</codeph> </p> </entry> |
|
82 <entry><p>Opaque data, which can be any other information for use in the fingerprint |
|
83 or to be displayed in the dialog. </p> </entry> |
|
84 </row> |
|
85 <row> |
|
86 <entry><p> <codeph>aStatus</codeph> </p> </entry> |
|
87 <entry><p>The request status used to contain completion information for the |
|
88 function. </p> </entry> |
|
89 </row> |
|
90 </tbody> |
|
91 </tgroup> |
|
92 </table> <p><note/> The UPS does not allow any responses to be returned |
|
93 to the system server except those defined in the UPS policy file. If the dialog |
|
94 creator returns an option that was not specified in the policy, the request |
|
95 is rejected and <codeph>EUpsDecNo</codeph> is returned. </p><p>Your implementation |
|
96 can assume that the pointers remain valid until after <codeph>DisplayDialog()</codeph> has |
|
97 been called. </p><p>The <codeph>PrepareDialog()</codeph> function sets values. </p><p>The<codeph> DoPrepareDialogL()</codeph> function |
|
98 prepares the data for the prompt. The DoPrepareDialogL() function is called |
|
99 through a switch statement, which can be seen in the full code sample at the |
|
100 end of this. </p> <p><b>Displaying the dialog </b> </p> <p>The <codeph>DisplayDialog()</codeph> function |
|
101 displays the dialog created by <codeph>PrepareDialog()</codeph>. On completion, |
|
102 it sets the option selected by the user and the fingerprint value if “Always” |
|
103 or “Never” was selected. Usually, dialogs are displayed using the notifier |
|
104 framework, but device creators are free to use other mechanisms. </p> <p>On |
|
105 completion <codeph>iOptionSelected</codeph> must be set to the option selected |
|
106 by the user: Yes, No, Session, Always or Never. </p> <ul> |
|
107 <li id="GUID-C657A459-6ED4-59EF-9A8A-C9FE41AF2DD0"><p>If the user selects |
|
108 “Always” or “Never”, <codeph>iFingerprint</codeph> must be set to point to |
|
109 the fingerprint to use for the new decision record. Usually, this would just |
|
110 point to one of the fingerprints passed to <codeph>PrepareDialog()</codeph>, |
|
111 but generating a new fingerprint is also permitted. </p> </li> |
|
112 <li id="GUID-0E2690AB-B44B-5C8B-9365-E09BC3031398"><p>If the decision record |
|
113 already exists and <codeph>DisplayDialog()</codeph> modifies the value of <codeph>aEvaluatorInfo</codeph>, |
|
114 the record is updated with the new value. </p> </li> |
|
115 </ul> <p>In the example at the end of this section, the <codeph>DisplayDialog()</codeph> function |
|
116 sets values. The <codeph>DoDisplayDialogL()</codeph> function calls the notifier |
|
117 framework to display the dialogs. The <codeph>DoDisplayDialogL()</codeph> function |
|
118 is called through a <codeph>switch</codeph> statement, which can be seen in |
|
119 the full code sample at the end of this section: </p> </section> |
|
120 <section><title>Example</title> <p>The following code shows an example of |
|
121 a full implementation of the dialog creator file: </p> <codeblock id="GUID-314673F2-BBA0-56C0-A76D-07862BB4592F" xml:space="preserve">// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
122 // All rights reserved. |
|
123 // This component and the accompanying materials are made available |
|
124 // under the terms of the License "Symbian Foundation License v1.0" |
|
125 // which accompanies this distribution, and is available |
|
126 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
127 // |
|
128 // Initial Contributors: |
|
129 // Nokia Corporation - initial contribution. |
|
130 |
|
131 // refdialogcreator.cpp |
|
132 |
|
133 |
|
134 #include "refdialogcreator.h" |
|
135 #include <ecom/implementationproxy.h> |
|
136 #include <apaid.h> |
|
137 #include <apgcli.h> |
|
138 #include <ups/promptrequest.h> |
|
139 #include <swi/sisregistrypackage.h> |
|
140 #include <swi/sisregistrysession.h> |
|
141 #include <scs/nullstream.h> |
|
142 #include <s32mem.h> |
|
143 |
|
144 static const TUint KRefDialogCreatorImplementationId = 0x10283694; |
|
145 |
|
146 static const TUint KRefNotifierImplementationId = 0x1028369B; |
|
147 |
|
148 CDialogCreator* CRefDialogCreator::CreateDialogCreatorL() |
|
149 /** |
|
150 Factory method that instantiates a new dialog creator EComplug-in. |
|
151 |
|
152 @return A pointer to the new reference dialog creator object. |
|
153 */ |
|
154 { |
|
155 CRefDialogCreator* self = new (ELeave)CRefDialogCreator(); |
|
156 CleanupStack::PushL(self); |
|
157 self->ConstructL(); |
|
158 CleanupStack::Pop(self); |
|
159 return self; |
|
160 } |
|
161 |
|
162 static const TImplementationProxy ImplementationTable[] = |
|
163 { |
|
164 IMPLEMENTATION_PROXY_ENTRY(KRefDialogCreatorImplementationId, CRefDialogCreator::CreateDialogCreatorL) |
|
165 }; |
|
166 |
|
167 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) |
|
168 /** |
|
169 Standard EComfactory |
|
170 */ |
|
171 { |
|
172 aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); |
|
173 return ImplementationTable; |
|
174 } |
|
175 |
|
176 |
|
177 CRefDialogCreator::CRefDialogCreator() |
|
178 /** |
|
179 Constructor |
|
180 */ |
|
181 : CDialogCreator(), iPromptResult(), iPromptResultPckg(iPromptResult), iState(EIdle) |
|
182 { |
|
183 CActiveScheduler::Add(this); |
|
184 } |
|
185 |
|
186 CRefDialogCreator::~CRefDialogCreator() |
|
187 /** |
|
188 Destructor |
|
189 */ |
|
190 { |
|
191 Deque(); |
|
192 delete iPromptData; |
|
193 iPromptDataDes.Close(); |
|
194 iNotifier.Close(); |
|
195 } |
|
196 |
|
197 void CRefDialogCreator::ConstructL() |
|
198 /** |
|
199 Second phase constructor |
|
200 */ |
|
201 { |
|
202 User::LeaveIfError(iNotifier.Connect()); |
|
203 } |
|
204 |
|
205 void CRefDialogCreator::DoCancel() |
|
206 { |
|
207 if (iState == EProcessResult) |
|
208 { |
|
209 iNotifier.CancelNotifier(TUid::Uid(KRefNotifierImplementationId)); |
|
210 } |
|
211 if (iClientStatus) |
|
212 { |
|
213 User::RequestComplete(iClientStatus, KErrCancel); |
|
214 } |
|
215 } |
|
216 |
|
217 TInt CRefDialogCreator::RunError(TInt aError) |
|
218 { |
|
219 if (iClientStatus) |
|
220 { |
|
221 User::RequestComplete(iClientStatus, aError); |
|
222 } |
|
223 return KErrNone; |
|
224 } |
|
225 |
|
226 void CRefDialogCreator::RunL() |
|
227 { |
|
228 User::LeaveIfError(iStatus.Int()); |
|
229 switch (iState) |
|
230 { |
|
231 case EPrepareDialog: |
|
232 DoPrepareDialogL(); |
|
233 break; |
|
234 case EDisplayDialog: |
|
235 DoDisplayDialogL(); |
|
236 break; |
|
237 case EProcessResult: |
|
238 DoProcessResultL(); |
|
239 break; |
|
240 default: |
|
241 ASSERT(EFalse); |
|
242 } |
|
243 } |
|
244 |
|
245 void CRefDialogCreator::DoPrepareDialogL() |
|
246 { |
|
247 iPromptData = CPromptData::NewL(); |
|
248 |
|
249 // Only one state at the moment but more should be |
|
250 // added for long running operators e.g. querying the SIS registry |
|
251 // or resolving the client entity. |
|
252 ResolveClientNameL(iRequest->ClientSid()); |
|
253 |
|
254 // Get the vendor name for the client process |
|
255 ResolveVendorNameL(iRequest->ClientVid()); |
|
256 |
|
257 // Server / Service localized names generated in notifier plug-in. |
|
258 iPromptData->iServerSid = iRequest->ServerSid(); |
|
259 iPromptData->iServiceId = iRequest->ServiceId(); |
|
260 |
|
261 // Different dialog text is displayed depending on whether the client application |
|
262 // is signed. |
|
263 // N.B. Protected SID is assumed to be signed or included at ROM build. |
|
264 if (iRequest->IsClientSidProtected()) iPromptData->iFlags |= ETrustedClient; |
|
265 |
|
266 // Use the options specified by the policy |
|
267 iPromptData->iOptions = iPolicy->Options(); |
|
268 |
|
269 // Add the descriptions of the fingerprints. This could be used |
|
270 // to allow the user to grant access to all destinations |
|
271 // or a single destination. |
|
272 TInt count = iFingerprints->Count(); |
|
273 for (TInt i = 0; i < count; ++i) |
|
274 { |
|
275 HBufC* description = (*iFingerprints)[i]->Description().AllocLC(); |
|
276 iPromptData->iDescriptions.AppendL(description); |
|
277 CleanupStack::Pop(description); |
|
278 } |
|
279 |
|
280 User::RequestComplete(iClientStatus, KErrNone); |
|
281 // DisplayDialog is invoked by the UPS, this just verifies |
|
282 // that PrepareDialog was called first. |
|
283 iState = EDisplayDialog; |
|
284 } |
|
285 |
|
286 void CRefDialogCreator::DoDisplayDialogL() |
|
287 /** |
|
288 Uses the notifier framework to display the dialog. |
|
289 */ |
|
290 { |
|
291 // Externalize the prompt data to a descriptor |
|
292 RNullWriteStream ns; |
|
293 ns << *iPromptData; |
|
294 ns.CommitL(); |
|
295 iPromptDataDes.CreateL(ns.BytesWritten()); |
|
296 RDesWriteStream ws; |
|
297 ws.Open(iPromptDataDes); |
|
298 ws << *iPromptData; |
|
299 ws.CommitL(); |
|
300 iNotifier.StartNotifierAndGetResponse(iStatus, TUid::Uid(KRefNotifierImplementationId), |
|
301 iPromptDataDes, iPromptResultPckg); |
|
302 SetActive(); |
|
303 iState = EProcessResult; |
|
304 } |
|
305 |
|
306 void CRefDialogCreator::DoProcessResultL() |
|
307 /** |
|
308 Processes the result returned by the notifier. |
|
309 */ |
|
310 { |
|
311 if (iPromptResult.iSelected == CPolicy::EAlways || |
|
312 iPromptResult.iSelected == CPolicy::ENever) |
|
313 { |
|
314 // The Always or Never option was selected so return the fingerprint |
|
315 // for the new decision record. |
|
316 // |
|
317 // In this implementation a copy of the original fingerprint is returned. However, |
|
318 // it is permitted to return a different fingerprint e.g. a modifier description. |
|
319 if (iPromptResult.iDestination >= 0 && iPromptResult.iDestination < iFingerprints->Count()) |
|
320 { |
|
321 *iFingerprint = (*iFingerprints)[iPromptResult.iDestination]; |
|
322 } |
|
323 else |
|
324 { |
|
325 ASSERT(EFalse); // should never happen, unless the notifier has errors. |
|
326 } |
|
327 } |
|
328 *iOptionSelected = iPromptResult.iSelected; |
|
329 iState = EIdle; |
|
330 User::RequestComplete(iClientStatus, KErrNone); |
|
331 } |
|
332 |
|
333 void CRefDialogCreator::ResolveVendorNameL(const TVendorId& aVid) |
|
334 /** |
|
335 Looks up the localized vendor name for the client process and writes |
|
336 this to iPromptData->iVendorName. |
|
337 |
|
338 Typically, this would be resolved from the SIS registry or a lookup table. |
|
339 |
|
340 @param aVid The vendor id of the client process. |
|
341 */ |
|
342 { |
|
343 if (iPromptData->iVendorName.Length() != 0) |
|
344 { |
|
345 // already obtained vendor name from SIS registry |
|
346 return; |
|
347 } |
|
348 |
|
349 if (aVid.iId == 0x70000001) |
|
350 { |
|
351 _LIT(KSymbian, "Symbian Foundation"); |
|
352 iPromptData->iVendorName.Create(KSymbian); |
|
353 } |
|
354 else |
|
355 { |
|
356 _LIT(KUnknown, "Unknown vendor"); |
|
357 iPromptData->iVendorName.Create(KUnknown); |
|
358 } |
|
359 } |
|
360 |
|
361 void CRefDialogCreator::ResolveClientNameL(const TSecureId& aSid) |
|
362 /** |
|
363 Generates a human readable name for the client process. In order of |
|
364 preference the following data is returned |
|
365 |
|
366 - The AppArc caption name. |
|
367 - The localized package name that owns this SID. |
|
368 - A value from a lookup table. |
|
369 - The filename for the client process executable. |
|
370 |
|
371 @param aSid The secure id of the client process. |
|
372 */ |
|
373 { |
|
374 TBool found = EFalse; |
|
375 |
|
376 // Although the client name from AppArc takes precedance the SIS |
|
377 // registry is always invoked in order to retrieve the vendor name |
|
378 found |= ResolveClientNameFromSisRegistryL(aSid); |
|
379 found |= ResolveClientNameFromAppArcL(aSid); |
|
380 |
|
381 // A lookup that maps secure-ids to application names could |
|
382 // be used here. |
|
383 |
|
384 // Fall back to the filename of the client process |
|
385 // The original thread may have exited so the process handle is used instead. |
|
386 // because the client-side object e.g. RSocket may be shared between threads. |
|
387 |
|
388 // If the process has exited then it's o.k. to leave. |
|
389 if (! found) |
|
390 { |
|
391 RProcess clientProcess; |
|
392 User::LeaveIfError(clientProcess.Open(iRequest->ClientProcessId())); |
|
393 CleanupClosePushL(clientProcess); |
|
394 iPromptData->iClientName.Create(clientProcess.FileName()); |
|
395 CleanupStack::PopAndDestroy(&clientProcess); |
|
396 } |
|
397 } |
|
398 |
|
399 TBool CRefDialogCreator::ResolveClientNameFromAppArcL(const TSecureId& aSid) |
|
400 /** |
|
401 Gets the caption name for the application from AppArc (if available). |
|
402 |
|
403 @param aSid The secure id of the client process. |
|
404 @return ETrue if a match was found in apparc; otherwise, EFalse is returned. |
|
405 */ |
|
406 { |
|
407 TBool found(EFalse); |
|
408 |
|
409 RApaLsSession apa; |
|
410 CleanupClosePushL(apa); |
|
411 TInt err = apa.Connect(); |
|
412 if (err == KErrNone) |
|
413 { |
|
414 TApaAppInfo* info = new(ELeave) TApaAppInfo(); |
|
415 CleanupStack::PushL(info); |
|
416 |
|
417 err = apa.GetAppInfo(*info, TUid::Uid(aSid)); |
|
418 if (err == KErrNone) |
|
419 { |
|
420 iPromptData->iClientName.Close(); |
|
421 iPromptData->iClientName.Create(info->iCaption); |
|
422 found = ETrue; |
|
423 } |
|
424 else if (err != KErrNotFound) |
|
425 { |
|
426 User::Leave(err); |
|
427 } |
|
428 CleanupStack::PopAndDestroy(info); |
|
429 } |
|
430 else if (err != KErrNotFound) |
|
431 { |
|
432 // If the connection to apparc failed with KErrNotFound |
|
433 // then the error is ignored becase we assume the dialog |
|
434 // creator was invoked from text-shell |
|
435 User::Leave(err); |
|
436 } |
|
437 CleanupStack::PopAndDestroy(&apa); |
|
438 return found; |
|
439 } |
|
440 |
|
441 TBool CRefDialogCreator::ResolveClientNameFromSisRegistryL(const TSecureId& aSid) |
|
442 /** |
|
443 Retrieves the client and vendor information from the SIS registry. |
|
444 @param aSid The secure-id of the client application to lookup in the registry. |
|
445 @return ETrue, if the lookup was successful; otherwise, EFalse is returned. |
|
446 */ |
|
447 { |
|
448 TBool found(EFalse); |
|
449 Swi::RSisRegistrySession r; |
|
450 User::LeaveIfError(r.Connect()); |
|
451 CleanupClosePushL(r); |
|
452 |
|
453 Swi::CSisRegistryPackage* p(0); |
|
454 TRAPD(err, p = r.SidToPackageL(TUid::Uid(aSid.iId))); |
|
455 if (err == KErrNone) |
|
456 { |
|
457 iPromptData->iClientName.Create(p->Name()); |
|
458 iPromptData->iVendorName.Create(p->Vendor()); |
|
459 found = ETrue; |
|
460 delete p; |
|
461 } |
|
462 CleanupStack::PopAndDestroy(&r); |
|
463 return found; |
|
464 } |
|
465 |
|
466 // From CDialogCreator |
|
467 void CRefDialogCreator::PrepareDialog( |
|
468 const UserPromptService::CPromptRequest& aRequest, const CPolicy& aPolicy, |
|
469 const RPointerArray<CFingerprint>& aFingerprints, const CClientEntity* aClientEntity, |
|
470 const TAny* aEvalPrivateData, TRequestStatus& aStatus) |
|
471 { |
|
472 aStatus = KRequestPending; |
|
473 iClientStatus = &aStatus; |
|
474 |
|
475 iRequest = &aRequest; |
|
476 iPolicy = &aPolicy; |
|
477 iFingerprints = &aFingerprints; |
|
478 iEvalPrivateData = aEvalPrivateData; |
|
479 (void) aClientEntity; |
|
480 |
|
481 // Kick off dialog creator state machine |
|
482 iState = EPrepareDialog; |
|
483 iStatus = KRequestPending; |
|
484 TRequestStatus* status = &iStatus; |
|
485 SetActive(); |
|
486 User::RequestComplete(status, KErrNone); |
|
487 } |
|
488 |
|
489 void CRefDialogCreator::DisplayDialog(CPolicy::TOptions& aOptions, const CFingerprint*& aFingerprint, |
|
490 TUint& aEvaluatorInfo, TRequestStatus& aStatus) |
|
491 { |
|
492 aStatus = KRequestPending; |
|
493 iClientStatus = &aStatus; |
|
494 |
|
495 iOptionSelected = &aOptions; |
|
496 iFingerprint = &aFingerprint; |
|
497 aFingerprint = 0; |
|
498 iEvaluatorInfo = &aEvaluatorInfo; |
|
499 iClientStatus = &aStatus; |
|
500 |
|
501 // Start state machine |
|
502 ASSERT(iState == EDisplayDialog); // PrepareDialog should have been called first |
|
503 iStatus = KRequestPending; |
|
504 TRequestStatus* status = &iStatus; |
|
505 SetActive(); |
|
506 User::RequestComplete(status, KErrNone); |
|
507 } |
|
508 </codeblock> </section> |
|
509 </conbody></concept> |