Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 16 Jul 2010 17:23:46 +0100
changeset 12 80ef3a206772
parent 9 59758314f811
child 14 578be2adaf3e
permissions -rw-r--r--
Week 28 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 1897, Bug 344, Bug 2681, Bug 463, Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C" xml:lang="en"><title>Handling
DRM Content</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>Content Access Framework (CAF) provides services that enable agents to
publish content in a generic manner that is easy for applications to use.
Applications use the Consumer API to render a content and multimedia plug-ins. </p>
<p> <b>Note:</b> Rendering is a process of reading data from a file, transforming
it, then playing or displaying it on the device. </p>
<p><b>Access to content within archive files </b> </p>
<p>An archive file contains content objects and other containers within the
file. Each container within the file may contain more content objects or further
containers. Common examples of archive files are zip and tar files. </p>
<p>CAF allows applications to open archive files and read content from inside
them. The content objects and containers inside the file can be traversed
using the <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-FC40011B-32D3-328B-BB59-35BEF46A215A"><apiname>ContentAccess::CContent</apiname></xref> class. The class allows
applications to use the content within these container files without needing
to understand any specifics of the compression or storage mechanism used by
the archive. </p>
<section><title>Required background</title> <p>Before you start, you must
understand: </p> <ul>
<li id="GUID-099EC8EB-0A45-5FBF-9F55-B38D9C0AFCA8"><p><xref href="GUID-84B6389A-55CC-53EB-8725-65F753FD7217.dita"> Content
Access Framework for DRM</xref>  </p> </li>
<li id="GUID-16D006BB-3D7E-5439-BFFC-727EFF82D40E"><p><xref href="GUID-B5CC77D2-5871-51D8-B359-77EFC081B423.dita">Files
Containing Multiple Content Objects</xref>  </p> </li>
<li id="GUID-7029E2F7-A26A-5EC7-A435-0984C2CEE717"><p><xref href="GUID-B6912FE7-4C2A-5FC7-BDA8-702CA2C0214A.dita">Content
Object Attributes</xref>  </p> </li>
</ul> </section>
<section><title>Introduction</title> <p>Content Access Framework also allows
applications to open archive files and read content from inside them. The
content objects and containers inside the file can be traversed using the <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-FC40011B-32D3-328B-BB59-35BEF46A215A"><apiname>ContentAccess::CContent</apiname></xref> class.
This class allows applications to use the content within the container files
without needing to understand any specifics of the compression or storage
mechanism used by the archive. See <xref href="GUID-B5CC77D2-5871-51D8-B359-77EFC081B423.dita">Files
Containing Multiple Content Objects</xref> for more information. </p> <p>The
following diagram is an example of a content file. The same diagram is used
in the procedure to illustrate the implementation of Consumer API. </p> <fig id="GUID-BA86F65C-C34B-57C3-8FD5-A76C61EDF035">
<title>              Example content file            </title>
<image href="GUID-1467745D-7C3F-52EC-8C1E-7E2F505B7313_d0e588963_href.png" placement="inline"/>
</fig> </section>
<section><title>Procedure</title> <ol id="GUID-FE716629-86BE-513F-82F5-89107FB41F0E">
<li id="GUID-BD7166E0-7D9C-5F55-9DF3-1DE17AEBB80B"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-09F7434B-318B-5084-8E8B-54FA0ED48031">Create a content object</xref>. </p> </li>
<li id="GUID-2BADD3D3-D167-5212-942C-3A3CF4B7D25F"><p>Perform one or more
of the following tasks as per your requirement: </p> <ul>
<li id="GUID-8DFAF3E7-DC67-51E2-B609-85975BD6A564"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-26189931-0BE0-5BB7-98F1-9B7DF08C6C8F">List objects within a container</xref>. </p> </li>
<li id="GUID-74B9014B-EFCA-5BFA-8E15-286E837D832C"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-03355CA5-D049-5625-9187-2E91FFAF703A">Open a container</xref>. </p> </li>
<li id="GUID-ACC262EF-BBD6-5811-9EE3-A346FE600694"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-71C5AA3E-9C4B-5F77-B6D8-D09E00593EB8">Open the metadata specific to an agent</xref>. </p> </li>
<li id="GUID-34F3E3F3-816A-5B92-8772-05AD72910F56"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-5B42E479-D3F1-5B2A-8B6F-4841E49E4B3D">Display content object information</xref>. </p> </li>
<li id="GUID-5EC62609-8B8E-549A-806F-628C64FBE81B"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-20F9B6AC-F2B1-5E8E-93F2-8AE4AD0ED1F6">Retrieve the attributes of a content</xref>. </p> </li>
<li id="GUID-C5F1A5F7-D83B-5FD1-814C-4B0E9416C815"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-8D6C9025-7409-5019-88B2-A99A8E020443">Search for a MIME type within a file</xref>. </p> </li>
<li id="GUID-12C912EE-4195-5B3C-82C6-007E76629156"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-447A73D2-AF49-598E-865E-C2CEF1958C14">Read data from a content object</xref>. </p> </li>
<li id="GUID-A9FB0738-754E-5879-A2F5-E88C5F4C7751"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-AAFE84D9-01AF-5F27-9BC2-064A565F3D53">Handle data corruption</xref>. </p> </li>
<li id="GUID-E57145C0-DF25-5F32-9368-D86627E97B05"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-15A1A9B3-BB5D-5677-BFE9-47EABD4064BF">Handle errors</xref>. </p> </li>
<li id="GUID-935D7FB6-15EB-5DFB-89A0-58C0C29E736D"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-6A50AE44-E618-5D99-B5D8-7BBA8FE7948A">Handle rights for DRM content</xref>. </p> </li>
<li id="GUID-BEA5163A-5A5E-510B-AD36-313CC820DDBD"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-635EE5EF-469D-5FD3-9400-25DF95FD2E96">Get content object notifications</xref>. </p> </li>
<li id="GUID-2828C1A0-8E91-5B46-88FD-09CF0C36F40B"><p><xref href="GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita#GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C/GUID-DDAE0B57-B296-58E8-8220-AE5AA9BF7B8D">Close a container</xref>. </p> </li>
</ul> </li>
</ol> <p id="GUID-09F7434B-318B-5084-8E8B-54FA0ED48031"><b>Create a CContent
object</b> </p> <p>The <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-FC40011B-32D3-328B-BB59-35BEF46A215A"><apiname>ContentAccess::CContent</apiname></xref> object encapsulates
a single file. It allows an application to look at the structure of the objects
within the file and the attributes of those objects. </p> <p>There are two
ways to create a <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> object. The application can specify
the URI of the content or it can supply an open file handle, see <xref href="GUID-B5CC77D2-5871-51D8-B359-77EFC081B423.dita#GUID-B5CC77D2-5871-51D8-B359-77EFC081B423/GUID-28BE6074-E800-5320-89DD-D047F5C0FD86">Objects used to identify a content object within a file</xref>. </p> <codeblock id="GUID-AAF09718-0FF4-544F-B5B1-3202C58ABC95" xml:space="preserve">// Create a CContent with a URI 
CContent *content = CContent::NewL(uri); 

