sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Some of the examples below do not include fully comprehensive error checking. They are written this way to simplify the sl@0: // understanding of the basic steps involved. All errors should be handled appropriately in production code. sl@0: // Consumer API sl@0: // Supplier API sl@0: //
sl@0: // This example function takes the URI of a file and displays the plaintext version of that content on screen. sl@0: // If anything goes wrong, for instance the file does not exist or there are no valid rights sl@0: // that will allow the file to be displayed, the function will just leave. sl@0: // It's important to notice the call to ContentAccess::CData::ExecuteIntent(), this should always be called, even if you sl@0: // think it's unlikely you will open DRM content. sl@0: // class CContentViewer : public CBase sl@0: // public: sl@0: // static CContentViewer* NewL(); sl@0: // static CContentViewer* NewLC(); sl@0: // // Display given content. sl@0: // void DisplayContent(const TDesC& aUri, TRequestStatus& aStatus) sl@0: // TRAPD(err, DisplayContentL(aUri)); sl@0: // User::RequestComplete(aStatus, err); sl@0: // private: sl@0: // CContentViewer() : CBase() {} sl@0: // ~CContentViewer() {} sl@0: // void DisplayContentL(const TDesC& aUri) sl@0: // TInt size = 0; sl@0: // TInt i = 0; sl@0: // // Create a CContent object sl@0: // // CAF will figure out the appropriate agent sl@0: // CContent *content = CContent::NewLC(aUri); sl@0: // // Create a CData object to read the content sl@0: // // Tell the agent we are planning to display the content sl@0: // CData *data = content->OpenContentLC(EDisplay); sl@0: // // Don't need content object any more sl@0: // CleanupStack::PopAndDestroy(content); sl@0: // // get the size of the plaintext content sl@0: // data->DataSizeL(size); sl@0: // // Execute the intent, tell the agent that we plan to display the content sl@0: // // It is at this point that any stateful rights will be decremented sl@0: // data->ExecuteIntentL(EDisplay); sl@0: // // read and display the file until we reach the end of the file sl@0: // TBuf <128> buffer; sl@0: // while(i < size) sl@0: // // read from the file sl@0: // User::LeaveIfError(data->Read(buffer)); sl@0: // i += buffer.Length(); sl@0: // // display on screen sl@0: // printf(buffer); sl@0: // // finished with Data object sl@0: // CleanupStack::PopAndDestroy(data); sl@0: //
sl@0: // This example is the same as before except it attempts to obtain or wait for rights sl@0: // to become available rather than just leaving if access to the content is restricted. sl@0: // class CContentViewer : public CActive sl@0: // public: sl@0: // static CContentViewer* NewL(); sl@0: // static CContentViewer* NewLC(); sl@0: // // Display given content. sl@0: // void DisplayContent(const TDesC& aUri, TRequestStatus& aStatus) sl@0: // iUri = aUri; sl@0: // iClientStatus = &aStatus; sl@0: // iClientStatus = KRequestPending; sl@0: // iCurrentState = EOpenFile; sl@0: // // trigger our RunL sl@0: // iStatus = KRequestPending; sl@0: // SetActive(); sl@0: // User::RequestComplete(iStatus, KErrNone); sl@0: // void RunL() sl@0: // TInt err = iStatus.Int(); sl@0: // switch (iCurrentState) sl@0: // case EOpenFile: sl@0: // iContent = CContent::NewL(aUri); sl@0: // TRAP(err, iData = iContent->OpenContentL(EDisplay)); sl@0: // iCurrentState = EReadAndDisplay; // follow through... sl@0: // case EReadAndDisplay: sl@0: // if(err == KErrNone) sl@0: // TRAP(err, DisplayFile()); sl@0: // iCurrentState = EFinished; sl@0: // // tell client iStatus that we have finished sl@0: // User::RequestComplete(*iClientStatus, err); sl@0: // return; sl@0: // else if(err == KErrCANoRights) sl@0: // // we don't have rights so we need to wait for them sl@0: // iCurrentState = EWaitingForRights; sl@0: // // ask CAF to initiate download of rights sl@0: // iContent->RequestRights(iStatus); sl@0: // else if(err == KErrCAPendingRights) sl@0: // // waiting for rights to arrive, expected any minute now sl@0: // iCurrentState = EWaitingForRights; sl@0: // // ask CAF to notify us when they arrive sl@0: // iContent->NotifyStatusChange(ERightsAvailable , iStatus); sl@0: // // wait for CAF to complete our request sl@0: // iLastError = err; sl@0: // iStatus = KRequestPending; sl@0: // SetActive(); sl@0: // break; sl@0: // case EWaitingForRights: sl@0: // if(ret == KErrNone) sl@0: // // change the state to try and display content again sl@0: // iCurrentState = EReadAndDisplay; sl@0: // // trigger our RunL sl@0: // iLastError = err; sl@0: // iStatus = KRequestPending; sl@0: // SetActive(); sl@0: // User::RequestComplete(iStatus, KErrNone); sl@0: // else sl@0: // // couldn't get rights, tell parent active object we're finished sl@0: // User::RequestComplete(iClientStatus, err); sl@0: // return; sl@0: // break; sl@0: // protected: sl@0: // void DoCancel() sl@0: // if (iLastError == KErrCAPendingRights) sl@0: // iContent->CancelNotifyStatusChange(iStatus); sl@0: // else if (iLastError == KErrCANoRights) sl@0: // iContent->CancelRequestRights(iStatus); sl@0: // private: sl@0: // CContentViewer() : CActive(EPriorityStandard) sl@0: // CActiveScheduler::Add(this); sl@0: // ~CContentViewer() sl@0: // Cancel(); sl@0: // if (iData) delete iData; sl@0: // if (iContent) delete iContent; sl@0: // // Display the content, if any error occurs then leave sl@0: // void DisplayContentL(); sl@0: // TInt size = 0; sl@0: // TInt i = 0; sl@0: // TBuf <128> buffer; sl@0: // // Execute the intent, tell the agent that we plan to display the content sl@0: // // It is at this point that any stateful rights will be decremented sl@0: // iData->ExecuteIntentL(EDisplay); sl@0: // // get the size of the plaintext content sl@0: // iData->DataSizeL(size); sl@0: // // read and display the file until we reach the end of the file sl@0: // while(i < size) sl@0: // // read from the file sl@0: // User::LeaveIfError(iData->Read(buffer)); sl@0: // i += buffer.Length(); sl@0: // // Display on screen sl@0: // printf(buffer); sl@0: // private: sl@0: // enum TState sl@0: // EOpenFile = 0, sl@0: // EReadAndDisplay, sl@0: // EWaitingForRights, sl@0: // EFinished sl@0: // CContent* iContent; sl@0: // CData* iData; sl@0: // TDesC iUri; sl@0: // TState iCurrentState; sl@0: // TInt iLastError; sl@0: // TRequestStatus* iClientStatus; sl@0: //
sl@0: // Some servers may wish to prevent access to DRM content by untrusted clients, even if sl@0: // the server itself has DRM capability. sl@0: // To achieve this the server should use the ContentAccess::TIntent::EUnknown intent when sl@0: // accessing content. Content files that are not DRM protected will still work normally, but sl@0: // access to DRM protected content will be blocked. sl@0: // // Tell the agent we have no idea what the application plans to do sl@0: // CData *data = content->OpenContentL(EUnknown); sl@0: // // Execute the intent, tell the agent that we have no idea what the content will be used for sl@0: // data->ExecuteIntentL(EUnknown); sl@0: //
sl@0: // When reading from a particular content object within a file the application must supply sl@0: // the \c UniqueId of the object when calling ContentAccess::CContent::OpenContentL(). sl@0: // void DisplayTextFileL(const TDesC& aUri) sl@0: // TInt size = 0; sl@0: // TInt i = 0; sl@0: // TBuf <128> buffer; sl@0: // // Create a CContent object sl@0: // // CAF will figure out the appropriate agent sl@0: // CContent *content = CContent::NewLC(aUri); sl@0: // // Find the objects in the file with MIME type image/jpeg sl@0: // RStreamablePtrArray myArray; sl@0: // CleanupClosePushL(myArray); sl@0: // User::LeaveIfError(content->Search(myArray, _L("image/jpeg"), EFalse)); sl@0: // // Get the virtual path of the first image/jpeg we find sl@0: // TVirtualPathPtr picture = *myArray[0]; sl@0: // // Tell the agent to open the object with the given UniqueId sl@0: // CData *data = content->OpenContentLC(EDisplay, picture.UniqueId()); sl@0: // // Don't need content object or array any more sl@0: // CleanupStack::PopAndDestroy(2); // content, myArray sl@0: // // get the size of the plaintext content sl@0: // data->DataSizeL(size); sl@0: // // Execute the intent, tell the agent that we plan to display the content sl@0: // // It is at this point that any stateful rights will be decremented sl@0: // data->ExecuteIntentL(EDisplay); sl@0: // // read and display the file until we reach the end of the file sl@0: // while(i < size) sl@0: // // read from the file sl@0: // User::LeaveIfError(data->Read(buffer)); sl@0: // i += buffer.Length(); sl@0: // // display on screen sl@0: // printf(buffer); sl@0: // // finished with Data object sl@0: // CleanupStack::PopAndDestroy(data); sl@0: //
sl@0: // This example shows how a messaging application that has just received sl@0: // a message attachment from a mail server can offer the attachment sl@0: // to CAF for processing. The output files will be saved in C:\\files\\. sl@0: // void CMyApp::ReceiveMessageAttachment(const TDesC8& aContentType, const TDesC8& aMessageAttachment) sl@0: // // Create supplier object sl@0: // CSupplier* supplier = CSupplier::NewLC(); sl@0: // // Tell the agent where we would like the output files to be written sl@0: // supplier->SetOutputDirectoryL(_L("C:\\files")); sl@0: // // Check if CAF can import this attachment we just received sl@0: // if(supplier->IsImportSupported(aContentType)) sl@0: // ProcessAttachmentL(supplier, aContentType, aMessageAttachment); sl@0: // else sl@0: // // just save the message to a file in its current form sl@0: // RFile theFile; sl@0: // theFile.Open(iFs, "myFile"); sl@0: // theFile.Write(aMessageAttachment); sl@0: // theFile.Close(); sl@0: // // Add the file to the list of attachments sl@0: // AddAttachment("myFile"); sl@0: // void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8& aContentType, const TDesC8& aMessageAttachment) sl@0: // TInt err = KErrNone; sl@0: // TBuf <128> buf; sl@0: // // Create meta-data array sl@0: // CMetaDataArray* metaDataArray = new (ELeave) CMetaDataArray(); sl@0: // CleanupStack::PushL(metaDataArray); sl@0: // // Add any useful information we can think of.... sl@0: // // Obviously these would not be hardcoded this way in a real import sl@0: // metaDataArray->AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm")); sl@0: // metaDataArray->AddL(_L("Content Length"), _L("1201")); sl@0: // metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6")); sl@0: // // Create the import object sl@0: // CImportFile* import = aSupplier->ImportFileL(aContentType, *metaDataArray, _L("myfile")); sl@0: // CleanupStack::PushL(import); sl@0: // // import the attachment sl@0: // err = import->WriteData(aMessageText); sl@0: // // tell CAF (and hence the agent) it's now got the entire file sl@0: // if (err == KErrNone) sl@0: // err = import->WriteDataComplete(); sl@0: // if (err == KErrNone) sl@0: // // Look at the output of the import operation sl@0: // for(TInt i = 0; i < import->OutputFileCountL(); i++) sl@0: // // for this example only add content output files sl@0: // // (absorb any rights in the original attachment 'silently') sl@0: // if(import->OutputFilesL(i).OutputType == EContent) sl@0: // // Add file to list of attachments for this message sl@0: // AddAttachment(import->OutputFilesL(i).FileName()); sl@0: // // Error handling sl@0: // if (err != KErrNone) sl@0: // if (err == KErrNotReady) sl@0: // DisplayErrorMsg("Agent not ready for import"); sl@0: // else if (err == KErrCACorruptContent) sl@0: // DisplayErrorMsg("Content data is corrupt"); sl@0: // else sl@0: // DisplayErrorMsg("Unexpected error: %d", err); sl@0: // // Finished sl@0: // CleanupStack::PopAndDestroy(2); // metaDataArray, import sl@0: //
sl@0: // This example shows how a messaging application that has just received sl@0: // a message attachment from a mail server can offer the attachment sl@0: // to CAF for processing and store the file in its own private directory. sl@0: // void CMyApp::ReceiveMessageAttachment(const TDesC8& aContentType, const TDesC8& aMessageAttachment) sl@0: // // Create supplier object sl@0: // CSupplier* supplier = CSupplier::NewLC(); sl@0: // // Check if CAF can import this attachment we just received sl@0: // if(supplier->IsImportSupported(aContentType)) sl@0: // ProcessAttachmentL(supplier, aContentType, aMessageAttachment); sl@0: // else sl@0: // // just save the message to a file in its current form sl@0: // RFile theFile; sl@0: // theFile.Open(iFs, "myFile"); sl@0: // theFile.Write(aMessageAttachment); sl@0: // theFile.Close(); sl@0: // // Add the file to the list of attachments sl@0: // AddAttachment("myFile"); sl@0: // void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8& aContentType, const TDesC8& aMessageAttachment) sl@0: // TInt err = KErrNone; sl@0: // TBuf <128> buf; sl@0: // TBuf <4> fileExtension; sl@0: // _LIT(KOutputFileName, "\\private\\12345678\\outputfile."); sl@0: // TFileName fileName(KOutputFileExtension); sl@0: // RFile file; sl@0: // // Create meta-data array sl@0: // CMetaDataArray* metaDataArray = CMetaDataArray::NewLC(); sl@0: // // Add any useful information we can think of.... sl@0: // // Obviously these would not be hardcoded this way in a real import sl@0: // metaDataArray->AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm")); sl@0: // metaDataArray->AddL(_L("Content Length"), _L("1201")); sl@0: // metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6")); sl@0: // // Create the import object, no suggested file name implies the application will supply output files sl@0: // CImportFile* import = aSupplier->ImportFileL(aContentType, *metaDataArray); sl@0: // CleanupStack::PushL(import); sl@0: // // Start importing the attachment sl@0: // // (if the agent needs one or more output files, continue looping until sl@0: // // the agent finishes the previous) sl@0: // TInt err = import->WriteData(aMessageText); sl@0: // while(err == KErrCANewFileHandleRequired) sl@0: // import->GetSuggestedOutputFileExtension(fileExtension); sl@0: // filName.Append(fileExtension); sl@0: // User::LeaveIfError(file.Open(iFs, fileName)); sl@0: // err = import->ContinueWithNewOutputFile(file); sl@0: // file.Close(); sl@0: // if (err == KErrNone) sl@0: // // Complete the import process sl@0: // err = import->WriteDataComplete(); sl@0: // while(err == KErrCANewFileHandleRequired) sl@0: // import->GetSuggestedOutputFileExtension(fileExtension); sl@0: // filName.Append(fileExtension); sl@0: // User::LeaveIfError(file.Open(iFs, fileName)); sl@0: // err = import->ContinueWithNewOutputFile(file); sl@0: // file.Close(); sl@0: // if (err == KErrNone) sl@0: // // Look at the output of the import operation sl@0: // for(TInt i = 0; i < import->OutputFileCountL(); i++) sl@0: // // for this example only add content output files sl@0: // // (absorb any rights in the original attachment 'silently') sl@0: // if(import->OutputFilesL(i).OutputType == EContent) sl@0: // // Add file to list of attachments for this message sl@0: // AddAttachment(import->OutputFilesL(i).FileName()); sl@0: // // Error handling sl@0: // if (err != KErrNone) sl@0: // if (err == KErrNotReady) sl@0: // DisplayErrorMsg("Agent not ready for import"); sl@0: // else if (err == KErrCACorruptContent) sl@0: // DisplayErrorMsg("Content data is corrupt"); sl@0: // else sl@0: // DisplayErrorMsg("Unexpected error: %d", err); sl@0: // // Finshed sl@0: // CleanupStack::PopAndDestroy(2); // metaDataArray, import sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @page CAFExamples Example source code using CAF sl@0: - @ref ExampleRead1 sl@0: - @ref ExampleReadWithErrCheck sl@0: - @ref PlayingUnprotectedOnly sl@0: - @ref MultipleContentExample sl@0: - @ref ExampleSupplier1 sl@0: - @ref ExampleSupplier2 sl@0: @section ExampleRead1 Reading from a file, no error checking sl@0: @code sl@0: @endcode sl@0: @section ExampleReadWithErrCheck Reading from a file, with error checking sl@0: @code sl@0: @endcode sl@0: @section PlayingUnprotectedOnly Preventing access to DRM content sl@0: @code sl@0: @endcode sl@0: @section MultipleContentExample File containing several content objects sl@0: @code sl@0: @endcode sl@0: @section ExampleSupplier1 Importing a content file, agent provides output files sl@0: @code sl@0: @endcode sl@0: @section ExampleSupplier2 Importing a content file, application provides output files sl@0: @code sl@0: @endcode sl@0: */