webfilewriter_base.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebFileError.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebFileWriterClient.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURL.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) {
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK_EQ(kOperationNone, operation_);
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK_EQ(kCancelNotInProgress, cancel_state_);
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  operation_ = kOperationWrite;
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DoWriteDeprecated(path_, blob_url, position);
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void WebFileWriterBase::write(
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      long long position,
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const WebKit::WebString& id) {
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK_EQ(kOperationNone, operation_);
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK_EQ(kCancelNotInProgress, cancel_state_);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation_ = kOperationWrite;
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DoWrite(path_, id.utf8(), position);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we cancel a write/truncate, we always get back the result of the write
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the result of the cancel, no matter what happens.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So we'll get back either
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   success [of the write/truncate, in a DidWrite(XXX, true)/DidSucceed() call]
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     followed by failure [of the cancel]; or
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   failure [of the write, either from cancel or other reasons] followed by
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     the result of the cancel.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the write case, there could also be queued up non-terminal DidWrite calls
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before any of that comes back, but there will always be a terminal write
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// response [success or failure] after them, followed by the cancel result, so
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can ignore non-terminal write responses, take the terminal write success
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or the first failure as the last write response, then know that the next
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thing to come back is the cancel response.  We only notify the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AsyncFileWriterClient when it's all over.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::cancel() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for the cancel passing the previous operation's return in-flight.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kOperationWrite != operation_ && kOperationTruncate != operation_)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kCancelNotInProgress != cancel_state_)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cancel_state_ = kCancelSent;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoCancel();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterBase::DidFinish(base::PlatformFileError error_code) {
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error_code == base::PLATFORM_FILE_OK)
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DidSucceed();
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DidFail(error_code);
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterBase::DidWrite(int64 bytes, bool complete) {
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(kOperationWrite == operation_);
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (cancel_state_) {
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelNotInProgress:
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (complete)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        operation_ = kOperationNone;
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      client_->didWrite(bytes, complete);
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelSent:
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // This is the success call of the write, which we'll eat, even though
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // it succeeded before the cancel got there.  We accepted the cancel call,
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // so the write will eventually return an error.
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (complete)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        cancel_state_ = kCancelReceivedWriteResponse;
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kCancelReceivedWriteResponse:
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED();
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::DidSucceed() {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write never gets a DidSucceed call, so this is either a cancel or truncate
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cancel_state_) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelNotInProgress:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A truncate succeeded, with no complications.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(kOperationTruncate == operation_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operation_ = kOperationNone;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_->didTruncate();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelSent:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(kOperationTruncate == operation_);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the success call of the truncate, which we'll eat, even though
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it succeeded before the cancel got there.  We accepted the cancel call,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // so the truncate will eventually return an error.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_state_ = kCancelReceivedWriteResponse;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelReceivedWriteResponse:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the success of the cancel operation.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FinishCancel();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::DidFail(base::PlatformFileError error_code) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone != operation_);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cancel_state_) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelNotInProgress:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A write or truncate failed.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operation_ = kOperationNone;
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      client_->didFail(PlatformFileErrorToWebFileError(error_code));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelSent:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the failure of a write or truncate; the next message should be
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the result of the cancel.  We don't assume that it'll be a success, as
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the write/truncate could have failed for other reasons.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel_state_ = kCancelReceivedWriteResponse;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCancelReceivedWriteResponse:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The cancel reported failure, meaning that the write or truncate
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finished before the cancel got there.  But we suppressed the
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // write/truncate's response, and will now report that it was cancelled.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FinishCancel();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebFileWriterBase::FinishCancel() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kCancelReceivedWriteResponse == cancel_state_);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(kOperationNone != operation_);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cancel_state_ = kCancelNotInProgress;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation_ = kOperationNone;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->didFail(WebKit::WebFileErrorAbort);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace content
162