NS_METHOD nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile **aLocalFile)
{
    if (NS_WARN_IF(!aLocalFile))
        return NS_ERROR_INVALID_ARG;
    nsresult rv;

    if (!mMozBinDirectory)
    {
        // Get the mozilla bin directory
        // 1. Check the directory service first for NS_XPCOM_CURRENT_PROCESS_DIR
        //    This will be set if a directory was passed to NS_InitXPCOM
        // 2. If that doesn't work, set it to be the current process directory
        nsCOMPtr<nsIProperties>
          directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
        if (NS_FAILED(rv))
            return rv;

        rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
        if (NS_FAILED(rv)) {
            rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
            if (NS_FAILED(rv))
                return rv;
        }
    }

    nsCOMPtr<nsIFile> aFile;
    rv = mMozBinDirectory->Clone(getter_AddRefs(aFile));
    if (NS_FAILED(rv))
        return rv;

    NS_IF_ADDREF(*aLocalFile = aFile);
    return NS_OK;
}
// A helper function for AutoObjectMapperFaultyLib::Map.  Finds out
// where the installation's lib directory is, since we'll have to look
// in there to get hold of libmozglue.so.  Returned C string is heap
// allocated and the caller must deallocate it.
static char*
get_installation_lib_dir()
{
    nsCOMPtr<nsIProperties>
    directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
    if (!directoryService) {
        return nullptr;
    }
    nsCOMPtr<nsIFile> greDir;
    nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
                                        getter_AddRefs(greDir));
    if (NS_FAILED(rv)) return nullptr;
    nsCString path;
    rv = greDir->GetNativePath(path);
    if (NS_FAILED(rv)) {
        return nullptr;
    }
    return strdup(path.get());
}
bool
PluginHangUIParent::Init(const nsString& aPluginName)
{
  if (mHangUIProcessHandle) {
    return false;
  }

  nsresult rv;
  rv = mMiniShm.Init(this, ::IsDebuggerPresent() ? INFINITE : kTimeout);
  NS_ENSURE_SUCCESS(rv, false);
  nsCOMPtr<nsIProperties>
    directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
  if (!directoryService) {
    return false;
  }
  nsCOMPtr<nsIFile> greDir;
  rv = directoryService->Get(NS_GRE_DIR,
                             NS_GET_IID(nsIFile),
                             getter_AddRefs(greDir));
  if (NS_FAILED(rv)) {
    return false;
  }
  nsAutoString path;
  greDir->GetPath(path);

  FilePath exePath(path.get());
  exePath = exePath.AppendASCII(MOZ_HANGUI_PROCESS_NAME);
  CommandLine commandLine(exePath.value());

  nsXPIDLString localizedStr;
  const PRUnichar* formatParams[] = { aPluginName.get() };
  rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                             "PluginHangUIMessage",
                                             formatParams,
                                             localizedStr);
  if (NS_FAILED(rv)) {
    return false;
  }
  commandLine.AppendLooseValue(localizedStr.get());

  const char* keys[] = { "PluginHangUITitle",
                         "PluginHangUIWaitButton",
                         "PluginHangUIStopButton",
                         "DontAskAgain" };
  for (unsigned int i = 0; i < ArrayLength(keys); ++i) {
    rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                            keys[i],
                                            localizedStr);
    if (NS_FAILED(rv)) {
      return false;
    }
    commandLine.AppendLooseValue(localizedStr.get());
  }

  rv = GetHangUIOwnerWindowHandle(mMainWindowHandle);
  if (NS_FAILED(rv)) {
    return false;
  }
  nsAutoString hwndStr;
  hwndStr.AppendPrintf("%p", mMainWindowHandle);
  commandLine.AppendLooseValue(hwndStr.get());

  ScopedHandle procHandle(::OpenProcess(SYNCHRONIZE,
                                        TRUE,
                                        GetCurrentProcessId()));
  if (!procHandle.IsValid()) {
    return false;
  }
  nsAutoString procHandleStr;
  procHandleStr.AppendPrintf("%p", procHandle.Get());
  commandLine.AppendLooseValue(procHandleStr.get());

  std::wstring ipcCookie;
  rv = mMiniShm.GetCookie(ipcCookie);
  if (NS_FAILED(rv)) {
    return false;
  }
  commandLine.AppendLooseValue(ipcCookie);

  mShowEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  ScopedHandle showEvent(::CreateEvent(NULL, FALSE, FALSE, NULL));
  if (!showEvent.IsValid()) {
    return false;
  }
  mShowEvent = showEvent.Get();

  STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
  PROCESS_INFORMATION processInfo = { NULL };
  BOOL isProcessCreated = ::CreateProcess(exePath.value().c_str(),
                                          const_cast<wchar_t*>(commandLine.command_line_string().c_str()),
                                          nullptr,
                                          nullptr,
                                          TRUE,
                                          DETACHED_PROCESS,
                                          nullptr,
                                          nullptr,
                                          &startupInfo,
                                          &processInfo);
  if (isProcessCreated) {
    ::CloseHandle(processInfo.hThread);
    mHangUIProcessHandle = processInfo.hProcess;
    ::RegisterWaitForSingleObject(&mRegWait,
                                  processInfo.hProcess,
                                  &SOnHangUIProcessExit,
                                  this,
                                  INFINITE,
                                  WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE);
    ::WaitForSingleObject(mShowEvent, kTimeout);
  }
  mShowEvent = NULL;
  return !(!isProcessCreated);
}
NS_IMETHODIMP 
sbLocalDatabaseLibraryLoader::Observe(nsISupports *aSubject,
                                      const char *aTopic,
                                      const PRUnichar *aData)
{
  nsresult rv;

  if (strcmp(aTopic, NS_FINAL_UI_STARTUP_CATEGORY) == 0) {
    if (m_DetectedCorruptLibrary) {
      /* check to see if the prefs file is writable, to recover from people
       * running the app with sudo :(
       */
      nsCOMPtr<nsIProperties> dirService =
        do_GetService("@mozilla.org/file/directory_service;1", &rv);
      NS_ENSURE_SUCCESS(rv, rv);
      
      nsCOMPtr<nsIFile> prefFile;
      rv = dirService->Get("PrefF",
                           NS_GET_IID(nsIFile),
                           getter_AddRefs(prefFile));
      NS_ENSURE_SUCCESS(rv, rv);
      
      PRBool prefExists;
      /* if the pref file is missing we go through the normal first-run process
       * and therefore don't need to care about this
       */
      PRBool prefWritable = PR_TRUE;
      rv = prefFile->Exists(&prefExists);
      if (NS_SUCCEEDED(rv) && prefExists) {
        rv = prefFile->IsWritable(&prefWritable);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      if (prefWritable) {
        rv = PromptToDeleteLibraries();
        NS_ENSURE_SUCCESS(rv, rv);
      } else {
        // database file is not writable, just bail
        rv = PromptInaccessibleLibraries();
        NS_ENSURE_SUCCESS(rv, rv);
      }
    }
  } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
    // By now, databases should all be closed so it is safe to delete
    // the db directory.
    if (m_DeleteLibrariesAtShutdown) {
      // get profile directory
      nsCOMPtr<nsIProperties> directoryService(
        do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
      NS_ENSURE_SUCCESS(rv, rv);
     
      nsCOMPtr<nsIFile> siteDBDir;
      rv = directoryService->Get("ProfD", NS_GET_IID(nsIFile),
                                 getter_AddRefs(siteDBDir));
      NS_ENSURE_SUCCESS(rv, rv);
     
      // append the database dir name
      siteDBDir->Append(NS_LITERAL_STRING("db"));
     

      // Delete all the databases but the metrics DB. (which hopefully
      // is not corrupt)
      nsCOMPtr<nsISimpleEnumerator> dirEnumerator;
      rv = siteDBDir->GetDirectoryEntries(getter_AddRefs(dirEnumerator));
      NS_ENSURE_SUCCESS(rv, rv);

      nsString metricsdb = NS_LITERAL_STRING("metrics.db");

      PRBool hasMore;
      dirEnumerator->HasMoreElements(&hasMore);
      while (hasMore && NS_SUCCEEDED(rv)) {
        nsCOMPtr<nsISupports> aSupport;
        rv = dirEnumerator->GetNext(getter_AddRefs(aSupport));
        if (NS_FAILED(rv)) break;
        nsCOMPtr<nsIFile> curFile(do_QueryInterface(aSupport, &rv));
        if (NS_FAILED(rv)) break;

        nsString leafName;
        rv = curFile->GetLeafName(leafName);
        if (NS_FAILED(rv)) break;
       
        if (leafName.Compare(metricsdb) != 0) {
          rv = curFile->Remove(false);
          NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to delete file");
        }
       
        dirEnumerator->HasMoreElements(&hasMore);
      }

      // We want to prompt the user to rescan on restart.
      nsCAutoString scancompleteBranch("songbird.firstrun.scancomplete");
      sbLocalDatabaseLibraryLoader::RemovePrefBranch(scancompleteBranch);

      // And delete all the library prefs, so they get recreated on
      // startup.  (It would be nice to not need to do this, so that
      // users could delete their db directory by hand and restart, but
      // bad things happen due to prefs and it's not worth putting time
      // into.)
      nsCAutoString prefBranch(PREFBRANCH_LOADER);
      sbLocalDatabaseLibraryLoader::RemovePrefBranch(prefBranch);
    }
  }

   return NS_OK;
}
bool
PluginHangUIParent::Init(const nsString& aPluginName)
{
  if (mHangUIProcessHandle) {
    return false;
  }

  nsresult rv;
  rv = mMiniShm.Init(this, ::IsDebuggerPresent() ? INFINITE : mIPCTimeoutMs);
  NS_ENSURE_SUCCESS(rv, false);
  nsCOMPtr<nsIProperties>
    directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
  if (!directoryService) {
    return false;
  }
  nsCOMPtr<nsIFile> greDir;
  rv = directoryService->Get(NS_GRE_DIR,
                             NS_GET_IID(nsIFile),
                             getter_AddRefs(greDir));
  if (NS_FAILED(rv)) {
    return false;
  }
  nsAutoString path;
  greDir->GetPath(path);

  FilePath exePath(path.get());
  exePath = exePath.AppendASCII(MOZ_HANGUI_PROCESS_NAME);
  CommandLine commandLine(exePath.value());

  nsXPIDLString localizedStr;
  const PRUnichar* formatParams[] = { aPluginName.get() };
  rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                             "PluginHangUIMessage",
                                             formatParams,
                                             localizedStr);
  if (NS_FAILED(rv)) {
    return false;
  }
  commandLine.AppendLooseValue(localizedStr.get());

  const char* keys[] = { "PluginHangUITitle",
                         "PluginHangUIWaitButton",
                         "PluginHangUIStopButton",
                         "DontAskAgain" };
  for (unsigned int i = 0; i < ArrayLength(keys); ++i) {
    rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                            keys[i],
                                            localizedStr);
    if (NS_FAILED(rv)) {
      return false;
    }
    commandLine.AppendLooseValue(localizedStr.get());
  }

  rv = GetHangUIOwnerWindowHandle(mMainWindowHandle);
  if (NS_FAILED(rv)) {
    return false;
  }
  nsAutoString hwndStr;
  hwndStr.AppendPrintf("%p", mMainWindowHandle);
  commandLine.AppendLooseValue(hwndStr.get());

  ScopedHandle procHandle(::OpenProcess(SYNCHRONIZE,
                                        TRUE,
                                        GetCurrentProcessId()));
  if (!procHandle.IsValid()) {
    return false;
  }
  nsAutoString procHandleStr;
  procHandleStr.AppendPrintf("%p", procHandle.Get());
  commandLine.AppendLooseValue(procHandleStr.get());

  // On Win7+, pass the application user model to the child, so it can
  // register with it. This insures windows created by the Hang UI
  // properly group with the parent app on the Win7 taskbar.
  nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
  if (taskbarInfo) {
    bool isSupported = false;
    taskbarInfo->GetAvailable(&isSupported);
    nsAutoString appId;
    if (isSupported && NS_SUCCEEDED(taskbarInfo->GetDefaultGroupId(appId))) {
      commandLine.AppendLooseValue(appId.get());
    } else {
      commandLine.AppendLooseValue(L"-");
    }
  } else {
    commandLine.AppendLooseValue(L"-");
  }

  nsAutoString ipcTimeoutStr;
  ipcTimeoutStr.AppendInt(mIPCTimeoutMs);
  commandLine.AppendLooseValue(ipcTimeoutStr.get());

  std::wstring ipcCookie;
  rv = mMiniShm.GetCookie(ipcCookie);
  if (NS_FAILED(rv)) {
    return false;
  }
  commandLine.AppendLooseValue(ipcCookie);

  ScopedHandle showEvent(::CreateEvent(nullptr, FALSE, FALSE, nullptr));
  if (!showEvent.IsValid()) {
    return false;
  }
  mShowEvent = showEvent.Get();

  MutexAutoLock lock(mMutex);
  STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
  PROCESS_INFORMATION processInfo = { nullptr };
  BOOL isProcessCreated = ::CreateProcess(exePath.value().c_str(),
                                          const_cast<wchar_t*>(commandLine.command_line_string().c_str()),
                                          nullptr,
                                          nullptr,
                                          TRUE,
                                          DETACHED_PROCESS,
                                          nullptr,
                                          nullptr,
                                          &startupInfo,
                                          &processInfo);
  if (isProcessCreated) {
    ::CloseHandle(processInfo.hThread);
    mHangUIProcessHandle = processInfo.hProcess;
    ::RegisterWaitForSingleObject(&mRegWait,
                                  processInfo.hProcess,
                                  &SOnHangUIProcessExit,
                                  this,
                                  INFINITE,
                                  WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE);
    ::WaitForSingleObject(mShowEvent, ::IsDebuggerPresent() ? INFINITE
                                                            : mIPCTimeoutMs);
    // Setting this to true even if we time out on mShowEvent. This timeout 
    // typically occurs when the machine is thrashing so badly that 
    // plugin-hang-ui.exe is taking a while to start. If we didn't set 
    // this to true, Firefox would keep spawning additional plugin-hang-ui 
    // processes, which is not what we want.
    mIsShowing = true;
  }
  mShowEvent = nullptr;
  return !(!isProcessCreated);
}
Example #6
0
/* nsIFile getFile (in string prop, out bool\/* PRBool *\/ persistent); */
NS_IMETHODIMP 
LocationProvider::GetFile(const char *prop, bool/* PRBool */ *persistent, nsIFile **_retval)
{
    nsCOMPtr<nsILocalFile>  localFile;
    nsresult rv = NS_ERROR_FAILURE;

    *_retval = nsnull;
    *persistent = PR_TRUE;


    if (strcmp(prop, NS_GRE_DIR) == 0)
		rv = GetAvailableRuntime (getter_AddRefs(localFile));

    else if (strcmp(prop, NS_APP_DEFAULTS_50_DIR) == 0)
    {
        rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv))
            rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
    }
    else if (strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR) == 0)
    {
        rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv)) {
            rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
            if (NS_SUCCEEDED(rv))
                rv = localFile->AppendRelativeNativePath(DEFAULTS_PREF_DIR_NAME);
        }
    }
    else if (strcmp(prop, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR) == 0 ||
             strcmp(prop, NS_APP_PROFILE_DEFAULTS_50_DIR) == 0)
	{
        rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv)) {
            rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
            if (NS_SUCCEEDED(rv))
                rv = localFile->AppendRelativeNativePath(DEFAULTS_PROFILE_DIR_NAME);
        }
    }
    else if (strcmp(prop, NS_APP_USER_PROFILE_50_DIR) == 0 ||
			 strcmp(prop, NS_APP_PREFS_50_DIR) == 0)
	{

        nsCOMPtr<nsIProperties>
          directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
        if (NS_FAILED(rv))
            return rv;

        rv = directoryService->Get(NS_APP_USER_PROFILES_ROOT_DIR, NS_GET_IID(nsIFile), getter_AddRefs(localFile));
		
//		nsEmbedCString file(widget->startDir);
//		rv = NS_NewNativeLocalFile(file, PR_TRUE, getter_AddRefs(localFile));

//      if (NS_SUCCEEDED(rv)) {
//          rv = localFile->AppendRelativeNativePath(PROFILE_ROOT_DIR_NAME);
//          if (NS_SUCCEEDED(rv))
//              rv = localFile->AppendRelativeNativePath(DEFAULTS_PROFILE_DIR_NAME);
//      }
    }
    else if (strcmp(prop, NS_APP_RES_DIR) == 0)
    {
        rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv))
            rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
    }
    else if (strcmp(prop, NS_APP_CHROME_DIR) == 0)
    {
        rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv))
            rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
    }
    //else if (strcmp(prop, NS_APP_PLUGINS_DIR) == 0)
    //{
    //    rv = GetAvailableRuntime (getter_AddRefs(localFile));
    //    if (NS_SUCCEEDED(rv))
    //        rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
    //}
    //else if (strcmp(prop, NS_APP_SEARCH_DIR) == 0)
    //{
    //    rv = GetAvailableRuntime (getter_AddRefs(localFile));
    //    if (NS_SUCCEEDED(rv))
    //        rv = localFile->AppendRelativeNativePath(SEARCH_DIR_NAME);
    //}
	else if (strcmp(prop, NS_GRE_COMPONENT_DIR) == 0 ||
		strcmp(prop, NS_XPCOM_COMPONENT_DIR) == 0)
	{
		rv = GetAvailableRuntime (getter_AddRefs(localFile));
        if (NS_SUCCEEDED(rv))
            rv = localFile->AppendRelativeNativePath(COMPONENTS_DIR_NAME);
	}
	else if (strcmp (prop, NS_XPCOM_COMPONENT_REGISTRY_FILE) == 0)
	{
		nsEmbedCString file(widget->dataDir);
		rv = NS_NewNativeLocalFile(file, PR_TRUE, getter_AddRefs(localFile));
		if (NS_SUCCEEDED(rv))
		{
			bool/* PRBool */ exists;
			rv = localFile->AppendNative(COMPONENT_DIRECTORY);
			if (NS_FAILED(rv)) return rv;
			rv = localFile->Exists (&exists);
			if (NS_FAILED(rv)) return rv;
			if (!exists)
				rv = localFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
			if (NS_FAILED(rv)) return rv;
	        rv = localFile->AppendNative(COMPONENT_REGISTRY_NAME);
		}
	}
	else if (strcmp(prop, NS_XPCOM_XPTI_REGISTRY_FILE) == 0)
	{
		nsEmbedCString file(widget->dataDir);
		rv = NS_NewNativeLocalFile(file, PR_TRUE, getter_AddRefs(localFile));
		if (NS_SUCCEEDED(rv))
		{
			bool/* PRBool */ exists;
			rv = localFile->AppendNative(COMPONENT_DIRECTORY);
			if (NS_FAILED(rv)) return rv;
			rv = localFile->Exists (&exists);
			if (NS_FAILED(rv)) return rv;
			if (!exists)
				rv = localFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
			if (NS_FAILED(rv)) return rv;
	        rv = localFile->AppendNative(XPTI_REGISTRY_NAME);           
		}
	}
	
    if (localFile && NS_SUCCEEDED(rv))
        return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
        
    return rv;
}
Example #7
0
NS_IMETHODIMP nsPrefBranch::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *_retval)
{
  nsresult       rv;
  nsXPIDLCString utf8String;

  // we have to do this one first because it's different than all the rest
  if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString))) {
    nsCOMPtr<nsIPrefLocalizedString> theString(do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID, &rv));

    if (NS_SUCCEEDED(rv)) {
      const char *pref;
      PRBool  bNeedDefault = PR_FALSE;

      rv = getValidatedPrefName(aPrefName, &pref);
      if (NS_FAILED(rv))
        return rv;

      if (mIsDefault) {
        bNeedDefault = PR_TRUE;
      } else {
        // if there is no user (or locked) value
        if (!PREF_HasUserPref(pref) && !PREF_PrefIsLocked(pref)) {
          bNeedDefault = PR_TRUE;
        }
      }

      // if we need to fetch the default value, do that instead, otherwise use the
      // value we pulled in at the top of this function
      if (bNeedDefault) {
        nsXPIDLString utf16String;
        rv = GetDefaultFromPropertiesFile(pref, getter_Copies(utf16String));
        if (NS_SUCCEEDED(rv)) {
          rv = theString->SetData(utf16String.get());
        }
      } else {
        rv = GetCharPref(aPrefName, getter_Copies(utf8String));
        if (NS_SUCCEEDED(rv)) {
          rv = theString->SetData(NS_ConvertUTF8toUCS2(utf8String).get());
        }
      }
      if (NS_SUCCEEDED(rv)) {
        nsIPrefLocalizedString *temp = theString;

        NS_ADDREF(temp);
        *_retval = (void *)temp;
      }
    }

    return rv;
  }

  // if we can't get the pref, there's no point in being here
  rv = GetCharPref(aPrefName, getter_Copies(utf8String));
  if (NS_FAILED(rv)) {
    return rv;
  }

  if (aType.Equals(NS_GET_IID(nsILocalFile))) {
    nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));

    if (NS_SUCCEEDED(rv)) {
      rv = file->SetPersistentDescriptor(utf8String);
      if (NS_SUCCEEDED(rv)) {
        nsILocalFile *temp = file;

        NS_ADDREF(temp);
        *_retval = (void *)temp;
        return NS_OK;
      }
    }
    return rv;
  }

  if (aType.Equals(NS_GET_IID(nsIRelativeFilePref))) {
    nsACString::const_iterator keyBegin, strEnd;
    utf8String.BeginReading(keyBegin);
    utf8String.EndReading(strEnd);    

    // The pref has the format: [fromKey]a/b/c
    if (*keyBegin++ != '[')        
        return NS_ERROR_FAILURE;
    nsACString::const_iterator keyEnd(keyBegin);
    if (!FindCharInReadable(']', keyEnd, strEnd))
        return NS_ERROR_FAILURE;
    nsCAutoString key(Substring(keyBegin, keyEnd));
    
    nsCOMPtr<nsILocalFile> fromFile;        
    nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
    if (NS_FAILED(rv))
      return rv;
    rv = directoryService->Get(key.get(), NS_GET_IID(nsILocalFile), getter_AddRefs(fromFile));
    if (NS_FAILED(rv))
      return rv;
    
    nsCOMPtr<nsILocalFile> theFile;
    rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(theFile));
    if (NS_FAILED(rv))
      return rv;
    rv = theFile->SetRelativeDescriptor(fromFile, Substring(++keyEnd, strEnd));
    if (NS_FAILED(rv))
      return rv;
    nsCOMPtr<nsIRelativeFilePref> relativePref;
    rv = NS_NewRelativeFilePref(theFile, key, getter_AddRefs(relativePref));
    if (NS_FAILED(rv))
      return rv;

    *_retval = relativePref;
    NS_ADDREF(NS_STATIC_CAST(nsIRelativeFilePref*, *_retval));
    return NS_OK;
  }