OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "webkit/fileapi/webfilewriter_base.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" | |
9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileError.h" | |
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileWriterClient.h
" | |
11 #include "webkit/fileapi/file_system_util.h" | |
12 | |
13 namespace fileapi { | |
14 | |
15 WebFileWriterBase::WebFileWriterBase( | |
16 const GURL& path, WebKit::WebFileWriterClient* client) | |
17 : path_(path), | |
18 client_(client), | |
19 operation_(kOperationNone), | |
20 cancel_state_(kCancelNotInProgress) { | |
21 } | |
22 | |
23 WebFileWriterBase::~WebFileWriterBase() { | |
24 } | |
25 | |
26 void WebFileWriterBase::truncate(long long length) { | |
27 DCHECK(kOperationNone == operation_); | |
28 DCHECK(kCancelNotInProgress == cancel_state_); | |
29 operation_ = kOperationTruncate; | |
30 DoTruncate(path_, length); | |
31 } | |
32 | |
33 void WebFileWriterBase::write( | |
34 long long position, | |
35 const WebKit::WebURL& blob_url) { | |
36 DCHECK(kOperationNone == operation_); | |
37 DCHECK(kCancelNotInProgress == cancel_state_); | |
38 operation_ = kOperationWrite; | |
39 DoWrite(path_, blob_url, position); | |
40 } | |
41 | |
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_) | |
59 return; | |
60 if (kCancelNotInProgress != cancel_state_) | |
61 return; | |
62 cancel_state_ = kCancelSent; | |
63 DoCancel(); | |
64 } | |
65 | |
66 void WebFileWriterBase::DidFinish(base::PlatformFileError error_code) { | |
67 if (error_code == base::PLATFORM_FILE_OK) | |
68 DidSucceed(); | |
69 else | |
70 DidFail(error_code); | |
71 } | |
72 | |
73 void WebFileWriterBase::DidWrite(int64 bytes, bool complete) { | |
74 DCHECK(kOperationWrite == operation_); | |
75 switch (cancel_state_) { | |
76 case kCancelNotInProgress: | |
77 if (complete) | |
78 operation_ = kOperationNone; | |
79 client_->didWrite(bytes, complete); | |
80 break; | |
81 case kCancelSent: | |
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. | |
85 if (complete) | |
86 cancel_state_ = kCancelReceivedWriteResponse; | |
87 break; | |
88 case kCancelReceivedWriteResponse: | |
89 default: | |
90 NOTREACHED(); | |
91 } | |
92 } | |
93 | |
94 void WebFileWriterBase::DidSucceed() { | |
95 // Write never gets a DidSucceed call, so this is either a cancel or truncate | |
96 // response. | |
97 switch (cancel_state_) { | |
98 case kCancelNotInProgress: | |
99 // A truncate succeeded, with no complications. | |
100 DCHECK(kOperationTruncate == operation_); | |
101 operation_ = kOperationNone; | |
102 client_->didTruncate(); | |
103 break; | |
104 case kCancelSent: | |
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; | |
110 break; | |
111 case kCancelReceivedWriteResponse: | |
112 // This is the success of the cancel operation. | |
113 FinishCancel(); | |
114 break; | |
115 default: | |
116 NOTREACHED(); | |
117 } | |
118 } | |
119 | |
120 void WebFileWriterBase::DidFail(base::PlatformFileError 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( | |
127 PlatformFileErrorToWebFileError(error_code)); | |
128 break; | |
129 case kCancelSent: | |
130 // This is the failure of a write or truncate; the next message should be | |
131 // the result of the cancel. We don't assume that it'll be a success, as | |
132 // the write/truncate could have failed for other reasons. | |
133 cancel_state_ = kCancelReceivedWriteResponse; | |
134 break; | |
135 case kCancelReceivedWriteResponse: | |
136 // The cancel reported failure, meaning that the write or truncate | |
137 // finished before the cancel got there. But we suppressed the | |
138 // write/truncate's response, and will now report that it was cancelled. | |
139 FinishCancel(); | |
140 break; | |
141 default: | |
142 NOTREACHED(); | |
143 } | |
144 } | |
145 | |
146 void WebFileWriterBase::FinishCancel() { | |
147 DCHECK(kCancelReceivedWriteResponse == cancel_state_); | |
148 DCHECK(kOperationNone != operation_); | |
149 cancel_state_ = kCancelNotInProgress; | |
150 operation_ = kOperationNone; | |
151 client_->didFail(WebKit::WebFileErrorAbort); | |
152 } | |
153 | |
154 } // namespace fileapi | |
OLD | NEW |