webfilewriter_impl.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/fileapi/webfilewriter_impl.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h" 8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/platform_file.h" 93240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/synchronization/waitable_event.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/fileapi/file_system_dispatcher.h" 12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "webkit/child/worker_task_runner.h" 13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using webkit_glue::WorkerTaskRunner; 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace content { 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FileSystemDispatcher* GetFileSystemDispatcher() { 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return ChildThread::current() ? 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher() : NULL; 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)typedef FileSystemDispatcher::StatusCallback StatusCallback; 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)typedef FileSystemDispatcher::WriteCallback WriteCallback; 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This instance may be created outside main thread but runs mainly 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// on main thread. 32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class WebFileWriterImpl::WriterBridge 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : public base::RefCountedThreadSafe<WriterBridge> { 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public: 353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch WriterBridge(WebFileWriterImpl::Type type) 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : request_id_(0), 373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch thread_id_(WorkerTaskRunner::Instance()->CurrentWorkerId()), 383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_(0) { 393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (type == WebFileWriterImpl::TYPE_SYNC) 403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_.reset(new base::WaitableEvent(false, false)); 413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Truncate(const GURL& path, int64 offset, 44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const StatusCallback& status_callback) { 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = status_callback; 46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Truncate( 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, offset, &request_id_, 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Write(const GURL& path, const GURL& blob_url, int64 offset, 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const WriteCallback& write_callback, 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const StatusCallback& error_callback) { 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) write_callback_ = write_callback; 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = error_callback; 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Write( 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, blob_url, offset, &request_id_, 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidWrite, this), 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Cancel(const StatusCallback& status_callback) { 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = status_callback; 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Cancel( 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) request_id_, 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::WaitableEvent* waitable_event() { 763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return waitable_event_.get(); 773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void WaitAndRun() { 803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_->Wait(); 813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!results_closure_.is_null()); 823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch results_closure_.Run(); 833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private: 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) friend class base::RefCountedThreadSafe<WriterBridge>; 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual ~WriterBridge() {} 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void DidWrite(int64 bytes, bool complete) { 903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_ += bytes; 913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (waitable_event_ && !complete) 923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PostTaskToWorker(base::Bind(write_callback_, written_bytes_, complete)); 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void DidFinish(base::PlatformFileError status) { 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostTaskToWorker(base::Bind(status_callback_, status)); 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void PostTaskToWorker(const base::Closure& closure) { 1013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_ = 0; 1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!thread_id_) { 1033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!waitable_event_); 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) closure.Run(); 1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (waitable_event_) { 1083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch results_closure_ = closure; 1093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_->Signal(); 1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch WorkerTaskRunner::Instance()->PostTask(thread_id_, closure); 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StatusCallback status_callback_; 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) WriteCallback write_callback_; 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int request_id_; 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int thread_id_; 1193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int written_bytes_; 1203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::WaitableEvent> waitable_event_; 1213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::Closure results_closure_; 122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WebFileWriterImpl::WebFileWriterImpl( 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const GURL& path, WebKit::WebFileWriterClient* client, 1263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Type type, 127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoopProxy* main_thread_loop) 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : WebFileWriterBase(path, client), 129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) main_thread_loop_(main_thread_loop), 1303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bridge_(new WriterBridge(type)) { 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WebFileWriterImpl::~WebFileWriterImpl() { 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterImpl::DoTruncate(const GURL& path, int64 offset) { 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Truncate, bridge_, 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, offset, 139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterImpl::DoWrite( 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& path, const GURL& blob_url, int64 offset) { 144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_, 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, blob_url, offset, 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()), 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterImpl::DoCancel() { 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Cancel, bridge_, 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void WebFileWriterImpl::RunOnMainThread(const base::Closure& closure) { 1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (main_thread_loop_->RunsTasksOnCurrentThread()) { 1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!bridge_->waitable_event()); 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) closure.Run(); 1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch main_thread_loop_->PostTask(FROM_HERE, closure); 1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (bridge_->waitable_event()) 1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bridge_->WaitAndRun(); 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace content 167