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