|
1 // Copyright (c) 2002-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 // |
|
15 |
|
16 #include <mmf/common/mmfcontroller.h> |
|
17 #include <mmf/server/mmffile.h> |
|
18 #include <mmf/common/mmfdrmcustomcommands.h> |
|
19 #include <mmf/common/mmfstandardcustomcommands.h> |
|
20 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
21 #include <mmf/common/mmfcontrollerextendeddata.h> |
|
22 #include <mmf/common/mmfcustomcommandparsermanager.h> |
|
23 #endif |
|
24 |
|
25 inline void ExtendedDataTlsCleanup(TAny* /*aPtr*/) |
|
26 { |
|
27 delete static_cast<CMMFControllerExtendedData*>(Dll::Tls()); |
|
28 Dll::SetTls(NULL); |
|
29 } |
|
30 |
|
31 CMMFController* CMMFController::NewL(TUid aControllerUid, MAsyncEventHandler& aEventHandler, TThreadId aClientTid) |
|
32 { |
|
33 Dll::SetTls(CMMFController::CreateExtendedDataL(aClientTid)); |
|
34 CleanupStack::PushL(TCleanupItem(&ExtendedDataTlsCleanup, NULL)); |
|
35 CMMFController* s = REINTERPRET_CAST(CMMFController*,REComSession::CreateImplementationL(aControllerUid,_FOFF(CMMFController,iDtor_ID_Key))); |
|
36 CleanupStack::PushL(s); |
|
37 s->ConstructL(aEventHandler, aClientTid); |
|
38 CleanupStack::Pop(s); |
|
39 CleanupStack::PopAndDestroy(); // TCleanupItem(ExtendedDataTlsCleanup) |
|
40 return s; |
|
41 } |
|
42 |
|
43 void CMMFController::ConstructL(MAsyncEventHandler& aEventHandler, TThreadId aClientTid) |
|
44 { |
|
45 iAsyncEventHandler = &aEventHandler; |
|
46 |
|
47 // If extended data hasn't been initialized, GetExtendedDataL will initialize it and |
|
48 // add it into iMMFObjectContainer |
|
49 #ifdef _DEBUG |
|
50 CMMFControllerExtendedData* extendData = |
|
51 #endif |
|
52 GetExtendedDataL(); |
|
53 #ifdef _DEBUG |
|
54 ASSERT(extendData->ClientThreadId() == aClientTid); |
|
55 #else |
|
56 (void)aClientTid; // remove compilation error |
|
57 #endif |
|
58 } |
|
59 |
|
60 EXPORT_C CMMFController::~CMMFController() |
|
61 { |
|
62 delete iCustomCommandParserManager; |
|
63 delete iMMFObjectContainer; |
|
64 delete iMetaDataBuffer; |
|
65 REComSession::DestroyedImplementation(iDtor_ID_Key); |
|
66 } |
|
67 |
|
68 EXPORT_C TInt CMMFController::DoSendEventToClient(const TMMFEvent& aEvent) |
|
69 { |
|
70 return iAsyncEventHandler->SendEventToClient(aEvent); |
|
71 } |
|
72 |
|
73 EXPORT_C CMMFObjectContainer& CMMFController::MMFObjectContainerL() |
|
74 { |
|
75 // Construct iMMFObjectContainer if we haven't already. |
|
76 if (!iMMFObjectContainer) |
|
77 iMMFObjectContainer = new(ELeave) CMMFObjectContainer; |
|
78 return *iMMFObjectContainer; |
|
79 } |
|
80 |
|
81 EXPORT_C void CMMFController::AddCustomCommandParserL(CMMFCustomCommandParserBase& aParser) |
|
82 { |
|
83 // Construct iCustomCommandParserManager if we haven't already |
|
84 if (!iCustomCommandParserManager) |
|
85 iCustomCommandParserManager = CMMFCustomCommandParserManager::NewL(); |
|
86 iCustomCommandParserManager->AddCustomCommandParserL(aParser); |
|
87 } |
|
88 |
|
89 |
|
90 EXPORT_C void CMMFController::HandleRequestL(TMMFMessage& aMessage) |
|
91 { |
|
92 // If the message has the constant controller destination handle, pass the message to |
|
93 // the controller plugin to handle. |
|
94 // Otherwise, the message must be for one of the MMFObjects. |
|
95 if (aMessage.Destination().DestinationHandle() == KMMFObjectHandleController) |
|
96 { |
|
97 // If the message has an interface ID for this controller, handle it here. |
|
98 // Otherwise, pass it to the controller plugin to handle as a custom command. |
|
99 if (aMessage.Destination().InterfaceId() == KUidInterfaceMMFController) |
|
100 { |
|
101 TBool complete = ETrue; |
|
102 switch (aMessage.Function()) |
|
103 { |
|
104 case EMMFControllerAddDataSource: |
|
105 complete = DoAddDataSourceL(aMessage); |
|
106 break; |
|
107 case EMMFControllerAddDataSink: |
|
108 complete = DoAddDataSinkL(aMessage); |
|
109 break; |
|
110 case EMMFControllerRemoveDataSource: |
|
111 complete = DoRemoveDataSourceL(aMessage); |
|
112 break; |
|
113 case EMMFControllerRemoveDataSink: |
|
114 complete = DoRemoveDataSinkL(aMessage); |
|
115 break; |
|
116 case EMMFControllerReset: |
|
117 complete = DoResetL(aMessage); |
|
118 break; |
|
119 case EMMFControllerPrime: |
|
120 complete = DoPrimeL(aMessage); |
|
121 break; |
|
122 case EMMFControllerPlay: |
|
123 complete = DoPlayL(aMessage); |
|
124 break; |
|
125 case EMMFControllerPause: |
|
126 complete = DoPauseL(aMessage); |
|
127 break; |
|
128 case EMMFControllerStop: |
|
129 complete = DoStopL(aMessage); |
|
130 break; |
|
131 case EMMFControllerGetPosition: |
|
132 complete = DoGetPositionL(aMessage); |
|
133 break; |
|
134 case EMMFControllerSetPosition: |
|
135 complete = DoSetPositionL(aMessage); |
|
136 break; |
|
137 case EMMFControllerGetDuration: |
|
138 complete = DoGetDurationL(aMessage); |
|
139 break; |
|
140 case EMMFControllerGetNumberOfMetaDataEntries: |
|
141 complete = DoGetNumberOfMetaDataEntriesL(aMessage); |
|
142 break; |
|
143 case EMMFControllerGetSizeOfMetaDataEntry: |
|
144 complete = DoGetSizeOfMetaDataEntryL(aMessage); |
|
145 break; |
|
146 case EMMFControllerGetMetaDataEntry: |
|
147 complete = DoGetMetaDataEntryL(aMessage); |
|
148 break; |
|
149 case EMMFControllerSetPrioritySettings: |
|
150 complete = DoSetPrioritySettingsL(aMessage); |
|
151 break; |
|
152 case EMMFControllerCancelAddDataSource: |
|
153 complete = ETrue;//Nothing to cancel since AddDataSource is synchronous server-side |
|
154 break; |
|
155 case EMMFControllerCancelAddDataSink: |
|
156 complete = ETrue;//Nothing to cancel since AddDataSink is synchronous server-side |
|
157 break; |
|
158 case EMMFControllerAddFileHandleDataSource: |
|
159 complete = DoAddFileHandleDataSourceL(aMessage); |
|
160 break; |
|
161 case EMMFControllerAddFileHandleDataSink: |
|
162 complete = DoAddFileHandleDataSinkL(aMessage); |
|
163 break; |
|
164 case EMMFControllerSourceSinkInitDataPreload: |
|
165 complete = DoPreloadSourceSinkInitDataL(aMessage); |
|
166 break; |
|
167 case EMMFControllerAddFileHandleDataSourceWithInitData: |
|
168 complete = DoAddFileHandleDataSourceWithInitDataL(aMessage); |
|
169 break; |
|
170 case EMMFControllerAddFileHandleDataSinkWithInitData: |
|
171 complete = DoAddFileHandleDataSinkWithInitDataL(aMessage); |
|
172 break; |
|
173 default: |
|
174 User::Leave(KErrNotSupported); |
|
175 break; |
|
176 } |
|
177 if (complete) |
|
178 aMessage.Complete(KErrNone); |
|
179 } |
|
180 else |
|
181 { |
|
182 // Must be a custom command |
|
183 DoCustomCommand(aMessage); |
|
184 } |
|
185 } |
|
186 else |
|
187 { |
|
188 // Message for one of the MMF Objects |
|
189 CMMFObject* object = NULL; |
|
190 User::LeaveIfError(MMFObjectContainerL().FindMMFObject(aMessage.Destination(), object)); |
|
191 object->HandleRequest(aMessage); |
|
192 } |
|
193 |
|
194 } |
|
195 |
|
196 TBool CMMFController::DoAddDataSourceL(TMMFMessage& aMessage) |
|
197 { |
|
198 // Get the UID of the source from the client |
|
199 TMMFUidPckg uidPckg; |
|
200 aMessage.ReadData1FromClientL(uidPckg); |
|
201 |
|
202 // Get the size of the init data and create a buffer to hold it |
|
203 TInt desLength = aMessage.SizeOfData2FromClient(); |
|
204 // Leaving here in order to prevent a panic in the NewLC if the value is negative |
|
205 User::LeaveIfError(desLength); |
|
206 HBufC8* buf = HBufC8::NewLC(desLength); |
|
207 TPtr8 ptr = buf->Des(); |
|
208 aMessage.ReadData2FromClientL(ptr); |
|
209 |
|
210 // Create the source |
|
211 MDataSource* source = MDataSource::NewSourceL(uidPckg(), *buf); |
|
212 CleanupStack::PopAndDestroy(buf);//buf |
|
213 AddMDataSourceAndRepondClientL(source, aMessage); |
|
214 |
|
215 return ETrue; |
|
216 } |
|
217 |
|
218 |
|
219 TBool CMMFController::DoAddDataSinkL(TMMFMessage& aMessage) |
|
220 { |
|
221 // Get the UID of the sink from the client |
|
222 TMMFUidPckg uidPckg; |
|
223 aMessage.ReadData1FromClientL(uidPckg); |
|
224 |
|
225 // Get the size of the init data and create a buffer to hold it |
|
226 TInt desLength = aMessage.SizeOfData2FromClient(); |
|
227 // Leaving here in order to prevent a panic in the NewLC if the value is negative |
|
228 User::LeaveIfError(desLength); |
|
229 HBufC8* buf = HBufC8::NewLC(desLength); |
|
230 TPtr8 ptr = buf->Des(); |
|
231 aMessage.ReadData2FromClientL(ptr); |
|
232 |
|
233 // Create the sink |
|
234 MDataSink* sink = MDataSink::NewSinkL(uidPckg(), *buf); |
|
235 CleanupStack::PopAndDestroy(buf);//buf |
|
236 AddMDataSinkAndRepondClientL(sink, aMessage); |
|
237 |
|
238 return ETrue; |
|
239 } |
|
240 |
|
241 TBool CMMFController::DoRemoveDataSourceL(TMMFMessage& aMessage) |
|
242 { |
|
243 TMMFMessageDestinationPckg handleInfo; |
|
244 aMessage.ReadData1FromClientL(handleInfo); |
|
245 |
|
246 // Find the correct source |
|
247 CMMFObject* object = NULL; |
|
248 CMMFDataSourceHolder* holder = NULL; |
|
249 User::LeaveIfError(MMFObjectContainerL().FindMMFObject(handleInfo(), object)); |
|
250 // Cast the object found if possible.. |
|
251 if (object->Handle().InterfaceId() == KUidInterfaceMMFDataSourceHolder) |
|
252 holder = STATIC_CAST(CMMFDataSourceHolder*, object); |
|
253 else |
|
254 User::Leave(KErrBadHandle); |
|
255 |
|
256 // Try to remove the data source from the plugin |
|
257 RemoveDataSourceL(holder->DataSource()); |
|
258 |
|
259 // If we're here, the removal worked so remove the source from the object array and delete it |
|
260 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
261 return ETrue; |
|
262 } |
|
263 |
|
264 TBool CMMFController::DoRemoveDataSinkL(TMMFMessage& aMessage) |
|
265 { |
|
266 TMMFMessageDestinationPckg handleInfo; |
|
267 aMessage.ReadData1FromClientL(handleInfo); |
|
268 |
|
269 // Find the correct source |
|
270 CMMFObject* object = NULL; |
|
271 CMMFDataSinkHolder* holder = NULL; |
|
272 User::LeaveIfError(MMFObjectContainerL().FindMMFObject(handleInfo(), object)); |
|
273 // Cast the object found if possible.. |
|
274 if (object->Handle().InterfaceId() == KUidInterfaceMMFDataSinkHolder) |
|
275 holder = STATIC_CAST(CMMFDataSinkHolder*, object); |
|
276 else |
|
277 User::Leave(KErrBadHandle); |
|
278 |
|
279 // Try to remove the data sink from the plugin |
|
280 RemoveDataSinkL(holder->DataSink()); |
|
281 |
|
282 // If we're here, the removal worked so remove the source from the object array and delete it |
|
283 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
284 return ETrue; |
|
285 } |
|
286 |
|
287 TBool CMMFController::DoResetL(TMMFMessage& /*aMessage*/) |
|
288 { |
|
289 ResetL(); |
|
290 // Controller extended data must be kept until the death of controller |
|
291 const RPointerArray<CMMFObject>& objects = iMMFObjectContainer->MMFObjects(); |
|
292 for (TInt i = objects.Count()-1; i >= 0; i--) |
|
293 { |
|
294 CMMFObject* object = objects[i]; |
|
295 if (object->Handle().InterfaceId() != KUidMMFControllerExtendedDataHolder) |
|
296 { |
|
297 iMMFObjectContainer->RemoveAndDestroyMMFObject(*object); |
|
298 } |
|
299 } |
|
300 return ETrue; |
|
301 } |
|
302 |
|
303 TBool CMMFController::DoPrimeL(TMMFMessage& aMessage) |
|
304 { |
|
305 PrimeL(aMessage); |
|
306 return EFalse; |
|
307 } |
|
308 |
|
309 |
|
310 EXPORT_C void CMMFController::PrimeL(TMMFMessage& aMessage) |
|
311 { |
|
312 PrimeL(); |
|
313 aMessage.Complete(KErrNone); |
|
314 } |
|
315 |
|
316 |
|
317 TBool CMMFController::DoPlayL(TMMFMessage& aMessage) |
|
318 { |
|
319 PlayL(aMessage); |
|
320 return EFalse; |
|
321 } |
|
322 |
|
323 EXPORT_C void CMMFController::PlayL(TMMFMessage& aMessage) |
|
324 { |
|
325 PlayL(); |
|
326 aMessage.Complete(KErrNone); |
|
327 } |
|
328 |
|
329 |
|
330 |
|
331 TBool CMMFController::DoPauseL(TMMFMessage& aMessage) |
|
332 { |
|
333 PauseL(aMessage); |
|
334 return EFalse; |
|
335 } |
|
336 |
|
337 EXPORT_C void CMMFController::PauseL(TMMFMessage& aMessage) |
|
338 { |
|
339 PauseL(); |
|
340 aMessage.Complete(KErrNone); |
|
341 } |
|
342 |
|
343 |
|
344 TBool CMMFController::DoStopL(TMMFMessage& aMessage) |
|
345 { |
|
346 StopL(aMessage); |
|
347 return EFalse; |
|
348 } |
|
349 |
|
350 EXPORT_C void CMMFController::StopL(TMMFMessage& aMessage) |
|
351 { |
|
352 StopL(); |
|
353 aMessage.Complete(KErrNone); |
|
354 } |
|
355 |
|
356 |
|
357 |
|
358 TBool CMMFController::DoGetPositionL(TMMFMessage& aMessage) |
|
359 { |
|
360 TMMFTimeIntervalMicroSecondsPckg pckg(PositionL()); |
|
361 aMessage.WriteDataToClientL(pckg); |
|
362 return ETrue; |
|
363 } |
|
364 |
|
365 TBool CMMFController::DoSetPositionL(TMMFMessage& aMessage) |
|
366 { |
|
367 TMMFTimeIntervalMicroSecondsPckg pckg; |
|
368 aMessage.ReadData1FromClientL(pckg); |
|
369 SetPositionL(pckg()); |
|
370 return ETrue; |
|
371 } |
|
372 |
|
373 TBool CMMFController::DoGetDurationL(TMMFMessage& aMessage) |
|
374 { |
|
375 TMMFTimeIntervalMicroSecondsPckg pckg(DurationL()); |
|
376 aMessage.WriteDataToClientL(pckg); |
|
377 return ETrue; |
|
378 } |
|
379 |
|
380 TBool CMMFController::DoSetPrioritySettingsL(TMMFMessage& aMessage) |
|
381 { |
|
382 TMMFPrioritySettingsPckg pckg; |
|
383 aMessage.ReadData1FromClientL(pckg); |
|
384 SetPrioritySettings(pckg()); |
|
385 return ETrue; |
|
386 } |
|
387 |
|
388 void CMMFController::DoCustomCommand(TMMFMessage& aMessage) |
|
389 { |
|
390 // First, try giving the message to the custom command parser manager... |
|
391 TBool handled = EFalse; |
|
392 if (iCustomCommandParserManager) |
|
393 { |
|
394 if (aMessage.Destination().InterfaceId() == KUidInterfaceMMFDRMControl || |
|
395 aMessage.Destination().InterfaceId() == KUidInterfaceMMFVideoDRMExt) |
|
396 { |
|
397 TBool secureDrmMode = EFalse; |
|
398 TRAPD(err, secureDrmMode = GetExtendedDataL()->SecureDrmMode()); |
|
399 if (err) |
|
400 { |
|
401 aMessage.Complete(err); |
|
402 handled = ETrue; |
|
403 } |
|
404 else if (secureDrmMode) |
|
405 { |
|
406 aMessage.Complete(KErrPermissionDenied); |
|
407 handled = ETrue; |
|
408 } |
|
409 } |
|
410 |
|
411 if (!handled) |
|
412 { |
|
413 handled = iCustomCommandParserManager->HandleRequest(aMessage); |
|
414 } |
|
415 } |
|
416 |
|
417 // If the ccp manager couldn't handle the message, pass directly to the |
|
418 // controller plugin as a custom command. |
|
419 if (!handled) |
|
420 CustomCommand(aMessage); |
|
421 } |
|
422 |
|
423 TBool CMMFController::DoGetNumberOfMetaDataEntriesL(TMMFMessage& aMessage) |
|
424 { |
|
425 TInt numberOfEntries; |
|
426 GetNumberOfMetaDataEntriesL(numberOfEntries); |
|
427 TPckgBuf<TInt> pckg(numberOfEntries); |
|
428 aMessage.WriteDataToClientL(pckg); |
|
429 return ETrue; |
|
430 } |
|
431 |
|
432 TBool CMMFController::DoGetSizeOfMetaDataEntryL(TMMFMessage& aMessage) |
|
433 { |
|
434 // Get the index of the required entry |
|
435 TPckgBuf<TInt> pckg; |
|
436 aMessage.ReadData1FromClientL(pckg); |
|
437 // Get the entry |
|
438 CMMFMetaDataEntry* entry = GetMetaDataEntryL(pckg()); |
|
439 CleanupStack::PushL(entry); |
|
440 // Delete any existing buffer |
|
441 delete iMetaDataBuffer; |
|
442 iMetaDataBuffer = NULL; |
|
443 // Create a buffer to hold the externalised entry |
|
444 iMetaDataBuffer = CBufFlat::NewL(32); |
|
445 RBufWriteStream s; |
|
446 s.Open(*iMetaDataBuffer); |
|
447 CleanupClosePushL(s); |
|
448 entry->ExternalizeL(s); |
|
449 CleanupStack::PopAndDestroy(2);//s, entry |
|
450 // Write the size of the externalised data back to the client |
|
451 pckg() = iMetaDataBuffer->Ptr(0).Length(); |
|
452 aMessage.WriteDataToClientL(pckg); |
|
453 return ETrue; |
|
454 } |
|
455 |
|
456 TBool CMMFController::DoGetMetaDataEntryL(TMMFMessage& aMessage) |
|
457 { |
|
458 // We should have already prepared the buffer |
|
459 if (!iMetaDataBuffer) |
|
460 User::Leave(KErrNotReady); |
|
461 aMessage.WriteDataToClientL(iMetaDataBuffer->Ptr(0)); |
|
462 return ETrue; |
|
463 } |
|
464 |
|
465 TBool CMMFController::DoPreloadSourceSinkInitDataL(TMMFMessage& aMessage) |
|
466 { |
|
467 GetExtendedDataL()->ResetSourceSinkInitData(); |
|
468 |
|
469 // Get the size of the init data and create a buffer to hold it |
|
470 TInt desLength = aMessage.SizeOfData1FromClient(); |
|
471 HBufC8* sourceSinkInitData = HBufC8::NewLC(desLength); |
|
472 TPtr8 ptr = sourceSinkInitData->Des(); |
|
473 aMessage.ReadData1FromClientL(ptr); |
|
474 |
|
475 GetExtendedDataL()->SetSourceSinkInitData(sourceSinkInitData); |
|
476 CleanupStack::Pop(sourceSinkInitData); |
|
477 return ETrue; |
|
478 } |
|
479 |
|
480 TBool CMMFController::DoAddFileHandleDataSourceWithInitDataL(TMMFMessage& aMessage) |
|
481 { |
|
482 if (GetExtendedDataL()->SourceSinkInitData() == NULL) |
|
483 { |
|
484 User::Leave(KErrNotReady); |
|
485 } |
|
486 HBufC8* initData = GetExtendedDataL()->SourceSinkInitData()->AllocLC(); |
|
487 |
|
488 // Get the client file handle and replace |
|
489 RFile file; |
|
490 aMessage.AdoptFileHandleFromClientL(1,2, file); |
|
491 CleanupClosePushL(file); |
|
492 TPtr8 initDataPtr(initData->Des()); |
|
493 ReplaceFileHandleInInitDataL(&file, initDataPtr); |
|
494 |
|
495 // Create the source |
|
496 MDataSource* source = MDataSource::NewSourceL(KUidMmfFileSource, *initData); |
|
497 CleanupStack::PopAndDestroy(2, initData); //file, initData |
|
498 AddMDataSourceAndRepondClientL(source, aMessage); |
|
499 |
|
500 GetExtendedDataL()->ResetSourceSinkInitData(); |
|
501 return ETrue; |
|
502 } |
|
503 |
|
504 TBool CMMFController::DoAddFileHandleDataSinkWithInitDataL(TMMFMessage& aMessage) |
|
505 { |
|
506 if (GetExtendedDataL()->SourceSinkInitData() == NULL) |
|
507 { |
|
508 User::Leave(KErrNotReady); |
|
509 } |
|
510 HBufC8* initData = GetExtendedDataL()->SourceSinkInitData()->AllocLC(); |
|
511 |
|
512 // Get the client file handle and replace |
|
513 RFile file; |
|
514 aMessage.AdoptFileHandleFromClientL(1,2, file); |
|
515 CleanupClosePushL(file); |
|
516 TPtr8 initDataPtr(initData->Des()); |
|
517 ReplaceFileHandleInInitDataL(&file, initDataPtr); |
|
518 |
|
519 // Create the sink |
|
520 MDataSink* sink = MDataSink::NewSinkL(KUidMmfFileSink, *initData); |
|
521 CleanupStack::PopAndDestroy(2, initData); //file, initData |
|
522 AddMDataSinkAndRepondClientL(sink, aMessage); |
|
523 |
|
524 GetExtendedDataL()->ResetSourceSinkInitData(); |
|
525 return ETrue; |
|
526 } |
|
527 |
|
528 void CMMFController::ReplaceFileHandleInInitDataL(RFile* aFile, TDes8& aInitData) |
|
529 { |
|
530 // aInitData should have the second 4bytes data (first 4bytes represent TUid) containing |
|
531 // a client RFile pointer. |
|
532 // This RFile pointer may be invalid due to the fact that client and server threads |
|
533 // may reside in different processes, and therefore, different memory space. |
|
534 // In this context, we would rather trust the file handle retrieve from the call |
|
535 // AdoptFileHandleFromClientL, and replace the RFile pointer with a more reliable one |
|
536 TPtr8 filePtrStart = aInitData.MidTPtr(sizeof(TUid)); |
|
537 RDesWriteStream writeStream; |
|
538 writeStream.Open(filePtrStart); |
|
539 CleanupClosePushL(writeStream); |
|
540 TPckgBuf<RFile*> filePtr(aFile); |
|
541 writeStream.WriteL(filePtr); |
|
542 writeStream.CommitL(); |
|
543 CleanupStack::PopAndDestroy(&writeStream); |
|
544 } |
|
545 |
|
546 void CMMFController::AddMDataSourceAndRepondClientL(MDataSource* aSource, TMMFMessage& aMessage) |
|
547 { |
|
548 CleanupDeletePushL(aSource); |
|
549 CMMFDataSourceHolder* holder = new(ELeave) CMMFDataSourceHolder(*aSource); |
|
550 CleanupStack::Pop(aSource); //aSource (since now owned by holder) |
|
551 |
|
552 CleanupStack::PushL(holder); |
|
553 // Append holder to array of MMFObjects |
|
554 User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); |
|
555 CleanupStack::Pop(holder);//holder |
|
556 |
|
557 // Write source handle info back to client |
|
558 TMMFMessageDestination handleInfo(holder->Handle()); |
|
559 TMMFMessageDestinationPckg handlePckg(handleInfo); |
|
560 TInt error = aMessage.WriteDataToClient(handlePckg); |
|
561 |
|
562 // Add source to plugin |
|
563 if (!error) |
|
564 TRAP(error, AddDataSourceL(*aSource)); |
|
565 |
|
566 if (error) |
|
567 { |
|
568 // Source not accepted by plugin or we couldn't write handle info back to client, |
|
569 // so delete it and return error to client |
|
570 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
571 User::Leave(error); |
|
572 } |
|
573 } |
|
574 |
|
575 void CMMFController::AddMDataSinkAndRepondClientL(MDataSink* aSink, TMMFMessage& aMessage) |
|
576 { |
|
577 CleanupDeletePushL(aSink); |
|
578 CMMFDataSinkHolder* holder = new(ELeave) CMMFDataSinkHolder(*aSink); |
|
579 CleanupStack::Pop(aSink); //aSink (since now owned by holder) |
|
580 |
|
581 CleanupStack::PushL(holder); |
|
582 // Append sink to array |
|
583 User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); |
|
584 CleanupStack::Pop(holder);//holder |
|
585 |
|
586 // Write sink handle info back to client |
|
587 TMMFMessageDestination handleInfo(holder->Handle()); |
|
588 TMMFMessageDestinationPckg handlePckg(handleInfo); |
|
589 TInt error = aMessage.WriteDataToClient(handlePckg); |
|
590 |
|
591 // Add sink to plugin |
|
592 if (!error) |
|
593 TRAP(error, AddDataSinkL(*aSink)); |
|
594 |
|
595 if (error) |
|
596 { |
|
597 // Sink not accepted by plugin or we couldn't write handle info back to client, |
|
598 // so delete it and return error to client |
|
599 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
600 User::Leave(error); |
|
601 } |
|
602 } |
|
603 |
|
604 CMMFControllerExtendedData* CMMFController::GetExtendedDataL() |
|
605 { |
|
606 CMMFControllerExtendedData* data = NULL; |
|
607 |
|
608 // iMMFObjectContainer and CMMFControllerExtendedData must be constructed |
|
609 // in CMMFController constructor. Only 1 CMMFControllerExtendedData object can |
|
610 // be found in iMMFObjectContainer. |
|
611 const RPointerArray<CMMFObject>& objects = MMFObjectContainerL().MMFObjects(); |
|
612 for (TInt i = 0; i < objects.Count(); i++) |
|
613 { |
|
614 if (objects[i]->Handle().InterfaceId() == KUidMMFControllerExtendedDataHolder) |
|
615 { |
|
616 data = static_cast<CMMFControllerExtendedData*>(objects[i]); |
|
617 break; |
|
618 } |
|
619 } |
|
620 if (data == NULL) |
|
621 { |
|
622 // In this case, extended data has not been constructed and added into iMMFObjectContainer. |
|
623 // This is a situation where GetExtendedDataL is being indirectly called in the controller |
|
624 // initialization process (i.e. CMMFController::NewL() or constructor of licensee's controller). |
|
625 // Extended data should have a copy stored in Dll::Tls already at this point. |
|
626 const CMMFControllerExtendedData* dataCopy = static_cast<CMMFControllerExtendedData*>(Dll::Tls()); |
|
627 data = CreateExtendedDataL(dataCopy->ClientThreadId()); |
|
628 CleanupStack::PushL(data); |
|
629 User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*data)); |
|
630 CleanupStack::Pop(data); |
|
631 } |
|
632 return data; |
|
633 } |
|
634 |
|
635 CMMFControllerExtendedData* CMMFController::CreateExtendedDataL(TThreadId aClientTid) |
|
636 { |
|
637 // In secureDRMMode, SecureDRM server and user are running in |
|
638 // different processes. |
|
639 TProcessId clientProcessId; |
|
640 RThread clientThread; |
|
641 CleanupClosePushL(clientThread); |
|
642 User::LeaveIfError(clientThread.Open(aClientTid)); |
|
643 |
|
644 RProcess clientProcess; |
|
645 CleanupClosePushL(clientProcess); |
|
646 User::LeaveIfError(clientThread.Process(clientProcess)); |
|
647 clientProcessId = clientProcess.Id(); |
|
648 CleanupStack::PopAndDestroy(2, &clientThread); // clientProcess, clientThread |
|
649 |
|
650 RProcess thisProcess; |
|
651 TBool secureDrmMode = clientProcessId != thisProcess.Id(); |
|
652 thisProcess.Close(); |
|
653 |
|
654 CMMFControllerExtendedData* dataSet = new(ELeave) CMMFControllerExtendedData(); |
|
655 CleanupStack::PushL(dataSet); |
|
656 dataSet->SetClientThreadId(aClientTid); |
|
657 dataSet->SetSecureDrmMode(secureDrmMode); |
|
658 CleanupStack::Pop(dataSet); |
|
659 |
|
660 return dataSet; |
|
661 } |
|
662 |
|
663 |
|
664 EXPORT_C CMMFCustomCommandParserManager* CMMFCustomCommandParserManager::NewL() |
|
665 { |
|
666 return new(ELeave) CMMFCustomCommandParserManager; |
|
667 } |
|
668 |
|
669 CMMFCustomCommandParserManager::CMMFCustomCommandParserManager() |
|
670 { |
|
671 } |
|
672 |
|
673 EXPORT_C CMMFCustomCommandParserManager::~CMMFCustomCommandParserManager() |
|
674 { |
|
675 iParsers.ResetAndDestroy(); |
|
676 iParsers.Close(); |
|
677 } |
|
678 |
|
679 EXPORT_C TBool CMMFCustomCommandParserManager::HandleRequest(TMMFMessage& aMessage) |
|
680 { |
|
681 TBool handledRequest = EFalse; |
|
682 for (TInt i=0; i<iParsers.Count(); i++) |
|
683 { |
|
684 CMMFCustomCommandParserBase* c = iParsers[i]; |
|
685 if (c->InterfaceId() == aMessage.Destination().InterfaceId()) |
|
686 { |
|
687 c->HandleRequest(aMessage); |
|
688 handledRequest = ETrue; |
|
689 break; |
|
690 } |
|
691 } |
|
692 return handledRequest; |
|
693 } |
|
694 |
|
695 EXPORT_C void CMMFCustomCommandParserManager::AddCustomCommandParserL(CMMFCustomCommandParserBase& aParser) |
|
696 { |
|
697 User::LeaveIfError(iParsers.Append(&aParser)); |
|
698 } |
|
699 |
|
700 |
|
701 TBool CMMFController::DoAddFileHandleDataSourceL(TMMFMessage& aMessage) |
|
702 { |
|
703 RFile file; |
|
704 aMessage.AdoptFileHandleFromClientL(1,2, file); |
|
705 CleanupClosePushL(file); |
|
706 TMMFFileHandleConfig fileConfig; |
|
707 fileConfig().iFile = &file; |
|
708 // Create the source |
|
709 MDataSource* source = MDataSource::NewSourceL(KUidMmfFileSource, fileConfig); |
|
710 CleanupStack::PopAndDestroy(&file); |
|
711 CleanupDeletePushL(source); |
|
712 CMMFDataSourceHolder* holder = new(ELeave) CMMFDataSourceHolder(*source); |
|
713 CleanupStack::Pop(source);//source (since now owned by holder) |
|
714 |
|
715 CleanupStack::PushL(holder); |
|
716 // Append holder to array of MMFObjects |
|
717 User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); |
|
718 CleanupStack::Pop(holder);//holder |
|
719 |
|
720 // Write source handle info back to client |
|
721 TMMFMessageDestination handleInfo(holder->Handle()); |
|
722 TMMFMessageDestinationPckg handlePckg(handleInfo); |
|
723 TInt error = aMessage.WriteDataToClient(handlePckg); |
|
724 |
|
725 // Add source to plugin |
|
726 if (!error) |
|
727 TRAP(error, AddDataSourceL(*source)); |
|
728 |
|
729 if (error) |
|
730 { |
|
731 // Source not accepted by plugin or we couldn't write handle info back to client, |
|
732 // so delete it and return error to client |
|
733 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
734 User::Leave(error); |
|
735 } |
|
736 |
|
737 return ETrue; |
|
738 } |
|
739 |
|
740 |
|
741 TBool CMMFController::DoAddFileHandleDataSinkL(TMMFMessage& aMessage) |
|
742 { |
|
743 RFile file; |
|
744 aMessage.AdoptFileHandleFromClientL(1,2, file); |
|
745 CleanupClosePushL(file); |
|
746 TMMFFileHandleConfig fileConfig; |
|
747 fileConfig().iFile = &file; |
|
748 // Create the sink |
|
749 MDataSink* sink = MDataSink::NewSinkL(KUidMmfFileSink, fileConfig); |
|
750 CleanupStack::PopAndDestroy(&file); // close our handle to the file |
|
751 CleanupDeletePushL(sink); |
|
752 CMMFDataSinkHolder* holder = new(ELeave) CMMFDataSinkHolder(*sink); |
|
753 CleanupStack::Pop(sink);//sink (since now owned by holder) |
|
754 |
|
755 CleanupStack::PushL(holder); |
|
756 // Append sink to array |
|
757 User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); |
|
758 CleanupStack::Pop(holder);//holder |
|
759 |
|
760 |
|
761 // Write sink handle info back to client |
|
762 TMMFMessageDestination handleInfo(holder->Handle()); |
|
763 TMMFMessageDestinationPckg handlePckg(handleInfo); |
|
764 TInt error = aMessage.WriteDataToClient(handlePckg); |
|
765 |
|
766 // Add sink to plugin |
|
767 if (!error) |
|
768 TRAP(error, AddDataSinkL(*sink)); |
|
769 |
|
770 if (error) |
|
771 { |
|
772 // Sink not accepted by plugin or we couldn't write handle info back to client, |
|
773 // so delete it and return error to client |
|
774 MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); |
|
775 User::Leave(error); |
|
776 } |
|
777 |
|
778 return ETrue; |
|
779 } |
|
780 |
|
781 EXPORT_C TThreadId CMMFController::ClientThreadIdL() |
|
782 { |
|
783 return GetExtendedDataL()->ClientThreadId(); |
|
784 } |
|
785 |
|
786 EXPORT_C TBool CMMFController::IsSecureDrmModeL() |
|
787 { |
|
788 return GetExtendedDataL()->SecureDrmMode(); |
|
789 } |
|
790 |