diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,271 @@ + + + + + +Handling +DRM Content +

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.

+

Note: Rendering is a process of reading data from a file, transforming +it, then playing or displaying it on the device.

+

Access to content within archive files

+

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.

+

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 ContentAccess::CContent 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.

+
Required background

Before you start, you must +understand:

    +
  • Content +Access Framework for DRM

  • +
  • Files +Containing Multiple Content Objects

  • +
  • Content +Object Attributes

  • +
+
Introduction

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 ContentAccess::CContent 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 Files +Containing Multiple Content Objects for more information.

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.

+ Example content file + +
+
Procedure
    +
  1. Create a content object.

  2. +
  3. Perform one or more +of the following tasks as per your requirement:

      +
    • List objects within a container.

    • +
    • Open a container.

    • +
    • Open the metadata specific to an agent.

    • +
    • Display content object information.

    • +
    • Retrieve the attributes of a content.

    • +
    • Search for a MIME type within a file.

    • +
    • Read data from a content object.

    • +
    • Handle data corruption.

    • +
    • Handle errors.

    • +
    • Handle rights for DRM content.

    • +
    • Get content object notifications.

    • +
    • Close a container.

    • +
  4. +

Create a CContent +object

The ContentAccess::CContent 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.

There are two +ways to create a CContent object. The application can specify +the URI of the content or it can supply an open file handle, see Objects used to identify a content object within a file.

// 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);

Upon creation, CContent selects +the agent that handles the file.

List +objects within a container

ContentAccess::CContent acts +like a cursor, only able to list the contents of one container object at any +one time. When CContent 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.

Even a content file such +as a jpeg image is a container, it's just that the file only has the "DEFAULT" object +embedded inside.

So, when the example file shown earlier is opened, +the following objects can be seen by the CContent:

+ +

In this top level container, there is only one embedded content +object visible (the .jpg file) and two embedded container +objects.

// Create an array to store the results of CContent::GetEmbeddedObjectsL() +RStreamablePtrArray<CEmbeddedObject> myArray; +CleanupClosePushL(myArray); + +// Get the embedded content objects in the current container +content->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->GetEmbeddedObjectsL(myArray, EContainerObject); + +i = myArray.Count(); // Two container objects + +// clear the contents of the array +myArray->ResetAndDestroy();

Open +a container

To investigate the objects inside a container, CContent must +first open the container. This changes CContent's focus +from the current container to the container specified in the ContentAccess::CContent::OpenContainer() function.

Open +container 1 from the top level of the file

// Get the container objects in the top level of the file +content->GetEmbeddedObjects(myArray, EContainerObject); + +// Find the Unique Id of the first container +TPtrC UniqueId = myArray[0]->UniqueId() + +// Open the first container +content->OpenContainer(UniqueId);

Now CContent can +see the contents of Container 1:

+ +

At this point, listing the objects that CContent can +see gives six MP3 files and one container object.

// Get the embedded content objects in the current container +content->GetEmbeddedObjectsL(myArray, EContentObject); + +i = myArray.Count(); // Six content objects +myArray.ResetAndDestroy(); + +// Get the number of container objects in the current container +content->GetEmbeddedObjectsL(myArray, EContainerObject); + +i = myArray.Count(); // One container object +myArray.ResetAndDestroy();

Note: The same process +can be followed again to see the contents of Container 1.1.

Open +the metadata specific to an agent

Some agents may expose metadata +so they can be read using a CData 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.

CData objects for agent specific metadata can +be opened in the same way content objects are opened, using the ContentAccess::CContent::OpenContentL() function.

// Create an array to store the embedded objects +... + +// Get the embedded "Agent Specific" objects in the current container +content->GetEmbeddedObjectsL(myArray, EAgentSpecificObject); + +// Get the unique Id of the first meta-data object +TPtrC uniqueId = myArray[0]->UniqueId(); + +// create a CData object to read the meta data +CData *myMetaData = content->OpenContent(EPeek, uniqueId);

Display content object information

The CContent::DisplayInfoL() function +allows the application to display file information, such as last modification +date and DRM rights information.

... +content->DisplayInfoL(TDisplayInfo aInfo); +... +

Retrieve +the attributes of a content

Content and container objects have +properties or attributes associated with it. Applications can retrieve single +or mulitple attributes using the ContentAccess::TAttributeCAF enumeration +and the ContentAccess::TStringAttribute enumeration. See Content Object Attributes for +details on implementing different methods of retrieving attributes.

