BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / scoped_file_opener.cc
blobeb7ba498257ada500e955a7dd609d341bbb6d01b
1 // Copyright 2015 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 "chrome/browser/chromeos/file_system_provider/scoped_file_opener.h"
7 #include "base/memory/weak_ptr.h"
8 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h"
10 namespace chromeos {
11 namespace file_system_provider {
13 using OpenFileCallback = ProvidedFileSystemInterface::OpenFileCallback;
15 // Opens and closes files automatically. Extracted from ScopedFileOpener to
16 // be able to make ScopedFileOpener *not* ref counted.
17 class ScopedFileOpener::Runner
18 : public base::RefCounted<ScopedFileOpener::Runner> {
19 public:
20 Runner(ProvidedFileSystemInterface* file_system,
21 const base::FilePath& file_path,
22 OpenFileMode mode,
23 const OpenFileCallback& callback)
24 : file_system_(file_system->GetWeakPtr()),
25 open_callback_(callback),
26 aborting_requested_(false),
27 open_completed_(false),
28 file_handle_(-1) {
29 abort_callback_ = file_system_->OpenFile(
30 file_path, mode,
31 base::Bind(&ScopedFileOpener::Runner::OnOpenFileCompleted, this));
34 // Aborts pending open operation, or closes a file if it's already opened.
35 // Called from ScopedFileOpener::~ScopedFileOpener.
36 void AbortOrClose() {
37 if (!open_completed_) {
38 aborting_requested_ = true;
39 abort_callback_.Run();
40 return;
43 if (open_completed_ && file_handle_ != -1) {
44 if (file_system_.get()) {
45 file_system_->CloseFile(
46 file_handle_,
47 base::Bind(
48 &ScopedFileOpener::Runner::OnCloseFileAfterAbortCompleted, this,
49 file_handle_));
51 return;
54 // Otherwise nothing to abort nor to close - the opening process has
55 // completed, but the file failed to open, so there is no need to close it.
56 DCHECK(open_completed_ && file_handle_ == -1);
59 private:
60 friend class base::RefCounted<ScopedFileOpener::Runner>;
62 ~Runner() {}
64 // Called when opening is completed with either a success or an error.
65 void OnOpenFileCompleted(int file_handle, base::File::Error result) {
66 open_completed_ = true;
67 file_handle_ = file_handle;
69 if (result != base::File::FILE_OK) {
70 CallOpenCallbackOnce(file_handle, result);
71 return;
74 if (aborting_requested_ && file_system_.get()) {
75 // The opening request has been aborted earlier, but the abort request
76 // either hasn't arrived yet the extension, or it abort request events are
77 // not handled by the extension. In either case, close the file now.
78 file_system_->CloseFile(
79 file_handle,
80 base::Bind(&ScopedFileOpener::Runner::OnCloseFileAfterAbortCompleted,
81 this, file_handle_));
82 return;
85 DCHECK_EQ(base::File::FILE_OK, result);
86 CallOpenCallbackOnce(file_handle, base::File::FILE_OK);
89 // Called when automatic closing a file is completed. It's performed when
90 // a file is opened successfully after the abort callback is called.
91 void OnCloseFileAfterAbortCompleted(int file_handle,
92 base::File::Error result) {
93 if (result == base::File::FILE_ERROR_ABORT) {
94 // Closing is aborted, so the file is still open. Call the OpenFile
95 // callback with a success error code and mark the file as opened.
97 // This is not good, as callers, such as file stream readers may expect
98 // aborting to *always* work, and leave the file opened permanently.
99 // The problem will go away once we remove the dialog to abort slow
100 // operations. See: crbug.com/475355.
101 CallOpenCallbackOnce(file_handle, base::File::FILE_OK);
102 return;
105 // Call the OpenFile callback with the ABORT error code, as the file is not
106 // opened anymore.
107 CallOpenCallbackOnce(file_handle, base::File::FILE_ERROR_ABORT);
110 // Calls the |open_callback_| only once with a result for opening a file.
111 void CallOpenCallbackOnce(int file_handle, base::File::Error result) {
112 if (open_callback_.is_null())
113 return;
115 OpenFileCallback open_callback = open_callback_;
116 open_callback_ = OpenFileCallback();
117 open_callback.Run(file_handle, result);
120 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
121 OpenFileCallback open_callback_;
122 AbortCallback abort_callback_;
123 bool aborting_requested_;
124 bool open_completed_;
125 int file_handle_;
128 ScopedFileOpener::ScopedFileOpener(ProvidedFileSystemInterface* file_system,
129 const base::FilePath& file_path,
130 OpenFileMode mode,
131 const OpenFileCallback& callback)
132 : runner_(new Runner(file_system, file_path, mode, callback)) {}
134 ScopedFileOpener::~ScopedFileOpener() {
135 runner_->AbortOrClose();
138 } // namespace file_system_provider
139 } // namespace chromeos