blob: 25d63485aa4c4c623582db22e7db058898c12ddd [file] [log] [blame]
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001// 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/files/file_path.h"
9#include "base/logging.h"
10#include "base/message_loop/message_loop_proxy.h"
11#include "base/task_runner_util.h"
12#include "chrome/browser/chromeos/drive/drive.pb.h"
13#include "chrome/browser/chromeos/drive/file_cache.h"
14#include "chrome/browser/chromeos/drive/file_errors.h"
15#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
16#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010017#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010018#include "chrome/browser/chromeos/drive/file_system_interface.h"
19#include "content/public/browser/browser_thread.h"
20
21using content::BrowserThread;
22
23namespace drive {
24namespace file_system {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010025
26OpenFileOperation::OpenFileOperation(
27 base::SequencedTaskRunner* blocking_task_runner,
28 OperationObserver* observer,
29 JobScheduler* scheduler,
30 internal::ResourceMetadata* metadata,
31 internal::FileCache* cache,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010032 const base::FilePath& temporary_file_directory)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010033 : blocking_task_runner_(blocking_task_runner),
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010034 observer_(observer),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010035 cache_(cache),
36 create_file_operation_(new CreateFileOperation(
37 blocking_task_runner, observer, scheduler, metadata, cache)),
38 download_operation_(new DownloadOperation(
39 blocking_task_runner, observer, scheduler,
40 metadata, cache, temporary_file_directory)),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010041 weak_ptr_factory_(this) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010042}
43
44OpenFileOperation::~OpenFileOperation() {
45}
46
47void OpenFileOperation::OpenFile(const base::FilePath& file_path,
48 OpenMode open_mode,
49 const OpenFileCallback& callback) {
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51 DCHECK(!callback.is_null());
52
53 switch (open_mode) {
54 case OPEN_FILE:
55 // It is not necessary to create a new file even if not exists.
56 // So call OpenFileAfterCreateFile directly with FILE_ERROR_OK
57 // to skip file creation.
58 OpenFileAfterCreateFile(file_path, callback, FILE_ERROR_OK);
59 break;
60 case CREATE_FILE:
61 create_file_operation_->CreateFile(
62 file_path,
63 true /* exclusive */,
64 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
65 weak_ptr_factory_.GetWeakPtr(), file_path, callback));
66 break;
67 case OPEN_OR_CREATE_FILE:
68 create_file_operation_->CreateFile(
69 file_path,
70 false /* not-exclusive */,
71 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
72 weak_ptr_factory_.GetWeakPtr(), file_path, callback));
73 break;
74 }
75}
76
77void OpenFileOperation::OpenFileAfterCreateFile(
78 const base::FilePath& file_path,
79 const OpenFileCallback& callback,
80 FileError error) {
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82 DCHECK(!callback.is_null());
83
84 if (error != FILE_ERROR_OK) {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010085 callback.Run(error, base::FilePath(), base::Closure());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010086 return;
87 }
88
89 download_operation_->EnsureFileDownloadedByPath(
90 file_path,
91 ClientContext(USER_INITIATED),
92 GetFileContentInitializedCallback(),
93 google_apis::GetContentCallback(),
94 base::Bind(
95 &OpenFileOperation::OpenFileAfterFileDownloaded,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010096 weak_ptr_factory_.GetWeakPtr(), callback));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010097}
98
99void OpenFileOperation::OpenFileAfterFileDownloaded(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100100 const OpenFileCallback& callback,
101 FileError error,
102 const base::FilePath& local_file_path,
103 scoped_ptr<ResourceEntry> entry) {
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105 DCHECK(!callback.is_null());
106
107 if (error == FILE_ERROR_OK) {
108 DCHECK(entry);
109 DCHECK(entry->has_file_specific_info());
110 if (entry->file_specific_info().is_hosted_document())
111 // No support for opening a hosted document.
112 error = FILE_ERROR_INVALID_OPERATION;
113 }
114
115 if (error != FILE_ERROR_OK) {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100116 callback.Run(error, base::FilePath(), base::Closure());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100117 return;
118 }
119
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100120 base::PostTaskAndReplyWithResult(
121 blocking_task_runner_.get(),
122 FROM_HERE,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100123 base::Bind(&internal::FileCache::MarkDirty,
124 base::Unretained(cache_),
125 entry->resource_id()),
126 base::Bind(&OpenFileOperation::OpenFileAfterMarkDirty,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100127 weak_ptr_factory_.GetWeakPtr(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100128 local_file_path,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100129 entry->resource_id(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100130 callback));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100131}
132
Ben Murdochbb1529c2013-08-08 10:24:53 +0100133void OpenFileOperation::OpenFileAfterMarkDirty(
134 const base::FilePath& local_file_path,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100135 const std::string& resource_id,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100136 const OpenFileCallback& callback,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100137 FileError error) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 DCHECK(!callback.is_null());
140
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100141 if (error != FILE_ERROR_OK) {
142 callback.Run(error, base::FilePath(), base::Closure());
143 return;
144 }
145
146 ++open_files_[resource_id];
Ben Murdochbb1529c2013-08-08 10:24:53 +0100147 callback.Run(error, local_file_path,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100148 base::Bind(&OpenFileOperation::CloseFile,
149 weak_ptr_factory_.GetWeakPtr(), resource_id));
150}
151
152void OpenFileOperation::CloseFile(const std::string& resource_id) {
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
154 DCHECK_GT(open_files_[resource_id], 0);
155
156 if (--open_files_[resource_id] == 0) {
157 // All clients closes this file, so notify to upload the file.
158 open_files_.erase(resource_id);
159 observer_->OnCacheFileUploadNeededByOperation(resource_id);
160 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100161}
162
163} // namespace file_system
164} // namespace drive