Symbian3/PDK/Source/GUID-AC2903B2-0C3A-5104-B2A2-866DDAAAE2A9.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     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 xml:lang="en" id="GUID-AC2903B2-0C3A-5104-B2A2-866DDAAAE2A9"><title>Example Code</title><prolog><metadata><keywords/></metadata></prolog><conbody><p>The example code demonstrates how to implement the CAF functions. Some of these examples listed here do not include complete error checking. The examples are written this way to simplify the understanding of the basic steps involved. All errors must be handled appropriately in production code. </p> <section><title>Reading from a file without checking errors </title> <p>This example function takes the URI of a file and displays the plaintext version of that content on screen. If anything goes wrong, for instance the file does not exist or there are no valid rights that allows the file to be displayed, the function leaves. </p> <p>It is important to notice the call to <xref href="GUID-B54C8391-FE69-324C-AC0A-1E88C2555F00.dita#GUID-B54C8391-FE69-324C-AC0A-1E88C2555F00/GUID-3E5B2A86-A06B-3710-99C9-FA205E99088F"><apiname>ContentAccess::CData::ExecuteIntent()</apiname></xref>. This must always be called, even if you think it is unlikely to open DRM content. </p> <codeblock id="GUID-5BC1FDCA-0E8A-5118-AE09-19B9896C2C3E" xml:space="preserve">class CContentViewer : public CBase
       
    13         {
       
    14 public:
       
    15         static CContentViewer* NewL();
       
    16         static CContentViewer* NewLC();
       
    17         
       
    18         // Display given content.
       
    19         void DisplayContent(const TDesC&amp; aUri, TRequestStatus&amp; aStatus)
       
    20                 {
       
    21                 TRAPD(err, DisplayContentL(aUri));
       
    22                 User::RequestComplete(aStatus, err);
       
    23                 }
       
    24                 
       
    25 private:
       
    26         CContentViewer() : CBase() {}
       
    27         ~CContentViewer() {} 
       
    28 
       
    29         void DisplayContentL(const TDesC&amp; aUri)
       
    30                 {
       
    31                 TInt size = 0;
       
    32                 TInt I = 0;
       
    33         
       
    34                 // Create a CContent object
       
    35                 // CAF figures out the appropriate agent
       
    36                 CContent *content = CContent::NewLC(aUri);
       
    37         
       
    38                 // Create a CData object to read the content
       
    39                 // Tell the agent we are planning to display the content
       
    40                 CData *data = content-&gt;OpenContentLC(EDisplay);
       
    41         
       
    42                 // Don't need content object any more
       
    43                 CleanupStack::PopAndDestroy(content);
       
    44         
       
    45                 // get the size of the plaintext content
       
    46                 data-&gt;DataSizeL(size);
       
    47         
       
    48                 // Execute the intent, tell the agent that we plan to display the content
       
    49                 // It is at this point that any stateful rights is decremented
       
    50                 data-&gt;ExecuteIntentL(EDisplay);
       
    51         
       
    52                 // read and display the file until we reach the end of the file
       
    53                 TBuf &lt;128&gt; buffer;              
       
    54                 while(I &lt; size)
       
    55                         {
       
    56                         // read from the file
       
    57                         User::LeaveIfError(data-&gt;Read(buffer));
       
    58                         I += buffer.Length();
       
    59         
       
    60                         // display on screen
       
    61                         printf(buffer);
       
    62                         }
       
    63         
       
    64                 // finished with Data object
       
    65                 CleanupStack::PopAndDestroy(data);
       
    66                 }
       
    67         };
       
    68 
       
    69 </codeblock> </section> <section><title>Reading from a file, with error checking</title> <p>This example is the same as before except it attempts to obtain or wait for rights to become available rather than just leaving if access to the content is restricted. </p> <codeblock id="GUID-C197103B-57E1-506D-9E63-F37A8CAB31E7" xml:space="preserve">class CContentViewer : public CActive
       
    70         {
       
    71 public:
       
    72         static CContentViewer* NewL();
       
    73         static CContentViewer* NewLC();
       
    74         
       
    75         // Display given content.
       
    76         void DisplayContent(const TDesC&amp; aUri, TRequestStatus&amp; aStatus)
       
    77                 {
       
    78                 iUri = aUri;
       
    79                 iClientStatus = &amp;aStatus;
       
    80                 *iClientStatus = KRequestPending;
       
    81                 iCurrentState = EOpenFile;
       
    82                 // trigger our RunL
       
    83                 iStatus = KRequestPending;
       
    84                 SetActive();
       
    85                 User::RequestComplete(iStatus, KErrNone);
       
    86                 }
       
    87         
       
    88         void RunL()
       
    89                 {
       
    90                 TInt err = iStatus.Int();
       
    91                 
       
    92                 switch (iCurrentState)
       
    93                         {
       
    94                         case EOpenFile:
       
    95                                 iContent = CContent::NewL(aUri);
       
    96                                 TRAP(err, iData = iContent-&gt;OpenContentL(EDisplay));
       
    97                                 iCurrentState = EReadAndDisplay;        // follow through...
       
    98                         case EReadAndDisplay:
       
    99                                 if(err == KErrNone)
       
   100                                         {
       
   101                                         TRAP(err, DisplayFile());
       
   102                                         iCurrentState = EFinished;
       
   103                                         // tell client iStatus that we have finished
       
   104                                         User::RequestComplete(*iClientStatus, err);
       
   105                                         return;
       
   106                                         }       
       
   107                                 else if(err == KErrCANoRights)
       
   108                                         {
       
   109                                         // we don't have rights so we need to wait for them
       
   110                                         iCurrentState = EWaitingForRights;
       
   111                                         // ask CAF to initiate download of rights
       
   112                                         iContent-&gt;RequestRights(iStatus);
       
   113                                         }
       
   114                                 else if(err == KErrCAPendingRights)
       
   115                                         {
       
   116                                         // waiting for rights to arrive, expected any minute now
       
   117                                         iCurrentState = EWaitingForRights;
       
   118                                         // ask CAF to notify us when they arrive
       
   119                                         iContent-&gt;NotifyStatusChange(ERightsAvailable , iStatus);
       
   120                                         }
       
   121                                 // wait for CAF to complete our request 
       
   122                                 iLastError = err;
       
   123                                 iStatus = KRequestPending;
       
   124                                 SetActive();
       
   125                                 break;
       
   126                         case EWaitingForRights:
       
   127                                 if(ret == KErrNone)
       
   128                                         {
       
   129                                         // change the state to try and display content again
       
   130                                         iCurrentState = EReadAndDisplay;
       
   131                                         // trigger our RunL
       
   132                                         iLastError = err;
       
   133                                         iStatus = KRequestPending;
       
   134                                         SetActive();
       
   135                                         User::RequestComplete(iStatus, KErrNone);
       
   136                                         }
       
   137                                 else
       
   138                                         {
       
   139                                         // couldn't get rights, tell parent active object we're finished
       
   140                                         User::RequestComplete(iClientStatus, err);
       
   141                                         return;
       
   142                                         }
       
   143                                 break;
       
   144                         }
       
   145                 }
       
   146                 
       
   147 protected:              
       
   148         void DoCancel()
       
   149                 {
       
   150                 if (iLastError == KErrCAPendingRights)
       
   151                         iContent-&gt;CancelNotifyStatusChange(iStatus);
       
   152                 else if (iLastError == KErrCANoRights)
       
   153                         iContent-&gt;CancelRequestRights(iStatus);
       
   154                 }
       
   155 
       
   156 private:
       
   157         CContentViewer() : CActive(EPriorityStandard)
       
   158                 { 
       
   159                 CActiveScheduler::Add(this); 
       
   160                 }
       
   161         ~CContentViewer() 
       
   162                 { 
       
   163                 Cancel();
       
   164                 if (iData) delete iData; 
       
   165                 if (iContent) delete iContent;
       
   166                 }       
       
   167 
       
   168         // Display the content, if any error occurs then leave
       
   169         void DisplayContentL();
       
   170                 {
       
   171                 TInt size = 0;
       
   172                 TInt I = 0;
       
   173                 TBuf &lt;128&gt; buffer;
       
   174         
       
   175                 // Execute the intent, tell the agent that we plan to display the content
       
   176                 // It is at this point that any stateful rights is decremented
       
   177                 iData-&gt;ExecuteIntentL(EDisplay);
       
   178         
       
   179                 // get the size of the plaintext content
       
   180                 iData-&gt;DataSizeL(size);
       
   181         
       
   182                 // read and display the file until we reach the end of the file
       
   183                 while(I &lt; size)
       
   184                         {
       
   185                         // read from the file
       
   186                         User::LeaveIfError(iData-&gt;Read(buffer));
       
   187                         I += buffer.Length();
       
   188                 
       
   189                         // Display on screen
       
   190                         printf(buffer);
       
   191                         }
       
   192                 }
       
   193 
       
   194 private:
       
   195         enum TState
       
   196                 {
       
   197                 EOpenFile = 0,
       
   198                 EReadAndDisplay,
       
   199                 EWaitingForRights,
       
   200                 EFinished
       
   201                 };
       
   202 
       
   203         CContent*       iContent;
       
   204         CData*          iData;
       
   205         TDesC           iUri;
       
   206 
       
   207         TState                  iCurrentState;
       
   208         TInt                    iLastError;
       
   209         TRequestStatus*         iClientStatus;
       
   210         }; </codeblock> </section> <section><title>Preventing access to DRM content</title> <p>Some servers may wish to prevent access to DRM content by untrusted clients, even if the server itself has DRM capability. </p> <p>To achieve this, the server must use the <xref href="GUID-EC31A59B-B7BB-3064-B327-4FAE7E702E6C.dita#GUID-EC31A59B-B7BB-3064-B327-4FAE7E702E6C/GUID-828A8D23-ADF3-333E-B8F0-C62519D3A511"><apiname>ContentAccess::TIntent::EUnknown</apiname></xref> intent when accessing content. Content files that are not DRM protected still work normally, but access to DRM protected content is blocked. </p> <codeblock id="GUID-9A600CE9-BFEF-5474-9977-CBFAEA77979C" xml:space="preserve">// Tell the agent we have no idea what the application plans to do 
       
   211 CData *data = content-&gt;OpenContentL(EUnknown); 
       
   212 
       
   213 // Execute the intent, tell the agent that we have no idea what the content is used for 
       
   214 data-&gt;ExecuteIntentL(EUnknown);</codeblock> </section> <section><title>File containing several content objects</title> <p>When reading from a particular content object within a file, the application must supply the <codeph>UniqueId</codeph> of the object when calling <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-32BA0116-1D7F-31B1-B80E-32E1F55803C3"><apiname>ContentAccess::CContent::OpenContentL()</apiname></xref>. </p> <codeblock id="GUID-65AF3C9B-23DE-547B-BADA-553161E69564" xml:space="preserve">void DisplayTextFileL(const TDesC&amp; aUri)
       
   215         {
       
   216         TInt size = 0;
       
   217         TInt I = 0;
       
   218 
       
   219         TBuf &lt;128&gt; buffer;
       
   220 
       
   221         // Create a CContent object
       
   222         // CAF figures out the appropriate agent
       
   223         CContent *content = CContent::NewLC(aUri);
       
   224 
       
   225         // Find the objects in the file with MIME type image/jpeg
       
   226         RStreamablePtrArray&lt;CEmbeddedObject&gt; myArray;
       
   227         CleanupClosePushL(myArray);
       
   228 
       
   229         User::LeaveIfError(content-&gt;Search(myArray, _L("image/jpeg"), EFalse));
       
   230 
       
   231         // Get the virtual path of the first image/jpeg we find
       
   232         TVirtualPathPtr picture = *myArray[0];
       
   233 
       
   234         // Tell the agent to open the object with the given UniqueId
       
   235         CData *data = content-&gt;OpenContentLC(EDisplay, picture.UniqueId());
       
   236         
       
   237         // Don't need content object or array any more
       
   238         CleanupStack::PopAndDestroy(2); // content, myArray
       
   239 
       
   240         // get the size of the plaintext content
       
   241         data-&gt;DataSizeL(size);
       
   242 
       
   243         // Execute the intent, tell the agent that we plan to display the content
       
   244         // It is at this point that any stateful rights is decremented
       
   245         data-&gt;ExecuteIntentL(EDisplay);
       
   246 
       
   247         // read and display the file until we reach the end of the file
       
   248         while(I &lt; size)
       
   249                 {
       
   250                 // read from the file
       
   251                 User::LeaveIfError(data-&gt;Read(buffer));
       
   252                 I += buffer.Length();
       
   253 
       
   254                 // display on screen
       
   255                 printf(buffer);
       
   256                 }
       
   257 
       
   258         // finished with Data object
       
   259         CleanupStack::PopAndDestroy(data);
       
   260         }
       
   261 
       
   262 </codeblock> </section> <section><title>Importing a content file, agent provides output files</title> <p>This example shows how a messaging application that has just received a message attachment from a mail server can offer the attachment to CAF for processing. The output files is saved in <filepath>C:\files\</filepath>. </p> <codeblock id="GUID-EA47147D-FF97-5C4B-A75F-1E86CFB5E210" xml:space="preserve">void CMyApp::ReceiveMessageAttachment(const TDesC8&amp; aContentType, const TDesC8&amp; aMessageAttachment)
       
   263         {
       
   264         // Create supplier object
       
   265         CSupplier* supplier = CSupplier::NewLC();
       
   266 
       
   267         // Tell the agent where we would like the output files to be written
       
   268         supplier-&gt;SetOutputDirectoryL(_L("C:\\files"));
       
   269 
       
   270         // Check if CAF can import this attachment we just received
       
   271         if(supplier-&gt;IsImportSupported(aContentType))
       
   272                 {
       
   273                 ProcessAttachmentL(supplier, aContentType, aMessageAttachment); 
       
   274                 }
       
   275         else
       
   276                 {
       
   277                 // just save the message to a file in its current form
       
   278                 RFile theFile;
       
   279                 theFile.Open(iFs, "myFile");
       
   280                 theFile.Write(aMessageAttachment);
       
   281                 theFile.Close();
       
   282                 
       
   283                 // Add the file to the list of attachments
       
   284                 AddAttachment("myFile");
       
   285                 }
       
   286         }
       
   287 
       
   288 
       
   289 void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8&amp; aContentType, const TDesC8&amp; aMessageAttachment)
       
   290         {
       
   291         TInt err = KErrNone;
       
   292         TBuf &lt;128&gt; buf;
       
   293 
       
   294         // Create meta-data array
       
   295         CMetaDataArray* metaDataArray = new (ELeave) CMetaDataArray();
       
   296         CleanupStack::PushL(metaDataArray);
       
   297 
       
   298         // Add any useful information we can think of....
       
   299         // Obviously these would not be hardcoded this way in a real import
       
   300         metaDataArray-&gt;AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm"));
       
   301         metaDataArray-&gt;AddL(_L("Content Length"), _L("1201"));
       
   302         metaDataArray-&gt;AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6"));
       
   303 
       
   304         // Create the import object
       
   305         CImportFile* import = aSupplier-&gt;ImportFileL(aContentType, *metaDataArray, _L("myfile"));
       
   306         CleanupStack::PushL(import);
       
   307 
       
   308         // import the attachment
       
   309         err = import-&gt;WriteData(aMessageText);
       
   310 
       
   311         // tell CAF (and hence the agent) it's now got the entire file
       
   312         if (err == KErrNone)
       
   313                 {
       
   314                 err = import-&gt;WriteDataComplete();
       
   315                 if (err == KErrNone)
       
   316                         {
       
   317                         // Look at the output of the import operation
       
   318                         for(TInt I = 0; I &lt; import-&gt;OutputFileCountL(); I++)
       
   319                                 {
       
   320                                 // for this example only add content output files
       
   321                                 // (absorb any rights in the original attachment 'silently')
       
   322                                 if(import-&gt;OutputFilesL(I).OutputType == EContent)
       
   323                                         {
       
   324                                         // Add file to list of attachments for this message
       
   325                                         AddAttachment(import-&gt;OutputFilesL(I).FileName());
       
   326                                         }               
       
   327                                 }
       
   328                         }
       
   329                 }
       
   330 
       
   331         // Error handling
       
   332         if (err != KErrNone)
       
   333                 {
       
   334                 if (err == KErrNotReady)        
       
   335                         {
       
   336                         DisplayErrorMsg("Agent not ready for import");
       
   337                         }
       
   338                 else if (err == KErrCACorruptContent)
       
   339                         {
       
   340                         DisplayErrorMsg("Content data is corrupt");
       
   341                         }
       
   342                 else
       
   343                         {       
       
   344                         DisplayErrorMsg("Unexpected error: %d", err);
       
   345                         }
       
   346                 }
       
   347 
       
   348         // Finished
       
   349         CleanupStack::PopAndDestroy(2);         // metaDataArray, import
       
   350         }</codeblock> </section> <section><title>Importing a content file (application provides output files)</title> <p>This example shows how a messaging application that has just received a message attachment from a mail server can offer the attachment to CAF for processing and store the file in its own private directory. </p> <codeblock id="GUID-D7E16FC9-B524-5C09-B575-3A09B87004B9" xml:space="preserve">void CMyApp::ReceiveMessageAttachment(const TDesC8&amp; aContentType, const TDesC8&amp; aMessageAttachment)
       
   351         {
       
   352         // Create supplier object
       
   353         CSupplier* supplier = CSupplier::NewLC();
       
   354 
       
   355         // Check if CAF can import this attachment we just received
       
   356         if(supplier-&gt;IsImportSupported(aContentType))
       
   357                 {
       
   358                 ProcessAttachmentL(supplier, aContentType, aMessageAttachment); 
       
   359                 }
       
   360         else
       
   361                 {
       
   362                 // just save the message to a file in its current form
       
   363                 RFile theFile;
       
   364                 theFile.Open(iFs, "myFile");
       
   365                 theFile.Write(aMessageAttachment);
       
   366                 theFile.Close();
       
   367                 
       
   368                 // Add the file to the list of attachments
       
   369                 AddAttachment("myFile");
       
   370                 }
       
   371         }
       
   372 
       
   373 
       
   374 void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8&amp; aContentType, const TDesC8&amp; aMessageAttachment)
       
   375         {
       
   376         TInt err = KErrNone;
       
   377         TBuf &lt;128&gt; buf;
       
   378         TBuf &lt;4&gt; fileExtension;
       
   379 
       
   380         _LIT(KOutputFileName, "\\private\\12345678\\outputfile.");
       
   381         TFileName fileName(KOutputFileExtension);
       
   382 
       
   383         RFile file;
       
   384         
       
   385         // Create meta-data array
       
   386         CMetaDataArray* metaDataArray = CMetaDataArray::NewLC();
       
   387 
       
   388         // Add any useful information we can think of....
       
   389         // Obviously these would not be hardcoded this way in a real import
       
   390         metaDataArray-&gt;AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm"));
       
   391         metaDataArray-&gt;AddL(_L("Content Length"), _L("1201"));
       
   392         metaDataArray-&gt;AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6"));
       
   393 
       
   394         // Create the import object, no suggested file name implies the application supplies output files
       
   395         CImportFile* import = aSupplier-&gt;ImportFileL(aContentType, *metaDataArray);
       
   396         CleanupStack::PushL(import);
       
   397 
       
   398         // Start importing the attachment
       
   399         // (if the agent needs one or more output files, continue looping until 
       
   400         // the agent finishes the previous)
       
   401         TInt err = import-&gt;WriteData(aMessageText);
       
   402         while(err == KErrCANewFileHandleRequired)
       
   403                 {
       
   404                 import-&gt;GetSuggestedOutputFileExtension(fileExtension);
       
   405                 filName.Append(fileExtension);
       
   406 
       
   407                 User::LeaveIfError(file.Open(iFs, fileName));
       
   408                 err = import-&gt;ContinueWithNewOutputFile(file);
       
   409                 file.Close();
       
   410                 }
       
   411         
       
   412         if (err == KErrNone)
       
   413                 {
       
   414                 // Complete the import process
       
   415                 err = import-&gt;WriteDataComplete();
       
   416                 while(err == KErrCANewFileHandleRequired)
       
   417                         {
       
   418                         import-&gt;GetSuggestedOutputFileExtension(fileExtension);
       
   419                         filName.Append(fileExtension);
       
   420         
       
   421                         User::LeaveIfError(file.Open(iFs, fileName));
       
   422                         err = import-&gt;ContinueWithNewOutputFile(file);
       
   423                         file.Close();
       
   424                         }
       
   425                 
       
   426                 if (err == KErrNone)
       
   427                         {
       
   428                         // Look at the output of the import operation
       
   429                         for(TInt I = 0; I &lt; import-&gt;OutputFileCountL(); I++)
       
   430                                 {
       
   431                                 // for this example only add content output files
       
   432                                 // (absorb any rights in the original attachment 'silently')
       
   433                                 if(import-&gt;OutputFilesL(I).OutputType == EContent)
       
   434                                         {
       
   435                                         // Add file to list of attachments for this message
       
   436                                         AddAttachment(import-&gt;OutputFilesL(I).FileName());
       
   437                                         }               
       
   438                                 }
       
   439                         }
       
   440                 }
       
   441                 
       
   442         // Error handling
       
   443         if (err != KErrNone)
       
   444                 {
       
   445                 if (err == KErrNotReady)        
       
   446                         {
       
   447                         DisplayErrorMsg("Agent not ready for import");
       
   448                         }
       
   449                 else if (err == KErrCACorruptContent)
       
   450                         {
       
   451                         DisplayErrorMsg("Content data is corrupt");
       
   452                         }
       
   453                 else
       
   454                         {       
       
   455                         DisplayErrorMsg("Unexpected error: %d", err);
       
   456                         }
       
   457                 }
       
   458 
       
   459         // Finshed
       
   460         CleanupStack::PopAndDestroy(2);         // metaDataArray, import
       
   461         }</codeblock> </section> </conbody></concept>