|
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 the License "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: Plugin handling, manages the loading and unloading of the |
|
15 * plugin. Initializes the CInfoArray that contains the plugin |
|
16 * MIME-types supported. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 #include <e32std.h> |
|
23 #include <e32uid.h> |
|
24 #include <sysutil.h> |
|
25 #include "../../bidi.h" |
|
26 |
|
27 // System includes |
|
28 #include <ecom/ecom.h> |
|
29 |
|
30 |
|
31 // INCLUDES |
|
32 #include "WebCorePluginHandler.h" |
|
33 #include "NPNImplementation.h" |
|
34 #include "PluginHandler.h" |
|
35 |
|
36 // CONSTANTS |
|
37 |
|
38 const TInt KPluginGranularity = 3; |
|
39 const TInt KMimeTypeLength = 7; |
|
40 |
|
41 _LIT( KMimeTypeAudio, "audio/" ); |
|
42 _LIT( KMimeTypeVideo, "video/" ); |
|
43 |
|
44 // LOCAL FUNCTION PROTOTYPES |
|
45 typedef NPError (*NPP_InitializeFunc)(NPNetscapeFuncs *netscapeFuncs, |
|
46 NPPluginFuncs *pluginFuncs); |
|
47 typedef void (*NPP_ShutdownFunc)(void); |
|
48 |
|
49 #define LOAD_PLUGINS if(!m_pluginsLoaded) { TRAP_IGNORE(loadPluginsL()); m_pluginsLoaded = ETrue; } |
|
50 |
|
51 |
|
52 // ============================ MEMBER FUNCTIONS =============================== |
|
53 |
|
54 void panicHandler(TInt error = KErrNone) |
|
55 { |
|
56 User::Panic(_L("Object Handling Panic"), error); |
|
57 } |
|
58 |
|
59 |
|
60 // ============================ MEMBER FUNCTIONS =============================== |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // PluginInfo::PluginInfo |
|
64 // C++ default constructor can NOT contain any code, that might leave. |
|
65 // ----------------------------------------------------------------------------- |
|
66 // |
|
67 PluginInfo::PluginInfo() |
|
68 : m_mimeTypes(KPluginGranularity), |
|
69 m_mimeFileExtensions(KPluginGranularity), |
|
70 m_mimeExtensionToTypeMap(KPluginGranularity), |
|
71 m_mimeDescriptions(KPluginGranularity), |
|
72 m_handle(-1) |
|
73 { |
|
74 } |
|
75 |
|
76 // ----------------------------------------------------------------------------- |
|
77 // PluginInfo::~PluginInfo |
|
78 // |
|
79 // Deconstructor. |
|
80 // ----------------------------------------------------------------------------- |
|
81 // |
|
82 PluginInfo::~PluginInfo() |
|
83 { |
|
84 m_mimeDescriptions.ResetAndDestroy(); |
|
85 m_mimeDescriptions.Close(); |
|
86 |
|
87 // Don't ResetAndDestroy() the m_mimeExtensionToTypeMap array, this array |
|
88 // contains pointers (memory) that is cleaned up in the m_mimeTypes array |
|
89 m_mimeExtensionToTypeMap.Close(); |
|
90 |
|
91 m_mimeFileExtensions.ResetAndDestroy(); |
|
92 m_mimeFileExtensions.Close(); |
|
93 |
|
94 m_mimeTypes.ResetAndDestroy(); |
|
95 m_mimeTypes.Close(); |
|
96 |
|
97 delete m_name; |
|
98 delete m_description; |
|
99 delete m_nppFuncs; |
|
100 delete m_filename; |
|
101 |
|
102 } |
|
103 |
|
104 // ----------------------------------------------------------------------------- |
|
105 // PluginInfo::ShouldLoad |
|
106 // |
|
107 // Returns ETrue if the plugin should be loaded. |
|
108 // ----------------------------------------------------------------------------- |
|
109 // |
|
110 TBool PluginInfo::shouldLoad() |
|
111 { |
|
112 return m_ref < 1; |
|
113 } |
|
114 |
|
115 // ----------------------------------------------------------------------------- |
|
116 // PluginInfo::ShouldUnload |
|
117 // |
|
118 // Returns ETrue if the plugin should be unloaded. |
|
119 // ----------------------------------------------------------------------------- |
|
120 // |
|
121 TBool PluginInfo::shouldUnload() |
|
122 { |
|
123 return m_ref == 1; |
|
124 } |
|
125 |
|
126 // ----------------------------------------------------------------------------- |
|
127 // PluginInfo::LoadInstance |
|
128 // |
|
129 // Increments the PluginInfo's reference count |
|
130 // ----------------------------------------------------------------------------- |
|
131 // |
|
132 void PluginInfo::loadInstance() |
|
133 { |
|
134 m_ref++; |
|
135 } |
|
136 |
|
137 // ----------------------------------------------------------------------------- |
|
138 // PluginInfo::UnloadInstance |
|
139 // |
|
140 // Decrements the PluginInfo's reference count. |
|
141 // ----------------------------------------------------------------------------- |
|
142 // |
|
143 void PluginInfo::unloadInstance() |
|
144 { |
|
145 m_ref--; |
|
146 } |
|
147 |
|
148 // ----------------------------------------------------------------------------- |
|
149 // PluginInfo::CopyMimeDescription |
|
150 // |
|
151 // Copy the mimetypes and file extention from one plugin info struct to another, |
|
152 // Called after a rescan of the file system |
|
153 // ----------------------------------------------------------------------------- |
|
154 // |
|
155 void PluginInfo::copyMimeDescription(PluginInfo& pluginInfo) |
|
156 { |
|
157 TUint i; |
|
158 TUint count; |
|
159 HBufC* entry; |
|
160 |
|
161 m_mimeTypes.ResetAndDestroy(); |
|
162 m_mimeExtensionToTypeMap.Reset(); |
|
163 count = pluginInfo.m_mimeTypes.Count(); |
|
164 for (i = 0; i < count; i++) { |
|
165 entry = pluginInfo.m_mimeTypes[0]->Des().Alloc(); |
|
166 pluginInfo.m_mimeTypes.Remove(0); |
|
167 m_mimeTypes.Append(entry); |
|
168 } |
|
169 |
|
170 HBufC8* extEntry; |
|
171 m_mimeFileExtensions.ResetAndDestroy(); |
|
172 count = pluginInfo.m_mimeFileExtensions.Count(); |
|
173 for (i = 0; i < count; i++) { |
|
174 extEntry = pluginInfo.m_mimeFileExtensions[0]->Des().Alloc(); |
|
175 pluginInfo.m_mimeFileExtensions.Remove(0); |
|
176 m_mimeFileExtensions.Append(extEntry); |
|
177 m_mimeExtensionToTypeMap.Append(entry); |
|
178 } |
|
179 } |
|
180 |
|
181 // ----------------------------------------------------------------------------- |
|
182 // PluginInfo::GetMimeExtensionsL |
|
183 // |
|
184 // Gets the supported mimeExtensions for the mimeType presented. Returns a HBufC* |
|
185 // that has allocated memory, which is the responsibility of the caller to |
|
186 // clean up. The HBufC* will be NULL if no supported mimeExtensions are supported. |
|
187 // ----------------------------------------------------------------------------- |
|
188 // |
|
189 HBufC8* PluginInfo::getMimeExtensionsL(const TDesC& mimeType) |
|
190 { |
|
191 HBufC8* mimeTypeBuf = HBufC8::NewLC(128); |
|
192 TPtr8 mimeTypePtr(mimeTypeBuf->Des()); |
|
193 // |
|
194 for (TInt i = 0; i < m_mimeExtensionToTypeMap.Count(); i++) { |
|
195 |
|
196 if (*(m_mimeExtensionToTypeMap[i]) == mimeType) { |
|
197 // We found a mimeType match, save the mimeExtension |
|
198 HBufC8* mimeExtensionBuf = m_mimeFileExtensions[i]; |
|
199 // Make sure we can fit this mimeFileExtension |
|
200 TInt length = mimeExtensionBuf->Length(); |
|
201 // +1 is for ',' |
|
202 if (mimeTypePtr.Length() + length + 1 > mimeTypePtr.MaxLength()) { |
|
203 HBufC8* tmp = HBufC8::NewL(mimeTypePtr.Length() + 2 * length); |
|
204 mimeTypePtr.Set(tmp->Des()); |
|
205 mimeTypePtr.Copy(*mimeTypeBuf); |
|
206 CleanupStack::PopAndDestroy(); // mimeTypeBuf |
|
207 mimeTypeBuf = tmp; |
|
208 CleanupStack::PushL(mimeTypeBuf); |
|
209 } |
|
210 // append ',' unless this is the first item in the list |
|
211 if (mimeTypePtr.Length()) |
|
212 mimeTypePtr.Append(','); |
|
213 |
|
214 mimeTypePtr.Append(*mimeExtensionBuf); |
|
215 } |
|
216 } |
|
217 |
|
218 CleanupStack::Pop(); //mimeTypeBuf |
|
219 return mimeTypeBuf; |
|
220 } |
|
221 |
|
222 // ----------------------------------------------------------------------------- |
|
223 // PluginInfo::ParseDefaultDataL(const TDesC8& mimeDesc) |
|
224 // |
|
225 // Parses the default_data string from resource file to populate the mimeTypes, mimeExtensions, |
|
226 // and mimeDescriptions arrays. |
|
227 // ----------------------------------------------------------------------------- |
|
228 // |
|
229 void PluginInfo::parseDefaultDataL(const TDesC8& mimeDesc) |
|
230 { |
|
231 __ASSERT_DEBUG(mimeDesc.Ptr() != NULL, panicHandler()); |
|
232 |
|
233 _LIT(KPattern1Ptr, ",;|"); |
|
234 _LIT(KPattern2Ptr, ";|"); |
|
235 |
|
236 TUint end(mimeDesc.Length()); |
|
237 TUint i(0); |
|
238 TUint marker(0); |
|
239 TUint16 mimeSeparator('|'); |
|
240 TUint fieldSeparator(';'); |
|
241 HBufC* newMimeTypeEntry = NULL; |
|
242 HBufC8* newMimeFileExtEntry = NULL; |
|
243 HBufC* newMimeDescriptionEntry = NULL; |
|
244 |
|
245 // Parse the mimeDesc string to populate the mimeTypes, mimeExtensions, |
|
246 // and mimeDescriptions arrays. |
|
247 |
|
248 for (; i < end;) { // outer for loop |
|
249 // Search until end of buffer or match one of the delimiters ';' or '|'. |
|
250 // We are looking for the mimeType, ie "text/html", "application/pdf", etc. |
|
251 for (; (i < end) && (KPattern2Ptr().Locate((mimeDesc)[i]) == KErrNotFound); i++) { |
|
252 // Walking the mimeDesc string |
|
253 } |
|
254 |
|
255 if (i > marker) { |
|
256 // Create new mimeType entry, the first entry is mimeType |
|
257 TPtrC8 mimeType8(mimeDesc.Mid(marker,i-marker)); |
|
258 newMimeTypeEntry = HBufC::NewLC(i-marker); |
|
259 newMimeTypeEntry->Des().Copy(mimeType8); |
|
260 User::LeaveIfError(m_mimeTypes.Append(newMimeTypeEntry)); |
|
261 CleanupStack::Pop(); //pop newMimeTypeEntry |
|
262 } |
|
263 |
|
264 // Are we at the end of the supported mime string |
|
265 if (i == end) { |
|
266 // This break with i=end means we leave outer for loop |
|
267 break; |
|
268 } |
|
269 |
|
270 marker = ++i; |
|
271 if ((mimeDesc)[i - 1] == mimeSeparator) { |
|
272 // Found a mime separator '|', get next supported mime |
|
273 continue; |
|
274 } |
|
275 |
|
276 // We are looking for the mimeFileExtensions, ie "html", "htm", "pdf", "txt", etc. |
|
277 // There can be multiple mimeFileExtentions per mimeType |
|
278 for (; (i < end);) { // inner for loop |
|
279 |
|
280 // Search until end of buffer or match one of the delimiters ';' or ',' or '|'. |
|
281 for (; (i < end) && (KPattern1Ptr().Locate((mimeDesc)[i]) == KErrNotFound); i++) { |
|
282 // Walking the mimeDesc string |
|
283 } |
|
284 |
|
285 if (i > marker) { |
|
286 TPtrC8 mimeFileExt8(mimeDesc.Mid(marker,i-marker)); |
|
287 newMimeFileExtEntry = HBufC8::NewLC(i-marker); |
|
288 newMimeFileExtEntry->Des().Copy(mimeFileExt8); |
|
289 User::LeaveIfError(m_mimeFileExtensions.Append(newMimeFileExtEntry)); |
|
290 CleanupStack::Pop(); //pop newMimeFileExtEntry |
|
291 |
|
292 // Add the mimeType to the mapping array. Every mimeFileExtension entry |
|
293 // in m_mimeFileExtensions, has a corresponding mimeType entry in |
|
294 // m_mimeExtensionToTypeMap. This allows us to provide a list of |
|
295 // extensions for each supported mimeType. |
|
296 User::LeaveIfError(m_mimeExtensionToTypeMap.Append(newMimeTypeEntry)); |
|
297 } |
|
298 |
|
299 // Are we at the end of the supported mime string |
|
300 if (i == end) { |
|
301 // This break means we leave the inner loop, and with i=end means |
|
302 // we leave the outer loop |
|
303 break; |
|
304 } |
|
305 |
|
306 marker = ++i; |
|
307 if ((mimeDesc)[i - 1] == mimeSeparator) { |
|
308 // Found a mime separator '|', get next supported mime |
|
309 break; |
|
310 } |
|
311 |
|
312 if ((mimeDesc)[i - 1] == fieldSeparator) { |
|
313 |
|
314 // Found a field separator ';', get the mimeDescription. |
|
315 // Search until end of buffer or match one of the delimiters ';' or '|'. |
|
316 for (; (i < end) && (KPattern2Ptr().Locate((mimeDesc)[i]) == KErrNotFound); i++) { |
|
317 // Walking the mimeDesc string |
|
318 } |
|
319 |
|
320 if (i > marker) { |
|
321 // Create new mimeDescription entry |
|
322 TPtrC8 mimeDesc8(mimeDesc.Mid(marker,i-marker)); |
|
323 newMimeDescriptionEntry = HBufC::NewLC(i-marker); |
|
324 newMimeDescriptionEntry->Des().Copy(mimeDesc8); |
|
325 |
|
326 User::LeaveIfError(m_mimeDescriptions.Append(newMimeDescriptionEntry)); |
|
327 CleanupStack::Pop(); //pop newMimeDescriptionEntry |
|
328 } |
|
329 |
|
330 // Are we at the end of the supported mime string |
|
331 if (i == end) { |
|
332 // This break means we leave the inner loop, and with i=end means |
|
333 // we leave the outer loop |
|
334 break; |
|
335 } |
|
336 |
|
337 marker = ++i; |
|
338 // Make sure we start at the next mime, after we found the mimeDescription. |
|
339 // We are handling a mime string with an extra semi-colon(s), |
|
340 // ie "...mimeDescription1;|mimeType2 |
|
341 for (; (i < end) && ((mimeDesc)[i-1] != mimeSeparator); i++) { |
|
342 // Walking the mimeDesc string |
|
343 } |
|
344 |
|
345 // Leave the inner loop and look for the next mime |
|
346 break; |
|
347 |
|
348 } // end of if fieldSeparator aka get mimeDescription |
|
349 |
|
350 // If we get here, we have another mimeFileExtension. Continue on the |
|
351 // inner loop to find additional mimeFileExtensions. |
|
352 |
|
353 } // end of inner for (;i<end;) |
|
354 } // end of outer for (;i<end;) |
|
355 } |
|
356 |
|
357 |
|
358 // ----------------------------------------------------------------------------- |
|
359 // PluginInfo::ParseDisplayNameL(const TDesC& nameDesc) |
|
360 // |
|
361 // Parses the display_name string from resource file to populate the file name and plugin name |
|
362 // ----------------------------------------------------------------------------- |
|
363 // |
|
364 void PluginInfo::parseDisplayNameL(const TDesC& nameDesc) |
|
365 { |
|
366 __ASSERT_DEBUG(nameDesc.Ptr() != NULL, panicHandler()); |
|
367 |
|
368 _LIT16(KSeparator, ";"); |
|
369 |
|
370 TUint end(nameDesc.Length()); |
|
371 TInt offset; |
|
372 TPtrC fileNamePtr; |
|
373 TPtrC namePtr; |
|
374 |
|
375 offset = nameDesc.Find(KSeparator); |
|
376 if (offset != KErrNotFound) { |
|
377 if (offset) { |
|
378 fileNamePtr.Set(nameDesc.Left(offset)); |
|
379 namePtr.Set(nameDesc.Right(end - offset - 1)); |
|
380 m_filename = fileNamePtr.AllocL(); |
|
381 m_name = namePtr.AllocL(); |
|
382 } |
|
383 } |
|
384 |
|
385 } |
|
386 |
|
387 // ============================ MEMBER FUNCTIONS =============================== |
|
388 |
|
389 |
|
390 // ----------------------------------------------------------------------------- |
|
391 // PluginHandler::PluginHandler |
|
392 // |
|
393 // C++ default constructor can NOT contain any code, that |
|
394 // might leave. |
|
395 // ----------------------------------------------------------------------------- |
|
396 // |
|
397 PluginHandler::PluginHandler(TBool enablePlugins) |
|
398 : m_pluginInfoArray( KPluginGranularity ) |
|
399 ,m_enablePlugins(enablePlugins) |
|
400 ,m_asyncLoading(ETrue) |
|
401 { |
|
402 } |
|
403 |
|
404 |
|
405 // ----------------------------------------------------------------------------- |
|
406 // PluginHandler::ConstructL |
|
407 // |
|
408 // Symbian 2nd phase constructor can leave. |
|
409 // ----------------------------------------------------------------------------- |
|
410 // |
|
411 void PluginHandler::ConstructL() |
|
412 { |
|
413 m_idle = CIdle::NewL(CActive::EPriorityLow); |
|
414 m_idle->Start(TCallBack(initialize, this)); |
|
415 } |
|
416 |
|
417 |
|
418 // ----------------------------------------------------------------------------- |
|
419 // PluginHandler::NewL |
|
420 // |
|
421 // Two-phased constructor. |
|
422 // ----------------------------------------------------------------------------- |
|
423 // |
|
424 PluginHandler* PluginHandler::NewL(TBool enablePlugins) |
|
425 { |
|
426 PluginHandler* self = new(ELeave) PluginHandler(enablePlugins); |
|
427 CleanupStack::PushL(self); |
|
428 self->ConstructL(); |
|
429 CleanupStack::Pop(); |
|
430 return self; |
|
431 } |
|
432 |
|
433 // ----------------------------------------------------------------------------- |
|
434 // PluginHandler::~PluginHandler |
|
435 // |
|
436 // Deconstructor. |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 PluginHandler::~PluginHandler() |
|
440 { |
|
441 m_pluginInfoArray.ResetAndDestroy(); |
|
442 m_pluginInfoArray.Close(); |
|
443 if (m_idle) { |
|
444 m_idle->Cancel(); |
|
445 } |
|
446 delete m_idle; |
|
447 } |
|
448 |
|
449 // ----------------------------------------------------------------------------- |
|
450 // PluginHandler::Initialize |
|
451 // |
|
452 // Initializes the PluginHandler, possibly asynchronously |
|
453 // ----------------------------------------------------------------------------- |
|
454 // |
|
455 TBool PluginHandler::initialize(TAny* pluginHandler) |
|
456 { |
|
457 TBool doneInit(EFalse); |
|
458 |
|
459 PluginHandler* handler = (PluginHandler*)pluginHandler; |
|
460 |
|
461 TRAPD(err, doneInit = handler->loadPluginsL()); |
|
462 if (err) { |
|
463 // If we leave from LoadPluginsL, stop CIdle |
|
464 doneInit = EFalse; |
|
465 } |
|
466 |
|
467 return doneInit; |
|
468 } |
|
469 |
|
470 //------------------------------------------------------------------------------ |
|
471 // PluginHandler::loadPluginsL |
|
472 // |
|
473 // Loads all the plugins and query them for details. |
|
474 // ----------------------------------------------------------------------------- |
|
475 // |
|
476 TBool PluginHandler::loadPluginsL() |
|
477 { |
|
478 |
|
479 if(m_pluginsLoaded) { |
|
480 return EFalse; |
|
481 } |
|
482 |
|
483 // 1) fetch CImplementationInformation instances from the ECOM infrastructure |
|
484 // 2) create plugin info for each plugin |
|
485 |
|
486 // Create the ECom info array, contains the plugin information |
|
487 RImplInfoPtrArray ecomPluginInfoArray; |
|
488 |
|
489 // Get list of ECOM plugins that match the KNBrowserPluginInterfaceUid |
|
490 REComSession::ListImplementationsL(KBrowserPluginInterfaceUid, ecomPluginInfoArray); |
|
491 |
|
492 // Loop through all the Netscape plugins found by ECom and populate the |
|
493 // m_pluginInfoArray |
|
494 m_nextHandle = 0; |
|
495 const TInt pluginCount = ecomPluginInfoArray.Count(); |
|
496 for (TInt index=0; index<pluginCount; ++index) { |
|
497 PluginInfo* pluginInfo = new(ELeave) PluginInfo; |
|
498 pluginInfo->m_handle = m_nextHandle++; |
|
499 CleanupStack::PushL(pluginInfo); |
|
500 |
|
501 // Set the plugin properties |
|
502 pluginInfo->m_pluginInfo = ecomPluginInfoArray[index]; |
|
503 // Read the plugin's name and plugin FileName (display_name) from the IMPLEMENTATION_INFO |
|
504 pluginInfo->parseDisplayNameL(pluginInfo->m_pluginInfo->DisplayName()); |
|
505 pluginInfo->m_description = HBufC::NewL(pluginInfo->m_pluginInfo->OpaqueData().Length()); |
|
506 pluginInfo->m_description->Des().Copy(pluginInfo->m_pluginInfo->OpaqueData()); |
|
507 pluginInfo->m_uid = pluginInfo->m_pluginInfo->ImplementationUid(); |
|
508 // Parses the mimeDesc string to populate the mimeTypes, mimeExtensions, |
|
509 // and mimeDescriptions arrays. |
|
510 pluginInfo->parseDefaultDataL(pluginInfo->m_pluginInfo->DataType()); |
|
511 |
|
512 // Add the filter information to the list |
|
513 User::LeaveIfError(m_pluginInfoArray.Append(pluginInfo)); |
|
514 CleanupStack::Pop(); // pluginInfo |
|
515 } |
|
516 |
|
517 // Clean up the ECom info array |
|
518 ecomPluginInfoArray.ResetAndDestroy(); |
|
519 ecomPluginInfoArray.Close(); |
|
520 |
|
521 m_pluginsLoaded = ETrue; |
|
522 return EFalse; |
|
523 } |
|
524 |
|
525 // ----------------------------------------------------------------------------- |
|
526 // PluginHandler::findPlugin |
|
527 // |
|
528 // Find a plugin by MIME type. |
|
529 // ----------------------------------------------------------------------------- |
|
530 // |
|
531 TInt PluginHandler::findPlugin(const TDesC& mimeType) |
|
532 { |
|
533 LOAD_PLUGINS |
|
534 |
|
535 HBufC* newMimeType = NULL; |
|
536 _LIT(KSeparator, "*"); |
|
537 TInt pluginIndex; |
|
538 TInt mimeIndex; |
|
539 |
|
540 if (mimeType.FindF(KMimeTypeAudio) != KErrNotFound){ |
|
541 newMimeType = HBufC::NewLC(KMimeTypeLength); |
|
542 newMimeType->Des().Copy(KMimeTypeAudio); |
|
543 newMimeType->Des().Append(KSeparator); |
|
544 } |
|
545 else if (mimeType.FindF(KMimeTypeVideo) != KErrNotFound){ |
|
546 newMimeType = HBufC::NewLC(KMimeTypeLength); |
|
547 newMimeType->Des().Copy(KMimeTypeVideo); |
|
548 newMimeType->Des().Append(KSeparator); |
|
549 } |
|
550 else{ |
|
551 newMimeType = HBufC::NewLC(mimeType.Length()); |
|
552 newMimeType = mimeType.AllocL(); |
|
553 } |
|
554 CleanupStack::Pop(); //pop newMimeType |
|
555 |
|
556 for (pluginIndex = 0; pluginIndex < m_pluginInfoArray.Count(); pluginIndex++) { |
|
557 for (mimeIndex = 0; |
|
558 mimeIndex < m_pluginInfoArray[pluginIndex]->m_mimeTypes.Count(); |
|
559 mimeIndex++) { |
|
560 if (!m_pluginInfoArray[pluginIndex]->m_mimeTypes[mimeIndex]->CompareF(*newMimeType)) { |
|
561 delete newMimeType; |
|
562 return m_pluginInfoArray[pluginIndex]->m_handle; |
|
563 } |
|
564 } |
|
565 } |
|
566 delete newMimeType; |
|
567 return KErrNotFound; |
|
568 } |
|
569 |
|
570 // ----------------------------------------------------------------------------- |
|
571 // PluginHandler::findPluginByExtension |
|
572 // |
|
573 // Find a plugin by file extension. |
|
574 // ----------------------------------------------------------------------------- |
|
575 // |
|
576 TInt PluginHandler::findPluginByExtension(const TDesC8& url) |
|
577 { |
|
578 LOAD_PLUGINS |
|
579 |
|
580 TInt pluginIndex; |
|
581 TInt extIndex; |
|
582 |
|
583 TPtrC8 extPtr(url.Mid(url.LocateReverse('.') + 1)); |
|
584 for (pluginIndex = 0; pluginIndex < m_pluginInfoArray.Count(); pluginIndex++) { |
|
585 |
|
586 for (extIndex = 0; |
|
587 extIndex < m_pluginInfoArray[pluginIndex]-> |
|
588 m_mimeFileExtensions.Count(); extIndex++) { |
|
589 |
|
590 if (!m_pluginInfoArray[pluginIndex]->m_mimeFileExtensions[extIndex]->CompareF(extPtr)) { |
|
591 return m_pluginInfoArray[pluginIndex]->m_handle; |
|
592 } |
|
593 } |
|
594 } |
|
595 |
|
596 return KErrNotFound; |
|
597 } |
|
598 |
|
599 |
|
600 // ----------------------------------------------------------------------------- |
|
601 // PluginHandler::loadPluginL |
|
602 // |
|
603 // Load a plugin if not yet loaded and return its function table. The handle was |
|
604 // gotten from the methods FindPlugin and FindPluginFromExtension, so the |
|
605 // handle should be valid. |
|
606 // ----------------------------------------------------------------------------- |
|
607 // |
|
608 void PluginHandler::loadPluginL(TInt handle, NPPluginFuncs** retPluginFuncs) |
|
609 { |
|
610 LOAD_PLUGINS |
|
611 |
|
612 TUint index(getIndexFromHandle(handle)); |
|
613 __ASSERT_DEBUG(index < (TUint)m_pluginInfoArray.Count(), panicHandler()); |
|
614 |
|
615 PluginInfo* plugin = m_pluginInfoArray[index]; |
|
616 |
|
617 if (plugin->shouldLoad()) { |
|
618 |
|
619 NPPluginFuncs* pluginFuncs = (NPPluginFuncs*) User::AllocLC(sizeof (NPPluginFuncs)); |
|
620 Mem::FillZ((void*) pluginFuncs, sizeof (NPPluginFuncs)); |
|
621 // create CEcomBrowserPluginInterface, given the UID from the PLuginInfo, when ref count == 0 |
|
622 plugin->m_pluginInterface = CEcomBrowserPluginInterface::CreatePluginL(plugin->m_uid, |
|
623 (NPNetscapeFuncs *) (&NpnImplementationFuncs), pluginFuncs); |
|
624 |
|
625 CleanupStack::Pop(pluginFuncs); |
|
626 plugin->m_nppFuncs = pluginFuncs; |
|
627 pluginFuncs = NULL; |
|
628 } |
|
629 |
|
630 plugin->loadInstance(); |
|
631 __ASSERT_DEBUG(plugin->m_nppFuncs != NULL, panicHandler()); |
|
632 *retPluginFuncs = plugin->m_nppFuncs; |
|
633 |
|
634 } |
|
635 |
|
636 |
|
637 // ----------------------------------------------------------------------------- |
|
638 // PluginHandler::UnloadPlugin |
|
639 // |
|
640 // Unload a plugin. If this is the last instance, the library is unloaded. |
|
641 // The handle was gotten from the methods FindPlugin and FindPluginFromExtension, |
|
642 // so the handle should be valid. |
|
643 // ----------------------------------------------------------------------------- |
|
644 // |
|
645 void PluginHandler::unloadPlugin(TInt handle) |
|
646 { |
|
647 TUint index(getIndexFromHandle(handle)); |
|
648 __ASSERT_DEBUG(index < (TUint) m_pluginInfoArray.Count(), panicHandler()); |
|
649 |
|
650 PluginInfo* plugin = m_pluginInfoArray[index]; |
|
651 |
|
652 if (plugin->shouldUnload()) { |
|
653 User::Free(plugin->m_nppFuncs); |
|
654 plugin->m_nppFuncs = NULL; |
|
655 // delete the CEcomBrowserPluginInterface instance when ref count == 0 |
|
656 delete plugin->m_pluginInterface; |
|
657 } |
|
658 |
|
659 plugin->unloadInstance(); |
|
660 } |
|
661 |
|
662 // ----------------------------------------------------------------------------- |
|
663 // PluginHandler::GetIndexFromHandle |
|
664 // |
|
665 // Get the index of plugin info from its handle. This method should always |
|
666 // return a valid handle, since the calling program got the handle from the |
|
667 // methods FindPlugin and FindPluginFromExtension. |
|
668 // ----------------------------------------------------------------------------- |
|
669 // |
|
670 TUint PluginHandler::getIndexFromHandle(TInt handle) |
|
671 { |
|
672 LOAD_PLUGINS |
|
673 TUint index; |
|
674 TUint count(m_pluginInfoArray.Count()); |
|
675 |
|
676 __ASSERT_DEBUG(handle >= 0, panicHandler()); |
|
677 |
|
678 for (index = 0; index < count; index++) { |
|
679 if (m_pluginInfoArray[index]->m_handle == handle) { |
|
680 return index; |
|
681 } |
|
682 } |
|
683 |
|
684 // We should never get here. We should always return a valid handle. Return |
|
685 // the count (handle + 1), this should assert debug in calling methods, as |
|
686 // well as the forced assert debug . |
|
687 __ASSERT_DEBUG(EFalse, panicHandler()); |
|
688 return count; |
|
689 } |
|
690 |
|
691 // ----------------------------------------------------------------------------- |
|
692 // PluginHandler::GetPluginCount |
|
693 // |
|
694 // Returns the number of plugins supported by the platform |
|
695 // ----------------------------------------------------------------------------- |
|
696 TInt PluginHandler::getPluginCount() |
|
697 { |
|
698 LOAD_PLUGINS |
|
699 return m_pluginInfoArray.Count(); |
|
700 } |
|
701 |
|
702 TBool PluginHandler::pluginSupportsMIMEType(const TDesC& mimeType) |
|
703 { |
|
704 return findPlugin(mimeType) != KErrNotFound; |
|
705 } |
|
706 |
|
707 TBool PluginHandler::objectAtIndex(TInt index, TWebCorePluginInfo& pluginInfo ) |
|
708 { |
|
709 if (index<0 || index>m_pluginInfoArray.Count()-1) |
|
710 return EFalse; |
|
711 |
|
712 PluginInfo* pinfo = m_pluginInfoArray[index]; |
|
713 if (!pinfo) |
|
714 return EFalse; |
|
715 |
|
716 pluginInfo.iName.Set(KNullDesC()); |
|
717 pluginInfo.iFilename.Set(KNullDesC()); |
|
718 pluginInfo.iPluginDescription.Set(KNullDesC()); |
|
719 // |
|
720 if (pinfo->name()) |
|
721 pluginInfo.iName.Set(*(pinfo->name())); |
|
722 if (pinfo->fileName()) |
|
723 pluginInfo.iFilename.Set(*(pinfo->fileName())); |
|
724 if (pinfo->description()) |
|
725 pluginInfo.iPluginDescription.Set(*(pinfo->description())); |
|
726 |
|
727 pluginInfo.iMimeTypeArray = pinfo->mimeTypes(); |
|
728 |
|
729 return ETrue; |
|
730 } |
|
731 |
|
732 void PluginHandler::refreshPlugins(TBool reload) |
|
733 { |
|
734 TRAP_IGNORE(reloadPluginsL(reload)); |
|
735 } |
|
736 |
|
737 HBufC8* PluginHandler::extensionsForMIMEType(TInt index, TDesC& mimeType ) |
|
738 { |
|
739 PluginInfo *pluginInfo = m_pluginInfoArray[index]; |
|
740 HBufC8 *extn = NULL; |
|
741 TRAP_IGNORE(extn = pluginInfo->getMimeExtensionsL(mimeType)); |
|
742 return extn; |
|
743 } |
|
744 |
|
745 HBufC* PluginHandler::descriptionForMIMEType(TInt index, TDesC& mimeType ) |
|
746 { |
|
747 // there is no way to tell mimeType-description pairs. return the whole string |
|
748 PluginInfo *pluginInfo = m_pluginInfoArray[index]; |
|
749 RPointerArray<HBufC> items = pluginInfo->mimeDescriptions(); |
|
750 HBufC* descBuf = HBufC::New(128); |
|
751 if (!descBuf) |
|
752 return descBuf; |
|
753 |
|
754 TPtr descPtr(descBuf->Des()); |
|
755 for (TInt i=0; i<items.Count(); i++ ) { |
|
756 |
|
757 // Make sure we can fit this mimeFileExtension |
|
758 HBufC* desc = items[i]; |
|
759 TInt length = desc->Length(); |
|
760 // +1 is for ',' |
|
761 if (descPtr.Length() + length + 1 > descPtr.MaxLength()) { |
|
762 HBufC* tmp = HBufC::New(descPtr.Length() + 2 * length); |
|
763 if (!tmp) { |
|
764 // return whatever we have |
|
765 return descBuf; |
|
766 } |
|
767 descPtr.Set(tmp->Des()); |
|
768 descPtr.Copy(*descBuf); |
|
769 descBuf = tmp; |
|
770 } |
|
771 // append ',' unless this is the first item in the list |
|
772 if (descPtr.Length()) |
|
773 descPtr.Append(','); |
|
774 descPtr.Append(*desc); |
|
775 } |
|
776 |
|
777 return descBuf; |
|
778 } |
|
779 |
|
780 // ----------------------------------------------------------------------------- |
|
781 // PluginHandler::ReloadPluginsL |
|
782 // |
|
783 // Rescan for new plugins. |
|
784 // ----------------------------------------------------------------------------- |
|
785 // |
|
786 void PluginHandler::reloadPluginsL(TBool reload) |
|
787 { |
|
788 // This function stores the plugins that are currently loaded in a temp array |
|
789 // Then it rescans the drives for all plugins |
|
790 // Currently loaded plugins must exist in the new list because the dll is loaded |
|
791 // and the plugin could not be deleted from the file system while the dll is loaded. |
|
792 // After rescanning, each plugin from the temp array is matched with a plugin |
|
793 // in the new array. The matching is done by file name. |
|
794 // Each new entry is replaced with the existing entry from the temp array. |
|
795 // This is done because the CPluginInst object keeps the handle and |
|
796 // the function table of the existing plugin. |
|
797 |
|
798 RPointerArray<PluginInfo> tmpPluginInfoArray; |
|
799 PluginInfo* pluginInfo = NULL; |
|
800 TInt count(m_pluginInfoArray.Count()); |
|
801 TInt index; |
|
802 |
|
803 // Copy all the loaded plugins to a temp array |
|
804 for (index = 0; index < count; index++) { |
|
805 pluginInfo = m_pluginInfoArray[0]; |
|
806 if (pluginInfo->shouldLoad()) { // Is it currently loaded? |
|
807 m_pluginInfoArray.Remove(0); |
|
808 delete pluginInfo; |
|
809 pluginInfo = NULL; |
|
810 } |
|
811 else { |
|
812 m_pluginInfoArray.Remove(0); |
|
813 tmpPluginInfoArray.Append(pluginInfo); |
|
814 } |
|
815 } |
|
816 |
|
817 // reload the plugins by scanning the drives |
|
818 if (m_idle) { |
|
819 m_idle->Cancel(); |
|
820 } |
|
821 |
|
822 //Load the plugins synchronously |
|
823 m_asyncLoading = EFalse; |
|
824 m_pluginsLoaded =EFalse; |
|
825 loadPluginsL(); |
|
826 count = m_pluginInfoArray.Count(); |
|
827 |
|
828 TInt tmpCount(tmpPluginInfoArray.Count()); |
|
829 TInt i; |
|
830 PluginInfo* delPluginInfo = NULL; |
|
831 for (index = 0; index < tmpCount; index++) { |
|
832 pluginInfo = tmpPluginInfoArray[0]; |
|
833 tmpPluginInfoArray.Remove(0); |
|
834 // Search through the array for a filename match |
|
835 // use ECOM Uid rather then file names |
|
836 for (i = 0; i < count && (pluginInfo->m_uid != m_pluginInfoArray[i]->m_uid); i++) { |
|
837 } |
|
838 |
|
839 if (i == count) { |
|
840 i = -1; |
|
841 } |
|
842 |
|
843 if (i >= 0) { |
|
844 // i < 0 only if rescanning failed |
|
845 delPluginInfo = m_pluginInfoArray[i]; |
|
846 m_pluginInfoArray.Remove(i); |
|
847 // Save the new Mimetype and extensions. They might be different than before |
|
848 pluginInfo->copyMimeDescription(*delPluginInfo); |
|
849 |
|
850 delete (delPluginInfo); |
|
851 delPluginInfo = NULL; |
|
852 } |
|
853 |
|
854 m_pluginInfoArray.Append(pluginInfo); |
|
855 } |
|
856 |
|
857 tmpPluginInfoArray.Close(); |
|
858 if (reload) { |
|
859 //m_view.mainFrame().WebKitBridge().reload(); |
|
860 } |
|
861 |
|
862 } |
|
863 |
|
864 // ----------------------------------------------------------------------------- |
|
865 // PluginHandler::IsSupported |
|
866 // |
|
867 // Determines whether a given content-type of dot-extension has a cooresponding |
|
868 // plugin or external application. aContentType and aUrl can be NULL, but at least |
|
869 // one must be non-NULL (otherwise it will always return EFalse). If handlerType |
|
870 // is EPlugin then it returns ETrue only if their is a supported plugin. If handlerType |
|
871 // is EExternalApp then it returns ETrue only if their is a supported external |
|
872 // application. If handlerType is EBoth then it returns ETrue only if their is a |
|
873 // supported plugin or external application. |
|
874 // ----------------------------------------------------------------------------- |
|
875 TBool PluginHandler::isSupported(const TDesC& contentType, const TDesC8& url) |
|
876 { |
|
877 TBool isSupported(EFalse); |
|
878 |
|
879 // Do we have a plugin that supports this content type |
|
880 if (contentType.FindF(KMimeTypeAudio) != KErrNotFound || contentType.FindF(KMimeTypeVideo) != KErrNotFound |
|
881 || findPlugin(contentType) != KErrNotFound || findPluginByExtension(url) != KErrNotFound) { |
|
882 isSupported = ETrue; |
|
883 } |
|
884 // We don't have a plugin to support this content |
|
885 return isSupported; |
|
886 } |
|
887 |
|
888 // End of File |