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