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" 83240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/synchronization/waitable_event.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/fileapi/file_system_dispatcher.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/worker_task_runner.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace content { 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FileSystemDispatcher* GetFileSystemDispatcher() { 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return ChildThread::current() ? 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher() : NULL; 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)typedef FileSystemDispatcher::StatusCallback StatusCallback; 25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)typedef FileSystemDispatcher::WriteCallback WriteCallback; 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This instance may be created outside main thread but runs mainly 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// on main thread. 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class WebFileWriterImpl::WriterBridge 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : public base::RefCountedThreadSafe<WriterBridge> { 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public: 323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch WriterBridge(WebFileWriterImpl::Type type) 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : request_id_(0), 343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch thread_id_(WorkerTaskRunner::Instance()->CurrentWorkerId()), 353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_(0) { 363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (type == WebFileWriterImpl::TYPE_SYNC) 373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_.reset(new base::WaitableEvent(false, false)); 383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Truncate(const GURL& path, int64 offset, 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const StatusCallback& status_callback) { 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = status_callback; 43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Truncate( 46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, offset, &request_id_, 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void Write(const GURL& path, const std::string& id, int64 offset, 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const WriteCallback& write_callback, 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const StatusCallback& error_callback) { 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) write_callback_ = write_callback; 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = error_callback; 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Write( 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) path, id, offset, &request_id_, 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidWrite, this), 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Cancel(const StatusCallback& status_callback) { 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_callback_ = status_callback; 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!GetFileSystemDispatcher()) 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ChildThread::current()->file_system_dispatcher()->Cancel( 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) request_id_, 69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WriterBridge::DidFinish, this)); 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::WaitableEvent* waitable_event() { 733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return waitable_event_.get(); 743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void WaitAndRun() { 773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_->Wait(); 783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!results_closure_.is_null()); 793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch results_closure_.Run(); 803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private: 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) friend class base::RefCountedThreadSafe<WriterBridge>; 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual ~WriterBridge() {} 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void DidWrite(int64 bytes, bool complete) { 873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_ += bytes; 883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (waitable_event_ && !complete) 893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PostTaskToWorker(base::Bind(write_callback_, written_bytes_, complete)); 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void DidFinish(base::File::Error status) { 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostTaskToWorker(base::Bind(status_callback_, status)); 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void PostTaskToWorker(const base::Closure& closure) { 983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch written_bytes_ = 0; 993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!thread_id_) { 1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!waitable_event_); 101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) closure.Run(); 1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (waitable_event_) { 1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch results_closure_ = closure; 1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch waitable_event_->Signal(); 1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch WorkerTaskRunner::Instance()->PostTask(thread_id_, closure); 110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StatusCallback status_callback_; 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) WriteCallback write_callback_; 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int request_id_; 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int thread_id_; 1163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int written_bytes_; 1173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::WaitableEvent> waitable_event_; 1183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::Closure results_closure_; 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WebFileWriterImpl::WebFileWriterImpl( 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const GURL& path, blink::WebFileWriterClient* client, 1233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Type type, 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoopProxy* main_thread_loop) 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : WebFileWriterBase(path, client), 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) main_thread_loop_(main_thread_loop), 1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bridge_(new WriterBridge(type)) { 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WebFileWriterImpl::~WebFileWriterImpl() { 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterImpl::DoTruncate(const GURL& path, int64 offset) { 134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Truncate, bridge_, 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) path, offset, 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void WebFileWriterImpl::DoWrite( 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& path, const std::string& blob_id, int64 offset) { 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_, 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) path, blob_id, offset, 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()), 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WebFileWriterImpl::DoCancel() { 148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RunOnMainThread(base::Bind(&WriterBridge::Cancel, bridge_, 149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr()))); 150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void WebFileWriterImpl::RunOnMainThread(const base::Closure& closure) { 1533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (main_thread_loop_->RunsTasksOnCurrentThread()) { 1543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(!bridge_->waitable_event()); 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) closure.Run(); 1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch main_thread_loop_->PostTask(FROM_HERE, closure); 1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (bridge_->waitable_event()) 1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bridge_->WaitAndRun(); 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace content 164