LCOV - code coverage report
Current view: directory - xpcom/components - nsNativeComponentLoader.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 83 46 55.4 %
Date: 2012-06-02 Functions: 15 7 46.7 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org Code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK *****
      37                 :  * This Original Code has been modified by IBM Corporation.
      38                 :  * Modifications made by IBM described herein are
      39                 :  * Copyright (c) International Business Machines
      40                 :  * Corporation, 2000
      41                 :  *
      42                 :  * Modifications to Mozilla code or documentation
      43                 :  * identified per MPL Section 3.3
      44                 :  *
      45                 :  * Date             Modified by     Description of modification
      46                 :  * 04/20/2000       IBM Corp.      Added PR_CALLBACK for Optlink use in OS2
      47                 :  */
      48                 : 
      49                 : /* Allow logging in the release build */
      50                 : #ifdef MOZ_LOGGING
      51                 : #define FORCE_PR_LOG
      52                 : #endif
      53                 : 
      54                 : #include "nsNativeComponentLoader.h"
      55                 : 
      56                 : #include "prlog.h"
      57                 : #include "prinit.h"
      58                 : #include "prerror.h"
      59                 : 
      60                 : #include "nsComponentManager.h"
      61                 : #include "ManifestParser.h" // for LogMessage
      62                 : #include "nsCRTGlue.h"
      63                 : #include "nsThreadUtils.h"
      64                 : #include "nsTraceRefcntImpl.h"
      65                 : 
      66                 : #include "nsILocalFile.h"
      67                 : 
      68                 : #ifdef XP_WIN
      69                 : #include <windows.h>
      70                 : #endif
      71                 : 
      72                 : #ifdef XP_MACOSX
      73                 : #include <signal.h>
      74                 : #endif
      75                 : 
      76                 : #ifdef VMS
      77                 : #include <lib$routines.h>
      78                 : #include <ssdef.h>
      79                 : #endif
      80                 : 
      81                 : #ifdef DEBUG
      82                 : #define IMPLEMENT_BREAK_AFTER_LOAD
      83                 : #endif
      84                 : 
      85                 : using namespace mozilla;
      86                 : 
      87            1464 : static PRLogModuleInfo *nsNativeModuleLoaderLog =
      88            1464 :     PR_NewLogModule("nsNativeModuleLoader");
      89                 : 
      90                 : bool gInXPCOMLoadOnMainThread = false;
      91                 : 
      92                 : #define LOG(level, args) PR_LOG(nsNativeModuleLoaderLog, level, args)
      93                 : 
      94               0 : NS_IMPL_QUERY_INTERFACE1(nsNativeModuleLoader, 
      95                 :                          mozilla::ModuleLoader)
      96                 : 
      97               0 : NS_IMPL_ADDREF_USING_AGGREGATOR(nsNativeModuleLoader,
      98                 :                                 nsComponentManagerImpl::gComponentManager)
      99               0 : NS_IMPL_RELEASE_USING_AGGREGATOR(nsNativeModuleLoader,
     100                 :                                  nsComponentManagerImpl::gComponentManager)
     101                 : 
     102                 : nsresult
     103            1419 : nsNativeModuleLoader::Init()
     104                 : {
     105            1419 :     NS_ASSERTION(NS_IsMainThread(), "Startup not on main thread?");
     106                 : 
     107            1419 :     LOG(PR_LOG_DEBUG, ("nsNativeModuleLoader::Init()"));
     108                 : 
     109            1419 :     return mLibraries.Init() ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     110                 : }
     111                 : 
     112                 : class LoadModuleMainThreadRunnable : public nsRunnable
     113               0 : {
     114                 : public:
     115               0 :     LoadModuleMainThreadRunnable(nsNativeModuleLoader* loader,
     116                 :                                  FileLocation &file)
     117                 :         : mLoader(loader)
     118                 :         , mFile(file)
     119               0 :         , mResult(NULL)
     120               0 :     { }
     121                 : 
     122               0 :     NS_IMETHOD Run()
     123                 :     {
     124               0 :         mResult = mLoader->LoadModule(mFile);
     125               0 :         return NS_OK;
     126                 :     }
     127                 : 
     128                 :     nsRefPtr<nsNativeModuleLoader> mLoader;
     129                 :     FileLocation mFile;
     130                 :     const mozilla::Module* mResult;
     131                 : };
     132                 : 
     133                 : const mozilla::Module*
     134            5680 : nsNativeModuleLoader::LoadModule(FileLocation &aFile)
     135                 : {
     136            5680 :     if (aFile.IsZip()) {
     137               0 :         NS_ERROR("Binary components cannot be loaded from JARs");
     138               0 :         return NULL;
     139                 :     }
     140           11360 :     nsCOMPtr<nsILocalFile> file = aFile.GetBaseFile();
     141                 :     nsresult rv;
     142                 : 
     143            5680 :     if (!NS_IsMainThread()) {
     144                 :         // If this call is off the main thread, synchronously proxy it
     145                 :         // to the main thread.
     146               0 :         nsRefPtr<LoadModuleMainThreadRunnable> r = new LoadModuleMainThreadRunnable(this, aFile);
     147               0 :         NS_DispatchToMainThread(r, NS_DISPATCH_SYNC);
     148               0 :         return r->mResult;
     149                 :     }
     150                 : 
     151           11360 :     nsCOMPtr<nsIHashable> hashedFile(do_QueryInterface(file));
     152            5680 :     if (!hashedFile) {
     153               0 :         NS_ERROR("nsIFile is not nsIHashable");
     154               0 :         return NULL;
     155                 :     }
     156                 : 
     157           11360 :     nsCAutoString filePath;
     158            5680 :     file->GetNativePath(filePath);
     159                 : 
     160            5680 :     NativeLoadData data;
     161                 : 
     162            5680 :     if (mLibraries.Get(hashedFile, &data)) {
     163               0 :         NS_ASSERTION(data.module, "Corrupt mLibraries hash");
     164               0 :         LOG(PR_LOG_DEBUG,
     165                 :             ("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache",
     166                 :              filePath.get()));
     167               0 :         return data.module;
     168                 :     }
     169                 : 
     170                 :     // We haven't loaded this module before
     171                 : 
     172            5680 :     gInXPCOMLoadOnMainThread = true;
     173            5680 :     rv = file->Load(&data.library);
     174            5680 :     gInXPCOMLoadOnMainThread = false;
     175                 : 
     176            5680 :     if (NS_FAILED(rv)) {
     177               0 :         char errorMsg[1024] = "<unknown; can't get error from NSPR>";
     178                 : 
     179               0 :         if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
     180               0 :             PR_GetErrorText(errorMsg);
     181                 : 
     182                 :         LogMessage("Failed to load native module at path '%s': (%lx) %s",
     183               0 :                    filePath.get(), rv, errorMsg);
     184                 : 
     185               0 :         return NULL;
     186                 :     }
     187                 : 
     188                 : #ifdef IMPLEMENT_BREAK_AFTER_LOAD
     189           11360 :     nsCAutoString leafName;
     190            5680 :     file->GetNativeLeafName(leafName);
     191                 : 
     192            5680 :     char *env = getenv("XPCOM_BREAK_ON_LOAD");
     193                 :     char *blist;
     194            5680 :     if (env && *env && (blist = strdup(env))) {
     195               0 :         char *nextTok = blist;
     196               0 :         while (char *token = NS_strtok(":", &nextTok)) {
     197               0 :             if (leafName.Find(token, true) != kNotFound) {
     198               0 :                 NS_BREAK();
     199                 :             }
     200                 :         }
     201                 : 
     202               0 :         free(blist);
     203                 :     }
     204                 : #endif
     205                 : 
     206            5680 :     void *module = PR_FindSymbol(data.library, "NSModule");
     207            5680 :     if (!module) {
     208                 :         LogMessage("Native module at path '%s' doesn't export symbol `NSModule`.",
     209               0 :                    filePath.get());
     210               0 :         PR_UnloadLibrary(data.library);
     211               0 :         return NULL;
     212                 :     }
     213                 : 
     214            5680 :     data.module = *(mozilla::Module const *const *) module;
     215            5680 :     if (mozilla::Module::kVersion != data.module->mVersion) {
     216                 :         LogMessage("Native module at path '%s' is incompatible with this version of Firefox, has version %i, expected %i.",
     217                 :                    filePath.get(), data.module->mVersion,
     218               1 :                    mozilla::Module::kVersion);
     219               1 :         PR_UnloadLibrary(data.library);
     220               1 :         return NULL;
     221                 :     }
     222                 :         
     223            5679 :     mLibraries.Put(hashedFile, data); // infallible
     224            5679 :     return data.module;
     225                 : }
     226                 : 
     227                 : PLDHashOperator
     228            5679 : nsNativeModuleLoader::ReleaserFunc(nsIHashable* aHashedFile,
     229                 :                                    NativeLoadData& aLoadData, void*)
     230                 : {
     231            5679 :     aLoadData.module = nsnull;
     232            5679 :     return PL_DHASH_NEXT;
     233                 : }
     234                 : 
     235                 : PLDHashOperator
     236            5679 : nsNativeModuleLoader::UnloaderFunc(nsIHashable* aHashedFile,
     237                 :                                    NativeLoadData& aLoadData, void*)
     238                 : {
     239            5679 :     if (PR_LOG_TEST(nsNativeModuleLoaderLog, PR_LOG_DEBUG)) {
     240               0 :         nsCOMPtr<nsIFile> file(do_QueryInterface(aHashedFile));
     241                 : 
     242               0 :         nsCAutoString filePath;
     243               0 :         file->GetNativePath(filePath);
     244                 : 
     245               0 :         LOG(PR_LOG_DEBUG,
     246                 :             ("nsNativeModuleLoader::UnloaderFunc(\"%s\")", filePath.get()));
     247                 :     }
     248                 : 
     249                 : #ifdef NS_BUILD_REFCNT_LOGGING
     250            5679 :     nsTraceRefcntImpl::SetActivityIsLegal(false);
     251                 : #endif
     252                 : 
     253                 : #if 0
     254                 :     // XXXbsmedberg: do this as soon as the static-destructor crash(es)
     255                 :     // are fixed
     256                 :     PRStatus ret = PR_UnloadLibrary(aLoadData.library);
     257                 :     NS_ASSERTION(ret == PR_SUCCESS, "Failed to unload library");
     258                 : #endif
     259                 : 
     260                 : #ifdef NS_BUILD_REFCNT_LOGGING
     261            5679 :     nsTraceRefcntImpl::SetActivityIsLegal(true);
     262                 : #endif
     263                 : 
     264            5679 :     return PL_DHASH_REMOVE;
     265                 : }
     266                 : 
     267                 : void
     268            1419 : nsNativeModuleLoader::UnloadLibraries()
     269                 : {
     270            1419 :     NS_ASSERTION(NS_IsMainThread(), "Shutdown not on main thread?");
     271                 : 
     272            1419 :     mLibraries.Enumerate(ReleaserFunc, nsnull);
     273            1419 :     mLibraries.Enumerate(UnloaderFunc, nsnull);
     274            5811 : }

Generated by: LCOV version 1.7