diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 23:05:15 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 23:05:15 +0000 |
commit | 21ae1f956c163bc0e3b3e239b5c027a7ac93ae7f (patch) | |
tree | 4eee3fe37f83559b1a97f75dcdef0337b68e2cf1 | |
parent | 0436fcd542e8ce436fe9395a64cc03fa369276b1 (diff) | |
download | chromium_src-21ae1f956c163bc0e3b3e239b5c027a7ac93ae7f.zip chromium_src-21ae1f956c163bc0e3b3e239b5c027a7ac93ae7f.tar.gz chromium_src-21ae1f956c163bc0e3b3e239b5c027a7ac93ae7f.tar.bz2 |
Asynchronously open the temp file used for Pepper StreamToFile, and delete the
temp file once we are done with it.
We observe ResourceHandle::OnRequestClosed as a signal of when we should delete
the temp file. This corresponds to the WebURLLoader being closed (or
canceled).
This patch also includes some helpers:
base/scoped_callback_factory.h
This class makes it easy to allocate Callbacks that hold a weak reference
back to the owning class. It works just like ScopedRunnableMethodFactory
but for Callbacks instead of RunnableMethods.
base/platform_file.h
Added a PassPlatformFile class that is useful for cases where a callback may
decide not to take ownership of a PlatformFile (as can happen when using
ScopedCallbackFactory).
chrome/file_system_proxy.{h,cc}
This class provides static methods for executing file system commands on the
FILE thread. It routes callbacks back to the originating thread to deliver
results (file handles, etc.). Note: this file declares a few functions that
are not yet used. I anticipate that we'll make use of these and add more
functions here to support the Pepper and OWP FileSystem APIs.
chrome/chrome_thread_relay.{h,cc}
This class is a helper class for proxying calls over to a background
ChromeThread and then returning results to the originating ChromeThread.
R=brettw
BUG=49789
TEST=(more to be added in third_party/ppapi/tests)
Review URL: http://codereview.chromium.org/2878062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54402 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/platform_file.h | 38 | ||||
-rw-r--r-- | base/scoped_callback_factory.h | 133 | ||||
-rw-r--r-- | chrome/browser/chrome_thread_relay.cc | 26 | ||||
-rw-r--r-- | chrome/browser/chrome_thread_relay.h | 55 | ||||
-rw-r--r-- | chrome/browser/file_system_proxy.cc | 180 | ||||
-rw-r--r-- | chrome/browser/file_system_proxy.h | 49 | ||||
-rw-r--r-- | chrome/browser/renderer_host/redirect_to_file_resource_handler.cc | 58 | ||||
-rw-r--r-- | chrome/browser/renderer_host/redirect_to_file_resource_handler.h | 12 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 4 |
10 files changed, 539 insertions, 17 deletions
diff --git a/base/base.gypi b/base/base.gypi index a5fdfc6..75fcf5b 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -186,6 +186,7 @@ 'safe_strerror_posix.h', 'scoped_bstr_win.cc', 'scoped_bstr_win.h', + 'scoped_callback_factory.h', 'scoped_cftyperef.h', 'scoped_comptr_win.h', 'scoped_handle.h', diff --git a/base/platform_file.h b/base/platform_file.h index 3571e24..43f8511 100644 --- a/base/platform_file.h +++ b/base/platform_file.h @@ -54,6 +54,44 @@ PlatformFile CreatePlatformFile(const std::wstring& name, // Closes a file handle bool ClosePlatformFile(PlatformFile file); +// Use this class to pass ownership of a PlatformFile to a receiver that may or +// may not want to accept it. This class does not own the storage for the +// PlatformFile. +// +// EXAMPLE: +// +// void MaybeProcessFile(PassPlatformFile pass_file) { +// if (...) { +// PlatformFile file = pass_file.ReleaseValue(); +// // Now, we are responsible for closing |file|. +// } +// } +// +// void OpenAndMaybeProcessFile(const FilePath& path) { +// PlatformFile file = CreatePlatformFile(path, ...); +// MaybeProcessFile(PassPlatformFile(&file)); +// if (file != kInvalidPlatformFileValue) +// ClosePlatformFile(file); +// } +// +class PassPlatformFile { + public: + explicit PassPlatformFile(PlatformFile* value) : value_(value) { + } + + // Called to retrieve the PlatformFile stored in this object. The caller + // gains ownership of the PlatformFile and is now responsible for closing it. + // Any subsequent calls to this method will return an invalid PlatformFile. + PlatformFile ReleaseValue() { + PlatformFile temp = *value_; + *value_ = kInvalidPlatformFileValue; + return temp; + } + + private: + PlatformFile* value_; +}; + } // namespace base #endif // BASE_PLATFORM_FILE_H_ diff --git a/base/scoped_callback_factory.h b/base/scoped_callback_factory.h new file mode 100644 index 0000000..a2fc1f0 --- /dev/null +++ b/base/scoped_callback_factory.h @@ -0,0 +1,133 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ScopedCallbackFactory helps in cases where you wish to allocate a Callback +// (see base/callback.h), but need to prevent any pending callbacks from +// executing when your object gets destroyed. +// +// EXAMPLE: +// +// void GatherDataAsynchronously(Callback1<Data>::Type* callback); +// +// class MyClass { +// public: +// MyClass() : factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +// } +// +// void Process() { +// GatherDataAsynchronously(factory_.NewCallback(&MyClass::GotData)); +// } +// +// private: +// void GotData(const Data& data) { +// ... +// } +// +// base::ScopedCallbackFactory<MyClass> factory_; +// }; +// +// In the above example, the Process function calls GatherDataAsynchronously to +// kick off some asynchronous processing that upon completion will notify a +// callback. If in the meantime, the MyClass instance is destroyed, when the +// callback runs, it will notice that the MyClass instance is dead, and it will +// avoid calling the GotData method. + +#ifndef BASE_SCOPED_CALLBACK_FACTORY_H_ +#define BASE_SCOPED_CALLBACK_FACTORY_H_ + +#include "base/callback.h" +#include "base/weak_ptr.h" + +namespace base { + +template <class T> +class ScopedCallbackFactory { + public: + explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) { + } + + typename Callback0::Type* NewCallback( + void (T::*method)()) { + return new CallbackImpl<void (T::*)(), Tuple0 >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1> + typename Callback1<Arg1>::Type* NewCallback( + void (T::*method)(Arg1)) { + return new CallbackImpl<void (T::*)(Arg1), Tuple1<Arg1> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2> + typename Callback2<Arg1, Arg2>::Type* NewCallback( + void (T::*method)(Arg1, Arg2)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2), Tuple2<Arg1, Arg2> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3> + typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3), + Tuple3<Arg1, Arg2, Arg3> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> + typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4), + Tuple4<Arg1, Arg2, Arg3, Arg4> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, + typename Arg5> + typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), + Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >( + weak_factory_.GetWeakPtr(), method); + } + + void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } + bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); } + + private: + template <typename Method> + class CallbackStorage { + public: + CallbackStorage(const WeakPtr<T>& obj, Method meth) + : obj_(obj), + meth_(meth) { + } + + protected: + WeakPtr<T> obj_; + Method meth_; + }; + + template <typename Method, typename Params> + class CallbackImpl : public CallbackStorage<Method>, + public CallbackRunner<Params> { + public: + CallbackImpl(const WeakPtr<T>& obj, Method meth) + : CallbackStorage<Method>(obj, meth) { + } + virtual void RunWithParams(const Params& params) { + // Use "this->" to force C++ to look inside our templatized base class; + // see Effective C++, 3rd Ed, item 43, p210 for details. + if (!this->obj_) + return; + DispatchToMethod(this->obj_.get(), this->meth_, params); + } + }; + + WeakPtrFactory<T> weak_factory_; +}; + +} // namespace base + +#endif // BASE_SCOPED_CALLBACK_FACTORY_H_ diff --git a/chrome/browser/chrome_thread_relay.cc b/chrome/browser/chrome_thread_relay.cc new file mode 100644 index 0000000..e773f1d --- /dev/null +++ b/chrome/browser/chrome_thread_relay.cc @@ -0,0 +1,26 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_thread_relay.h" + +ChromeThreadRelay::ChromeThreadRelay() { + if (!ChromeThread::GetCurrentThreadIdentifier(&origin_thread_id_)) + NOTREACHED() << "Must be created on a valid ChromeThread"; +} + +void ChromeThreadRelay::Start(ChromeThread::ID target_thread_id, + const tracked_objects::Location& from_here) { + ChromeThread::PostTask( + target_thread_id, + from_here, + NewRunnableMethod(this, &ChromeThreadRelay::ProcessOnTargetThread)); +} + +void ChromeThreadRelay::ProcessOnTargetThread() { + RunWork(); + ChromeThread::PostTask( + origin_thread_id_, + FROM_HERE, + NewRunnableMethod(this, &ChromeThreadRelay::RunCallback)); +} diff --git a/chrome/browser/chrome_thread_relay.h b/chrome/browser/chrome_thread_relay.h new file mode 100644 index 0000000..657e587 --- /dev/null +++ b/chrome/browser/chrome_thread_relay.h @@ -0,0 +1,55 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ChromeThreadRelay provides a convenient way to bounce work to a specific +// ChromeThread and then return results back to the originating thread. +// +// EXAMPLE: +// +// class MyRelay : public ChromeThreadRelay { +// public: +// MyRelay(const Params& params) : params_(params) { +// } +// protected: +// virtual void RunWork() { +// results_ = DoWork(params_); +// } +// virtual void RunCallback() { +// ... use results_ on the originating thread ... +// } +// private: +// Params params_; +// Results_ results_; +// }; + +#ifndef CHROME_BROWSER_CHROME_THREAD_RELAY_H_ +#define CHROME_BROWSER_CHROME_THREAD_RELAY_H_ + +#include "base/ref_counted.h" +#include "chrome/browser/chrome_thread.h" + +class ChromeThreadRelay + : public base::RefCountedThreadSafe<ChromeThreadRelay> { + public: + ChromeThreadRelay(); + + void Start(ChromeThread::ID target_thread_id, + const tracked_objects::Location& from_here); + + protected: + friend class base::RefCountedThreadSafe<ChromeThreadRelay>; + virtual ~ChromeThreadRelay() {} + + // Called to perform work on the FILE thread. + virtual void RunWork() = 0; + + // Called to notify the callback on the origin thread. + virtual void RunCallback() = 0; + + private: + void ProcessOnTargetThread(); + ChromeThread::ID origin_thread_id_; +}; + +#endif // CHROME_BROWSER_CHROME_THREAD_RELAY_H_ diff --git a/chrome/browser/file_system_proxy.cc b/chrome/browser/file_system_proxy.cc new file mode 100644 index 0000000..1cf7b55 --- /dev/null +++ b/chrome/browser/file_system_proxy.cc @@ -0,0 +1,180 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/file_system_proxy.h" + +#include "base/file_util.h" +#include "chrome/browser/chrome_thread_relay.h" + +namespace { + +class RelayCreateOrOpen : public ChromeThreadRelay { + public: + RelayCreateOrOpen( + const FilePath& file_path, + int file_flags, + FileSystemProxy::CreateOrOpenCallback* callback) + : file_path_(file_path), + file_flags_(file_flags), + callback_(callback), + file_handle_(base::kInvalidPlatformFileValue), + created_(false) { + DCHECK(callback); + } + + protected: + virtual ~RelayCreateOrOpen() { + if (file_handle_ != base::kInvalidPlatformFileValue) + FileSystemProxy::Close(file_handle_, NULL); + } + + virtual void RunWork() { + file_handle_ = base::CreatePlatformFile(file_path_, file_flags_, &created_); + } + + virtual void RunCallback() { + callback_->Run(base::PassPlatformFile(&file_handle_), created_); + delete callback_; + } + + private: + FilePath file_path_; + int file_flags_; + FileSystemProxy::CreateOrOpenCallback* callback_; + base::PlatformFile file_handle_; + bool created_; +}; + +class RelayCreateTemporary : public ChromeThreadRelay { + public: + explicit RelayCreateTemporary( + FileSystemProxy::CreateTemporaryCallback* callback) + : callback_(callback), + file_handle_(base::kInvalidPlatformFileValue) { + DCHECK(callback); + } + + protected: + virtual ~RelayCreateTemporary() { + if (file_handle_ != base::kInvalidPlatformFileValue) + FileSystemProxy::Close(file_handle_, NULL); + } + + virtual void RunWork() { + // TODO(darin): file_util should have a variant of CreateTemporaryFile + // that returns a FilePath and a PlatformFile. + file_util::CreateTemporaryFile(&file_path_); + + // Use a fixed set of flags that are appropriate for writing to a temporary + // file from the IO thread using a net::FileStream. + int file_flags = + base::PLATFORM_FILE_CREATE_ALWAYS | + base::PLATFORM_FILE_WRITE | + base::PLATFORM_FILE_ASYNC | + base::PLATFORM_FILE_TEMPORARY; + file_handle_ = base::CreatePlatformFile(file_path_, file_flags, NULL); + } + + virtual void RunCallback() { + callback_->Run(base::PassPlatformFile(&file_handle_), file_path_); + delete callback_; + } + + private: + FileSystemProxy::CreateTemporaryCallback* callback_; + base::PlatformFile file_handle_; + FilePath file_path_; +}; + +class RelayWithStatusCallback : public ChromeThreadRelay { + public: + explicit RelayWithStatusCallback(FileSystemProxy::StatusCallback* callback) + : callback_(callback), + succeeded_(false) { + // It is OK for callback to be NULL. + } + + protected: + virtual void RunCallback() { + // The caller may not have been interested in the result. + if (callback_) { + callback_->Run(succeeded_); + delete callback_; + } + } + + void SetStatus(bool succeeded) { succeeded_ = succeeded; } + + private: + FileSystemProxy::StatusCallback* callback_; + bool succeeded_; +}; + +class RelayClose : public RelayWithStatusCallback { + public: + RelayClose(base::PlatformFile file_handle, + FileSystemProxy::StatusCallback* callback) + : RelayWithStatusCallback(callback), + file_handle_(file_handle) { + } + + protected: + virtual void RunWork() { + SetStatus(base::ClosePlatformFile(file_handle_)); + } + + private: + base::PlatformFile file_handle_; +}; + +class RelayDelete : public RelayWithStatusCallback { + public: + RelayDelete(const FilePath& file_path, + bool recursive, + FileSystemProxy::StatusCallback* callback) + : RelayWithStatusCallback(callback), + file_path_(file_path), + recursive_(recursive) { + } + + protected: + virtual void RunWork() { + SetStatus(file_util::Delete(file_path_, recursive_)); + } + + private: + FilePath file_path_; + bool recursive_; +}; + +void Start(const tracked_objects::Location& from_here, + scoped_refptr<ChromeThreadRelay> relay) { + relay->Start(ChromeThread::FILE, from_here); +} + +} // namespace + +void FileSystemProxy::CreateOrOpen(const FilePath& file_path, int file_flags, + CreateOrOpenCallback* callback) { + Start(FROM_HERE, new RelayCreateOrOpen(file_path, file_flags, callback)); +} + +void FileSystemProxy::CreateTemporary(CreateTemporaryCallback* callback) { + Start(FROM_HERE, new RelayCreateTemporary(callback)); +} + +void FileSystemProxy::Close(base::PlatformFile file_handle, + StatusCallback* callback) { + Start(FROM_HERE, new RelayClose(file_handle, callback)); +} + +void FileSystemProxy::Delete(const FilePath& file_path, + StatusCallback* callback) { + Start(FROM_HERE, new RelayDelete(file_path, false, callback)); +} + +void FileSystemProxy::RecursiveDelete(const FilePath& file_path, + StatusCallback* callback) { + Start(FROM_HERE, new RelayDelete(file_path, true, callback)); +} diff --git a/chrome/browser/file_system_proxy.h b/chrome/browser/file_system_proxy.h new file mode 100644 index 0000000..74cd215 --- /dev/null +++ b/chrome/browser/file_system_proxy.h @@ -0,0 +1,49 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_FILE_SYSTEM_PROXY_H_ +#define CHROME_BROWSER_FILE_SYSTEM_PROXY_H_ + +#include "base/callback.h" +#include "base/platform_file.h" +#include "base/ref_counted.h" + +// This class provides asynchronous access to common file routines. +class FileSystemProxy { + public: + // This callback is used by methods that report success with a bool. It is + // valid to pass NULL as the callback parameter to any function that takes a + // StatusCallback, in which case the operation will complete silently. + typedef Callback1<bool /* succeeded */>::Type StatusCallback; + + // Creates or opens a file with the given flags. It is invalid to pass NULL + // for the callback. + typedef Callback2<base::PassPlatformFile, bool /* created */>::Type + CreateOrOpenCallback; + static void CreateOrOpen(const FilePath& file_path, + int file_flags, + CreateOrOpenCallback* callback); + + // Creates a temporary file for writing. The path and an open file handle + // are returned. It is invalid to pass NULL for the callback. + typedef Callback2<base::PassPlatformFile, FilePath>::Type + CreateTemporaryCallback; + static void CreateTemporary(CreateTemporaryCallback* callback); + + // Close the given file handle. + static void Close(base::PlatformFile, StatusCallback* callback); + + // Deletes a file or empty directory. + static void Delete(const FilePath& file_path, + StatusCallback* callback); + + // Deletes a directory and all of its contents. + static void RecursiveDelete(const FilePath& file_path, + StatusCallback* callback); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemProxy); +}; + +#endif // CHROME_BROWSER_FILE_SYSTEM_PROXY_H_ diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc index 4f523b7..11beb73 100644 --- a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc +++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc @@ -5,9 +5,13 @@ #include "chrome/browser/renderer_host/redirect_to_file_resource_handler.h" #include "base/file_util.h" +#include "base/logging.h" #include "base/platform_file.h" +#include "base/task.h" +#include "chrome/browser/file_system_proxy.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/common/resource_response.h" +#include "net/base/file_stream.h" #include "net/base/io_buffer.h" #include "net/base/mime_sniffer.h" #include "net/base/net_errors.h" @@ -19,7 +23,8 @@ RedirectToFileResourceHandler::RedirectToFileResourceHandler( ResourceHandler* next_handler, int process_id, ResourceDispatcherHost* host) - : host_(host), + : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + host_(host), next_handler_(next_handler), process_id_(process_id), request_id_(-1), @@ -50,8 +55,7 @@ bool RedirectToFileResourceHandler::OnResponseStarted( int request_id, ResourceResponse* response) { if (response->response_head.status.is_success()) { - // TODO(darin): Move this file creation to a background thread. - file_util::CreateTemporaryFile(&file_path_); + DCHECK(!file_path_.empty()); response->response_head.download_file_path = file_path_; } return next_handler_->OnResponseStarted(request_id, response); @@ -60,6 +64,17 @@ bool RedirectToFileResourceHandler::OnResponseStarted( bool RedirectToFileResourceHandler::OnWillStart(int request_id, const GURL& url, bool* defer) { + request_id_ = request_id; + if (file_path_.empty()) { + // Defer starting the request until we have created the temporary file. + // TODO(darin): This is sub-optimal. We should not delay starting the + // network request like this. + *defer = true; + FileSystemProxy::CreateTemporary( + callback_factory_.NewCallback( + &RedirectToFileResourceHandler::DidCreateTemporaryFile)); + return true; + } return next_handler_->OnWillStart(request_id, url, defer); } @@ -103,18 +118,9 @@ bool RedirectToFileResourceHandler::OnReadCompleted(int request_id, DCHECK(new_offset <= buf_->capacity()); buf_->set_offset(new_offset); - if (!file_stream_.IsOpen()) { - int rv = file_stream_.Open(file_path_, base::PLATFORM_FILE_OPEN | - base::PLATFORM_FILE_WRITE | - base::PLATFORM_FILE_ASYNC); - if (rv != net::OK) - return false; - } - if (BufIsFull()) host_->PauseRequest(process_id_, request_id, true); - request_id_ = request_id; return WriteMore(); } @@ -127,9 +133,30 @@ bool RedirectToFileResourceHandler::OnResponseCompleted( void RedirectToFileResourceHandler::OnRequestClosed() { next_handler_->OnRequestClosed(); + + // The renderer no longer has a WebURLLoader open to this request, so we can + // close and unlink the file. + + // We require this explicit call to Close since file_stream_ was constructed + // directly from a PlatformFile. + file_stream_->Close(); + file_stream_.reset(); + + FileSystemProxy::Delete(file_path_, NULL); } RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { + DCHECK(!file_stream_.get()); +} + +void RedirectToFileResourceHandler::DidCreateTemporaryFile( + base::PassPlatformFile file_handle, + FilePath file_path) { + file_path_ = file_path; + file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(), + base::PLATFORM_FILE_WRITE | + base::PLATFORM_FILE_ASYNC)); + host_->StartDeferredRequest(process_id_, request_id_); } void RedirectToFileResourceHandler::DidWriteToFile(int result) { @@ -148,6 +175,7 @@ void RedirectToFileResourceHandler::DidWriteToFile(int result) { } bool RedirectToFileResourceHandler::WriteMore() { + DCHECK(file_stream_.get()); for (;;) { if (write_cursor_ == buf_->offset()) { // We've caught up to the network load, but it may be in the process of @@ -163,9 +191,9 @@ bool RedirectToFileResourceHandler::WriteMore() { if (write_callback_pending_) return true; DCHECK(write_cursor_ < buf_->offset()); - int rv = file_stream_.Write(buf_->StartOfBuffer() + write_cursor_, - buf_->offset() - write_cursor_, - &write_callback_); + int rv = file_stream_->Write(buf_->StartOfBuffer() + write_cursor_, + buf_->offset() - write_cursor_, + &write_callback_); if (rv == net::ERR_IO_PENDING) { write_callback_pending_ = true; return true; diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.h b/chrome/browser/renderer_host/redirect_to_file_resource_handler.h index f9d2b57..5dd4111 100644 --- a/chrome/browser/renderer_host/redirect_to_file_resource_handler.h +++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.h @@ -6,14 +6,18 @@ #define CHROME_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ #include "base/file_path.h" +#include "base/platform_file.h" #include "base/ref_counted.h" +#include "base/scoped_callback_factory.h" +#include "base/scoped_ptr.h" #include "chrome/browser/renderer_host/resource_handler.h" #include "net/base/completion_callback.h" -#include "net/base/file_stream.h" +class RefCountedPlatformFile; class ResourceDispatcherHost; namespace net { +class FileStream; class GrowableIOBuffer; } @@ -42,10 +46,14 @@ class RedirectToFileResourceHandler : public ResourceHandler { private: virtual ~RedirectToFileResourceHandler(); + void DidCreateTemporaryFile(base::PassPlatformFile file_handle, + FilePath file_path); void DidWriteToFile(int result); bool WriteMore(); bool BufIsFull() const; + base::ScopedCallbackFactory<RedirectToFileResourceHandler> callback_factory_; + ResourceDispatcherHost* host_; scoped_refptr<ResourceHandler> next_handler_; int process_id_; @@ -63,7 +71,7 @@ class RedirectToFileResourceHandler : public ResourceHandler { int write_cursor_; FilePath file_path_; - net::FileStream file_stream_; + scoped_ptr<net::FileStream> file_stream_; net::CompletionCallbackImpl<RedirectToFileResourceHandler> write_callback_; bool write_callback_pending_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 1b5ea58..25f9996 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -346,6 +346,8 @@ 'browser/chrome_plugin_host.h', 'browser/chrome_thread.cc', 'browser/chrome_thread.h', + 'browser/chrome_thread_relay.cc', + 'browser/chrome_thread_relay.h', 'browser/chromeos/notifications/balloon_collection_impl.h', 'browser/chromeos/notifications/balloon_collection_impl.cc', 'browser/chromeos/notifications/balloon_view.h', @@ -1390,6 +1392,8 @@ 'browser/file_watcher_inotify.cc', 'browser/file_watcher_mac.cc', 'browser/file_watcher_win.cc', + 'browser/file_system_proxy.cc', + 'browser/file_system_proxy.h', 'browser/find_bar.h', 'browser/find_bar_controller.cc', 'browser/find_bar_controller.h', |