webfilewriter_base.cc revision 3551c9c881056c480085172ff9840cab31610854
13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/child/fileapi/webfilewriter_base.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURL.h"
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFileError.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFileWriterClient.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/fileapi/file_system_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using fileapi::PlatformFileErrorToWebFileError;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace content {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)WebFileWriterBase::WebFileWriterBase(const GURL& path,
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     WebKit::WebFileWriterClient* client)
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : path_(path),
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      client_(client),
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      operation_(kOperationNone),
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      cancel_state_(kCancelNotInProgress) {}
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)WebFileWriterBase::~WebFileWriterBase() {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::truncate(long long length) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone == operation_);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kCancelNotInProgress == cancel_state_);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation_ = kOperationTruncate;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoTruncate(path_, length);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void WebFileWriterBase::write(long long position,
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              const WebKit::WebURL& blob_url) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone == operation_);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kCancelNotInProgress == cancel_state_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation_ = kOperationWrite;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoWrite(path_, blob_url, position);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we cancel a write/truncate, we always get back the result of the write
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the result of the cancel, no matter what happens.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So we'll get back either
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   success [of the write/truncate, in a DidWrite(XXX, true)/DidSucceed() call]
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     followed by failure [of the cancel]; or
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   failure [of the write, either from cancel or other reasons] followed by
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     the result of the cancel.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the write case, there could also be queued up non-terminal DidWrite calls
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before any of that comes back, but there will always be a terminal write
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// response [success or failure] after them, followed by the cancel result, so
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can ignore non-terminal write responses, take the terminal write success
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or the first failure as the last write response, then know that the next
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thing to come back is the cancel response.  We only notify the
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AsyncFileWriterClient when it's all over.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::cancel() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for the cancel passing the previous operation's return in-flight.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kOperationWrite != operation_ && kOperationTruncate != operation_)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kCancelNotInProgress != cancel_state_)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cancel_state_ = kCancelSent;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoCancel();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterBase::DidFinish(base::PlatformFileError error_code) {
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error_code == base::PLATFORM_FILE_OK)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DidSucceed();
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DidFail(error_code);
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterBase::DidWrite(int64 bytes, bool complete) {
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(kOperationWrite == operation_);
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (cancel_state_) {
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelNotInProgress:
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (complete)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        operation_ = kOperationNone;
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      client_->didWrite(bytes, complete);
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelSent:
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // This is the success call of the write, which we'll eat, even though
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // it succeeded before the cancel got there.  We accepted the cancel call,
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // so the write will eventually return an error.
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (complete)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        cancel_state_ = kCancelReceivedWriteResponse;
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelReceivedWriteResponse:
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::DidSucceed() {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write never gets a DidSucceed call, so this is either a cancel or truncate
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cancel_state_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelNotInProgress:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A truncate succeeded, with no complications.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(kOperationTruncate == operation_);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operation_ = kOperationNone;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_->didTruncate();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelSent:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(kOperationTruncate == operation_);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the success call of the truncate, which we'll eat, even though
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it succeeded before the cancel got there.  We accepted the cancel call,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // so the truncate will eventually return an error.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_state_ = kCancelReceivedWriteResponse;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelReceivedWriteResponse:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the success of the cancel operation.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FinishCancel();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::DidFail(base::PlatformFileError error_code) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone != operation_);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cancel_state_) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelNotInProgress:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A write or truncate failed.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operation_ = kOperationNone;
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      client_->didFail(PlatformFileErrorToWebFileError(error_code));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelSent:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the failure of a write or truncate; the next message should be
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the result of the cancel.  We don't assume that it'll be a success, as
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the write/truncate could have failed for other reasons.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_state_ = kCancelReceivedWriteResponse;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelReceivedWriteResponse:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The cancel reported failure, meaning that the write or truncate
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finished before the cancel got there.  But we suppressed the
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // write/truncate's response, and will now report that it was cancelled.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FinishCancel();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::FinishCancel() {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kCancelReceivedWriteResponse == cancel_state_);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone != operation_);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cancel_state_ = kCancelNotInProgress;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation_ = kOperationNone;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->didFail(WebKit::WebFileErrorAbort);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace content
153