|
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 "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
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> |
|
18 // <hr> |
|
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 |
|
25 // public: |
|
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); |
|
32 // private: |
|
33 // CContentViewer() : CBase() {} |
|
34 // ~CContentViewer() {} |
|
35 // void DisplayContentL(const TDesC& aUri) |
|
36 // TInt size = 0; |
|
37 // TInt i = 0; |
|
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 |
|
52 // TBuf <128> buffer; |
|
53 // while(i < size) |
|
54 // // read from the file |
|
55 // User::LeaveIfError(data->Read(buffer)); |
|
56 // i += buffer.Length(); |
|
57 // // display on screen |
|
58 // printf(buffer); |
|
59 // // finished with Data object |
|
60 // CleanupStack::PopAndDestroy(data); |
|
61 // <hr> |
|
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 |
|
65 // public: |
|
66 // static CContentViewer* NewL(); |
|
67 // static CContentViewer* NewLC(); |
|
68 // // Display given content. |
|
69 // void DisplayContent(const TDesC& aUri, TRequestStatus& aStatus) |
|
70 // iUri = aUri; |
|
71 // iClientStatus = &aStatus; |
|
72 // iClientStatus = KRequestPending; |
|
73 // iCurrentState = EOpenFile; |
|
74 // // trigger our RunL |
|
75 // iStatus = KRequestPending; |
|
76 // SetActive(); |
|
77 // User::RequestComplete(iStatus, KErrNone); |
|
78 // void RunL() |
|
79 // TInt err = iStatus.Int(); |
|
80 // switch (iCurrentState) |
|
81 // case EOpenFile: |
|
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); |
|
91 // return; |
|
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 |
|
103 // iLastError = err; |
|
104 // iStatus = KRequestPending; |
|
105 // SetActive(); |
|
106 // break; |
|
107 // case EWaitingForRights: |
|
108 // if(ret == KErrNone) |
|
109 // // change the state to try and display content again |
|
110 // iCurrentState = EReadAndDisplay; |
|
111 // // trigger our RunL |
|
112 // iLastError = err; |
|
113 // iStatus = KRequestPending; |
|
114 // SetActive(); |
|
115 // User::RequestComplete(iStatus, KErrNone); |
|
116 // else |
|
117 // // couldn't get rights, tell parent active object we're finished |
|
118 // User::RequestComplete(iClientStatus, err); |
|
119 // return; |
|
120 // break; |
|
121 // protected: |
|
122 // void DoCancel() |
|
123 // if (iLastError == KErrCAPendingRights) |
|
124 // iContent->CancelNotifyStatusChange(iStatus); |
|
125 // else if (iLastError == KErrCANoRights) |
|
126 // iContent->CancelRequestRights(iStatus); |
|
127 // private: |
|
128 // CContentViewer() : CActive(EPriorityStandard) |
|
129 // CActiveScheduler::Add(this); |
|
130 // ~CContentViewer() |
|
131 // Cancel(); |
|
132 // if (iData) delete iData; |
|
133 // if (iContent) delete iContent; |
|
134 // // Display the content, if any error occurs then leave |
|
135 // void DisplayContentL(); |
|
136 // TInt size = 0; |
|
137 // TInt i = 0; |
|
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 |
|
145 // while(i < size) |
|
146 // // read from the file |
|
147 // User::LeaveIfError(iData->Read(buffer)); |
|
148 // i += buffer.Length(); |
|
149 // // Display on screen |
|
150 // printf(buffer); |
|
151 // private: |
|
152 // enum TState |
|
153 // EOpenFile = 0, |
|
154 // EReadAndDisplay, |
|
155 // EWaitingForRights, |
|
156 // EFinished |
|
157 // CContent* iContent; |
|
158 // CData* iData; |
|
159 // TDesC iUri; |
|
160 // TState iCurrentState; |
|
161 // TInt iLastError; |
|
162 // TRequestStatus* iClientStatus; |
|
163 // <hr> |
|
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); |
|
173 // <hr> |
|
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) |
|
177 // TInt size = 0; |
|
178 // TInt i = 0; |
|
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 |
|
199 // while(i < size) |
|
200 // // read from the file |
|
201 // User::LeaveIfError(data->Read(buffer)); |
|
202 // i += buffer.Length(); |
|
203 // // display on screen |
|
204 // printf(buffer); |
|
205 // // finished with Data object |
|
206 // CleanupStack::PopAndDestroy(data); |
|
207 // <hr> |
|
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); |
|
219 // else |
|
220 // // just save the message to a file in its current form |
|
221 // RFile theFile; |
|
222 // theFile.Open(iFs, "myFile"); |
|
223 // theFile.Write(aMessageAttachment); |
|
224 // theFile.Close(); |
|
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; |
|
229 // TBuf <128> buf; |
|
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()); |
|
254 // // Error handling |
|
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"); |
|
260 // else |
|
261 // DisplayErrorMsg("Unexpected error: %d", err); |
|
262 // // Finished |
|
263 // CleanupStack::PopAndDestroy(2); // metaDataArray, import |
|
264 // <hr> |
|
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); |
|
274 // else |
|
275 // // just save the message to a file in its current form |
|
276 // RFile theFile; |
|
277 // theFile.Open(iFs, "myFile"); |
|
278 // theFile.Write(aMessageAttachment); |
|
279 // theFile.Close(); |
|
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; |
|
284 // TBuf <128> buf; |
|
285 // TBuf <4> fileExtension; |
|
286 // _LIT(KOutputFileName, "\\private\\12345678\\outputfile."); |
|
287 // TFileName fileName(KOutputFileExtension); |
|
288 // RFile file; |
|
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); |
|
308 // file.Close(); |
|
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); |
|
317 // file.Close(); |
|
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()); |
|
326 // // Error handling |
|
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"); |
|
332 // else |
|
333 // DisplayErrorMsg("Unexpected error: %d", err); |
|
334 // // Finshed |
|
335 // CleanupStack::PopAndDestroy(2); // metaDataArray, import |
|
336 // |
|
337 // |
|
338 |
|
339 |
|
340 |
|
341 /** |
|
342 @page CAFExamples Example source code using CAF |
|
343 - @ref ExampleRead1 |
|
344 - @ref ExampleReadWithErrCheck |
|
345 - @ref PlayingUnprotectedOnly |
|
346 - @ref MultipleContentExample |
|
347 - @ref ExampleSupplier1 |
|
348 - @ref ExampleSupplier2 |
|
349 @section ExampleRead1 Reading from a file, no error checking |
|
350 @code |
|
351 @endcode |
|
352 @section ExampleReadWithErrCheck Reading from a file, with error checking |
|
353 @code |
|
354 @endcode |
|
355 @section PlayingUnprotectedOnly Preventing access to DRM content |
|
356 @code |
|
357 @endcode |
|
358 @section MultipleContentExample File containing several content objects |
|
359 @code |
|
360 @endcode |
|
361 @section ExampleSupplier1 Importing a content file, agent provides output files |
|
362 @code |
|
363 @endcode |
|
364 @section ExampleSupplier2 Importing a content file, application provides output files |
|
365 @code |
|
366 @endcode |
|
367 */ |