// Create a CContent with an existing file handle
CContent *content = CContent::NewL(aFs, aFile);</codeblock> <p>Upon creation, <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> selects
the agent that handles the file. </p> <p id="GUID-26189931-0BE0-5BB7-98F1-9B7DF08C6C8F"><b>List
objects within a container</b> </p> <p> <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-FC40011B-32D3-328B-BB59-35BEF46A215A"><apiname>ContentAccess::CContent</apiname></xref> acts
like a cursor, only able to list the contents of one container object at any
one time. When <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> is first opened, it views the top-level
container within the file. The top level container is actually the file itself.
This top level container concept applies to all files, regardless of how many
content or container objects are inside. </p> <p>Even a content file such
as a jpeg image is a container, it's just that the file only has the <codeph>"DEFAULT"</codeph> object
embedded inside. </p> <p>So, when the example file shown earlier is opened,
the following objects can be seen by the <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref>: </p> <fig id="GUID-EC064DCF-FC5D-59AC-BF5F-378A57808A47">
<image href="GUID-518FC822-AF10-57E8-990E-BB03C2D6ACBE_d0e589136_href.png" placement="inline"/>
</fig> <p>In this top level container, there is only one embedded content
object visible (the <filepath>.jpg</filepath> file) and two embedded container
objects. </p> <codeblock id="GUID-87F01EE6-EDEC-584B-844C-1DDB939FB5B3" xml:space="preserve">// Create an array to store the results of CContent::GetEmbeddedObjectsL() 
RStreamablePtrArray&lt;CEmbeddedObject&gt; myArray; 
CleanupClosePushL(myArray); 
    
