| 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 |