• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
4  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef __LP64__
29 
30 #include "config.h"
31 #include "PluginPackage.h"
32 
33 #include <wtf/RetainPtr.h>
34 #include "CString.h"
35 #include "MIMETypeRegistry.h"
36 #include "npruntime_impl.h"
37 #include "PluginDatabase.h"
38 #include "PluginDebug.h"
39 #include "WebCoreNSStringExtras.h"
40 
41 #include <CoreFoundation/CoreFoundation.h>
42 
43 #define PluginNameOrDescriptionStringNumber     126
44 #define MIMEDescriptionStringNumber             127
45 #define MIMEListStringStringNumber              128
46 
47 namespace WebCore {
48 
determineQuirks(const String & mimeType)49 void PluginPackage::determineQuirks(const String& mimeType)
50 {
51     if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
52         // Because a single process cannot create multiple VMs, and we cannot reliably unload a
53         // Java VM, we cannot unload the Java Plugin, or we'll lose reference to our only VM
54         m_quirks.add(PluginQuirkDontUnloadPlugin);
55 
56         // Setting the window region to an empty region causes bad scrolling repaint problems
57         // with the Java plug-in.
58         m_quirks.add(PluginQuirkDontClipToZeroRectWhenScrolling);
59     }
60 
61     if (mimeType == "application/x-shockwave-flash") {
62         // The flash plugin only requests windowless plugins if we return a mozilla user agent
63         m_quirks.add(PluginQuirkWantsMozillaUserAgent);
64         m_quirks.add(PluginQuirkThrottleInvalidate);
65         m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
66         m_quirks.add(PluginQuirkFlashURLNotifyBug);
67     }
68 
69 }
70 
71 typedef void (*BP_CreatePluginMIMETypesPreferencesFuncPtr)(void);
72 
readPListFile(CFStringRef fileName,bool createFile,CFBundleRef bundle)73 static WTF::RetainPtr<CFDictionaryRef> readPListFile(CFStringRef fileName, bool createFile, CFBundleRef bundle)
74 {
75     if (createFile) {
76         BP_CreatePluginMIMETypesPreferencesFuncPtr funcPtr =
77             (BP_CreatePluginMIMETypesPreferencesFuncPtr)CFBundleGetFunctionPointerForName(bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
78         if (funcPtr)
79             funcPtr();
80     }
81 
82     WTF::RetainPtr<CFDictionaryRef> map;
83     WTF::RetainPtr<CFURLRef> url =
84         CFURLCreateWithFileSystemPath(kCFAllocatorDefault, fileName, kCFURLPOSIXPathStyle, false);
85 
86     CFDataRef resource = 0;
87     SInt32 code;
88     if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, url.get(), &resource, 0, 0, &code))
89         return map;
90 
91     WTF::RetainPtr<CFPropertyListRef> propertyList =
92             CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, kCFPropertyListImmutable, 0);
93 
94     CFRelease(resource);
95 
96     if (!propertyList)
97         return map;
98 
99     if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID())
100         return map;
101 
102     map = static_cast<CFDictionaryRef>(static_cast<CFPropertyListRef>(propertyList.get()));
103     return map;
104 }
105 
stringListFromResourceId(SInt16 id)106 static Vector<String> stringListFromResourceId(SInt16 id)
107 {
108     Vector<String> list;
109 
110     Handle handle = Get1Resource('STR#', id);
111     if (!handle)
112         return list;
113 
114     CFStringEncoding encoding = stringEncodingForResource(handle);
115 
116     unsigned char* p = (unsigned char*)*handle;
117     if (!p)
118         return list;
119 
120     SInt16 count = *(SInt16*)p;
121     p += sizeof(SInt16);
122 
123     for (SInt16 i = 0; i < count; ++i) {
124         unsigned char length = *p;
125         WTF::RetainPtr<CFStringRef> str = CFStringCreateWithPascalString(0, p, encoding);
126         list.append(str.get());
127         p += 1 + length;
128     }
129 
130     return list;
131 }
132 
fetchInfo()133 bool PluginPackage::fetchInfo()
134 {
135     if (!load())
136         return false;
137 
138     WTF::RetainPtr<CFDictionaryRef> mimeDict;
139 
140     WTF::RetainPtr<CFTypeRef> mimeTypesFileName = CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginMIMETypesFilename"));
141     if (mimeTypesFileName && CFGetTypeID(mimeTypesFileName.get()) == CFStringGetTypeID()) {
142 
143         WTF::RetainPtr<CFStringRef> fileName = (CFStringRef)mimeTypesFileName.get();
144         WTF::RetainPtr<CFStringRef> homeDir = homeDirectoryPath().createCFString();
145         WTF::RetainPtr<CFStringRef> path = CFStringCreateWithFormat(0, 0, CFSTR("%@/Library/Preferences/%@"), homeDir.get(), fileName.get());
146 
147         WTF::RetainPtr<CFDictionaryRef> plist = readPListFile(path.get(), /*createFile*/ false, m_module);
148         if (plist) {
149             // If the plist isn't localized, have the plug-in recreate it in the preferred language.
150             WTF::RetainPtr<CFStringRef> localizationName =
151                 (CFStringRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginLocalizationName"));
152             CFLocaleRef locale = CFLocaleCopyCurrent();
153             if (localizationName != CFLocaleGetIdentifier(locale))
154                 plist = readPListFile(path.get(), /*createFile*/ true, m_module);
155 
156             CFRelease(locale);
157         } else {
158             // Plist doesn't exist, ask the plug-in to create it.
159             plist = readPListFile(path.get(), /*createFile*/ true, m_module);
160         }
161 
162         mimeDict = (CFDictionaryRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginMIMETypes"));
163     }
164 
165     if (!mimeDict)
166         mimeDict = (CFDictionaryRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginMIMETypes"));
167 
168     if (mimeDict) {
169         CFIndex propCount = CFDictionaryGetCount(mimeDict.get());
170         Vector<const void*, 128> keys(propCount);
171         Vector<const void*, 128> values(propCount);
172         CFDictionaryGetKeysAndValues(mimeDict.get(), keys.data(), values.data());
173         for (int i = 0; i < propCount; ++i) {
174             String mimeType = (CFStringRef)keys[i];
175             mimeType = mimeType.lower();
176 
177             WTF::RetainPtr<CFDictionaryRef> extensionsDict = (CFDictionaryRef)values[i];
178 
179             WTF:RetainPtr<CFNumberRef> enabled = (CFNumberRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginTypeEnabled"));
180             if (enabled) {
181                 int enabledValue = 0;
182                 if (CFNumberGetValue(enabled.get(), kCFNumberIntType, &enabledValue) && enabledValue == 0)
183                     continue;
184             }
185 
186             Vector<String> mimeExtensions;
187             WTF::RetainPtr<CFArrayRef> extensions = (CFArrayRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginExtensions"));
188             if (extensions) {
189                 CFIndex extensionCount = CFArrayGetCount(extensions.get());
190                 for (CFIndex i = 0; i < extensionCount; ++i) {
191                     String extension =(CFStringRef)CFArrayGetValueAtIndex(extensions.get(), i);
192                     extension = extension.lower();
193                     mimeExtensions.append(extension);
194                 }
195             }
196             m_mimeToExtensions.set(mimeType, mimeExtensions);
197 
198             String description = (CFStringRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginTypeDescription"));
199             m_mimeToDescriptions.set(mimeType, description);
200         }
201 
202         m_name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginName"));
203         m_description = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginDescription"));
204 
205     } else {
206         int resFile = CFBundleOpenBundleResourceMap(m_module);
207 
208         UseResFile(resFile);
209 
210         Vector<String> mimes = stringListFromResourceId(MIMEListStringStringNumber);
211 
212         if (mimes.size() % 2 != 0)
213             return false;
214 
215         Vector<String> descriptions = stringListFromResourceId(MIMEDescriptionStringNumber);
216         if (descriptions.size() != mimes.size() / 2)
217             return false;
218 
219         for (size_t i = 0;  i < mimes.size(); i += 2) {
220             String mime = mimes[i].lower();
221             Vector<String> extensions;
222             mimes[i + 1].lower().split(UChar(','), extensions);
223 
224             m_mimeToExtensions.set(mime, extensions);
225 
226             m_mimeToDescriptions.set(mime, descriptions[i / 2]);
227         }
228 
229         Vector<String> names = stringListFromResourceId(PluginNameOrDescriptionStringNumber);
230         if (names.size() == 2) {
231             m_description = names[0];
232             m_name = names[1];
233         }
234 
235         CFBundleCloseBundleResourceMap(m_module, resFile);
236     }
237 
238     LOG(Plugins, "PluginPackage::fetchInfo(): Found plug-in '%s'", m_name.utf8().data());
239     if (isPluginBlacklisted()) {
240         LOG(Plugins, "\tPlug-in is blacklisted!");
241         return false;
242     }
243 
244     return true;
245 }
246 
isPluginBlacklisted()247 bool PluginPackage::isPluginBlacklisted()
248 {
249     if (name() == "Silverlight Plug-In" || name().startsWith("QuickTime Plug-in"))
250         return true;
251 
252     return false;
253 }
254 
load()255 bool PluginPackage::load()
256 {
257     if (m_isLoaded) {
258         m_loadCount++;
259         return true;
260     }
261 
262     WTF::RetainPtr<CFStringRef> path(AdoptCF, m_path.createCFString());
263     WTF::RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(),
264                                                                         kCFURLPOSIXPathStyle, false));
265     m_module = CFBundleCreate(NULL, url.get());
266     if (!m_module || !CFBundleLoadExecutable(m_module)) {
267         LOG(Plugins, "%s not loaded", m_path.utf8().data());
268         return false;
269     }
270 
271     m_isLoaded = true;
272 
273     NP_GetEntryPointsFuncPtr NP_GetEntryPoints = 0;
274     NP_InitializeFuncPtr NP_Initialize;
275     NPError npErr;
276 
277     NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_Initialize"));
278     NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_GetEntryPoints"));
279     m_NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_Shutdown"));
280 
281     if (!NP_Initialize || !NP_GetEntryPoints || !m_NPP_Shutdown)
282         goto abort;
283 
284     memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
285     m_pluginFuncs.size = sizeof(m_pluginFuncs);
286 
287     initializeBrowserFuncs();
288 
289     npErr = NP_Initialize(&m_browserFuncs);
290     LOG_NPERROR(npErr);
291     if (npErr != NPERR_NO_ERROR)
292         goto abort;
293 
294     npErr = NP_GetEntryPoints(&m_pluginFuncs);
295     LOG_NPERROR(npErr);
296     if (npErr != NPERR_NO_ERROR)
297         goto abort;
298 
299     m_loadCount++;
300     return true;
301 
302 abort:
303     unloadWithoutShutdown();
304     return false;
305 }
306 
307 } // namespace WebCore
308 
309 #else
310 
311 #include "../PluginPackageNone.cpp"
312 
313 #endif // !__LP64__
314