The +following example finds the author attribute of a content object.

// define a buffer to store the attribute value string +TBuf <100> buf; + +// retrieve the attribute +err = content->GetAttribute(EAuthor, buf, uniqueId); + +// Display the author's name on screen +DisplayAuthor(buf); +

Search for +a MIME type within a file

If an application wants to find all +the content with a particular MIME type within a file, it must use ContentAccess::CContent::Search(). +This function produces a list of all content objects with the specified MIME +type that are stored under the current container.

// Create an array for storing the result of the search +RStreamablePtrArray<CEmbeddedObject> myArray; + +// Find how many MP3 files are in Container 1 +TInt numMp3 = content->Search(myArray, _L("mpeg/audio"), EFalse);

Read data from a content +object

The functions described earlier can be used to locate a +particular content object within a file. ContentAccess::CContent::OpenContentL() can +be used to read the content object. The UniqueId parameter +can be used to identify a particular object within the file.

The call +to ContentAccess::CContent::OpenContentL() leaves if the +intent is not permitted. This could occur if the file is DRM-protected but +no rights are present.

If the file is DRM protected and the call to OpenContentL() succeeds, +the rights are not consumed at this point. CAF just checks that it is possible +to use the content.

// Open the content object specified by uniqueId with the EPlay intent +CData* data = content->OpenContentL(EPlay, uniqueId);

If the +application already knows the URI and unique ID of the content object it wants +to read from, it can create a CData object directly.

CData* data = CData::NewL(TVirtualPathPtr(uri, uniqueId), EPlay, EContentShareReadOnly);

Once the CData object has been constructed, it allows +the content object to be used as if it were a standalone unprotected file. +The client must call ContentAccess::CData::ExecuteIntent() when +the rights must be consumed. If the file is not DRM-protected, the call is +ignored by the agent handling the file.

TBuf8 <256> buf; +data->ExecuteIntent(EPlay); +data->Seek(ESEEK_START,SomePosition); +data->Read(buf);

There are several overloaded versions of the ContentAccess::CData::Read() function. +Only one is illustrated above for example purposes.

Handle +data corruption

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.

If +an agent detects corruption in a content object or in a rights object, it +ends the current DRM operation. The KErrCACorruptContent, KErrCACorruptRights or KErrCorrupt error +code is sent to clients, depending on the type of corruption detected and +how the client chooses to handle it.

Note: It is recommended +that clients be designed to handle such an error if received, as it can usually +be considered a fatal error.

// Create a CData object to read the content +... + +TRAP(err, data = content->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 == ...) + ... + } +... +

Handle errors

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 CContent::SetProperty() function.

// Disable UI +content->SetProperty(EAgentPropertyAgentUI , 0); +

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 KErrCancel, if the user presses cancel. +The CContent::SetProperty() function can also be used to +disable the confirmation dialogs.

Handle +rights for DRM content

There are two functions available that +give the application some control over the rights:

Request rights

ContentAccess::CContent::RequestRights() 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 KErrCANotSupported.

The +request rights call includes a TRequestStatus parameter, +which allows the application to be notified of the outcome of the rights request.

content->RequestRights(status, uniqueId);

Display +information

ContentAccess::CContent::DisplayInfoL() 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.

Some +agents may not support this mechanism, in which case they return KErrCANotSupported.

content->DisplayInfoL(EFileProperties, uniqueId);

Get content object notifications

The CContent interface +supports notification requests for content objects within files. The events +for which an application can request notification are given by the enumeration ContentAccess::TEventMask.

The +following example requests and cancels notification for rights becoming available:

// Request notification when rights become available for a particular content object +content->NotifyStatusChange(ERightsAvailable, status, uniqueId); + +// Cancel notification request +content->CancelNotifyStatusChange(status, uniqueId);

Close +a container

To close a container, use the ContentAccess::CContent::CloseContainer() function.

For +example, Container 1.1 is closed and Container 1 is still open:

//Close Container 1.1 +content->CloseContainer(); + +// Get the embedded content objects in the current container +content->GetEmbeddedObjectsL(myArray, EContentObject); +i = myArray.Count(); // Six content objects +myArray.ResetAndDestroy(); + +// Get the number of container objects in the current container +content->GetEmbeddedObjectsL(myArray, EContainerObject); +i = myArray.Count(); // One container object +myArray.ResetAndDestroy(); + +
+
\ No newline at end of file