nsresult
sbWatchFolder::InitInternal()
{
  nsresult rv;

  // Set the service as disabled, if this method exits cleanly, the service
  // will be considered 'started'.
  mServiceState = eDisabled;

  // If the service is set to be turned off, do not continue.
  if (!mMediaList) {
    return NS_OK;
  }

  // Don't start the service if the watch path isn't defined.
  if (mWatchPath.Equals(EmptyString())) {
    return NS_ERROR_UNEXPECTED;
  }

  // The service is now considered started.
  mServiceState = eStarted;

  // Now start watching the folder.
  rv = StartWatchingFolder();
  NS_ENSURE_SUCCESS(rv, rv);

  TRACE(("%s: started watching [%s]",
         __FUNCTION__,
         NS_ConvertUTF16toUTF8(mWatchPath).get()));

  return NS_OK;
}
NS_IMETHODIMP
sbWatchFolderService::Notify(nsITimer *aTimer)
{
  nsresult rv;

  // Handle startup delay (internally init)
  if (aTimer == mStartupDelayTimer) {
    LOG(("%s: startup delay timer [%08x] fired",
         __FUNCTION__, mStartupDelayTimer.get()));
    rv = InitInternal();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Handle flushing the old file system watcher with a new one
  else if (aTimer == mFlushFSWatcherTimer) {
    mFileSystemWatcher = nsnull;
    mShouldReinitWatcher = PR_FALSE;

    rv = StartWatchingFolder();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Standard processing of removed and non-queued changed paths.
  else if (aTimer == mEventPumpTimer) {
    if (mShouldProcessEvents) {
      // No events have been received since the event pump timer was armed. Go
      // ahead and process the event paths now.
      rv = ProcessEventPaths();
      NS_ENSURE_SUCCESS(rv, rv);

      mEventPumpTimerIsSet = PR_FALSE;
    }
    else {
      // Some event has happened since the last time the event pump timer was
      // armed. Go ahead and wait another |EVENT_PUMP_TIMER_DELAY| milliseconds.
      LOG(("%s: arming event pump timer [%08x]",
            __FUNCTION__, mEventPumpTimer.get()));
      rv = mEventPumpTimer->InitWithCallback(this,
                                             EVENT_PUMP_TIMER_DELAY,
                                             nsITimer::TYPE_ONE_SHOT);
      NS_ENSURE_SUCCESS(rv, rv);

      mShouldProcessEvents = PR_TRUE;
    }
  }

  // Process queued changed event paths.
  else if (aTimer == mChangeDelayTimer) {
    rv = HandleEventPathList(mDelayedChangedPaths, eChanged);
    NS_ENSURE_SUCCESS(rv, rv);

    mChangeDelayTimerIsSet = PR_FALSE;
  }

  return NS_OK;
}
nsresult
sbWatchFolderService::OnEnableWatchFolderChanged(bool aShouldEnable)
{
  LOG(("%s: OnEnableWatchFolderChanged( aShouldEnable=%s )",
        __FUNCTION__,
        (aShouldEnable ? "true" : "false")));

  nsresult rv;

  // Stop watching since the service is watching and the pref was toggled
  // to not watch.
  if (mServiceState == eWatching && !aShouldEnable) {
    rv = StopWatchingFolder();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Start watching since the service is not watching and the pref was
  // toggled to start watching.
  else if (mServiceState == eStarted && aShouldEnable) {
    rv = StartWatchingFolder();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // The service has not yet attempted to start up and was just turned on.
  // Start the timer if the service is in a disabled state, the watch path
  // has been defined, and the service should enable.
  else if (mServiceState == eDisabled &&
           !mWatchPath.IsEmpty() &&
           aShouldEnable)
  {
    rv = SetStartupDelayTimer();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return NS_OK;
}
nsresult
sbWatchFolderService::InitInternal()
{
  nsresult rv;
  nsCOMPtr<nsIPrefBranch2> prefBranch =
    do_GetService("@mozilla.org/preferences-service;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // First, check to see if the service should be running.
  bool shouldEnable = PR_FALSE;
  rv = prefBranch->GetBoolPref(PREF_WATCHFOLDER_ENABLE, &shouldEnable);
  if (NS_FAILED(rv)) {
    shouldEnable = PR_FALSE;
  }

  // Set the service as disabled, if this method exits cleanly, the service
  // will be considered 'started'.
  mServiceState = eDisabled;

  // If the service is set to be turned off, do not continue.
  if (!shouldEnable) {
    return NS_OK;
  }

  // Next, read in the watch path.
  nsCOMPtr<nsISupportsString> supportsString;
  rv = prefBranch->GetComplexValue(PREF_WATCHFOLDER_PATH,
                                   NS_GET_IID(nsISupportsString),
                                   getter_AddRefs(supportsString));

  // The service can not continue if the watch path does not exist.
  if (NS_FAILED(rv) || !supportsString) {
    return NS_ERROR_UNEXPECTED;
  }

  rv = supportsString->GetData(mWatchPath);
  NS_ENSURE_SUCCESS(rv, rv);

  // Don't start the service if the watch path isn't defined.
  if (mWatchPath.Equals(EmptyString())) {
    return NS_ERROR_UNEXPECTED;
  }

  // Look to see if the watch folder service has saved a previous file system
  // watcher session.
  // NOTE: Validating the return value is not needed, either there is a
  // saved session or there is not.
  prefBranch->GetCharPref(PREF_WATCHFOLDER_SESSIONGUID,
                          getter_Copies(mFileSystemWatcherGUID));

  mLibraryUtils =
    do_GetService("@songbirdnest.com/Songbird/library/Manager;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the main library (all changes will be pushed into this library).
  nsCOMPtr<sbILibraryManager> libraryMgr =
    do_QueryInterface(mLibraryUtils, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = libraryMgr->GetMainLibrary(getter_AddRefs(mMainLibrary));
  NS_ENSURE_SUCCESS(rv, rv);

  // The service is now considered started.
  mServiceState = eStarted;

  // Now start watching the folder.
  rv = StartWatchingFolder();
  NS_ENSURE_SUCCESS(rv, rv);

  TRACE(("%s: started watching [%s]",
         __FUNCTION__,
         NS_ConvertUTF16toUTF8(mWatchPath).get()));

  return NS_OK;
}