Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / open_file_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/open_file_operation.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/task_runner_util.h"
14 #include "chrome/browser/chromeos/drive/drive.pb.h"
15 #include "chrome/browser/chromeos/drive/file_cache.h"
16 #include "chrome/browser/chromeos/drive/file_errors.h"
17 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
18 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
19 #include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
20 #include "chrome/browser/chromeos/drive/job_scheduler.h"
21 #include "content/public/browser/browser_thread.h"
22
23 using content::BrowserThread;
24
25 namespace drive {
26 namespace file_system {
27
28 OpenFileOperation::OpenFileOperation(
29     base::SequencedTaskRunner* blocking_task_runner,
30     OperationDelegate* delegate,
31     JobScheduler* scheduler,
32     internal::ResourceMetadata* metadata,
33     internal::FileCache* cache,
34     const base::FilePath& temporary_file_directory)
35     : blocking_task_runner_(blocking_task_runner),
36       delegate_(delegate),
37       cache_(cache),
38       create_file_operation_(new CreateFileOperation(
39           blocking_task_runner, delegate, metadata)),
40       download_operation_(new DownloadOperation(
41           blocking_task_runner, delegate, scheduler,
42           metadata, cache, temporary_file_directory)),
43       weak_ptr_factory_(this) {
44 }
45
46 OpenFileOperation::~OpenFileOperation() {
47 }
48
49 void OpenFileOperation::OpenFile(const base::FilePath& file_path,
50                                  OpenMode open_mode,
51                                  const std::string& mime_type,
52                                  const OpenFileCallback& callback) {
53   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
54   DCHECK(!callback.is_null());
55
56   switch (open_mode) {
57     case OPEN_FILE:
58       // It is not necessary to create a new file even if not exists.
59       // So call OpenFileAfterCreateFile directly with FILE_ERROR_OK
60       // to skip file creation.
61       OpenFileAfterCreateFile(file_path, callback, FILE_ERROR_OK);
62       break;
63     case CREATE_FILE:
64       create_file_operation_->CreateFile(
65           file_path,
66           true,  // exclusive: fail if already exists
67           mime_type,
68           base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
69                      weak_ptr_factory_.GetWeakPtr(), file_path, callback));
70       break;
71     case OPEN_OR_CREATE_FILE:
72       create_file_operation_->CreateFile(
73           file_path,
74           false,  // not-exclusive
75           mime_type,
76           base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
77                      weak_ptr_factory_.GetWeakPtr(), file_path, callback));
78       break;
79   }
80 }
81
82 void OpenFileOperation::OpenFileAfterCreateFile(
83     const base::FilePath& file_path,
84     const OpenFileCallback& callback,
85     FileError error) {
86   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
87   DCHECK(!callback.is_null());
88
89   if (error != FILE_ERROR_OK) {
90     callback.Run(error, base::FilePath(), base::Closure());
91     return;
92   }
93
94   download_operation_->EnsureFileDownloadedByPath(
95       file_path,
96       ClientContext(USER_INITIATED),
97       GetFileContentInitializedCallback(),
98       google_apis::GetContentCallback(),
99       base::Bind(
100           &OpenFileOperation::OpenFileAfterFileDownloaded,
101           weak_ptr_factory_.GetWeakPtr(), callback));
102 }
103
104 void OpenFileOperation::OpenFileAfterFileDownloaded(
105     const OpenFileCallback& callback,
106     FileError error,
107     const base::FilePath& local_file_path,
108     scoped_ptr<ResourceEntry> entry) {
109   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110   DCHECK(!callback.is_null());
111
112   if (error == FILE_ERROR_OK) {
113     DCHECK(entry);
114     DCHECK(entry->has_file_specific_info());
115     if (entry->file_specific_info().is_hosted_document())
116       // No support for opening a hosted document.
117       error = FILE_ERROR_INVALID_OPERATION;
118   }
119
120   if (error != FILE_ERROR_OK) {
121     callback.Run(error, base::FilePath(), base::Closure());
122     return;
123   }
124
125   scoped_ptr<base::ScopedClosureRunner>* file_closer =
126       new scoped_ptr<base::ScopedClosureRunner>;
127   base::PostTaskAndReplyWithResult(
128       blocking_task_runner_.get(),
129       FROM_HERE,
130       base::Bind(&internal::FileCache::OpenForWrite,
131                  base::Unretained(cache_),
132                  entry->local_id(),
133                  file_closer),
134       base::Bind(&OpenFileOperation::OpenFileAfterOpenForWrite,
135                  weak_ptr_factory_.GetWeakPtr(),
136                  local_file_path,
137                  entry->local_id(),
138                  callback,
139                  base::Owned(file_closer)));
140 }
141
142 void OpenFileOperation::OpenFileAfterOpenForWrite(
143     const base::FilePath& local_file_path,
144     const std::string& local_id,
145     const OpenFileCallback& callback,
146     scoped_ptr<base::ScopedClosureRunner>* file_closer,
147     FileError error) {
148   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
149   DCHECK(!callback.is_null());
150
151   if (error != FILE_ERROR_OK) {
152     callback.Run(error, base::FilePath(), base::Closure());
153     return;
154   }
155
156   ++open_files_[local_id];
157   callback.Run(error, local_file_path,
158                base::Bind(&OpenFileOperation::CloseFile,
159                           weak_ptr_factory_.GetWeakPtr(),
160                           local_id,
161                           base::Passed(file_closer)));
162 }
163
164 void OpenFileOperation::CloseFile(
165     const std::string& local_id,
166     scoped_ptr<base::ScopedClosureRunner> file_closer) {
167   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168   DCHECK_GT(open_files_[local_id], 0);
169
170   if (--open_files_[local_id] == 0) {
171     // All clients closes this file, so notify to upload the file.
172     open_files_.erase(local_id);
173     delegate_->OnEntryUpdatedByOperation(local_id);
174
175     // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
176     // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
177     blocking_task_runner_->PostTask(
178         FROM_HERE,
179         base::Bind(base::IgnoreResult(
180             base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
181                        base::Unretained(cache_),
182                        0))));
183   }
184 }
185
186 }  // namespace file_system
187 }  // namespace drive