diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita --- a/Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-09A760FD-4C2A-5F79-91F2-DCC25A63699C.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,271 +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(); - -
+ + + + + +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