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 "content/child/fileapi/webfilewriter_base.h"
7 #include "base/logging.h"
8 #include "storage/common/fileapi/file_system_util.h"
9 #include "third_party/WebKit/public/platform/WebFileError.h"
10 #include "third_party/WebKit/public/platform/WebFileWriterClient.h"
11 #include "third_party/WebKit/public/platform/WebURL.h"
13 using storage::FileErrorToWebFileError
;
17 WebFileWriterBase::WebFileWriterBase(const GURL
& path
,
18 blink::WebFileWriterClient
* client
)
21 operation_(kOperationNone
),
22 cancel_state_(kCancelNotInProgress
) {}
24 WebFileWriterBase::~WebFileWriterBase() {}
26 void WebFileWriterBase::truncate(long long length
) {
27 DCHECK(kOperationNone
== operation_
);
28 DCHECK(kCancelNotInProgress
== cancel_state_
);
29 operation_
= kOperationTruncate
;
30 DoTruncate(path_
, length
);
33 void WebFileWriterBase::write(
35 const blink::WebString
& id
) {
36 DCHECK_EQ(kOperationNone
, operation_
);
37 DCHECK_EQ(kCancelNotInProgress
, cancel_state_
);
38 operation_
= kOperationWrite
;
39 DoWrite(path_
, id
.utf8(), position
);
42 // When we cancel a write/truncate, we always get back the result of the write
43 // before the result of the cancel, no matter what happens.
44 // So we'll get back either
45 // success [of the write/truncate, in a DidWrite(XXX, true)/DidSucceed() call]
46 // followed by failure [of the cancel]; or
47 // failure [of the write, either from cancel or other reasons] followed by
48 // the result of the cancel.
49 // In the write case, there could also be queued up non-terminal DidWrite calls
50 // before any of that comes back, but there will always be a terminal write
51 // response [success or failure] after them, followed by the cancel result, so
52 // we can ignore non-terminal write responses, take the terminal write success
53 // or the first failure as the last write response, then know that the next
54 // thing to come back is the cancel response. We only notify the
55 // AsyncFileWriterClient when it's all over.
56 void WebFileWriterBase::cancel() {
57 // Check for the cancel passing the previous operation's return in-flight.
58 if (kOperationWrite
!= operation_
&& kOperationTruncate
!= operation_
)
60 if (kCancelNotInProgress
!= cancel_state_
)
62 cancel_state_
= kCancelSent
;
66 void WebFileWriterBase::DidFinish(base::File::Error error_code
) {
67 if (error_code
== base::File::FILE_OK
)
73 void WebFileWriterBase::DidWrite(int64 bytes
, bool complete
) {
74 DCHECK(kOperationWrite
== operation_
);
75 switch (cancel_state_
) {
76 case kCancelNotInProgress
:
78 operation_
= kOperationNone
;
79 client_
->didWrite(bytes
, complete
);
82 // This is the success call of the write, which we'll eat, even though
83 // it succeeded before the cancel got there. We accepted the cancel call,
84 // so the write will eventually return an error.
86 cancel_state_
= kCancelReceivedWriteResponse
;
88 case kCancelReceivedWriteResponse
:
94 void WebFileWriterBase::DidSucceed() {
95 // Write never gets a DidSucceed call, so this is either a cancel or truncate
97 switch (cancel_state_
) {
98 case kCancelNotInProgress
:
99 // A truncate succeeded, with no complications.
100 DCHECK(kOperationTruncate
== operation_
);
101 operation_
= kOperationNone
;
102 client_
->didTruncate();
105 DCHECK(kOperationTruncate
== operation_
);
106 // This is the success call of the truncate, which we'll eat, even though
107 // it succeeded before the cancel got there. We accepted the cancel call,
108 // so the truncate will eventually return an error.
109 cancel_state_
= kCancelReceivedWriteResponse
;
111 case kCancelReceivedWriteResponse
:
112 // This is the success of the cancel operation.
120 void WebFileWriterBase::DidFail(base::File::Error error_code
) {
121 DCHECK(kOperationNone
!= operation_
);
122 switch (cancel_state_
) {
123 case kCancelNotInProgress
:
124 // A write or truncate failed.
125 operation_
= kOperationNone
;
126 client_
->didFail(FileErrorToWebFileError(error_code
));
129 // This is the failure of a write or truncate; the next message should be
130 // the result of the cancel. We don't assume that it'll be a success, as
131 // the write/truncate could have failed for other reasons.
132 cancel_state_
= kCancelReceivedWriteResponse
;
134 case kCancelReceivedWriteResponse
:
135 // The cancel reported failure, meaning that the write or truncate
136 // finished before the cancel got there. But we suppressed the
137 // write/truncate's response, and will now report that it was cancelled.
145 void WebFileWriterBase::FinishCancel() {
146 DCHECK(kCancelReceivedWriteResponse
== cancel_state_
);
147 DCHECK(kOperationNone
!= operation_
);
148 cancel_state_
= kCancelNotInProgress
;
149 operation_
= kOperationNone
;
150 client_
->didFail(blink::WebFileErrorAbort
);
153 } // namespace content