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: */