// Get the embedded content objects in the current container 
content-&gt;GetEmbeddedObjectsL(myArray, EContentObject); 

i = myArray.Count(); // One content object 

// clear the contents of the array 
myArray.ResetAndDestroy(); 
    
// Get the number of container objects in the current container
content-&gt;GetEmbeddedObjectsL(myArray, EContainerObject); 

i = myArray.Count(); // Two container objects 
                    
// clear the contents of the array 
myArray-&gt;ResetAndDestroy();</codeblock> <p id="GUID-03355CA5-D049-5625-9187-2E91FFAF703A"><b>Open
a container</b> </p> <p>To investigate the objects inside a container, <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> must
first open the container. This changes <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref>'s focus
from the current container to the container specified in the <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-BB793B8F-1A01-3169-99E6-4630E9B5581C"><apiname>ContentAccess::CContent::OpenContainer()</apiname></xref> function. </p> <p><i>Open
container 1 from the top level of the file</i> </p> <codeblock id="GUID-7239CC22-292D-54BD-A50B-76413A887AD7" xml:space="preserve">// Get the container objects in the top level of the file 
content-&gt;GetEmbeddedObjects(myArray, EContainerObject); 

// Find the Unique Id of the first container 
TPtrC UniqueId = myArray[0]-&gt;UniqueId() 

// Open the first container 
content-&gt;OpenContainer(UniqueId);</codeblock> <p>Now <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> can
see the contents of Container 1: </p> <fig id="GUID-2A67C29A-FBF3-553E-B653-462F5128B2F4">
<image href="GUID-DC7E3634-9762-542F-BDAE-AC1F2D03F55D_d0e589185_href.png" placement="inline"/>
</fig> <p>At this point, listing the objects that <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> can
see gives six MP3 files and one container object. </p> <codeblock id="GUID-F1A7C149-9AB1-5DD2-BE20-280431DBAF40" xml:space="preserve">// Get the embedded content objects in the current container 
content-&gt;GetEmbeddedObjectsL(myArray, EContentObject); 
                 
i = myArray.Count(); // Six content objects
myArray.ResetAndDestroy(); 
                    
// Get the number of container objects in the current container 
content-&gt;GetEmbeddedObjectsL(myArray, EContainerObject);
                          
i = myArray.Count(); // One container object 
myArray.ResetAndDestroy();</codeblock> <p> <b> Note: </b> The same process
can be followed again to see the contents of Container 1.1. </p> <p id="GUID-71C5AA3E-9C4B-5F77-B6D8-D09E00593EB8"><b>Open
the metadata specific to an agent</b> </p> <p>Some agents may expose metadata
so they can be read using a <xref href="GUID-136D0282-4C73-33E9-B9D4-9CE92A33BF75.dita"><apiname>CData</apiname></xref> object. The format of
these meta-data objects is not specified by the Content Access Framework but
can be useful for applications familiar with the agent to read meta data this
way. </p> <p> <codeph>CData</codeph> objects for agent specific metadata can
be opened in the same way content objects are opened, using the <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> function. </p> <codeblock id="GUID-62EB232A-E9D6-5151-A69B-87CA26E97A9D" xml:space="preserve">// Create an array to store the embedded objects 
...

// Get the embedded "Agent Specific" objects in the current container
content-&gt;GetEmbeddedObjectsL(myArray, EAgentSpecificObject); 

