Ensure low-memory renderers retry failed loads correctly.
[chromium-blink-merge.git] / components / drive / file_system / truncate_operation.cc
blob7ab44b4d2c27e131901af6066e8ea57770463d96
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.
5 #include "components/drive/file_system/truncate_operation.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/files/file.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/task_runner_util.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/drive/drive.pb.h"
16 #include "components/drive/file_cache.h"
17 #include "components/drive/file_errors.h"
18 #include "components/drive/file_system/download_operation.h"
19 #include "components/drive/file_system/operation_delegate.h"
20 #include "components/drive/job_scheduler.h"
22 namespace drive {
23 namespace file_system {
24 namespace {
26 // Truncates the local file at |local_cache_path| to the |length| bytes,
27 // then marks the resource is dirty on |cache|.
28 FileError TruncateOnBlockingPool(internal::ResourceMetadata* metadata,
29 internal::FileCache* cache,
30 const std::string& local_id,
31 const base::FilePath& local_cache_path,
32 int64 length) {
33 DCHECK(metadata);
34 DCHECK(cache);
36 scoped_ptr<base::ScopedClosureRunner> file_closer;
37 FileError error = cache->OpenForWrite(local_id, &file_closer);
38 if (error != FILE_ERROR_OK)
39 return error;
41 base::File file(local_cache_path,
42 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
43 if (!file.IsValid())
44 return FILE_ERROR_FAILED;
46 if (!file.SetLength(length))
47 return FILE_ERROR_FAILED;
49 return FILE_ERROR_OK;
52 } // namespace
54 TruncateOperation::TruncateOperation(
55 base::SequencedTaskRunner* blocking_task_runner,
56 OperationDelegate* delegate,
57 JobScheduler* scheduler,
58 internal::ResourceMetadata* metadata,
59 internal::FileCache* cache,
60 const base::FilePath& temporary_file_directory)
61 : blocking_task_runner_(blocking_task_runner),
62 delegate_(delegate),
63 metadata_(metadata),
64 cache_(cache),
65 download_operation_(new DownloadOperation(blocking_task_runner,
66 delegate,
67 scheduler,
68 metadata,
69 cache,
70 temporary_file_directory)),
71 weak_ptr_factory_(this) {
74 TruncateOperation::~TruncateOperation() {
77 void TruncateOperation::Truncate(const base::FilePath& file_path,
78 int64 length,
79 const FileOperationCallback& callback) {
80 DCHECK(thread_checker_.CalledOnValidThread());
81 DCHECK(!callback.is_null());
83 if (length < 0) {
84 base::ThreadTaskRunnerHandle::Get()->PostTask(
85 FROM_HERE,
86 base::Bind(callback, FILE_ERROR_INVALID_OPERATION));
87 return;
90 // TODO(kinaba): http://crbug.com/132780.
91 // Optimize the cases for small |length|, at least for |length| == 0.
92 download_operation_->EnsureFileDownloadedByPath(
93 file_path,
94 ClientContext(USER_INITIATED),
95 GetFileContentInitializedCallback(),
96 google_apis::GetContentCallback(),
97 base::Bind(&TruncateOperation::TruncateAfterEnsureFileDownloadedByPath,
98 weak_ptr_factory_.GetWeakPtr(), length, callback));
101 void TruncateOperation::TruncateAfterEnsureFileDownloadedByPath(
102 int64 length,
103 const FileOperationCallback& callback,
104 FileError error,
105 const base::FilePath& local_file_path,
106 scoped_ptr<ResourceEntry> entry) {
107 DCHECK(thread_checker_.CalledOnValidThread());
108 DCHECK(!callback.is_null());
110 if (error != FILE_ERROR_OK) {
111 callback.Run(error);
112 return;
114 DCHECK(entry);
115 DCHECK(entry->has_file_specific_info());
117 if (entry->file_specific_info().is_hosted_document()) {
118 callback.Run(FILE_ERROR_INVALID_OPERATION);
119 return;
122 base::PostTaskAndReplyWithResult(
123 blocking_task_runner_.get(),
124 FROM_HERE,
125 base::Bind(&TruncateOnBlockingPool,
126 metadata_, cache_, entry->local_id(), local_file_path, length),
127 base::Bind(
128 &TruncateOperation::TruncateAfterTruncateOnBlockingPool,
129 weak_ptr_factory_.GetWeakPtr(), entry->local_id(), callback));
132 void TruncateOperation::TruncateAfterTruncateOnBlockingPool(
133 const std::string& local_id,
134 const FileOperationCallback& callback,
135 FileError error) {
136 DCHECK(thread_checker_.CalledOnValidThread());
137 DCHECK(!callback.is_null());
139 delegate_->OnEntryUpdatedByOperation(ClientContext(USER_INITIATED), local_id);
141 callback.Run(error);
144 } // namespace file_system
145 } // namespace drive