From 42388fc100b1473b1643d95ef6d42e9d9f42895e Mon Sep 17 00:00:00 2001 From: "serge%netscape.com" Date: Wed, 14 Aug 2002 22:31:59 +0000 Subject: [PATCH] ix 109739, removed nsIRegistry and switched to flat file support for caching plugins info, r=av, sr=dveditz git-svn-id: svn://10.0.0.236/trunk@127285 18797224-902f-48f8-a5cc-f745e15eee43 --- .../plugin/base/src/nsPluginHostImpl.cpp | 805 +++++++----------- .../plugin/base/src/nsPluginHostImpl.h | 9 +- .../base/src/nsPluginManifestLineReader.h | 131 +++ 3 files changed, 439 insertions(+), 506 deletions(-) create mode 100644 mozilla/modules/plugin/base/src/nsPluginManifestLineReader.h diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index bbe0bc13061..d0a43684fec 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -93,7 +93,7 @@ #undef None #endif -#include "nsIRegistry.h" +//#include "nsIRegistry.h" #include "nsEnumeratorUtils.h" #include "nsISupportsPrimitives.h" // for the dialog @@ -149,6 +149,7 @@ #include "nsPluginError.h" #include "nsUnicharUtils.h" +#include "nsPluginManifestLineReader.h" #include "imgILoader.h" #include "nsDefaultPlugin.h" @@ -190,8 +191,9 @@ // 0.03 changed name, description and mime desc from string to bytes, bug 108246 // 0.04 added new mime entry point on Mac, bug 113464 // 0.05 added new entry point check for the default plugin, bug 132430 -// 0.06 strip off suffixes in mime description strings, bug 53895 -static const char *kPluginInfoVersion = "0.06"; +// 0.06 strip off suffixes in mime description strings, bug 53895 +// 0.07 changed nsIRegistry to flat file support for caching plugins info +static const char *kPluginInfoVersion = "0.07"; //////////////////////////////////////////////////////////////////////// // CID's && IID's static NS_DEFINE_IID(kIPluginInstanceIID, NS_IPLUGININSTANCE_IID); @@ -210,7 +212,6 @@ static NS_DEFINE_CID(kIHttpHeaderVisitorIID, NS_IHTTPHEADERVISITOR_IID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_IID(kIFileUtilitiesIID, NS_IFILEUTILITIES_IID); static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID); -static NS_DEFINE_CID(kRegistryCID, NS_REGISTRY_CID); static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1"; // for the dialog static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); @@ -232,6 +233,8 @@ static const char kPluginsMimeTypeKey[] = "mimetype"; static const char kPluginsMimeDescKey[] = "description"; static const char kPluginsMimeExtKey[] = "extension"; +#define kPluginRegistryFilename NS_LITERAL_CSTRING("pluginreg.dat") + #ifdef PLUGIN_LOGGING PRLogModuleInfo* nsPluginLogging::gNPNLog = nsnull; PRLogModuleInfo* nsPluginLogging::gNPPLog = nsnull; @@ -343,6 +346,31 @@ void DisplayNoDefaultPluginDialog(const char *mimeType, nsIPrompt *prompt) return; } +//////////////////////////////////////////////////////////////////////// +// flat file reg funcs +static +PRBool ReadSectionHeader(nsManifestLineReader& reader, const char *token) +{ + do { + if (*reader.LinePtr() == '[') { + char* p = reader.LinePtr() + (reader.LineLength() - 1); + if (*p != ']') + break; + *p = 0; + + char* values[1]; + if (1 != reader.ParseLine(values, 1)) + break; + // ignore the leading '[' + if (PL_strcmp(values[0]+1, token)) { + break; // it's wrong token + } + return PR_TRUE; + } + } while (reader.NextLine()); + return PR_FALSE; +} + //////////////////////////////////////////////////////////////////////// // Little helper struct to asynchronously reframe any presentations (embedded) // or reload any documents (full-page), that contained plugins @@ -1186,11 +1214,12 @@ PRBool nsPluginTag::Equals(nsPluginTag *aPluginTag) (mVariants != aPluginTag->mVariants) ) return PR_FALSE; - if (0 != mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) - for (PRInt32 i = 0; i < mVariants; i++) + if (mVariants && mMimeTypeArray && aPluginTag->mMimeTypeArray) { + for (PRInt32 i = 0; i < mVariants; i++) { if (PL_strcmp(mMimeTypeArray[i], aPluginTag->mMimeTypeArray[i]) != 0) return PR_FALSE; - + } + } return PR_TRUE; } @@ -3139,76 +3168,14 @@ NS_IMETHODIMP nsPluginHostImpl::RegisterPlugin(REFNSIID aCID, const char** aFileExtensions, PRInt32 aCount) { - PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginHostImpl::RegisterPlugin name=%s\n",aPluginName)); - - nsCOMPtr registry = do_CreateInstance(kRegistryCID); - if (! registry) - return NS_ERROR_FAILURE; - - nsresult rv; - rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry); - if (NS_FAILED(rv)) return rv; - - nsCAutoString path(kPluginsRootKey); - char* cid = aCID.ToString(); - if (! cid) - return NS_ERROR_OUT_OF_MEMORY; - path += '/'; - path += cid; - nsMemory::Free(cid); - - nsRegistryKey pluginKey; - rv = registry->AddSubtree(nsIRegistry::Common, path.get(), &pluginKey); - if (NS_FAILED(rv)) return rv; - - // we use SetBytes instead of SetString to address special character issue, see Mozilla bug 108246 - if(aPluginName) - registry->SetBytesUTF8(pluginKey, kPluginsNameKey, strlen(aPluginName) + 1, (PRUint8 *)aPluginName); - - if(aDescription) - registry->SetBytesUTF8(pluginKey, kPluginsDescKey, strlen(aDescription) + 1, (PRUint8 *)aDescription); - - for (PRInt32 i = 0; i < aCount; ++i) { - nsCAutoString mimepath; - mimepath.AppendInt(i); - - nsRegistryKey key; - registry->AddSubtree(pluginKey, mimepath.get(), &key); - - registry->SetStringUTF8(key, kPluginsMimeTypeKey, aMimeTypes[i]); - - if(aMimeDescriptions && aMimeDescriptions[i]) - registry->SetBytesUTF8(key, kPluginsMimeDescKey, - strlen(aMimeDescriptions[i]) + 1, - (PRUint8 *)aMimeDescriptions[i]); - - registry->SetStringUTF8(key, kPluginsMimeExtKey, aFileExtensions[i]); - } - - return NS_OK; + return NS_ERROR_NOT_IMPLEMENTED; } //////////////////////////////////////////////////////////////////////// NS_IMETHODIMP nsPluginHostImpl::UnregisterPlugin(REFNSIID aCID) { - nsCOMPtr registry = do_CreateInstance(kRegistryCID); - if (! registry) - return NS_ERROR_FAILURE; - - nsresult rv; - rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry); - if (NS_FAILED(rv)) return rv; - - nsCAutoString path("software/plugins/"); - char* cid = aCID.ToString(); - if (! cid) - return NS_ERROR_OUT_OF_MEMORY; - - path += cid; - nsMemory::Free(cid); - - return registry->RemoveSubtree(nsIRegistry::Common, path.get()); + return NS_ERROR_NOT_IMPLEMENTED; } @@ -5108,20 +5075,9 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi *aPluginsChanged = PR_FALSE; nsresult rv; - - // If the create instance failed, then it automatically disables all - // our caching functions and we will just end up loading the plugins - // on startup. - nsCOMPtr registry = do_CreateInstance(kRegistryCID); - if (registry) { - rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry); - if (NS_FAILED(rv)) { - registry = nsnull; - } - } - // Load cached plugins info - LoadCachedPluginsInfo(registry); + // Read cached plugins info + ReadPluginInfo(); nsCOMPtr compManager = do_GetService(kComponentManagerCID, &rv); if (compManager) @@ -5254,7 +5210,7 @@ nsresult nsPluginHostImpl::FindPlugins(PRBool aCreatePluginList, PRBool * aPlugi // if we are creating the list, it is already done; // update the plugins info cache if changes are detected if (*aPluginsChanged) - CachePluginsInfo(registry); + WritePluginInfo(); // No more need for cached plugins. Clear it up. ClearCachedPluginInfoList(); @@ -5293,236 +5249,13 @@ void nsPluginHostImpl::ClearCachedPluginInfoList() } } -//////////////////////////////////////////////////////////////////////// - -static nsresult -cidToDllname(nsIComponentManager* aComponentManager, nsIRegistry* aRegistry, - const nsACString &aCID, nsACString &dllName) -{ - // To figure out the filename of the plugin, we'll need to get the - // plugin's CID, and then navigate through the XPCOM registry to - // pull out the DLL name to which the CID is registered. - nsAutoString path(NS_LITERAL_STRING("software/mozilla/XPCOM/classID/") + NS_ConvertASCIItoUCS2(aCID)); - - nsRegistryKey cidKey; - nsresult rv = aRegistry->GetKey(nsIRegistry::Common, path.get(), &cidKey); - - if (NS_SUCCEEDED(rv)) { - PRUint8* library; - PRUint32 count; - // XXX Good grief, what does "GetBytesUTF8()" mean? They're bytes! - rv = aRegistry->GetBytesUTF8(cidKey, "InprocServer", &count, &library); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr file; - // what I want to do here is QI for a Component Registration Manager. Since this - // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home. - nsCOMPtr obsoleteManager = do_QueryInterface(aComponentManager, &rv); - if (obsoleteManager) - rv = obsoleteManager->SpecForRegistryLocation(NS_REINTERPRET_CAST(const char*, library), - getter_AddRefs(file)); - - if (NS_SUCCEEDED(rv)) { - file->GetNativePath(dllName); - } - - nsCRT::free(NS_REINTERPRET_CAST(char*, library)); - } - } - - return rv; -} - - -static nsresult -LoadXPCOMPlugin(nsIRegistry* aRegistry, - const char* aFilename, - nsRegistryKey aPluginKey, - nsPluginTag** aResult) -{ - nsresult rv; - - // The name, description, MIME types, MIME descriptions, and - // supported file extensions will all hang off of the plugin's key - // in the registry. Pull these out now. - PRUint8 * name=nsnull; - PRUint32 length; - aRegistry->GetBytesUTF8(aPluginKey, kPluginsNameKey, &length, &name); - - PRUint8 * description=nsnull; - aRegistry->GetBytesUTF8(aPluginKey, kPluginsDescKey, &length, &description); - - nsXPIDLCString filename; - nsXPIDLCString fullpath; - if (!aFilename) { - // Look for a filename key - aRegistry->GetStringUTF8(aPluginKey, kPluginsFilenameKey, getter_Copies(filename)); - aRegistry->GetStringUTF8(aPluginKey, kPluginsFullpathKey, getter_Copies(fullpath)); - } - - PRInt64 lastmod = LL_ZERO; - aRegistry->GetLongLong(aPluginKey, kPluginsModTimeKey, &lastmod); - - PRInt32 intval = 1; // Default for canunload is PR_TRUE - aRegistry->GetInt(aPluginKey, kPluginsCanUnload, &intval); - PRBool canunload = (intval > 0); - - nsCOMPtr enumerator; - rv = aRegistry->EnumerateAllSubtrees(aPluginKey, getter_AddRefs(enumerator)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr subtrees; - rv = NS_NewAdapterEnumerator(getter_AddRefs(subtrees), enumerator); - if (NS_FAILED(rv)) return rv; - - char** mimetypes = nsnull; - char** mimedescriptions = nsnull; - char** extensions = nsnull; - PRInt32 count = 0; - PRInt32 capacity = 0; - - for (;;) { - PRBool hasmore; - subtrees->HasMoreElements(&hasmore); - if (! hasmore) - break; - - nsCOMPtr isupports; - subtrees->GetNext(getter_AddRefs(isupports)); - - nsCOMPtr node = do_QueryInterface(isupports); - NS_ASSERTION(node != nsnull, "not an nsIRegistryNode"); - if (! node) - continue; - - nsRegistryKey key; - node->GetKey(&key); - - if (count >= capacity) { - capacity += capacity ? capacity : 4; - - char** newmimetypes = new char*[capacity]; - char** newmimedescriptions = new char*[capacity]; - char** newextensions = new char*[capacity]; - - if (!newmimetypes || !newmimedescriptions || !newextensions) { - rv = NS_ERROR_OUT_OF_MEMORY; - delete[] newmimetypes; - delete[] newmimedescriptions; - delete[] newextensions; - break; - } - - for (PRInt32 i = 0; i < count; ++i) { - newmimetypes[i] = mimetypes[i]; - newmimedescriptions[i] = mimedescriptions[i]; - newextensions[i] = extensions[i]; - } - - delete[] mimetypes; - delete[] mimedescriptions; - delete[] extensions; - - mimetypes = newmimetypes; - mimedescriptions = newmimedescriptions; - extensions = newextensions; - } - - aRegistry->GetStringUTF8(key, kPluginsMimeTypeKey, &mimetypes[count]); - - PRUint8 * md; - aRegistry->GetBytesUTF8(key, kPluginsMimeDescKey, &length, &md); - mimedescriptions[count] = NS_REINTERPRET_CAST(char *, md); - - aRegistry->GetStringUTF8(key, kPluginsMimeExtKey, &extensions[count]); - ++count; - } - - if (NS_SUCCEEDED(rv)) { - // All done! Create the new nsPluginTag info and send it back. - nsPluginTag* tag - = new nsPluginTag(NS_REINTERPRET_CAST(const char *, name), - NS_REINTERPRET_CAST(const char *, description), - aFilename ? aFilename : filename.get(), - fullpath.get(), - (const char* const*)mimetypes, - (const char* const*)mimedescriptions, - (const char* const*)extensions, - count, lastmod, canunload); - - if (! tag) - rv = NS_ERROR_OUT_OF_MEMORY; - - *aResult = tag; - } - - for (PRInt32 i = 0; i < count; ++i) { - CRTFREEIF(mimetypes[i]); - CRTFREEIF(mimedescriptions[i]); - CRTFREEIF(extensions[i]); - } - - delete[] mimetypes; - delete[] mimedescriptions; - delete[] extensions; - PR_FREEIF(name); - PR_FREEIF(description); - - return rv; -} - - -static nsresult -AddPluginInfoToRegistry(nsIRegistry* registry, nsRegistryKey top, - nsPluginTag *tag, const char *keyname) -{ - NS_ENSURE_ARG_POINTER(tag); - nsRegistryKey pluginKey; - nsresult rv = registry->AddSubtree(top, keyname, &pluginKey); - if (NS_FAILED(rv)) return rv; - - // Add filename, name and description - registry->SetStringUTF8(pluginKey, kPluginsFilenameKey, tag->mFileName); - if (tag->mFullPath) - registry->SetStringUTF8(pluginKey, kPluginsFullpathKey, tag->mFullPath); - - // we use SetBytes instead of SetString to address special character issue, see Mozilla bug 108246 - if(tag->mName) - registry->SetBytesUTF8(pluginKey, kPluginsNameKey, strlen(tag->mName) + 1, (PRUint8 *)tag->mName); - - if(tag->mDescription) - registry->SetBytesUTF8(pluginKey, kPluginsDescKey, strlen(tag->mDescription) + 1, (PRUint8 *)tag->mDescription); - - registry->SetLongLong(pluginKey, kPluginsModTimeKey, &(tag->mLastModifiedTime)); - registry->SetInt(pluginKey, kPluginsCanUnload, tag->mCanUnloadLibrary); - - // Add in each mimetype this plugin supports - for (int i=0; imVariants; i++) { - char mimetypeKeyName[16]; - nsRegistryKey mimetypeKey; - PR_snprintf(mimetypeKeyName, sizeof (mimetypeKeyName), "mimetype-%d", i); - rv = registry->AddSubtree(pluginKey, mimetypeKeyName, &mimetypeKey); - if (NS_FAILED(rv)) - break; - registry->SetStringUTF8(mimetypeKey, kPluginsMimeTypeKey, tag->mMimeTypeArray[i]); - - if(tag->mMimeDescriptionArray && tag->mMimeDescriptionArray[i]) - registry->SetBytesUTF8(mimetypeKey, kPluginsMimeDescKey, - strlen(tag->mMimeDescriptionArray[i]) + 1, - (PRUint8 *)tag->mMimeDescriptionArray[i]); - - registry->SetStringUTF8(mimetypeKey, kPluginsMimeExtKey, tag->mExtensionsArray[i]); - } - if (NS_FAILED(rv)) - rv = registry->RemoveSubtree(top, keyname); - - return rv; -} - - //////////////////////////////////////////////////////////////////////// nsresult nsPluginHostImpl::LoadXPCOMPlugins(nsIComponentManager* aComponentManager) -{ +{ + // the component reg is a flat file now see 48888 + // we have to reimplement this method if we need it + // The "new style" XPCOM plugins have their information stored in // the component registry, under the key // @@ -5530,213 +5263,281 @@ nsPluginHostImpl::LoadXPCOMPlugins(nsIComponentManager* aComponentManager) // // Enumerate through that list now, creating an nsPluginTag for // each. - nsCOMPtr registry = do_CreateInstance(kRegistryCID); - if (! registry) - return NS_ERROR_FAILURE; - - nsresult rv; - rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry); - if (NS_FAILED(rv)) return rv; - - nsRegistryKey pluginsKey; - rv = registry->GetSubtree(nsIRegistry::Common, kPluginsRootKey, &pluginsKey); - if (NS_FAILED(rv)) return rv; - - // XXX get rid nsIEnumerator someday! - nsCOMPtr enumerator; - rv = registry->EnumerateSubtrees(pluginsKey, getter_AddRefs(enumerator)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr plugins; - rv = NS_NewAdapterEnumerator(getter_AddRefs(plugins), enumerator); - if (NS_FAILED(rv)) return rv; - - for (;;) { - PRBool hasMore; - plugins->HasMoreElements(&hasMore); - if (! hasMore) - break; - - nsCOMPtr isupports; - plugins->GetNext(getter_AddRefs(isupports)); - - nsCOMPtr node = do_QueryInterface(isupports); - NS_ASSERTION(node != nsnull, "not an nsIRegistryNode"); - if (! node) - continue; - - // Pull out the information for an individual plugin, and link it - // in to the mPlugins list. - nsXPIDLCString cid; - node->GetNameUTF8(getter_Copies(cid)); - - nsRegistryKey key; - node->GetKey(&key); - - nsCAutoString filename; - rv = cidToDllname(aComponentManager, registry, cid, filename); - if (NS_FAILED(rv)) - continue; - - nsPluginTag* tag = nsnull; - rv = LoadXPCOMPlugin(registry, filename.get(), key, &tag); - if (NS_FAILED(rv)) - continue; - - PRBool bAddIt = PR_TRUE; - - // Find the same plugin in our cache and mark it as 'unwanted' so this plugin will - // just be added to the list without being detected as new. - // Note: Our XPCOM plugin probably shouldn't be in this list. If it is, it has been - // cached twice in the registry: - // a) ApplicationComponentRegistry: probably by the installer or regxpcom - // b) ApplicationRegistry: by us in |nsPluginHostImpl::CachePluginsInfo| - nsPluginTag *cachedTag = RemoveCachedPluginsInfo(filename.get()); - if (cachedTag) { - cachedTag->Mark(NS_PLUGIN_FLAG_UNWANTED); - cachedTag->mNext = mCachedPlugins; - mCachedPlugins = cachedTag; - } - - // skip it if we already have it - if (HaveSamePlugin(tag)) - bAddIt = PR_FALSE; - - if(!bAddIt) { - if(tag) - delete tag; - continue; - } - - tag->SetHost(this); - tag->mNext = mPlugins; - mPlugins = tag; - - // Create an nsIDocumentLoaderFactory wrapper in case we ever see - // any naked streams. - RegisterPluginMimeTypesWithLayout(tag, aComponentManager); - } - - return NS_OK; -} - - -nsresult -nsPluginHostImpl::LoadCachedPluginsInfo(nsIRegistry* registry) -{ - // Loads cached plugin info from registry - // - // Enumerate through that list now, creating an nsPluginTag for - // each. - if (! registry) - return NS_ERROR_FAILURE; - - nsRegistryKey pluginsKey; - nsresult rv = registry->GetSubtree(nsIRegistry::Common, kPluginsRootKey, &pluginsKey); - if (NS_FAILED(rv)) return rv; - - // Make sure we are dealing with the same version number of the plugin info - nsXPIDLCString version; - rv = registry->GetStringUTF8(pluginsKey, kPluginsVersionKey, getter_Copies(version)); - if (NS_FAILED(rv) || PL_strcmp(version.get(), kPluginInfoVersion)) { - // Version mismatch - // Nuke the subtree - registry->RemoveSubtree(nsIRegistry::Common, kPluginsRootKey); - PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, - ("LoadCachedPluginsInfo : Version %s mismatch - Expected %s. Nuking cached info.\n", - version.get(), kPluginInfoVersion)); - return NS_ERROR_FAILURE; - } - - // XXX get rid nsIEnumerator someday! - nsCOMPtr enumerator; - rv = registry->EnumerateSubtrees(pluginsKey, getter_AddRefs(enumerator)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr plugins; - rv = NS_NewAdapterEnumerator(getter_AddRefs(plugins), enumerator); - if (NS_FAILED(rv)) return rv; - - for (;;) { - PRBool hasMore; - plugins->HasMoreElements(&hasMore); - if (! hasMore) - break; - - nsCOMPtr isupports; - plugins->GetNext(getter_AddRefs(isupports)); - - nsCOMPtr node = do_QueryInterface(isupports); - NS_ASSERTION(node != nsnull, "not an nsIRegistryNode"); - if (! node) - continue; - - // Pull out the information for an individual plugin, and link it - // in to the mCachedPlugins list. - nsRegistryKey key; - node->GetKey(&key); - - nsPluginTag* tag = nsnull; - rv = LoadXPCOMPlugin(registry, nsnull, key, &tag); - if (NS_FAILED(rv)) - continue; - - tag->SetHost(this); - - // Mark plugin as loaded from cache - tag->Mark(NS_PLUGIN_FLAG_FROMCACHE); - PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, - ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->mFileName)); - tag->mNext = mCachedPlugins; - mCachedPlugins = tag; - } return NS_OK; } nsresult -nsPluginHostImpl::CachePluginsInfo(nsIRegistry* registry) +nsPluginHostImpl::WritePluginInfo() { - // Save plugin info from registry - if (! registry) + nsresult rv = NS_OK; + nsCOMPtr directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,&rv)); + if (NS_FAILED(rv)) + return rv; + + directoryService->Get(NS_APP_APPLICATION_REGISTRY_DIR, NS_GET_IID(nsIFile), + getter_AddRefs(mPluginsDir)); + + if (!mPluginsDir) return NS_ERROR_FAILURE; - // We don't want any old plugins that don't exist anymore hanging around - // So remove and re-add the root of the plugins info - nsresult rv = registry->RemoveSubtree(nsIRegistry::Common, kPluginsRootKey); - - nsRegistryKey pluginsSubtreeKey; - rv = registry->AddSubtree(nsIRegistry::Common, kPluginsRootKey, &pluginsSubtreeKey); - if (NS_FAILED(rv)) return rv; + PRFileDesc* fd = nsnull; + + nsCOMPtr pluginReg; - rv = registry->SetStringUTF8(pluginsSubtreeKey, kPluginsVersionKey, kPluginInfoVersion); - if (NS_FAILED(rv)) return rv; + rv = mPluginsDir->Clone(getter_AddRefs(pluginReg)); + if (NS_FAILED(rv)) + return rv; + + rv = pluginReg->AppendNative(kPluginRegistryFilename); + if (NS_FAILED(rv)) + return rv; - int count = 0; + nsCOMPtr localFile = do_QueryInterface(pluginReg, &rv); + if (NS_FAILED(rv)) + return rv; + + rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd); + if (NS_FAILED(rv)) + return rv; + + PR_fprintf(fd, "Generated File. Do not edit.\n"); + + PR_fprintf(fd, "\n[HEADER]\nVersion%c%d%c%d\n", + PLUGIN_REGISTRY_FIELD_DELIMITER, + PLUGIN_REGISTRY_VERSION_MAJOR, + PLUGIN_REGISTRY_FIELD_DELIMITER, + PLUGIN_REGISTRY_VERSION_MINOR); // Store all plugins in the mPlugins list - all plugins currently in use. - char pluginKeyName[64]; - nsPluginTag *tag; - for(tag = mPlugins; tag; tag=tag->mNext) { - // store each plugin info into the registry - PR_snprintf(pluginKeyName, sizeof(pluginKeyName), "plugin-%d", ++count); - AddPluginInfoToRegistry(registry, pluginsSubtreeKey, tag, pluginKeyName); + PR_fprintf(fd, "\n[PLUGINS]"); + + nsPluginTag *taglist[] = {mPlugins, mCachedPlugins}; + for (int i=0; imNext) { + // from mCachedPlugins list write down only unwanted plugins + if ((taglist[i] == mCachedPlugins) && !(tag->mFlags & NS_PLUGIN_FLAG_UNWANTED)) + continue; + // store each plugin info into the registry + //filename|fullpath|lastModifiedTimeStamp|canUnload|tag->mFlags + PR_fprintf(fd, "\n%s%c%s%c%lld%c%d%c%lu\n", + (tag->mFileName ? tag->mFileName : ""), + PLUGIN_REGISTRY_FIELD_DELIMITER, + (tag->mFullPath ? tag->mFullPath : ""), + PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mLastModifiedTime,PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mCanUnloadLibrary,PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mFlags); + + //description\n --\ on separate line, so there is no need to parse it + //name\n --/ and check for delimiters + //mtypecount + PR_fprintf(fd, "%s\n%s\n%d\n", + tag->mDescription, + tag->mName, + tag->mVariants); + + // Add in each mimetype this plugin supports + for (int i=0; imVariants; i++) { + PR_fprintf(fd, "%d%c%s%c%s%c%s\n", + i,PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mMimeTypeArray[i],PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mMimeDescriptionArray[i],PLUGIN_REGISTRY_FIELD_DELIMITER, + tag->mExtensionsArray[i]); + } + } } - // Store any unwanted plugins info so that we wont have to load - // them again the next time around - tag = mCachedPlugins; - for(tag = mCachedPlugins; tag; tag=tag->mNext) { - // Look for unwanted plugins - if (!(tag->mFlags & NS_PLUGIN_FLAG_UNWANTED)) + if (fd) + PR_Close(fd); + return NS_OK; +} + +nsresult +nsPluginHostImpl::ReadPluginInfo() +{ + nsresult rv; + + nsCOMPtr directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,&rv)); + if (NS_FAILED(rv)) + return rv; + + directoryService->Get(NS_APP_APPLICATION_REGISTRY_DIR, NS_GET_IID(nsIFile), + getter_AddRefs(mPluginsDir)); + + if (!mPluginsDir) + return NS_ERROR_FAILURE; + + PRFileDesc* fd = nsnull; + + nsCOMPtr pluginReg; + + rv = mPluginsDir->Clone(getter_AddRefs(pluginReg)); + if (NS_FAILED(rv)) + return rv; + + rv = pluginReg->AppendNative(kPluginRegistryFilename); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr localFile = do_QueryInterface(pluginReg, &rv); + if (NS_FAILED(rv)) + return rv; + + PRInt64 fileSize; + rv = localFile->GetFileSize(&fileSize); + if (NS_FAILED(rv)) { + return rv; + } + + PRInt32 flen = nsInt64(fileSize); + if (flen == 0) { + NS_WARNING("Plugins Registry Empty!"); + return NS_OK; // ERROR CONDITION + } + + nsManifestLineReader reader; + char* registry = reader.Init(flen); + if (!registry) { + return NS_ERROR_OUT_OF_MEMORY; + } + + rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd); + if (NS_FAILED(rv)) + return rv; + + // set rv to return an error on goto out + rv = NS_ERROR_FAILURE; + + PRInt32 bread = PR_Read(fd, registry, flen); + PR_Close(fd); + + if (flen > bread) + return rv; + + if (!ReadSectionHeader(reader, "HEADER")) { + return rv;; + } + + if (!reader.NextLine()) { + return rv; + } + + char* values[6]; + + // VersionLiteral,major,minor + if (3 != reader.ParseLine(values, 3)) { + return rv; + } + + // VersionLiteral + if (PL_strcmp(values[0], "Version")) { + return rv; + } + + // major + if (PLUGIN_REGISTRY_VERSION_MAJOR != atoi(values[1])) { + return rv; + } + + // minor + if (PLUGIN_REGISTRY_VERSION_MINOR != atoi(values[2])) { + return rv; + } + + if (!ReadSectionHeader(reader, "PLUGINS")) { + return rv; + } + + while (reader.NextLine()) { + + //filename|fullpath|lastModifiedTimeStamp|canUnload|tag.mFlag + if (5 != reader.ParseLine(values, 5)) + return rv; + + char *filename = values[0]; + char *fullpath = values[1]; + PRInt64 lastmod = nsCRT::atoll(values[2]); + PRBool canunload = atoi(values[3]); + PRUint32 tagflag = atoi(values[4]); + + //description is whole line and can contain any chars + if (!reader.NextLine()) + return rv; + char *description = reader.LinePtr(); + + //name is whole line and can contain any chars + if (!reader.NextLine()) + return rv; + char *name = reader.LinePtr(); + + //mimetypecount + if (!reader.NextLine()) + return rv; + int mimetypecount = atoi(reader.LinePtr()); + + char *stackalloced[PLUGIN_REGISTRY_MAX_MIMETYPES_PER_PLUGIN * 3]; + char **mimetypes; + char **mimedescriptions; + char **extensions; + char **heapalloced = 0; + if (mimetypecount > PLUGIN_REGISTRY_MAX_MIMETYPES_PER_PLUGIN - 1) { + heapalloced = new char *[mimetypecount * 3]; + mimetypes = heapalloced; + } else { + mimetypes = stackalloced; + } + mimedescriptions = mimetypes + mimetypecount; + extensions = mimedescriptions + mimetypecount; + + int mtr = 0; //mimetype read + for (; mtr < mimetypecount; mtr++) { + if (!reader.NextLine()) + break; + + //line number|mimetype|description|extension + if (4 != reader.ParseLine(values, 4)) + break; + int line = atoi(values[0]); + if (line != mtr) + break; + mimetypes[mtr] = values[1]; + mimedescriptions[mtr] = values[2]; + extensions[mtr] = values[3]; + } + + if (mtr != mimetypecount) { + if (heapalloced) { + delete [] heapalloced; + } + return rv; + } + + nsPluginTag* tag = new nsPluginTag(name, + description, + filename, + (*fullpath ? fullpath : 0), // we have to pass 0 prt if it's empty str + (const char* const*)mimetypes, + (const char* const*)mimedescriptions, + (const char* const*)extensions, + mimetypecount, lastmod, canunload); + if (heapalloced) { + delete [] heapalloced; + } + + if (!tag) { continue; - - // store each plugin info into the registry - PR_snprintf(pluginKeyName, sizeof(pluginKeyName), "plugin-%d", ++count); - AddPluginInfoToRegistry(registry, pluginsSubtreeKey, tag, pluginKeyName); + } + + // Mark plugin as loaded from cache + tag->Mark(tagflag | NS_PLUGIN_FLAG_FROMCACHE); + PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, + ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->mFileName)); + tag->mNext = mCachedPlugins; + mCachedPlugins = tag; + } - return NS_OK; } diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h index 186b06ce52e..ff46153d7d0 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -434,11 +434,11 @@ private: PRBool IsRunningPlugin(nsPluginTag * plugin); - // Loads all cached plugins info into mCachedPlugins - nsresult LoadCachedPluginsInfo(nsIRegistry* registry); - // Stores all plugins info into the registry - nsresult CachePluginsInfo(nsIRegistry* registry); + nsresult WritePluginInfo(); + + // Loads all cached plugins info into mCachedPlugins + nsresult ReadPluginInfo(); // Given a filename, returns the plugins info from our cache // and removes it from the cache. @@ -473,6 +473,7 @@ private: nsActivePluginList mActivePluginList; nsVoidArray mUnusedLibraries; + nsCOMPtr mPluginsDir; nsCOMPtr mPrivateDirServiceProvider; nsWeakPtr mCurrentDocument; // weak reference, we use it to id document only diff --git a/mozilla/modules/plugin/base/src/nsPluginManifestLineReader.h b/mozilla/modules/plugin/base/src/nsPluginManifestLineReader.h new file mode 100644 index 00000000000..ec209dc48e2 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginManifestLineReader.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsPluginManifestLineReader_h__ +#define nsPluginManifestLineReader_h__ + +#include "nspr.h" +#include "nsDebug.h" + + +#define PLUGIN_REGISTRY_VERSION_MINOR 6 +#define PLUGIN_REGISTRY_VERSION_MAJOR 0 +#ifdef XP_WIN +#define PLUGIN_REGISTRY_FIELD_DELIMITER '|' +#else +#define PLUGIN_REGISTRY_FIELD_DELIMITER ':' +#endif + +#define PLUGIN_REGISTRY_MAX_MIMETYPES_PER_PLUGIN 4 + +class nsManifestLineReader +{ +public: + nsManifestLineReader() {mBase = mCur = mNext = mLimit = 0;} + ~nsManifestLineReader() {delete [] mBase;} + + char* Init(PRUint32 flen) + { + mBase = mCur = mNext = new char[flen+1]; + if (mBase) { + mLimit = mBase + flen; + *mLimit = 0; + } + mLength = 0; + return mBase; + } + + PRBool NextLine() + { + if(mNext >= mLimit) + return PR_FALSE; + + mCur = mNext; + mLength = 0; + + while(mNext < mLimit) + { + if(IsEOL(*mNext)) + { + *mNext = '\0'; + for(++mNext; mNext < mLimit; ++mNext) + if(!IsEOL(*mNext)) + break; + return PR_TRUE; + } + ++mNext; + ++mLength; + } + return PR_FALSE; + } + + int ParseLine(char** chunks, int maxChunks) + { + NS_ASSERTION(mCur && maxChunks && chunks, "bad call to ParseLine"); + int found = 0; + chunks[found++] = mCur; + + if(found < maxChunks) + { + for(char* cur = mCur; *cur; cur++) + { + if(*cur == PLUGIN_REGISTRY_FIELD_DELIMITER) + { + *cur = 0; + chunks[found++] = cur+1; + if(found == maxChunks) + break; + } + } + } + return found; + } + + char* LinePtr() {return mCur;} + PRUint32 LineLength() {return mLength;} + + PRBool IsEOL(char c) {return c == '\n' || c == '\r';} + + char* mBase; +private: + char* mCur; + PRUint32 mLength; + char* mNext; + char* mLimit; +}; + +#endif