First public contribution.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Some of the examples below do not include fully comprehensive error checking. They are written this way to simplify the
15 // understanding of the basic steps involved. All errors should be handled appropriately in production code.
16 // <b>Consumer API </b>
17 // <b>Supplier API </b>
19 // This example function takes the URI of a file and displays the plaintext version of that content on screen.
20 // If anything goes wrong, for instance the file does not exist or there are no valid rights
21 // that will allow the file to be displayed, the function will just leave.
22 // It's important to notice the call to <code>ContentAccess::CData::ExecuteIntent()</code>, this should always be called, even if you
23 // think it's unlikely you will open DRM content.
24 // class CContentViewer : public CBase
26 // static CContentViewer* NewL();
27 // static CContentViewer* NewLC();
28 // // Display given content.
29 // void DisplayContent(const TDesC& aUri, TRequestStatus& aStatus)
30 // TRAPD(err, DisplayContentL(aUri));
31 // User::RequestComplete(aStatus, err);
33 // CContentViewer() : CBase() {}
34 // ~CContentViewer() {}
35 // void DisplayContentL(const TDesC& aUri)
38 // // Create a CContent object
39 // // CAF will figure out the appropriate agent
40 // CContent *content = CContent::NewLC(aUri);
41 // // Create a CData object to read the content
42 // // Tell the agent we are planning to display the content
43 // CData *data = content->OpenContentLC(EDisplay);
44 // // Don't need content object any more
45 // CleanupStack::PopAndDestroy(content);
46 // // get the size of the plaintext content
47 // data->DataSizeL(size);
48 // // Execute the intent, tell the agent that we plan to display the content
49 // // It is at this point that any stateful rights will be decremented
50 // data->ExecuteIntentL(EDisplay);
51 // // read and display the file until we reach the end of the file
54 // // read from the file
55 // User::LeaveIfError(data->Read(buffer));
56 // i += buffer.Length();
57 // // display on screen
59 // // finished with Data object
60 // CleanupStack::PopAndDestroy(data);
62 // This example is the same as before except it attempts to obtain or wait for rights
63 // to become available rather than just leaving if access to the content is restricted.
64 // class CContentViewer : public CActive
66 // static CContentViewer* NewL();
67 // static CContentViewer* NewLC();
68 // // Display given content.
69 // void DisplayContent(const TDesC& aUri, TRequestStatus& aStatus)
71 // iClientStatus = &aStatus;
72 // iClientStatus = KRequestPending;
73 // iCurrentState = EOpenFile;
74 // // trigger our RunL
75 // iStatus = KRequestPending;
77 // User::RequestComplete(iStatus, KErrNone);
79 // TInt err = iStatus.Int();
80 // switch (iCurrentState)
82 // iContent = CContent::NewL(aUri);
83 // TRAP(err, iData = iContent->OpenContentL(EDisplay));
84 // iCurrentState = EReadAndDisplay; // follow through...
85 // case EReadAndDisplay:
86 // if(err == KErrNone)
87 // TRAP(err, DisplayFile());
88 // iCurrentState = EFinished;
89 // // tell client iStatus that we have finished
90 // User::RequestComplete(*iClientStatus, err);
92 // else if(err == KErrCANoRights)
93 // // we don't have rights so we need to wait for them
94 // iCurrentState = EWaitingForRights;
95 // // ask CAF to initiate download of rights
96 // iContent->RequestRights(iStatus);
97 // else if(err == KErrCAPendingRights)
98 // // waiting for rights to arrive, expected any minute now
99 // iCurrentState = EWaitingForRights;
100 // // ask CAF to notify us when they arrive
101 // iContent->NotifyStatusChange(ERightsAvailable , iStatus);
102 // // wait for CAF to complete our request
104 // iStatus = KRequestPending;
107 // case EWaitingForRights:
108 // if(ret == KErrNone)
109 // // change the state to try and display content again
110 // iCurrentState = EReadAndDisplay;
111 // // trigger our RunL
113 // iStatus = KRequestPending;
115 // User::RequestComplete(iStatus, KErrNone);
117 // // couldn't get rights, tell parent active object we're finished
118 // User::RequestComplete(iClientStatus, err);
123 // if (iLastError == KErrCAPendingRights)
124 // iContent->CancelNotifyStatusChange(iStatus);
125 // else if (iLastError == KErrCANoRights)
126 // iContent->CancelRequestRights(iStatus);
128 // CContentViewer() : CActive(EPriorityStandard)
129 // CActiveScheduler::Add(this);
132 // if (iData) delete iData;
133 // if (iContent) delete iContent;
134 // // Display the content, if any error occurs then leave
135 // void DisplayContentL();
138 // TBuf <128> buffer;
139 // // Execute the intent, tell the agent that we plan to display the content
140 // // It is at this point that any stateful rights will be decremented
141 // iData->ExecuteIntentL(EDisplay);
142 // // get the size of the plaintext content
143 // iData->DataSizeL(size);
144 // // read and display the file until we reach the end of the file
146 // // read from the file
147 // User::LeaveIfError(iData->Read(buffer));
148 // i += buffer.Length();
149 // // Display on screen
155 // EWaitingForRights,
157 // CContent* iContent;
160 // TState iCurrentState;
162 // TRequestStatus* iClientStatus;
164 // Some servers may wish to prevent access to DRM content by untrusted clients, even if
165 // the server itself has DRM capability.
166 // To achieve this the server should use the <code>ContentAccess::TIntent::EUnknown</code> intent when
167 // accessing content. Content files that are not DRM protected will still work normally, but
168 // access to DRM protected content will be blocked.
169 // // Tell the agent we have no idea what the application plans to do
170 // CData *data = content->OpenContentL(EUnknown);
171 // // Execute the intent, tell the agent that we have no idea what the content will be used for
172 // data->ExecuteIntentL(EUnknown);
174 // When reading from a particular content object within a file the application must supply
175 // the \c UniqueId of the object when calling <code>ContentAccess::CContent::OpenContentL()</code>.
176 // void DisplayTextFileL(const TDesC& aUri)
179 // TBuf <128> buffer;
180 // // Create a CContent object
181 // // CAF will figure out the appropriate agent
182 // CContent *content = CContent::NewLC(aUri);
183 // // Find the objects in the file with MIME type image/jpeg
184 // RStreamablePtrArray<CEmbeddedObject> myArray;
185 // CleanupClosePushL(myArray);
186 // User::LeaveIfError(content->Search(myArray, _L("image/jpeg"), EFalse));
187 // // Get the virtual path of the first image/jpeg we find
188 // TVirtualPathPtr picture = *myArray[0];
189 // // Tell the agent to open the object with the given UniqueId
190 // CData *data = content->OpenContentLC(EDisplay, picture.UniqueId());
191 // // Don't need content object or array any more
192 // CleanupStack::PopAndDestroy(2); // content, myArray
193 // // get the size of the plaintext content
194 // data->DataSizeL(size);
195 // // Execute the intent, tell the agent that we plan to display the content
196 // // It is at this point that any stateful rights will be decremented
197 // data->ExecuteIntentL(EDisplay);
198 // // read and display the file until we reach the end of the file
200 // // read from the file
201 // User::LeaveIfError(data->Read(buffer));
202 // i += buffer.Length();
203 // // display on screen
205 // // finished with Data object
206 // CleanupStack::PopAndDestroy(data);
208 // This example shows how a messaging application that has just received
209 // a message attachment from a mail server can offer the attachment
210 // to CAF for processing. The output files will be saved in <code>C:\\files\\</code>.
211 // void CMyApp::ReceiveMessageAttachment(const TDesC8& aContentType, const TDesC8& aMessageAttachment)
212 // // Create supplier object
213 // CSupplier* supplier = CSupplier::NewLC();
214 // // Tell the agent where we would like the output files to be written
215 // supplier->SetOutputDirectoryL(_L("C:\\files"));
216 // // Check if CAF can import this attachment we just received
217 // if(supplier->IsImportSupported(aContentType))
218 // ProcessAttachmentL(supplier, aContentType, aMessageAttachment);
220 // // just save the message to a file in its current form
222 // theFile.Open(iFs, "myFile");
223 // theFile.Write(aMessageAttachment);
225 // // Add the file to the list of attachments
226 // AddAttachment("myFile");
227 // void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8& aContentType, const TDesC8& aMessageAttachment)
228 // TInt err = KErrNone;
230 // // Create meta-data array
231 // CMetaDataArray* metaDataArray = new (ELeave) CMetaDataArray();
232 // CleanupStack::PushL(metaDataArray);
233 // // Add any useful information we can think of....
234 // // Obviously these would not be hardcoded this way in a real import
235 // metaDataArray->AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm"));
236 // metaDataArray->AddL(_L("Content Length"), _L("1201"));
237 // metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6"));
238 // // Create the import object
239 // CImportFile* import = aSupplier->ImportFileL(aContentType, *metaDataArray, _L("myfile"));
240 // CleanupStack::PushL(import);
241 // // import the attachment
242 // err = import->WriteData(aMessageText);
243 // // tell CAF (and hence the agent) it's now got the entire file
244 // if (err == KErrNone)
245 // err = import->WriteDataComplete();
246 // if (err == KErrNone)
247 // // Look at the output of the import operation
248 // for(TInt i = 0; i < import->OutputFileCountL(); i++)
249 // // for this example only add content output files
250 // // (absorb any rights in the original attachment 'silently')
251 // if(import->OutputFilesL(i).OutputType == EContent)
252 // // Add file to list of attachments for this message
253 // AddAttachment(import->OutputFilesL(i).FileName());
255 // if (err != KErrNone)
256 // if (err == KErrNotReady)
257 // DisplayErrorMsg("Agent not ready for import");
258 // else if (err == KErrCACorruptContent)
259 // DisplayErrorMsg("Content data is corrupt");
261 // DisplayErrorMsg("Unexpected error: %d", err);
263 // CleanupStack::PopAndDestroy(2); // metaDataArray, import
265 // This example shows how a messaging application that has just received
266 // a message attachment from a mail server can offer the attachment
267 // to CAF for processing and store the file in its own private directory.
268 // void CMyApp::ReceiveMessageAttachment(const TDesC8& aContentType, const TDesC8& aMessageAttachment)
269 // // Create supplier object
270 // CSupplier* supplier = CSupplier::NewLC();
271 // // Check if CAF can import this attachment we just received
272 // if(supplier->IsImportSupported(aContentType))
273 // ProcessAttachmentL(supplier, aContentType, aMessageAttachment);
275 // // just save the message to a file in its current form
277 // theFile.Open(iFs, "myFile");
278 // theFile.Write(aMessageAttachment);
280 // // Add the file to the list of attachments
281 // AddAttachment("myFile");
282 // void CMyApp::ProcessAttachmentL(CSupplier* aSupplier, const TDesC8& aContentType, const TDesC8& aMessageAttachment)
283 // TInt err = KErrNone;
285 // TBuf <4> fileExtension;
286 // _LIT(KOutputFileName, "\\private\\12345678\\outputfile.");
287 // TFileName fileName(KOutputFileExtension);
289 // // Create meta-data array
290 // CMetaDataArray* metaDataArray = CMetaDataArray::NewLC();
291 // // Add any useful information we can think of....
292 // // Obviously these would not be hardcoded this way in a real import
293 // metaDataArray->AddL(_L("Content Type"), _L("application/vnd.oma.drm.dm"));
294 // metaDataArray->AddL(_L("Content Length"), _L("1201"));
295 // metaDataArray->AddL(_L("X-Oma-Drm-Separate-Delivery"), _L("6"));
296 // // Create the import object, no suggested file name implies the application will supply output files
297 // CImportFile* import = aSupplier->ImportFileL(aContentType, *metaDataArray);
298 // CleanupStack::PushL(import);
299 // // Start importing the attachment
300 // // (if the agent needs one or more output files, continue looping until
301 // // the agent finishes the previous)
302 // TInt err = import->WriteData(aMessageText);
303 // while(err == KErrCANewFileHandleRequired)
304 // import->GetSuggestedOutputFileExtension(fileExtension);
305 // filName.Append(fileExtension);
306 // User::LeaveIfError(file.Open(iFs, fileName));
307 // err = import->ContinueWithNewOutputFile(file);
309 // if (err == KErrNone)
310 // // Complete the import process
311 // err = import->WriteDataComplete();
312 // while(err == KErrCANewFileHandleRequired)
313 // import->GetSuggestedOutputFileExtension(fileExtension);
314 // filName.Append(fileExtension);
315 // User::LeaveIfError(file.Open(iFs, fileName));
316 // err = import->ContinueWithNewOutputFile(file);
318 // if (err == KErrNone)
319 // // Look at the output of the import operation
320 // for(TInt i = 0; i < import->OutputFileCountL(); i++)
321 // // for this example only add content output files
322 // // (absorb any rights in the original attachment 'silently')
323 // if(import->OutputFilesL(i).OutputType == EContent)
324 // // Add file to list of attachments for this message
325 // AddAttachment(import->OutputFilesL(i).FileName());
327 // if (err != KErrNone)
328 // if (err == KErrNotReady)
329 // DisplayErrorMsg("Agent not ready for import");
330 // else if (err == KErrCACorruptContent)
331 // DisplayErrorMsg("Content data is corrupt");
333 // DisplayErrorMsg("Unexpected error: %d", err);
335 // CleanupStack::PopAndDestroy(2); // metaDataArray, import
340 @page CAFExamples Example source code using CAF
342 - @ref ExampleReadWithErrCheck
343 - @ref PlayingUnprotectedOnly
344 - @ref MultipleContentExample
345 - @ref ExampleSupplier1
346 - @ref ExampleSupplier2
347 @section ExampleRead1 Reading from a file, no error checking
350 @section ExampleReadWithErrCheck Reading from a file, with error checking
353 @section PlayingUnprotectedOnly Preventing access to DRM content
356 @section MultipleContentExample File containing several content objects
359 @section ExampleSupplier1 Importing a content file, agent provides output files
362 @section ExampleSupplier2 Importing a content file, application provides output files