// Get the unique Id of the first meta-data object 
TPtrC uniqueId = myArray[0]-&gt;UniqueId();

// create a CData object to read the meta data 
CData *myMetaData = content-&gt;OpenContent(EPeek, uniqueId);</codeblock> <p id="GUID-5B42E479-D3F1-5B2A-8B6F-4841E49E4B3D"><b>Display content object information</b> </p> <p>The <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita#GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A/GUID-79E768C6-D63E-303F-943C-022F5A04AB08"><apiname>CContent::DisplayInfoL()</apiname></xref> function
allows the application to display file information, such as last modification
date and DRM rights information. </p> <codeblock id="GUID-62A01A68-2479-515C-B74D-C48721870F1D" xml:space="preserve">...
content-&gt;DisplayInfoL(TDisplayInfo  aInfo);
...
</codeblock> <p id="GUID-20F9B6AC-F2B1-5E8E-93F2-8AE4AD0ED1F6"><b>Retrieve
the attributes of a content</b> </p> <p>Content and container objects have
properties or attributes associated with it. Applications can retrieve single
or mulitple attributes using the <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-4FA0F8A6-7F9A-3AE6-BDEE-B3C8A53B0207"><apiname>ContentAccess::TAttributeCAF</apiname></xref> enumeration
and the <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-BC242813-E0F0-3DFE-AF97-6BE808D570DE"><apiname>ContentAccess::TStringAttribute</apiname></xref> enumeration. See <xref href="GUID-B6912FE7-4C2A-5FC7-BDA8-702CA2C0214A.dita">Content Object Attributes</xref> for
details on implementing different methods of retrieving attributes. </p> <p>The
following example finds the author attribute of a content object. </p> <codeblock id="GUID-5FB7E26E-E8CF-5A10-8B22-06FA45A69721" xml:space="preserve">// define a buffer to store the attribute value string 
TBuf &lt;100&gt; buf; 
    
// retrieve the attribute 
err = content-&gt;GetAttribute(EAuthor, buf, uniqueId); 

// Display the author's name on screen 
DisplayAuthor(buf);
</codeblock> <p id="GUID-8D6C9025-7409-5019-88B2-A99A8E020443"><b>Search for
a MIME type within a file</b> </p> <p>If an application wants to find all
the content with a particular MIME type within a file, it must use <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-FA4BB868-3297-39F0-BAB8-C4BF4F5A2B60"><apiname>ContentAccess::CContent::Search()</apiname></xref>.
This function produces a list of all content objects with the specified MIME
type that are stored under the current container. </p> <codeblock id="GUID-BD3FEDFD-DA3E-5491-BF97-60CFC9252935" xml:space="preserve">// Create an array for storing the result of the search 
RStreamablePtrArray&lt;CEmbeddedObject&gt; myArray; 

