|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implements CNcdNodeDownload class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <bautils.h> |
|
20 |
|
21 |
|
22 #include "ncdnodedownloadimpl.h" |
|
23 #include "catalogssession.h" |
|
24 #include "catalogsbasemessage.h" |
|
25 #include "ncdnodefunctionids.h" |
|
26 #include "ncdnodeclassids.h" |
|
27 #include "ncdpurchasedetails.h" |
|
28 #include "ncdutils.h" |
|
29 #include "catalogsconstants.h" |
|
30 #include "ncd_pp_dataentity.h" |
|
31 #include "ncd_cp_query.h" |
|
32 #include "catalogsutils.h" |
|
33 #include "catalogsdebug.h" |
|
34 #include "ncdproviderutils.h" |
|
35 |
|
36 |
|
37 CNcdNodeDownload::CNcdNodeDownload( NcdNodeClassIds::TNcdNodeClassId aClassId ) |
|
38 : CCatalogsCommunicable(), |
|
39 iClassId( aClassId ) |
|
40 { |
|
41 } |
|
42 |
|
43 void CNcdNodeDownload::ConstructL() |
|
44 { |
|
45 } |
|
46 |
|
47 |
|
48 CNcdNodeDownload* CNcdNodeDownload::NewL() |
|
49 { |
|
50 CNcdNodeDownload* self = |
|
51 CNcdNodeDownload::NewLC(); |
|
52 CleanupStack::Pop( self ); |
|
53 return self; |
|
54 } |
|
55 |
|
56 CNcdNodeDownload* CNcdNodeDownload::NewLC() |
|
57 { |
|
58 CNcdNodeDownload* self = |
|
59 new( ELeave ) CNcdNodeDownload( |
|
60 NcdNodeClassIds::ENcdNodeDownloadClassId ); |
|
61 CleanupClosePushL( *self ); |
|
62 self->ConstructL(); |
|
63 return self; |
|
64 } |
|
65 |
|
66 |
|
67 CNcdNodeDownload::~CNcdNodeDownload() |
|
68 { |
|
69 DLTRACEIN(("")); |
|
70 |
|
71 // Delete member variables here. |
|
72 |
|
73 TInt count = iDownloadInfo.Count(); |
|
74 for ( TInt i = 0; i < count; i++ ) |
|
75 { |
|
76 CNcdPurchaseDownloadInfo* info = |
|
77 static_cast<CNcdPurchaseDownloadInfo*>(iDownloadInfo[i]); |
|
78 delete info; |
|
79 info = NULL; |
|
80 } |
|
81 iDownloadInfo.Reset(); |
|
82 |
|
83 delete iFiles; |
|
84 |
|
85 DLTRACEOUT(("")); |
|
86 } |
|
87 |
|
88 NcdNodeClassIds::TNcdNodeClassId CNcdNodeDownload::ClassId() const |
|
89 { |
|
90 return iClassId; |
|
91 } |
|
92 |
|
93 |
|
94 // Internalization from the purchase history. |
|
95 |
|
96 TBool CNcdNodeDownload::InternalizeL( const MNcdPurchaseDetails& aDetails ) |
|
97 { |
|
98 DLTRACEIN(("this-ptr: %X", this)); |
|
99 |
|
100 TArray<MNcdPurchaseDownloadInfo*> dlInfos( aDetails.DownloadInfoL() ); |
|
101 |
|
102 TInt count = dlInfos.Count(); |
|
103 |
|
104 // Quit if no download data exists or it's consumable |
|
105 if ( count == 0 || ( count == 1 && |
|
106 dlInfos[0]->ContentUsage() == |
|
107 MNcdPurchaseDownloadInfo::EConsumable )) |
|
108 { |
|
109 // No download data found from purchase details. |
|
110 DLTRACEOUT(("")); |
|
111 return EFalse; |
|
112 } |
|
113 |
|
114 // Check for any downloadable URIs |
|
115 TBool uriExists = EFalse; |
|
116 for ( TInt i = 0; i < count; ++i ) |
|
117 { |
|
118 if ( dlInfos[i]->ContentUri().Length() || |
|
119 dlInfos[i]->DescriptorUri().Length() || |
|
120 dlInfos[i]->DescriptorData().Length() || |
|
121 dlInfos[i]->RightsUri().Length() ) |
|
122 { |
|
123 uriExists = ETrue; |
|
124 break; |
|
125 } |
|
126 } |
|
127 |
|
128 if ( !uriExists ) |
|
129 { |
|
130 DLTRACEOUT(("No URI, no download API")); |
|
131 return EFalse; |
|
132 } |
|
133 |
|
134 iIsDownloaded = EFalse; |
|
135 |
|
136 delete iFiles; |
|
137 iFiles = NULL; |
|
138 iFiles = new (ELeave) CDesCArrayFlat( KListGranularity ); |
|
139 |
|
140 RPointerArray<MNcdPurchaseDownloadInfo> tempInfos; |
|
141 |
|
142 // Can't use CleanupResetAndDestroyPushL because the array can't |
|
143 // be deleted with ResetAndDestroy |
|
144 TRAPD( err, |
|
145 { |
|
146 tempInfos.ReserveL( count ); |
|
147 DLTRACE(("Copying purchase download infos")); |
|
148 // Download data found from purchase details. |
|
149 for ( TInt i = 0; i < count; i++ ) |
|
150 { |
|
151 CNcdPurchaseDownloadInfo* info = |
|
152 CNcdPurchaseDownloadInfo::NewLC( *dlInfos[i] ); |
|
153 tempInfos.AppendL( info ); |
|
154 CleanupStack::Pop( info ); |
|
155 } |
|
156 |
|
157 // Check purchase details status. |
|
158 if ( aDetails.State() == MNcdPurchaseDetails::EStateDownloaded || |
|
159 aDetails.State() == MNcdPurchaseDetails::EStateInstalled ) |
|
160 { |
|
161 iIsDownloaded = ETrue; |
|
162 DLTRACE(("Copy file paths, iIsDownloaded = ETrue")); |
|
163 const MDesCArray& files( aDetails.DownloadedFiles() ); |
|
164 |
|
165 for ( TInt i = 0; i < files.MdcaCount(); ++i ) |
|
166 { |
|
167 iFiles->AppendL( files.MdcaPoint( i ) ); |
|
168 } |
|
169 } |
|
170 |
|
171 ResetAndDestroyWithCast<CNcdPurchaseDownloadInfo>( iDownloadInfo ); |
|
172 iDownloadInfo = tempInfos; |
|
173 |
|
174 }); |
|
175 |
|
176 if ( err != KErrNone ) |
|
177 { |
|
178 ResetAndDestroyWithCast<CNcdPurchaseDownloadInfo>( tempInfos ); |
|
179 } |
|
180 |
|
181 DLTRACEOUT(("iIsDownloaded: %d", iIsDownloaded)); |
|
182 return ETrue; |
|
183 } |
|
184 |
|
185 const RPointerArray< MNcdPurchaseDownloadInfo >& |
|
186 CNcdNodeDownload::DownloadInfo() const |
|
187 { |
|
188 return iDownloadInfo; |
|
189 } |
|
190 |
|
191 |
|
192 void CNcdNodeDownload::ReceiveMessage( MCatalogsBaseMessage* aMessage, |
|
193 TInt aFunctionNumber ) |
|
194 { |
|
195 DLTRACEIN(("this-ptr: %X", this)); |
|
196 |
|
197 DASSERT( aMessage ); |
|
198 |
|
199 // Now, we can be sure that rest of the time iMessage exists. |
|
200 // This member variable is set for the CounterPartLost function. |
|
201 iMessage = aMessage; |
|
202 |
|
203 TInt trapError( KErrNone ); |
|
204 |
|
205 // Check which function is called by the proxy side object. |
|
206 // Function number are located in ncdnodefunctinoids.h file. |
|
207 switch( aFunctionNumber ) |
|
208 { |
|
209 case NcdNodeFunctionIds::ENcdInternalize: |
|
210 // Internalize the proxy side according to the data |
|
211 // of this object. |
|
212 TRAP( trapError, InternalizeRequestL( *aMessage ) ); |
|
213 break; |
|
214 |
|
215 case NcdNodeFunctionIds::ENcdRelease: |
|
216 // The proxy does not want to use this object anymore. |
|
217 // So, release the handle from the session. |
|
218 ReleaseRequest( *aMessage ); |
|
219 break; |
|
220 |
|
221 case NcdNodeFunctionIds::ENcdFilesExist: |
|
222 TRAP( trapError, FilesExistRequestL( *aMessage ) ); |
|
223 break; |
|
224 default: |
|
225 break; |
|
226 } |
|
227 |
|
228 if ( trapError != KErrNone ) |
|
229 { |
|
230 // Because something went wrong, the complete has not been |
|
231 // yet called for the message. |
|
232 // So, inform the client about the error if the |
|
233 // message is still available. |
|
234 aMessage->CompleteAndRelease( trapError ); |
|
235 } |
|
236 |
|
237 // Because the message should not be used after this, set it NULL. |
|
238 // So, CounterPartLost function will know that no messages are |
|
239 // waiting the response at the moment. |
|
240 iMessage = NULL; |
|
241 |
|
242 DLTRACEOUT(("")); |
|
243 } |
|
244 |
|
245 void CNcdNodeDownload::CounterPartLost( const MCatalogsSession& aSession ) |
|
246 { |
|
247 // This function may be called whenever -- when the message is waiting |
|
248 // response or when the message does not exist. |
|
249 // iMessage may be NULL here, because in the end of the |
|
250 // ReceiveMessage it is set to NULL. The life time of the message |
|
251 // ends shortly after CompleteAndRelease is called. |
|
252 if ( iMessage != NULL ) |
|
253 { |
|
254 iMessage->CounterPartLost( aSession ); |
|
255 } |
|
256 } |
|
257 |
|
258 |
|
259 void CNcdNodeDownload::InternalizeRequestL( MCatalogsBaseMessage& aMessage ) |
|
260 { |
|
261 DLTRACEIN(("")); |
|
262 |
|
263 CBufBase* buf = CBufFlat::NewL( KBufExpandSize ); |
|
264 CleanupStack::PushL( buf ); |
|
265 |
|
266 RBufWriteStream stream( *buf ); |
|
267 CleanupClosePushL( stream ); |
|
268 |
|
269 |
|
270 // Include all the necessary node data to the stream |
|
271 ExternalizeDataForRequestL( stream ); |
|
272 |
|
273 |
|
274 // Commits data to the stream when closing. |
|
275 CleanupStack::PopAndDestroy( &stream ); |
|
276 |
|
277 |
|
278 // If this leaves, ReceiveMessage will complete the message. |
|
279 // NOTE: that here we expect that the buffer contains at least |
|
280 // some data. So, make sure that ExternalizeDataForRequestL inserts |
|
281 // something to the buffer. |
|
282 aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone ); |
|
283 |
|
284 |
|
285 DLTRACE(("Deleting the buf")); |
|
286 CleanupStack::PopAndDestroy( buf ); |
|
287 |
|
288 DLTRACEOUT(("")); |
|
289 } |
|
290 |
|
291 |
|
292 void CNcdNodeDownload::ExternalizeDataForRequestL( RWriteStream& aStream ) |
|
293 { |
|
294 DLTRACEIN(("")); |
|
295 |
|
296 // Download existed. So, insert info that meta data was found. |
|
297 aStream.WriteInt32L( ClassId() ); |
|
298 |
|
299 // Add additional content to the stream. |
|
300 // Make sure that this matches to the order that is used in the proxy |
|
301 // side when this stream is internalized. |
|
302 // NOTE: Be careful with the 8- and 16-bit descriptors. Remember to check |
|
303 // if the proxy wants the data in 16 or 8 bits? |
|
304 |
|
305 aStream.WriteInt32L( iIsDownloaded ); |
|
306 |
|
307 DLTRACEOUT(("iIsDownloaded: %d", iIsDownloaded )); |
|
308 } |
|
309 |
|
310 void CNcdNodeDownload::ReleaseRequest( MCatalogsBaseMessage& aMessage ) const |
|
311 { |
|
312 DLTRACEIN(("")); |
|
313 |
|
314 // Decrease the reference count for this object. |
|
315 // When the reference count reaches zero, this object will be destroyed |
|
316 // and removed from the session. |
|
317 MCatalogsSession& requestSession( aMessage.Session() ); |
|
318 TInt handle( aMessage.Handle() ); |
|
319 |
|
320 // Send complete information back to proxy. |
|
321 aMessage.CompleteAndRelease( KErrNone ); |
|
322 |
|
323 // Remove this object from the session. |
|
324 requestSession.RemoveObject( handle ); |
|
325 |
|
326 DLTRACEOUT(("")); |
|
327 } |
|
328 |
|
329 |
|
330 void CNcdNodeDownload::FilesExistRequestL( MCatalogsBaseMessage& aMessage ) |
|
331 { |
|
332 DLTRACEIN(("")); |
|
333 |
|
334 TBool filesExist = EFalse; |
|
335 if ( iIsDownloaded ) |
|
336 { |
|
337 filesExist = FilesExist(); |
|
338 } |
|
339 |
|
340 // If this leaves, ReceiveMessage will complete the message. |
|
341 // NOTE: that here we expect that the buffer contains at least |
|
342 // some data. So, make sure that ExternalizeDataForRequestL inserts |
|
343 // something to the buffer. |
|
344 aMessage.CompleteAndReleaseL( filesExist, KErrNone ); |
|
345 |
|
346 |
|
347 DLTRACEOUT(("filesExist: %d", filesExist)); |
|
348 } |
|
349 |
|
350 |
|
351 |
|
352 TBool CNcdNodeDownload::FilesExist() |
|
353 { |
|
354 DLTRACEIN(("")); |
|
355 DASSERT( iFiles->MdcaCount() == iDownloadInfo.Count() ); |
|
356 |
|
357 for ( TInt i = 0; i < iFiles->MdcaCount(); ++i ) |
|
358 { |
|
359 TInt shouldExist = 1; |
|
360 |
|
361 // AttributeInt32L leaves only with KErrNone and that happens |
|
362 // if the attribute is not set which means that that download |
|
363 // is required |
|
364 TRAP_IGNORE( shouldExist = iDownloadInfo[i]->AttributeInt32L( |
|
365 MNcdPurchaseDownloadInfo::EDownloadAttributeRequiredDownload ) ); |
|
366 |
|
367 if ( !iDownloadInfo[i]->ContentUri().Length() ) |
|
368 { |
|
369 DLTRACE(("No URI, no file")); |
|
370 shouldExist = EFalse; |
|
371 } |
|
372 |
|
373 DLTRACE(("Downloaded file should exist: %d", shouldExist)); |
|
374 |
|
375 // Dependencies and in Get-cases content file don't have to be |
|
376 // downloaded because they can already be installed. In those cases |
|
377 // shouldExist == 0 and this check is skipped |
|
378 if ( shouldExist && ( |
|
379 iFiles->MdcaPoint( i ).Length() == 0 || |
|
380 !BaflUtils::FileExists( |
|
381 CNcdProviderUtils::FileSession(), |
|
382 iFiles->MdcaPoint( i ) ) ) ) |
|
383 { |
|
384 return EFalse; |
|
385 } |
|
386 } |
|
387 return ETrue; |
|
388 } |