summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/ref_counted.h29
-rw-r--r--chrome/browser/chrome_thread.h29
-rw-r--r--chrome/browser/chrome_thread_unittest.cc156
-rw-r--r--chrome/browser/renderer_host/file_system_accessor.cc44
-rw-r--r--chrome/browser/renderer_host/file_system_accessor.h74
-rw-r--r--chrome/browser/renderer_host/file_system_accessor_unittest.cc115
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc70
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rwxr-xr-xchrome/chrome.gyp3
-rw-r--r--ipc/ipc_channel_proxy.cc6
-rw-r--r--ipc/ipc_channel_proxy.h16
11 files changed, 209 insertions, 341 deletions
diff --git a/base/ref_counted.h b/base/ref_counted.h
index e04bb7c..ea532a4 100644
--- a/base/ref_counted.h
+++ b/base/ref_counted.h
@@ -93,6 +93,21 @@ class RefCounted : public subtle::RefCountedBase {
DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
};
+// Forward declaration.
+template <class T, typename Traits> class RefCountedThreadSafe;
+
+// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
+// count reaches 0. Overload to delete it on a different thread etc.
+template<typename T>
+struct DefaultRefCountedThreadSafeTraits {
+ static void Destruct(T* x) {
+ // Delete through RefCountedThreadSafe to make child classes only need to be
+ // friend with RefCountedThreadSafe instead of this struct, which is an
+ // implementation detail.
+ RefCountedThreadSafe<T, DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
+ }
+};
+
//
// A thread-safe variant of RefCounted<T>
//
@@ -100,7 +115,12 @@ class RefCounted : public subtle::RefCountedBase {
// ...
// };
//
-template <class T>
+// If you're using the default trait, then you may choose to add compile time
+// asserts that no one else is deleting your object. i.e.
+// private:
+// friend struct base::RefCountedThreadSafe<MyFoo>;
+// ~MyFoo();
+template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
public:
RefCountedThreadSafe() { }
@@ -112,12 +132,15 @@ class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
void Release() {
if (subtle::RefCountedThreadSafeBase::Release()) {
- delete static_cast<T*>(this);
+ Traits::Destruct(static_cast<T*>(this));
}
}
private:
- DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe<T>);
+ friend struct DefaultRefCountedThreadSafeTraits<T>;
+ static void DeleteInternal(T* x) { delete x; }
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
};
//
diff --git a/chrome/browser/chrome_thread.h b/chrome/browser/chrome_thread.h
index 4240127..8f64dde 100644
--- a/chrome/browser/chrome_thread.h
+++ b/chrome/browser/chrome_thread.h
@@ -125,6 +125,35 @@ class ChromeThread : public base::Thread {
// sets identifier to its ID. Otherwise returns false.
static bool GetCurrentThreadIdentifier(ID* identifier);
+ // Use these templates in conjuction with RefCountedThreadSafe when you want
+ // to ensure that an object is deleted on a specific thread. This is needed
+ // when an object can hop between threads (i.e. IO -> FILE -> IO), and thread
+ // switching delays can mean that the final IO tasks executes before the FILE
+ // task's stack unwinds. This would lead to the object destructing on the
+ // FILE thread, which often is not what you want (i.e. to unregister from
+ // NotificationService, to notify other objects on the creating thread etc).
+ template<ID thread>
+ struct DeleteOnThread {
+ template<typename T>
+ static void Destruct(T* x) {
+ if (CurrentlyOn(thread)) {
+ delete x;
+ } else {
+ DeleteSoon(thread, FROM_HERE, x);
+ }
+ }
+ };
+
+ // Sample usage:
+ // class Foo
+ // : public base::RefCountedThreadSafe<
+ // Foo, ChromeThread::DeleteOnIOThread> {
+ struct DeleteOnUIThread : public DeleteOnThread<UI> { };
+ struct DeleteOnIOThread : public DeleteOnThread<IO> { };
+ struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
+ struct DeleteOnDBThread : public DeleteOnThread<DB> { };
+ struct DeleteOnWebKitThread : public DeleteOnThread<WEBKIT> { };
+
private:
// Common initialization code for the constructors.
void Initialize();
diff --git a/chrome/browser/chrome_thread_unittest.cc b/chrome/browser/chrome_thread_unittest.cc
index a6c9981..62f8097 100644
--- a/chrome/browser/chrome_thread_unittest.cc
+++ b/chrome/browser/chrome_thread_unittest.cc
@@ -1,72 +1,108 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 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 <vector>
-
#include "chrome/browser/chrome_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
-typedef PlatformTest ChromeThreadTest;
-
-TEST_F(ChromeThreadTest, Get) {
- /*
- // TODO(jabdelmalek): rewrite this test when the change to delete objects on
- // a specific thread lands.
- scoped_ptr<ChromeThread> io_thread;
- scoped_ptr<ChromeThread> file_thread;
- scoped_ptr<ChromeThread> db_thread;
-
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::IO) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::FILE) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::DB) == NULL);
-
- // Phase 1: Create threads.
-
- io_thread.reset(new ChromeThread(ChromeThread::IO));
- file_thread.reset(new ChromeThread(ChromeThread::FILE));
- db_thread.reset(new ChromeThread(ChromeThread::DB));
-
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::IO) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::FILE) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::DB) == NULL);
-
- // Phase 2: Start the threads.
-
- io_thread->Start();
- file_thread->Start();
- db_thread->Start();
-
- EXPECT_TRUE(io_thread->message_loop() != NULL);
- EXPECT_TRUE(file_thread->message_loop() != NULL);
- EXPECT_TRUE(db_thread->message_loop() != NULL);
-
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::IO) ==
- io_thread->message_loop());
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::FILE) ==
- file_thread->message_loop());
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::DB) ==
- db_thread->message_loop());
-
- // Phase 3: Stop the threads.
-
- io_thread->Stop();
- file_thread->Stop();
- db_thread->Stop();
+class ChromeThreadTest : public testing::Test {
+ public:
+ void Release() {
+ CHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask);
+ }
+
+ protected:
+ virtual void SetUp() {
+ file_thread_.reset(new ChromeThread(ChromeThread::FILE));
+ io_thread_.reset(new ChromeThread(ChromeThread::IO));
+ file_thread_->Start();
+ io_thread_->Start();
+ }
+
+ virtual void TearDown() {
+ file_thread_->Stop();
+ io_thread_->Stop();
+ }
+
+ static void BasicFunction(MessageLoop* message_loop) {
+ CHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+ }
+
+ class DummyTask : public Task {
+ public:
+ DummyTask(bool* deleted) : deleted_(deleted) { }
+ ~DummyTask() {
+ *deleted_ = true;
+ }
+
+ void Run() {
+ CHECK(false);
+ }
+
+ private:
+ bool* deleted_;
+ };
+
+ class DeletedOnIO
+ : public base::RefCountedThreadSafe<
+ DeletedOnIO, ChromeThread::DeleteOnIOThread> {
+ public:
+ DeletedOnIO(MessageLoop* message_loop) : message_loop_(message_loop) { }
+
+ ~DeletedOnIO() {
+ CHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ message_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ private:
+ MessageLoop* message_loop_;
+ };
+
+ class NeverDeleted
+ : public base::RefCountedThreadSafe<
+ NeverDeleted, ChromeThread::DeleteOnWebKitThread> {
+ public:
+ ~NeverDeleted() {
+ CHECK(false);
+ }
+ };
+
+ private:
+ scoped_ptr<ChromeThread> file_thread_;
+ scoped_ptr<ChromeThread> io_thread_;
+ MessageLoop loop_;
+};
+
+TEST_F(ChromeThreadTest, PostTask) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableFunction(&BasicFunction, MessageLoop::current()));
+ MessageLoop::current()->Run();
+}
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::IO) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::FILE) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::DB) == NULL);
+TEST_F(ChromeThreadTest, Release) {
+ ChromeThread::ReleaseSoon(ChromeThread::FILE, FROM_HERE, this);
+ MessageLoop::current()->Run();
+}
- // Phase 4: Destroy the threads.
+TEST_F(ChromeThreadTest, TaskToNonExistentThreadIsDeleted) {
+ bool deleted = false;
+ ChromeThread::PostTask(
+ ChromeThread::WEBKIT, FROM_HERE,
+ new DummyTask(&deleted));
+ EXPECT_TRUE(deleted);
+}
- io_thread.reset();
- file_thread.reset();
- db_thread.reset();
+TEST_F(ChromeThreadTest, ReleasedOnCorrectThread) {
+ {
+ scoped_refptr<DeletedOnIO> test(new DeletedOnIO(MessageLoop::current()));
+ }
+ MessageLoop::current()->Run();
+}
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::IO) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::FILE) == NULL);
- EXPECT_TRUE(ChromeThread::GetMessageLoop(ChromeThread::DB) == NULL);
- */
+TEST_F(ChromeThreadTest, NotReleasedIfTargetThreadNonExistent) {
+ scoped_refptr<NeverDeleted> test(new NeverDeleted());
}
diff --git a/chrome/browser/renderer_host/file_system_accessor.cc b/chrome/browser/renderer_host/file_system_accessor.cc
deleted file mode 100644
index de5fc7b..0000000
--- a/chrome/browser/renderer_host/file_system_accessor.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2006-2009 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/renderer_host/file_system_accessor.h"
-
-#include "base/file_util.h"
-#include "base/message_loop.h"
-#include "chrome/browser/chrome_thread.h"
-
-FileSystemAccessor::FileSystemAccessor(void* param, FileSizeCallback* callback)
- : param_(param), callback_(callback) {
- caller_loop_ = MessageLoop::current();
-}
-
-FileSystemAccessor::~FileSystemAccessor() {
-}
-
-void FileSystemAccessor::RequestFileSize(const FilePath& path,
- void* param,
- FileSizeCallback* callback) {
- // Getting file size could take long time if it lives on a network share,
- // so run it on FILE thread.
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableMethod(new FileSystemAccessor(param, callback),
- &FileSystemAccessor::GetFileSize, path));
-}
-
-void FileSystemAccessor::GetFileSize(const FilePath& path) {
- int64 result;
- // Set result to -1 if failed to get file size.
- if (!file_util::GetFileSize(path, &result))
- result = -1;
-
- // Pass the result back to the caller thread.
- caller_loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &FileSystemAccessor::GetFileSizeCompleted, result));
-}
-
-void FileSystemAccessor::GetFileSizeCompleted(int64 result) {
- callback_->Run(result, param_);
-}
diff --git a/chrome/browser/renderer_host/file_system_accessor.h b/chrome/browser/renderer_host/file_system_accessor.h
deleted file mode 100644
index 8400898..0000000
--- a/chrome/browser/renderer_host/file_system_accessor.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2006-2009 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.
-//
-// FileSystemAccessor provides functions so consumers can do file access
-// asynchronously. It would PostTask to FILE thread to access file info, then on
-// completion PostTask back to the caller thread and pass the result back.
-// Here is an example on how to use it to get file size:
-// 1. Define a callback function so FileSystemAccessor could run it after the
-// task has been completed:
-// void Foo::GetFileSizeCallback(int64 result, void* param) {
-// }
-// 2. Call static function FileSystemAccessor::RequestFileSize, provide file
-// path, param (any object you want to pass back to the callback function)
-// and callback:
-// FileSystemAccessor::RequestFileSize(
-// path,
-// param,
-// NewCallback(this, &Foo::GetFileSizeCallback));
-// 3. FileSystemAceessor would PostTask to FILE thread to get file size, then
-// on completion it would PostTask back to the current thread and run
-// Foo::GetFileSizeCallback.
-//
-
-#ifndef CHROME_BROWSER_RENDERER_HOST_FILE_SYSTEM_ACCESSOR_H_
-#define CHROME_BROWSER_RENDERER_HOST_FILE_SYSTEM_ACCESSOR_H_
-
-#include "base/scoped_ptr.h"
-#include "base/ref_counted.h"
-#include "base/task.h"
-
-class FilePath;
-class MessageLoop;
-
-class FileSystemAccessor
- : public base::RefCountedThreadSafe<FileSystemAccessor> {
- public:
- typedef Callback2<int64, void*>::Type FileSizeCallback;
-
- virtual ~FileSystemAccessor();
-
- // Request to get file size.
- //
- // param is an object that is owned by the caller and needs to pass back to
- // the caller by FileSystemAccessor through the callback function.
- // It can be set to NULL if no object needs to pass back.
- //
- // FileSizeCallback function is defined as:
- // void f(int64 result, void* param);
- // Variable result has the file size. If the file does not exist or there is
- // error accessing the file, result is set to -1. If the given path is a
- // directory, result is set to 0.
- static void RequestFileSize(const FilePath& path,
- void* param,
- FileSizeCallback* callback);
-
- private:
- FileSystemAccessor(void* param, FileSizeCallback* callback);
-
- // Get file size on the worker thread and pass result back to the caller
- // thread.
- void GetFileSize(const FilePath& path);
-
- // Getting file size completed, callback to reply message.
- void GetFileSizeCompleted(int64 result);
-
- MessageLoop* caller_loop_;
- void* param_;
- scoped_ptr<FileSizeCallback> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemAccessor);
-};
-
-#endif // CHROME_BROWSER_RENDERER_HOST_FILE_SYSTEM_ACCESSOR_H_
diff --git a/chrome/browser/renderer_host/file_system_accessor_unittest.cc b/chrome/browser/renderer_host/file_system_accessor_unittest.cc
deleted file mode 100644
index 62f1008..0000000
--- a/chrome/browser/renderer_host/file_system_accessor_unittest.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2006-2009 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 "base/file_util.h"
-#include "base/message_loop.h"
-#include "base/timer.h"
-#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/renderer_host/file_system_accessor.h"
-#include "chrome/test/file_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class FileSystemAccessorTest : public testing::Test {
- protected:
- virtual void SetUp() {
- // Make sure the current thread has a message loop.
- EXPECT_TRUE(MessageLoop::current() != NULL);
-
- // Create FILE thread which is used to do file access.
- file_thread_.reset(new ChromeThread(ChromeThread::FILE));
-
- // Start FILE thread and verify FILE message loop exists.
- file_thread_->Start();
- EXPECT_TRUE(file_thread_->message_loop() != NULL);
- }
-
- virtual void TearDown() {
- file_thread_->Stop();
- }
-
- void TestGetFileSize(const FilePath& path,
- void* param,
- int64 expected_result,
- void* expected_param) {
- // Initialize the actual result not equal to the expected result.
- result_ = expected_result + 1;
- param_ = NULL;
-
- FileSystemAccessor::RequestFileSize(
- path,
- param,
- NewCallback(this, &FileSystemAccessorTest::GetFileSizeCallback));
-
- // Time out if getting file size takes more than 10 seconds.
- const int kGetFileSizeTimeoutSeconds = 10;
- base::OneShotTimer<MessageLoop> timer;
- timer.Start(base::TimeDelta::FromSeconds(kGetFileSizeTimeoutSeconds),
- MessageLoop::current(), &MessageLoop::Quit);
-
- MessageLoop::current()->Run();
-
- EXPECT_EQ(expected_result, result_);
- EXPECT_EQ(expected_param, param_);
- }
-
- private:
- void GetFileSizeCallback(int64 result, void* param) {
- result_ = result;
- param_ = param;
- MessageLoop::current()->Quit();
- }
-
- scoped_ptr<ChromeThread> file_thread_;
- FilePath temp_file_;
- int64 result_;
- void* param_;
- MessageLoop loop_;
-};
-
-TEST_F(FileSystemAccessorTest, GetFileSize) {
- const std::string data("This is test data.");
-
- FilePath path;
- FILE* file = file_util::CreateAndOpenTemporaryFile(&path);
- EXPECT_TRUE(file != NULL);
- size_t bytes_written = fwrite(data.data(), 1, data.length(), file);
- EXPECT_TRUE(file_util::CloseFile(file));
-
- FileAutoDeleter deleter(path);
-
- TestGetFileSize(path, NULL, bytes_written, NULL);
-}
-
-TEST_F(FileSystemAccessorTest, GetFileSizeWithParam) {
- const std::string data("This is test data.");
-
- FilePath path;
- FILE* file = file_util::CreateAndOpenTemporaryFile(&path);
- EXPECT_TRUE(file != NULL);
- size_t bytes_written = fwrite(data.data(), 1, data.length(), file);
- EXPECT_TRUE(file_util::CloseFile(file));
-
- FileAutoDeleter deleter(path);
-
- int param = 100;
- TestGetFileSize(path, static_cast<void*>(&param),
- bytes_written, static_cast<void*>(&param));
-}
-
-TEST_F(FileSystemAccessorTest, GetFileSizeEmptyFile) {
- FilePath path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&path));
- FileAutoDeleter deleter(path);
-
- TestGetFileSize(path, NULL, 0, NULL);
-}
-
-TEST_F(FileSystemAccessorTest, GetFileSizeNotFound) {
- FilePath path;
- EXPECT_TRUE(file_util::CreateNewTempDirectory(
- FILE_PATH_LITERAL("chrome_test_"), &path));
- FileAutoDeleter deleter(path);
-
- TestGetFileSize(path.Append(FILE_PATH_LITERAL("foo.txt")), NULL, -1, NULL);
-}
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index c4ccda3..5b4aa81 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -7,6 +7,7 @@
#include "app/clipboard/clipboard.h"
#include "app/gfx/native_widget_types.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/histogram.h"
#include "base/process_util.h"
#include "base/thread.h"
@@ -28,7 +29,6 @@
#include "chrome/browser/renderer_host/audio_renderer_host.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
-#include "chrome/browser/renderer_host/file_system_accessor.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "chrome/browser/spellchecker.h"
@@ -406,6 +406,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+void ResourceMessageFilter::OnDestruct() {
+ ChromeThread::DeleteOnIOThread::Destruct(this);
+}
+
void ResourceMessageFilter::OnReceiveContextMenuMsg(const IPC::Message& msg) {
void* iter = NULL;
ContextMenuParams params;
@@ -594,35 +598,22 @@ void ResourceMessageFilter::OnLoadFont(LOGFONT font) {
void ResourceMessageFilter::OnGetPlugins(bool refresh,
IPC::Message* reply_msg) {
- // Schedule plugin loading on the file thread.
- // Note: it's possible that the only reference to this object is the task. If
- // If the task executes on the file thread, and before it returns, the task it
- // posts to the IO thread runs, then this object will get destructed on the
- // file thread. We need this object to be destructed on the IO thread, so do
- // the refcounting manually.
- AddRef();
ChromeThread::PostTask(
ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(&ResourceMessageFilter::OnGetPluginsOnFileThread,
- this, refresh, reply_msg));
+ NewRunnableMethod(
+ this, &ResourceMessageFilter::OnGetPluginsOnFileThread, refresh,
+ reply_msg));
}
void ResourceMessageFilter::OnGetPluginsOnFileThread(
- ResourceMessageFilter* filter,
- bool refresh,
- IPC::Message* reply_msg) {
+ bool refresh, IPC::Message* reply_msg) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
std::vector<WebPluginInfo> plugins;
NPAPI::PluginList::Singleton()->GetPlugins(refresh, &plugins);
ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(filter, &ResourceMessageFilter::OnPluginsLoaded,
- reply_msg));
-}
-
-void ResourceMessageFilter::OnPluginsLoaded(IPC::Message* reply_msg) {
- Send(reply_msg);
- Release();
+ NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg));
}
void ResourceMessageFilter::OnGetPluginPath(const GURL& url,
@@ -1130,29 +1121,36 @@ void ResourceMessageFilter::OnSetCacheMode(bool enabled) {
void ResourceMessageFilter::OnGetFileSize(const FilePath& path,
IPC::Message* reply_msg) {
- // Increase the ref count to ensure ResourceMessageFilter won't be destroyed
- // before GetFileSize callback is done.
- AddRef();
-
// Get file size only when the child process has been granted permission to
// upload the file.
- if (ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
- FileSystemAccessor::RequestFileSize(
- path,
- reply_msg,
- NewCallback(this, &ResourceMessageFilter::ReplyGetFileSize));
- } else {
- ReplyGetFileSize(-1, reply_msg);
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
+ ViewHostMsg_GetFileSize::WriteReplyParams(
+ reply_msg, static_cast<int64>(-1));
+ Send(reply_msg);
+ return;
}
+
+ // Getting file size could take long time if it lives on a network share,
+ // so run it on FILE thread.
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this, &ResourceMessageFilter::OnGetFileSizeOnFileThread, path,
+ reply_msg));
}
-void ResourceMessageFilter::ReplyGetFileSize(int64 result, void* param) {
- IPC::Message* reply_msg = static_cast<IPC::Message*>(param);
+void ResourceMessageFilter::OnGetFileSizeOnFileThread(
+ const FilePath& path, IPC::Message* reply_msg) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
+ int64 result;
+ if (!file_util::GetFileSize(path, &result))
+ result = -1;
ViewHostMsg_GetFileSize::WriteReplyParams(reply_msg, result);
- Send(reply_msg);
- // Getting file size callback done, decrease the ref count.
- Release();
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg));
}
void ResourceMessageFilter::OnKeygen(uint32 key_size_index,
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 1c3d520..0184591 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -97,6 +97,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
virtual void OnChannelError();
virtual void OnChannelClosing();
virtual bool OnMessageReceived(const IPC::Message& message);
+ virtual void OnDestruct();
// ResourceDispatcherHost::Receiver methods:
virtual bool Send(IPC::Message* message);
@@ -149,10 +150,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnGetScreenInfo(gfx::NativeViewId window, IPC::Message* reply);
#endif
void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
- static void OnGetPluginsOnFileThread(ResourceMessageFilter* filter,
- bool refresh,
- IPC::Message* reply_msg);
- void OnPluginsLoaded(IPC::Message* reply_msg);
+ void OnGetPluginsOnFileThread(bool refresh, IPC::Message* reply_msg);
void OnGetPluginPath(const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
@@ -283,7 +281,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnSetCacheMode(bool enabled);
void OnGetFileSize(const FilePath& path, IPC::Message* reply_msg);
- void ReplyGetFileSize(int64 result, void* param);
+ void OnGetFileSizeOnFileThread(const FilePath& path, IPC::Message* reply_msg);
void OnKeygen(uint32 key_size_index, const std::string& challenge_string,
const GURL& url, std::string* signed_public_key);
#if defined(OS_LINUX)
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index fe770c7..12eb600 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1946,8 +1946,6 @@
'browser/renderer_host/download_resource_handler.h',
'browser/renderer_host/download_throttling_resource_handler.cc',
'browser/renderer_host/download_throttling_resource_handler.h',
- 'browser/renderer_host/file_system_accessor.cc',
- 'browser/renderer_host/file_system_accessor.h',
'browser/renderer_host/gtk_im_context_wrapper.cc',
'browser/renderer_host/gtk_im_context_wrapper.h',
'browser/renderer_host/gtk_key_bindings_handler.cc',
@@ -4611,7 +4609,6 @@
'browser/privacy_blacklist/blacklist_io_unittest.cc',
'browser/profile_manager_unittest.cc',
'browser/renderer_host/audio_renderer_host_unittest.cc',
- 'browser/renderer_host/file_system_accessor_unittest.cc',
'browser/renderer_host/render_widget_host_unittest.cc',
'browser/renderer_host/resource_dispatcher_host_unittest.cc',
'browser/renderer_host/test/render_view_host_unittest.cc',
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index cbe8cc2..4d13b2b8 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -10,6 +10,12 @@
namespace IPC {
+// static
+void ChannelProxy::MessageFilterTraits::Destruct(
+ ChannelProxy::MessageFilter* filter) {
+ filter->OnDestruct();
+}
+
//------------------------------------------------------------------------------
// This task ensures the message is deleted if the task is deleted without
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
index a2d55be..3369f50 100644
--- a/ipc/ipc_channel_proxy.h
+++ b/ipc/ipc_channel_proxy.h
@@ -46,9 +46,16 @@ class SendTask;
//
class ChannelProxy : public Message::Sender {
public:
+
+ class MessageFilter;
+ struct MessageFilterTraits {
+ static void Destruct(MessageFilter* filter);
+ };
+
// A class that receives messages on the thread where the IPC channel is
// running. It can choose to prevent the default action for an IPC message.
- class MessageFilter : public base::RefCountedThreadSafe<MessageFilter> {
+ class MessageFilter
+ : public base::RefCountedThreadSafe<MessageFilter, MessageFilterTraits> {
public:
virtual ~MessageFilter() {}
@@ -79,6 +86,13 @@ class ChannelProxy : public Message::Sender {
virtual bool OnMessageReceived(const Message& message) {
return false;
}
+
+ // Called when the message filter is about to be deleted. This gives
+ // derived classes the option of controlling which thread they're deleted
+ // on etc.
+ virtual void OnDestruct() {
+ delete this;
+ }
};
// Initializes a channel proxy. The channel_id and mode parameters are