// Find how many MP3 files are in Container 1 
TInt numMp3 = content-&gt;Search(myArray, _L("mpeg/audio"), EFalse);</codeblock> <p id="GUID-447A73D2-AF49-598E-865E-C2CEF1958C14"><b>Read data from a content
object</b> </p> <p>The functions described earlier can be used to locate a
particular content object within a file. <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> can
be used to read the content object. The <codeph>UniqueId</codeph> parameter
can be used to identify a particular object within the file. </p> <p>The call
to <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> leaves if the
intent is not permitted. This could occur if the file is DRM-protected but
no rights are present. </p> <p>If the file is DRM protected and the call to <xref href="GUID-63702251-43C2-3A2C-B884-A865BB539B5C.dita"><apiname>OpenContentL()</apiname></xref> succeeds,
the rights are not consumed at this point. CAF just checks that it is possible
to use the content. </p> <codeblock id="GUID-DCA8F01C-9657-5F54-881E-0A297DD652AC" xml:space="preserve">// Open the content object specified by uniqueId with the EPlay intent 
CData* data = content-&gt;OpenContentL(EPlay, uniqueId);</codeblock> <p>If the
application already knows the URI and unique ID of the content object it wants
to read from, it can create a <codeph>CData</codeph> object directly. </p> <codeblock id="GUID-09916FE1-A7A6-5012-8057-ACC0BFB49EDC" xml:space="preserve">CData* data = CData::NewL(TVirtualPathPtr(uri, uniqueId), EPlay, EContentShareReadOnly);</codeblock> <p>Once the <codeph>CData</codeph> object has been constructed, it allows
the content object to be used as if it were a standalone unprotected file.
The client must call <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> when
the rights must be consumed. If the file is not DRM-protected, the call is
ignored by the agent handling the file. </p> <codeblock id="GUID-81167DB6-CD1B-5F19-88D2-ED6D5C66B5AA" xml:space="preserve">TBuf8 &lt;256&gt; buf; 
data-&gt;ExecuteIntent(EPlay); 
data-&gt;Seek(ESEEK_START,SomePosition); 
data-&gt;Read(buf);</codeblock> <p>There are several overloaded versions of the <xref href="GUID-B54C8391-FE69-324C-AC0A-1E88C2555F00.dita#GUID-B54C8391-FE69-324C-AC0A-1E88C2555F00/GUID-B6146300-5578-39D2-B7E2-19309B76A7F6"><apiname>ContentAccess::CData::Read()</apiname></xref> function.
Only one is illustrated above for example purposes. </p> <p id="GUID-AAFE84D9-01AF-5F27-9BC2-064A565F3D53"><b>Handle
data corruption</b> </p> <p>When consuming content it is possible that the
content data and rights data can be corrupted. This may be due to various
reasons including file or disk corruption, transmission errors and so on. </p> <p>If
an agent detects corruption in a content object or in a rights object, it
ends the current DRM operation. The <codeph>KErrCACorruptContent</codeph>, <codeph>KErrCACorruptRights</codeph> or <codeph>KErrCorrupt</codeph> error
code is sent to clients, depending on the type of corruption detected and
how the client chooses to handle it. </p> <p> <b>Note:</b> It is recommended
that clients be designed to handle such an error if received, as it can usually
be considered a fatal error. </p> <codeblock id="GUID-24C1BC9E-786E-5C1F-AA27-839B3DC9369F" xml:space="preserve">// Create a CData object to read the content
...

TRAP(err, data = content-&gt;OpenContentLC(EDisplay));

if (err != KErrNone)
        {
        if (err == KErrCACorruptRights)
                {
                //Agent may have performed some error handling. 
                //Client may need to perform some client specific operations(e.g. cleanup).
                }
        else if (err == KErrCorrupt)
                {
                DisplayErrorMsg('Unable to decode rights because it is corrupt!');
                }
        else if (err == ...)
        ...
        }       
