- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / get_file_for_saving_operation.cc
1 // Copyright 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 "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/browser/chromeos/drive/file_cache.h"
10 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
11 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
12 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
13 #include "chrome/browser/chromeos/drive/file_write_watcher.h"
14 #include "content/public/browser/browser_thread.h"
15
16 using content::BrowserThread;
17
18 namespace drive {
19 namespace file_system {
20
21 namespace {
22
23 // Marks the cache entry as dirty.
24 FileError MarkDirty(internal::ResourceMetadata* metadata,
25                     internal::FileCache* cache,
26                     const std::string& resource_id,
27                     std::string* local_id) {
28   FileError error = metadata->GetIdByResourceId(resource_id, local_id);
29   if (error != FILE_ERROR_OK)
30     return error;
31   return cache->MarkDirty(*local_id);
32 }
33
34 }  // namespace
35
36 GetFileForSavingOperation::GetFileForSavingOperation(
37     base::SequencedTaskRunner* blocking_task_runner,
38     OperationObserver* observer,
39     JobScheduler* scheduler,
40     internal::ResourceMetadata* metadata,
41     internal::FileCache* cache,
42     const base::FilePath& temporary_file_directory)
43     : create_file_operation_(new CreateFileOperation(blocking_task_runner,
44                                                      observer,
45                                                      scheduler,
46                                                      metadata,
47                                                      cache)),
48       download_operation_(new DownloadOperation(blocking_task_runner,
49                                                 observer,
50                                                 scheduler,
51                                                 metadata,
52                                                 cache,
53                                                 temporary_file_directory)),
54       file_write_watcher_(new internal::FileWriteWatcher),
55       blocking_task_runner_(blocking_task_runner),
56       observer_(observer),
57       metadata_(metadata),
58       cache_(cache),
59       weak_ptr_factory_(this) {
60 }
61
62 GetFileForSavingOperation::~GetFileForSavingOperation() {
63 }
64
65 void GetFileForSavingOperation::GetFileForSaving(
66     const base::FilePath& file_path,
67     const GetFileCallback& callback) {
68   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69   DCHECK(!callback.is_null());
70
71   create_file_operation_->CreateFile(
72       file_path,
73       false,  // error_if_already_exists
74       std::string(),  // no specific mime type
75       base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
76                  weak_ptr_factory_.GetWeakPtr(),
77                  file_path,
78                  callback));
79 }
80
81 void GetFileForSavingOperation::GetFileForSavingAfterCreate(
82     const base::FilePath& file_path,
83     const GetFileCallback& callback,
84     FileError error) {
85   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86   DCHECK(!callback.is_null());
87
88   if (error != FILE_ERROR_OK) {
89     callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
90     return;
91   }
92
93   download_operation_->EnsureFileDownloadedByPath(
94       file_path,
95       ClientContext(USER_INITIATED),
96       GetFileContentInitializedCallback(),
97       google_apis::GetContentCallback(),
98       base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
99                  weak_ptr_factory_.GetWeakPtr(),
100                  callback));
101 }
102
103 void GetFileForSavingOperation::GetFileForSavingAfterDownload(
104     const GetFileCallback& callback,
105     FileError error,
106     const base::FilePath& cache_path,
107     scoped_ptr<ResourceEntry> entry) {
108   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109   DCHECK(!callback.is_null());
110
111   if (error != FILE_ERROR_OK) {
112     callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
113     return;
114   }
115
116   const std::string& resource_id = entry->resource_id();
117   std::string* local_id = new std::string;
118   base::PostTaskAndReplyWithResult(
119       blocking_task_runner_.get(),
120       FROM_HERE,
121       base::Bind(&MarkDirty, metadata_, cache_, resource_id, local_id),
122       base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterMarkDirty,
123                  weak_ptr_factory_.GetWeakPtr(),
124                  callback,
125                  cache_path,
126                  base::Owned(local_id),
127                  base::Passed(&entry)));
128 }
129
130 void GetFileForSavingOperation::GetFileForSavingAfterMarkDirty(
131     const GetFileCallback& callback,
132     const base::FilePath& cache_path,
133     const std::string* local_id,
134     scoped_ptr<ResourceEntry> entry,
135     FileError error) {
136   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137   DCHECK(!callback.is_null());
138
139   if (error != FILE_ERROR_OK) {
140     callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
141     return;
142   }
143
144   file_write_watcher_->StartWatch(
145       cache_path,
146       base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
147                  weak_ptr_factory_.GetWeakPtr(),
148                  callback,
149                  cache_path,
150                  base::Passed(&entry)),
151       base::Bind(&GetFileForSavingOperation::OnWriteEvent,
152                  weak_ptr_factory_.GetWeakPtr(),
153                  *local_id));
154 }
155
156 void GetFileForSavingOperation::GetFileForSavingAfterWatch(
157     const GetFileCallback& callback,
158     const base::FilePath& cache_path,
159     scoped_ptr<ResourceEntry> entry,
160     bool success) {
161   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162   DCHECK(!callback.is_null());
163
164   if (!success) {
165     callback.Run(FILE_ERROR_FAILED,
166                  base::FilePath(), scoped_ptr<ResourceEntry>());
167     return;
168   }
169
170   callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
171 }
172
173 void GetFileForSavingOperation::OnWriteEvent(const std::string& local_id) {
174   observer_->OnCacheFileUploadNeededByOperation(local_id);
175
176   // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
177   // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
178   blocking_task_runner_->PostTask(
179       FROM_HERE,
180       base::Bind(base::IgnoreResult(
181           base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
182                      base::Unretained(cache_),
183                      0))));
184 }
185
186 }  // namespace file_system
187 }  // namespace drive