root/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_ptr_factory_
  2. GetFileForSavingAfterCreate
  3. GetFileForSavingAfterDownload
  4. GetFileForSavingAfterOpenForWrite
  5. GetFileForSavingAfterWatch
  6. OnWriteEvent

// Copyright 2013 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/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "chrome/browser/chromeos/drive/file_cache.h"
#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
#include "chrome/browser/chromeos/drive/file_write_watcher.h"
#include "chrome/browser/chromeos/drive/job_scheduler.h"
#include "chrome/browser/drive/event_logger.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace drive {
namespace file_system {

GetFileForSavingOperation::GetFileForSavingOperation(
    EventLogger* logger,
    base::SequencedTaskRunner* blocking_task_runner,
    OperationObserver* observer,
    JobScheduler* scheduler,
    internal::ResourceMetadata* metadata,
    internal::FileCache* cache,
    const base::FilePath& temporary_file_directory)
    : logger_(logger),
      create_file_operation_(new CreateFileOperation(blocking_task_runner,
                                                     observer,
                                                     metadata)),
      download_operation_(new DownloadOperation(blocking_task_runner,
                                                observer,
                                                scheduler,
                                                metadata,
                                                cache,
                                                temporary_file_directory)),
      file_write_watcher_(new internal::FileWriteWatcher),
      blocking_task_runner_(blocking_task_runner),
      observer_(observer),
      metadata_(metadata),
      cache_(cache),
      weak_ptr_factory_(this) {
}

GetFileForSavingOperation::~GetFileForSavingOperation() {
}

void GetFileForSavingOperation::GetFileForSaving(
    const base::FilePath& file_path,
    const GetFileCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  create_file_operation_->CreateFile(
      file_path,
      false,  // error_if_already_exists
      std::string(),  // no specific mime type
      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
                 weak_ptr_factory_.GetWeakPtr(),
                 file_path,
                 callback));
}

void GetFileForSavingOperation::GetFileForSavingAfterCreate(
    const base::FilePath& file_path,
    const GetFileCallback& callback,
    FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  if (error != FILE_ERROR_OK) {
    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
    return;
  }

  download_operation_->EnsureFileDownloadedByPath(
      file_path,
      ClientContext(USER_INITIATED),
      GetFileContentInitializedCallback(),
      google_apis::GetContentCallback(),
      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback));
}

void GetFileForSavingOperation::GetFileForSavingAfterDownload(
    const GetFileCallback& callback,
    FileError error,
    const base::FilePath& cache_path,
    scoped_ptr<ResourceEntry> entry) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  if (error != FILE_ERROR_OK) {
    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
    return;
  }

  const std::string& local_id = entry->local_id();
  scoped_ptr<base::ScopedClosureRunner>* file_closer =
      new scoped_ptr<base::ScopedClosureRunner>;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner_.get(),
      FROM_HERE,
      base::Bind(&internal::FileCache::OpenForWrite,
                 base::Unretained(cache_),
                 local_id,
                 file_closer),
      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 cache_path,
                 base::Passed(&entry),
                 base::Owned(file_closer)));
}

void GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite(
    const GetFileCallback& callback,
    const base::FilePath& cache_path,
    scoped_ptr<ResourceEntry> entry,
    scoped_ptr<base::ScopedClosureRunner>* file_closer,
    FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  if (error != FILE_ERROR_OK) {
    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
    return;
  }

  const std::string& local_id = entry->local_id();
  file_write_watcher_->StartWatch(
      cache_path,
      base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 cache_path,
                 base::Passed(&entry)),
      base::Bind(&GetFileForSavingOperation::OnWriteEvent,
                 weak_ptr_factory_.GetWeakPtr(),
                 local_id,
                 base::Passed(file_closer)));
}

void GetFileForSavingOperation::GetFileForSavingAfterWatch(
    const GetFileCallback& callback,
    const base::FilePath& cache_path,
    scoped_ptr<ResourceEntry> entry,
    bool success) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  logger_->Log(logging::LOG_INFO, "Started watching modification to %s [%s].",
               entry->local_id().c_str(),
               success ? "ok" : "fail");

  if (!success) {
    callback.Run(FILE_ERROR_FAILED,
                 base::FilePath(), scoped_ptr<ResourceEntry>());
    return;
  }

  callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
}

void GetFileForSavingOperation::OnWriteEvent(
    const std::string& local_id,
    scoped_ptr<base::ScopedClosureRunner> file_closer) {
  logger_->Log(logging::LOG_INFO, "Detected modification to %s.",
               local_id.c_str());

  observer_->OnEntryUpdatedByOperation(local_id);

  // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
  // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(base::IgnoreResult(
          base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
                     base::Unretained(cache_),
                     0))));
}

}  // namespace file_system
}  // namespace drive

/* [<][>][^][v][top][bottom][index][help] */