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"
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
> {
20 Runner(ProvidedFileSystemInterface
* file_system
,
21 const base::FilePath
& file_path
,
23 const OpenFileCallback
& callback
)
24 : file_system_(file_system
->GetWeakPtr()),
25 open_callback_(callback
),
26 aborting_requested_(false),
27 open_completed_(false),
29 abort_callback_
= file_system_
->OpenFile(
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.
37 if (!open_completed_
) {
38 aborting_requested_
= true;
39 abort_callback_
.Run();
43 if (open_completed_
&& file_handle_
!= -1) {
44 if (file_system_
.get()) {
45 file_system_
->CloseFile(
48 &ScopedFileOpener::Runner::OnCloseFileAfterAbortCompleted
, this,
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);
60 friend class base::RefCounted
<ScopedFileOpener::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
);
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(
80 base::Bind(&ScopedFileOpener::Runner::OnCloseFileAfterAbortCompleted
,
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
);
105 // Call the OpenFile callback with the ABORT error code, as the file is not
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())
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_
;
128 ScopedFileOpener::ScopedFileOpener(ProvidedFileSystemInterface
* file_system
,
129 const base::FilePath
& file_path
,
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