1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "storage/common/blob/scoped_file.h"
6
7#include "base/bind.h"
8#include "base/callback.h"
9#include "base/files/file_util.h"
10#include "base/location.h"
11#include "base/message_loop/message_loop_proxy.h"
12#include "base/task_runner.h"
13
14namespace storage {
15
16ScopedFile::ScopedFile()
17    : scope_out_policy_(DONT_DELETE_ON_SCOPE_OUT) {
18}
19
20ScopedFile::ScopedFile(const base::FilePath& path,
21                       ScopeOutPolicy policy,
22                       const scoped_refptr<base::TaskRunner>& file_task_runner)
23    : path_(path),
24      scope_out_policy_(policy),
25      file_task_runner_(file_task_runner) {
26  DCHECK(path.empty() || policy != DELETE_ON_SCOPE_OUT ||
27         file_task_runner.get())
28      << "path:" << path.value() << " policy:" << policy
29      << " runner:" << file_task_runner.get();
30}
31
32ScopedFile::ScopedFile(RValue other) {
33  MoveFrom(*other.object);
34}
35
36ScopedFile::~ScopedFile() {
37  Reset();
38}
39
40void ScopedFile::AddScopeOutCallback(
41    const ScopeOutCallback& callback,
42    base::TaskRunner* callback_runner) {
43  if (!callback_runner)
44    callback_runner = base::MessageLoopProxy::current().get();
45  scope_out_callbacks_.push_back(std::make_pair(callback, callback_runner));
46}
47
48base::FilePath ScopedFile::Release() {
49  base::FilePath path = path_;
50  path_.clear();
51  scope_out_callbacks_.clear();
52  scope_out_policy_ = DONT_DELETE_ON_SCOPE_OUT;
53  return path;
54}
55
56void ScopedFile::Reset() {
57  if (path_.empty())
58    return;
59
60  for (ScopeOutCallbackList::iterator iter = scope_out_callbacks_.begin();
61       iter != scope_out_callbacks_.end(); ++iter) {
62    iter->second->PostTask(FROM_HERE, base::Bind(iter->first, path_));
63  }
64
65  if (scope_out_policy_ == DELETE_ON_SCOPE_OUT) {
66    file_task_runner_->PostTask(
67        FROM_HERE,
68        base::Bind(base::IgnoreResult(&base::DeleteFile),
69                   path_, false /* recursive */));
70  }
71
72  // Clear all fields.
73  Release();
74}
75
76void ScopedFile::MoveFrom(ScopedFile& other) {
77  Reset();
78
79  scope_out_policy_ = other.scope_out_policy_;
80  scope_out_callbacks_.swap(other.scope_out_callbacks_);
81  file_task_runner_ = other.file_task_runner_;
82  path_ = other.Release();
83}
84
85}  // namespace storage
86