...
</codeblock> <p id="GUID-15A1A9B3-BB5D-5677-BFE9-47EABD4064BF"><b>Handle errors</b> </p> <p>Agents
display the errors on screen when they occur. Once the error has been acknowledged
by the user, the agent returns the error code to the client application. If
a client application does not want errors displayed on screen, it can request
to disable the agent UI using the <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita#GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A/GUID-4F452F1F-FFDA-34F4-9625-0A047CF44DE1"><apiname>CContent::SetProperty()</apiname></xref> function. </p> <codeblock id="GUID-20598B16-CC87-5BE1-8B7D-CF612A2150FB" xml:space="preserve">// Disable UI
content-&gt;SetProperty(EAgentPropertyAgentUI , 0);
</codeblock> <p>Some agents may present confirmation dialogs to the user before
allowing them to perform certain operations. For example, when a user inadvertently
tries to delete a DRM-protected file. The agent can present a dialog asking
"are you sure?". The agent can then return the outcome of the delete to the
application, that is <codeph>KErrCancel</codeph>, if the user presses cancel.
The <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita#GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A/GUID-4F452F1F-FFDA-34F4-9625-0A047CF44DE1"><apiname>CContent::SetProperty()</apiname></xref> function can also be used to
disable the confirmation dialogs. </p> <p id="GUID-6A50AE44-E618-5D99-B5D8-7BBA8FE7948A"><b>Handle
rights for DRM content</b> </p> <p>There are two functions available that
give the application some control over the rights: </p> <p><i>Request rights</i> </p> <p> <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-BF3DA6BD-A779-3BD8-B668-DB8E900F9053"><apiname> ContentAccess::CContent::RequestRights()</apiname></xref> allows the application to ask the agent to undertake whatever steps are
necessary to obtain rights for the given content object. Some agents may not
support this mechanism, in which case they returns <codeph>KErrCANotSupported</codeph>. </p> <p>The
request rights call includes a <codeph>TRequestStatus</codeph> parameter,
which allows the application to be notified of the outcome of the rights request. </p> <codeblock id="GUID-FEA60E64-1735-5D3D-8D14-6BA3E6F8A54E" xml:space="preserve">content-&gt;RequestRights(status, uniqueId);</codeblock> <p><i>Display
information</i></p> <p> <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-6613813A-5621-3F0F-B64F-DA2E1F89D7E7"><apiname>ContentAccess::CContent::DisplayInfoL()</apiname></xref> allows
the application to ask the agent to display the file and/or rights information
for the given content object. The call returns when the display is dismissed. </p> <p>Some
agents may not support this mechanism, in which case they return <codeph>KErrCANotSupported</codeph>. </p> <codeblock id="GUID-8B96985A-4810-5CE1-9561-0C8BC5D725C0" xml:space="preserve">content-&gt;DisplayInfoL(EFileProperties, uniqueId);</codeblock> <p id="GUID-635EE5EF-469D-5FD3-9400-25DF95FD2E96"><b>Get content object notifications</b> </p> <p>The <xref href="GUID-EF3C33C0-F02E-3C35-B289-3800631EDC3A.dita"><apiname>CContent</apiname></xref> interface
supports notification requests for content objects within files. The events
for which an application can request notification are given by the enumeration <xref href="GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601.dita#GUID-0F5CE9B5-E674-3962-8376-CFB1ECB2F601/GUID-20035389-F839-3ACF-B892-B6A58A13460A"><apiname>ContentAccess::TEventMask</apiname></xref>. </p> <p>The
following example requests and cancels notification for rights becoming available: </p> <codeblock id="GUID-81C47EF6-AF59-59AC-B07F-D190ABE89973" xml:space="preserve">// Request notification when rights become available for a particular content object
content-&gt;NotifyStatusChange(ERightsAvailable, status, uniqueId);

// Cancel notification request
content-&gt;CancelNotifyStatusChange(status, uniqueId);</codeblock> <p id="GUID-DDAE0B57-B296-58E8-8220-AE5AA9BF7B8D"><b>Close
a container</b> </p> <p>To close a container, use the <xref href="GUID-FC40011B-32D3-328B-BB59-35BEF46A215A.dita#GUID-FC40011B-32D3-328B-BB59-35BEF46A215A/GUID-E4CAB325-A0BC-3A43-A1CD-F099B478B188"><apiname>ContentAccess::CContent::CloseContainer()</apiname></xref> function. </p> <p>For
example, Container 1.1 is closed and Container 1 is still open: </p> <codeblock id="GUID-FDDCBB26-6FA6-5B1C-87EA-EE32182A97C1" xml:space="preserve">//Close Container 1.1 
content-&gt;CloseContainer(); 

// Get the embedded content objects in the current container 
content-&gt;GetEmbeddedObjectsL(myArray, EContentObject);
i = myArray.Count(); // Six content objects 
myArray.ResetAndDestroy(); 

// Get the number of container objects in the current container 
content-&gt;GetEmbeddedObjectsL(myArray, EContainerObject); 
i = myArray.Count(); // One container object 
myArray.ResetAndDestroy();</codeblock> <fig id="GUID-F3A1B237-A07C-5AE7-82F1-5DAA3BA65553">
<image href="GUID-DC7E3634-9762-542F-BDAE-AC1F2D03F55D_d0e589493_href.png" placement="inline"/>
</fig> </section>
</conbody></concept>