// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/self_cleaning_temp_dir.h"

#include <windows.h>

#include "base/file_util.h"
#include "base/logging.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"

namespace installer {

// Populates |base_dir| with the topmost directory in the hierarchy of
// |temp_parent_dir| that does not exist.  If |temp_parent_dir| exists,
// |base_dir| is cleared.
// static
void SelfCleaningTempDir::GetTopDirToCreate(
    const base::FilePath& temp_parent_dir,
    base::FilePath* base_dir) {
  DCHECK(base_dir);

  if (base::PathExists(temp_parent_dir)) {
    // Empty base_dir means that we didn't create any extra directories.
    base_dir->clear();
  } else {
    base::FilePath parent_dir(temp_parent_dir);
    do {
      *base_dir = parent_dir;
      parent_dir = parent_dir.DirName();
    } while (parent_dir != *base_dir && !base::PathExists(parent_dir));
    LOG_IF(WARNING, !base::DirectoryExists(parent_dir))
        << "A non-directory is at the base of the path leading to a desired "
           "temp directory location: " << parent_dir.value();
  }
}

SelfCleaningTempDir::SelfCleaningTempDir() {
}

SelfCleaningTempDir::~SelfCleaningTempDir() {
  if (!path().empty() && !Delete())
    LOG(WARNING) << "Failed to clean temp dir in dtor " << path().value();
}

bool SelfCleaningTempDir::Initialize(const base::FilePath& parent_dir,
                                     const StringType& temp_name) {
  DCHECK(parent_dir.IsAbsolute());
  DCHECK(!temp_name.empty());

  if (!path().empty()) {
    LOG(DFATAL) << "Attempting to re-initialize a SelfSelfCleaningTempDir.";
    return false;
  }

  base::FilePath temp_dir(parent_dir.Append(temp_name));
  base::FilePath base_dir;
  GetTopDirToCreate(parent_dir, &base_dir);

  if (base::CreateDirectory(temp_dir)) {
    base_dir_ = base_dir;
    temp_dir_ = temp_dir;
    return true;
  }

  return false;
}

bool SelfCleaningTempDir::Delete() {
  if (path().empty()) {
    LOG(DFATAL) << "Attempting to Delete an uninitialized SelfCleaningTempDir.";
    return false;
  }

  base::FilePath next_dir(path().DirName());
  bool schedule_deletes = false;

  // First try to recursively delete the leaf directory managed by our
  // base::ScopedTempDir.
  if (!base::DeleteFile(path(), true)) {
    // That failed, so schedule the temp dir and its contents for deletion after
    // reboot.
    LOG(WARNING) << "Failed to delete temporary directory " << path().value()
                 << ". Scheduling for deletion at reboot.";
    schedule_deletes = true;
    if (!ScheduleDirectoryForDeletion(path()))
      return false;  // Entirely unexpected failure (Schedule logs the reason).
  }

  // Now delete or schedule all empty directories up to and including our
  // base_dir_.  Any that can't be deleted are scheduled for deletion at reboot.
  // This is safe since they'll only be deleted in that case if they're empty.
  if (!base_dir_.empty()) {
    do {
      if (!schedule_deletes && !RemoveDirectory(next_dir.value().c_str())) {
        PLOG_IF(WARNING, GetLastError() != ERROR_DIR_NOT_EMPTY)
              << "Error removing directory " << next_dir.value().c_str();
        schedule_deletes = true;
      }
      if (schedule_deletes) {
        // Ignore the return code.  If we fail to schedule, go ahead and add the
        // other parent directories anyway.
        ScheduleFileSystemEntityForDeletion(next_dir);
      }
      if (next_dir == base_dir_)
        break;  // We just processed the topmost directory we created.
      next_dir = next_dir.DirName();
    } while (true);
  }

  base_dir_.clear();
  temp_dir_.clear();

  return true;
}

}  // namespace installer
