Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


Importing files into the Content Access Framework

[Top]


Supplier API

The Supplier API allows agents to publicise the MIME types they are interested in. When files arrive on the device, message handling applications can check these MIME types and import the file into CAF. The agent transforms the file into a different format for use within the device.

In most cases this won't be necessary, since the files will arrive in the same format that they will be used in. However, some agents require the device to protect (encrypt) the content at the moment it arrives; the Supplier API fulfills that role.

The classes used in the supply operation are:

ContentAccess::CSupplier and instances of ContentAccess::CImportFile.

[Top]


Starting a new import session

The ContentAccess::CSupplier is designed to allow several unrelated files to be imported into CAF. It uses its ContentAccess::CAgentResolver member to determine which CA agent should be used to import each file. The CAgentResolver builds a list of all agents when it is created and updates the list if new agents are installed.

A typical import session will start with the creation of a CSupplier, for example:

// Create Supplier 
CSupplier *mySupplier = CSupplier::NewL();

Most applications will have a preference for the directory where output files are to be stored. Usually the first thing to do with the new CSupplier instance is to set the output path.

// Set output path for DRM protected content 
_LIT(KPath,"C:\\myOutputFiles");
mySupplier->SetOutputDirectoryL(KPath());

It is not necessary to set the output path if the application provides output file handles to the agent.

[Top]


Preparing to import the file

Check that the MIME type is supported

Before importing a file into the content access framework, an application should check that the MIME type of the file is supported. Each agent publishes a list of the MIME types it supports. The list is configured in the agent's resource file and can be checked using ContentAccess::CSupplier::IsImportSupported().

if(!mySupplier->IsImportSupported(myMimeType)) 
    { 
    return; 
    }

Create a CMetaDataList object

The CMetaDataList object is used to store any information associated with the import file that may be useful for the agent. These values will be passed to the agent.

For example OMA DRM 1.0 files sometimes arrive with the HTTP header X-Oma-Drm-Separate-Delivery. This informs the agent how long before rights are expected for the content. If the rights were expected in 12 seconds it would be something like the following:

// Create meta-data array 
CMetaDataArray *metaDataArray = new (ELeave) CMetaDataArray(); 
CleanupStack::PushL(metaDataArray);

// Add any useful information we can think of.... 
metaDataArray->AddL(_L("Content Type"),_L("application/vnd.oma.drm.dm")); 
metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"),_L("12"));

[Top]


Creating the CImportFile object

The file is 'written' to CAF using a ContentAccess::CImportFile object. ContentAccess::CSupplier::ImportFileL() creates an CImportFile object for importing a file.

The parameters supplied indicate whether the agent will create the output files or whether the application using CAF will generate output files for the agent on demand.

// Create the import object, passing in the metaDataArray created earlier 
// The application will supply the output files 
            
CImportFile *import = mySupplier->ImportFileL(sourceMimeType, *metaDataArray);

The application should now transfer the file to CAF using the CImportFile object. Only one file can be transferred by each instance although several output files may be produced. Applications should create new CImportFile objects in order to import more files.

Agents generating the output files

If the application wants the agent to generate the output files, it should supply a suggested file name in the call to CSupplier::ImportFileL(). Even if this parameter is a zero length descriptor, it still indicates that the agent is responsible for generating output files.

Agents will create the output files in a directory nominated by the application when it called CSupplier::SetOutputDirectoryL() or they may decide to store the output files in their private directory.

Applications should check at the end of the import to find out how many output files were created and where they are stored.

Application generating the output files

If no suggested file name is passed to the agent, the application will provide output files for the agent to use. This mechanism allows applications to open files in their own private directory and ask the CAF agent to store the output in those files.

The way it works is the same as in any other import operation, the difference is that the call to CImportFile::WriteData() or CImportFile::WriteDataComplete() may return an error code of KErrCANewFileHandleRequired.

This error code indicates that the agent needs a new output file handle in order to continue. The application should open a new output file with write access and call CImportFile::ContinueWithNewOutputFile() to supply the new handle to the agent. It is possible that further handles may be needed. If so, CImportFile::ContinueWithNewOutputFile() will return KErrCANewFileHandleRequired and the application should repeat the procedure with another file.

The agent must cache its state before returning KErrCANewFileHandleRequired. The application must not resend the same WriteData() or WriteDataComplete() command.

At the end of the import operation the output files will still be listed regardless of whether they were supplied by the application or the agent.

[Top]


Transferring the file to the Content Access Agent

ContentAccess::CImportFile is the class used to write the file data to CAF. It is created by ContentAccess::CSupplier and can only be used to import a single file.

An application should call WriteData() to transfer a field in 'chunks' to the Content Access Framework. Usually this would be something like the following:

ImportFile *import; 
TFileName fileName; 
TPath outputfileName; 
TBuf8 data <128> 
_LIT(KDirectoryPath, "C:\\private\\12345678\\");
... 

while(!endofsource) 
    {
    source.read(data); 
    err = import->WriteData(data); 

    // When application supplies file handles it must always check to see if 
    // the agent needs a new file handle 
    while(err == KErrCANewFileHandleRequired) 
        {               
        RFile newFile; 
        import->GetSuggestedOutputFileName(fileName); 
        outputFileName.Copy(KDirectoryPath); 
        outputFileName.Append(fileName);
        newFile.Open(outputFileName, EFileWrite); 
        err = import->ContinueWithNewOutputFile(newFile, outputFileName); 
        // It is possible that the agent needs yet another file handle 
        newFile.Close(); // agent makes a copy so we don't need to keep our file handle 
        }
    }

[Top]


Completing the import

When all the data is written, the application should call ContentAccess::CImportFile::WriteDataComplete(), which will let the agent know that all the data has been transferred and allow it to perform any final processing.

err = import->WriteDataComplete(); 

// When the application supplies file handles it must always check to see if 
// the agent needs a new file handle 
while(err == KErrCANewFileHandleRequired) 
    {
    RFile newFile; 
    import->GetSuggestedOutputFileName(fileName); 
    outputFileName.Copy(KDirectoryPath); 
    outputFileName.Append(fileName);  
    newFile.Open(outputFileName, EFileWrite);  
    err = import->ContinueWithNewOutputFile(newFile, outputFileName);
    // It is possible that the agent needs yet another file handle 
    newFile.Close(); // agent makes a copy so we don't need to keep our file handle
    }

// Finished

At this stage all the agent's work is done and the CImportFile object can be deleted.

[Top]


Output files produced

When the import is finished, the application may wish to check if any output files have been produced. The list of output files is accessed using ContentAccess::CImportFile::OutputFileL().

// loop over all the output files produced 
for(TInt i =0; i < import->OutputFileCountL(); i++) 
    {
    // Can now retrieve filename, type of file (receipt or content) and MIME type for the file produced
    TPtr filename = import->OutputFileL(i).FileName(); 
    TOutputType type = import->OutputFileL(i).OutputType();
    TPtr8 mimetype = import->OutputFileL(i).MimeType(); 
    }

The output files can be either content files or receipts for DRM rights. It is possible that no output files will be generated and the file will be "absorbed" into the agent.

Also, it is important to remember that the MIME type and most likely the file extension of the output files are almost certainly different to the MIME type and file extension of the imported file.