summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
Diffstat (limited to 'mojo')
-rw-r--r--mojo/common/bindings_support_impl.cc65
-rw-r--r--mojo/common/bindings_support_impl.h39
-rw-r--r--mojo/common/handle_watcher.cc26
-rw-r--r--mojo/common/handle_watcher.h4
-rw-r--r--mojo/common/handle_watcher_unittest.cc33
-rw-r--r--mojo/mojo.gyp5
-rw-r--r--mojo/public/bindings/lib/bindings_support.h28
-rw-r--r--mojo/public/bindings/lib/connector.cc41
-rw-r--r--mojo/public/bindings/lib/connector.h7
-rw-r--r--mojo/public/tests/simple_bindings_support.cc47
-rw-r--r--mojo/public/tests/simple_bindings_support.h13
-rw-r--r--mojo/shell/context.cc2
-rw-r--r--mojo/shell/context.h2
13 files changed, 231 insertions, 81 deletions
diff --git a/mojo/common/bindings_support_impl.cc b/mojo/common/bindings_support_impl.cc
new file mode 100644
index 0000000..9cec141
--- /dev/null
+++ b/mojo/common/bindings_support_impl.cc
@@ -0,0 +1,65 @@
+// Copyright 2013 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 "mojo/common/bindings_support_impl.h"
+
+#include "base/atomic_ref_count.h"
+#include "base/bind.h"
+#include "mojo/common/handle_watcher.h"
+
+namespace mojo {
+namespace common {
+
+// Context is used to track the number of HandleWatcher objects in use by a
+// particular BindingsSupportImpl instance.
+class BindingsSupportImpl::Context
+ : public base::RefCountedThreadSafe<BindingsSupportImpl::Context> {
+ public:
+ void CallOnHandleReady(HandleWatcher* watcher,
+ AsyncWaitCallback* callback,
+ MojoResult result) {
+ delete watcher;
+ callback->OnHandleReady(result);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<Context>;
+ virtual ~Context() {}
+};
+
+BindingsSupportImpl::BindingsSupportImpl()
+ : context_(new Context()) {
+}
+
+BindingsSupportImpl::~BindingsSupportImpl() {
+ // All HandleWatcher instances created through this interface should have
+ // been destroyed.
+ DCHECK(context_->HasOneRef());
+}
+
+BindingsSupport::AsyncWaitID BindingsSupportImpl::AsyncWait(
+ Handle handle,
+ MojoWaitFlags flags,
+ AsyncWaitCallback* callback) {
+ // This instance will be deleted when done or cancelled.
+ HandleWatcher* watcher = new HandleWatcher();
+
+ // TODO(darin): Standardize on mojo::Handle instead of MojoHandle?
+ watcher->Start(handle.value,
+ flags,
+ MOJO_DEADLINE_INDEFINITE,
+ base::Bind(&Context::CallOnHandleReady,
+ context_,
+ watcher,
+ callback));
+ return watcher;
+}
+
+void BindingsSupportImpl::CancelWait(AsyncWaitID async_wait_id) {
+ HandleWatcher* watcher = static_cast<HandleWatcher*>(async_wait_id);
+ delete watcher;
+}
+
+} // namespace common
+} // namespace mojo
diff --git a/mojo/common/bindings_support_impl.h b/mojo/common/bindings_support_impl.h
new file mode 100644
index 0000000..1178644
--- /dev/null
+++ b/mojo/common/bindings_support_impl.h
@@ -0,0 +1,39 @@
+// Copyright 2013 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 MOJO_COMMON_BINDINGS_SUPPORT_IMPL_H_
+#define MOJO_COMMON_BINDINGS_SUPPORT_IMPL_H_
+
+#include "mojo/public/bindings/lib/bindings_support.h"
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "mojo/common/mojo_common_export.h"
+
+namespace mojo {
+namespace common {
+
+class MOJO_COMMON_EXPORT BindingsSupportImpl
+ : NON_EXPORTED_BASE(public BindingsSupport) {
+ public:
+ BindingsSupportImpl();
+ virtual ~BindingsSupportImpl();
+
+ // BindingsSupport methods:
+ virtual AsyncWaitID AsyncWait(Handle handle, MojoWaitFlags flags,
+ AsyncWaitCallback* callback) OVERRIDE;
+ virtual void CancelWait(AsyncWaitID async_wait_id) OVERRIDE;
+
+ private:
+ class Context;
+ scoped_refptr<Context> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(BindingsSupportImpl);
+};
+
+} // namespace common
+} // namespace mojo
+
+#endif // MOJO_COMMON_BINDINGS_SUPPORT_IMPL_H_
diff --git a/mojo/common/handle_watcher.cc b/mojo/common/handle_watcher.cc
index 1fef74a..a159185 100644
--- a/mojo/common/handle_watcher.cc
+++ b/mojo/common/handle_watcher.cc
@@ -47,7 +47,7 @@ class WatcherThreadManager {
WatcherID StartWatching(MojoHandle handle,
MojoWaitFlags wait_flags,
base::TimeTicks deadline,
- const base::Closure& callback);
+ const base::Callback<void(MojoResult)>& callback);
// Stops watching a handle.
void StopWatching(WatcherID watcher_id);
@@ -65,7 +65,7 @@ class WatcherThreadManager {
MojoHandle handle;
MojoWaitFlags wait_flags;
base::TimeTicks deadline;
- base::Closure callback;
+ base::Callback<void(MojoResult)> callback;
scoped_refptr<base::MessageLoopProxy> message_loop;
};
@@ -138,10 +138,11 @@ WatcherThreadManager* WatcherThreadManager::GetInstance() {
return &instance.Get();
}
-WatcherID WatcherThreadManager::StartWatching(MojoHandle handle,
- MojoWaitFlags wait_flags,
- base::TimeTicks deadline,
- const base::Closure& callback) {
+WatcherID WatcherThreadManager::StartWatching(
+ MojoHandle handle,
+ MojoWaitFlags wait_flags,
+ base::TimeTicks deadline,
+ const base::Callback<void(MojoResult)>& callback) {
WatcherID id = 0;
{
static int next_id = 0;
@@ -264,7 +265,8 @@ void WatcherThreadManager::RemoveAndNotify(WatcherID id, MojoResult result) {
to_notify = i->second;
id_to_callback_.erase(i);
}
- to_notify.message_loop->PostTask(FROM_HERE, to_notify.callback);
+ to_notify.message_loop->PostTask(FROM_HERE,
+ base::Bind(to_notify.callback, result));
}
void WatcherThreadManager::RemoveHandle(MojoHandle handle) {
@@ -328,7 +330,7 @@ struct HandleWatcher::StartState {
WatcherID watcher_id;
// Callback to notify when done.
- base::Closure callback;
+ base::Callback<void(MojoResult)> callback;
// When Start() is invoked a callback is passed to WatcherThreadManager
// using a WeakRef from |weak_refactory_|. The callback invokes
@@ -354,7 +356,7 @@ HandleWatcher::~HandleWatcher() {
void HandleWatcher::Start(MojoHandle handle,
MojoWaitFlags wait_flags,
MojoDeadline deadline,
- const base::Closure& callback) {
+ const base::Callback<void(MojoResult)>& callback) {
DCHECK_NE(MOJO_HANDLE_INVALID, handle);
DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags);
@@ -379,10 +381,12 @@ void HandleWatcher::Stop() {
WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id);
}
-void HandleWatcher::OnHandleReady() {
+void HandleWatcher::OnHandleReady(MojoResult result) {
DCHECK(start_state_.get());
scoped_ptr<StartState> old_state(start_state_.Pass());
- old_state->callback.Run();
+ old_state->callback.Run(result);
+
+ // NOTE: We may have been deleted during callback execution.
}
// static
diff --git a/mojo/common/handle_watcher.h b/mojo/common/handle_watcher.h
index 8e04aa7..a6a73ea 100644
--- a/mojo/common/handle_watcher.h
+++ b/mojo/common/handle_watcher.h
@@ -38,7 +38,7 @@ class MOJO_COMMON_EXPORT HandleWatcher {
void Start(MojoHandle handle,
MojoWaitFlags wait_flags,
MojoDeadline deadline,
- const base::Closure& callback);
+ const base::Callback<void(MojoResult)>& callback);
// Stops listening. Does nothing if not in the process of listening.
void Stop();
@@ -54,7 +54,7 @@ class MOJO_COMMON_EXPORT HandleWatcher {
struct StartState;
// See description of |StartState::weak_factory| for details.
- void OnHandleReady();
+ void OnHandleReady(MojoResult result);
// If non-NULL Start() has been invoked.
scoped_ptr<StartState> start_state_;
diff --git a/mojo/common/handle_watcher_unittest.cc b/mojo/common/handle_watcher_unittest.cc
index ae1a175..a10585a 100644
--- a/mojo/common/handle_watcher_unittest.cc
+++ b/mojo/common/handle_watcher_unittest.cc
@@ -32,6 +32,14 @@ void RunUntilIdle() {
run_loop.RunUntilIdle();
}
+void DeleteWatcherAndForwardResult(
+ HandleWatcher* watcher,
+ base::Callback<void(MojoResult)> next_callback,
+ MojoResult result) {
+ delete watcher;
+ next_callback.Run(result);
+}
+
// Helper class to manage the callback and running the message loop waiting for
// message to be received. Typical usage is something like:
// Schedule callback returned from GetCallback().
@@ -59,17 +67,22 @@ class CallbackHelper {
run_loop.Run();
}
- base::Closure GetCallback() {
+ base::Callback<void(MojoResult)> GetCallback() {
return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr());
}
void Start(HandleWatcher* watcher, MojoHandle handle) {
+ StartWithCallback(watcher, handle, GetCallback());
+ }
+
+ void StartWithCallback(HandleWatcher* watcher, MojoHandle handle,
+ const base::Callback<void(MojoResult)>& callback) {
watcher->Start(handle, MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE,
- GetCallback());
+ callback);
}
private:
- void OnCallback() {
+ void OnCallback(MojoResult result) {
got_callback_ = true;
if (run_loop_)
run_loop_->Quit();
@@ -275,6 +288,20 @@ TEST_F(HandleWatcherTest, Deadline) {
EXPECT_FALSE(callback_helper3.got_callback());
}
+TEST_F(HandleWatcherTest, DeleteInCallback) {
+ ScopedMessagePipe test_pipe;
+ CallbackHelper callback_helper;
+
+ HandleWatcher* watcher = new HandleWatcher();
+ callback_helper.StartWithCallback(watcher, test_pipe.handle_1(),
+ base::Bind(&DeleteWatcherAndForwardResult,
+ watcher,
+ callback_helper.GetCallback()));
+ WriteToHandle(test_pipe.handle_0());
+ callback_helper.RunUntilGotCallback();
+ EXPECT_TRUE(callback_helper.got_callback());
+}
+
} // namespace test
} // namespace common
} // namespace mojo
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index a01aa88..3e71fe2 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -69,6 +69,8 @@
'mojo_system',
],
'sources': [
+ 'common/bindings_support_impl.cc',
+ 'common/bindings_support_impl.h',
'common/handle_watcher.cc',
'common/handle_watcher.h',
'common/scoped_message_pipe.cc',
@@ -217,6 +219,7 @@
'../base/base.gyp:base',
'../net/net.gyp:net',
'../url/url.gyp:url_lib',
+ 'mojo_bindings',
'mojo_system',
'mojo_utility',
'native_viewport',
@@ -257,6 +260,7 @@
'../base/base.gyp:base',
'../ui/gl/gl.gyp:gl',
'../url/url.gyp:url_lib',
+ 'mojo_common_lib',
'mojo_shell_lib',
'mojo_system',
],
@@ -478,6 +482,7 @@
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
+ 'mojo_common_lib',
'mojo_jni_headers',
'mojo_shell_lib',
],
diff --git a/mojo/public/bindings/lib/bindings_support.h b/mojo/public/bindings/lib/bindings_support.h
index 15aa65b..a1979f6 100644
--- a/mojo/public/bindings/lib/bindings_support.h
+++ b/mojo/public/bindings/lib/bindings_support.h
@@ -15,22 +15,30 @@ class BindingsSupport {
public:
class AsyncWaitCallback {
public:
+ virtual ~AsyncWaitCallback() {}
virtual void OnHandleReady(MojoResult result) = 0;
};
- // Asynchronously call MojoWait on a background thread, and return the result
- // to the current thread via the given AsyncWaitCallback.
- virtual bool AsyncWait(Handle handle,
- MojoWaitFlags flags,
- MojoDeadline deadline,
- AsyncWaitCallback* callback) = 0;
-
- // Cancel an existing call to AsyncWait with the given callback. The
- // callback's OnHandleReady method should not be called in this case.
- virtual void CancelWait(AsyncWaitCallback* callback) = 0;
+ typedef void* AsyncWaitID;
static void Set(BindingsSupport* support);
static BindingsSupport* Get();
+
+ // Asynchronously call MojoWait on a background thread, and pass the result
+ // of MojoWait to the given AsyncWaitCallback on the current thread. Returns
+ // an AsyncWaitID that can be used with CancelWait to stop waiting. This
+ // identifier becomes invalid once the callback runs.
+ virtual AsyncWaitID AsyncWait(Handle handle,
+ MojoWaitFlags flags,
+ AsyncWaitCallback* callback) = 0;
+
+ // Cancel an existing call to AsyncWait with the given AsyncWaitID. The
+ // corresponding AsyncWaitCallback's OnHandleReady method will not be called
+ // in this case.
+ virtual void CancelWait(AsyncWaitID id) = 0;
+
+ protected:
+ virtual ~BindingsSupport() {}
};
} // namespace mojo
diff --git a/mojo/public/bindings/lib/connector.cc b/mojo/public/bindings/lib/connector.cc
index f72bca3..3185536 100644
--- a/mojo/public/bindings/lib/connector.cc
+++ b/mojo/public/bindings/lib/connector.cc
@@ -20,10 +20,6 @@ Connector::Connector(Handle message_pipe)
}
Connector::~Connector() {
- if (read_callback_.IsPending())
- read_callback_.Cancel();
- if (write_callback_.IsPending())
- write_callback_.Cancel();
}
void Connector::SetIncomingReceiver(MessageReceiver* receiver) {
@@ -58,24 +54,18 @@ void Connector::OnHandleReady(Callback* callback, MojoResult result) {
void Connector::WaitToReadMore() {
read_callback_.SetOwnerToNotify(this);
-
- bool ok = BindingsSupport::Get()->AsyncWait(message_pipe_,
- MOJO_WAIT_FLAG_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- &read_callback_);
- if (!ok)
- error_ = true;
+ read_callback_.SetAsyncWaitID(
+ BindingsSupport::Get()->AsyncWait(message_pipe_,
+ MOJO_WAIT_FLAG_READABLE,
+ &read_callback_));
}
void Connector::WaitToWriteMore() {
write_callback_.SetOwnerToNotify(this);
-
- bool ok = BindingsSupport::Get()->AsyncWait(message_pipe_,
- MOJO_WAIT_FLAG_WRITABLE,
- MOJO_DEADLINE_INDEFINITE,
- &write_callback_);
- if (!ok)
- error_ = true;
+ write_callback_.SetAsyncWaitID(
+ BindingsSupport::Get()->AsyncWait(message_pipe_,
+ MOJO_WAIT_FLAG_WRITABLE,
+ &write_callback_));
}
void Connector::ReadMore() {
@@ -140,7 +130,7 @@ void Connector::WriteOne(Message* message, bool* wait_to_write) {
MojoResult rv = WriteMessage(message_pipe_,
message->data,
message->data->header.num_bytes,
- message->handles.data(),
+ &message->handles[0],
static_cast<uint32_t>(message->handles.size()),
MOJO_WRITE_MESSAGE_FLAG_NONE);
if (rv == MOJO_RESULT_OK) {
@@ -155,12 +145,13 @@ void Connector::WriteOne(Message* message, bool* wait_to_write) {
// ----------------------------------------------------------------------------
Connector::Callback::Callback()
- : owner_(NULL) {
+ : owner_(NULL),
+ async_wait_id_(0) {
}
-void Connector::Callback::Cancel() {
- owner_ = NULL;
- BindingsSupport::Get()->CancelWait(this);
+Connector::Callback::~Callback() {
+ if (owner_)
+ BindingsSupport::Get()->CancelWait(async_wait_id_);
}
void Connector::Callback::SetOwnerToNotify(Connector* owner) {
@@ -168,8 +159,8 @@ void Connector::Callback::SetOwnerToNotify(Connector* owner) {
owner_ = owner;
}
-bool Connector::Callback::IsPending() const {
- return owner_ != NULL;
+void Connector::Callback::SetAsyncWaitID(BindingsSupport::AsyncWaitID id) {
+ async_wait_id_ = id;
}
void Connector::Callback::OnHandleReady(MojoResult result) {
diff --git a/mojo/public/bindings/lib/connector.h b/mojo/public/bindings/lib/connector.h
index 808ab54..4953e82 100644
--- a/mojo/public/bindings/lib/connector.h
+++ b/mojo/public/bindings/lib/connector.h
@@ -42,15 +42,16 @@ class Connector : public MessageReceiver {
class Callback : public BindingsSupport::AsyncWaitCallback {
public:
Callback();
+ virtual ~Callback();
- void Cancel();
void SetOwnerToNotify(Connector* owner);
- bool IsPending() const;
+ void SetAsyncWaitID(BindingsSupport::AsyncWaitID async_wait_id);
virtual void OnHandleReady(MojoResult result) MOJO_OVERRIDE;
private:
Connector* owner_;
+ BindingsSupport::AsyncWaitID async_wait_id_;
};
friend class Callback;
@@ -69,6 +70,8 @@ class Connector : public MessageReceiver {
Callback write_callback_;
bool error_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Connector);
};
} // namespace mojo
diff --git a/mojo/public/tests/simple_bindings_support.cc b/mojo/public/tests/simple_bindings_support.cc
index 979474d..a59a66e 100644
--- a/mojo/public/tests/simple_bindings_support.cc
+++ b/mojo/public/tests/simple_bindings_support.cc
@@ -15,47 +15,52 @@ SimpleBindingsSupport::SimpleBindingsSupport() {
SimpleBindingsSupport::~SimpleBindingsSupport() {
BindingsSupport::Set(NULL);
+
+ for (WaiterList::iterator it = waiters_.begin(); it != waiters_.end(); ++it)
+ delete *it;
}
-bool SimpleBindingsSupport::AsyncWait(Handle handle,
- MojoWaitFlags flags,
- MojoDeadline deadline,
- AsyncWaitCallback* callback) {
- Waiter waiter;
- waiter.handle = handle;
- waiter.flags = flags;
- waiter.deadline = deadline;
- waiter.callback = callback;
+BindingsSupport::AsyncWaitID SimpleBindingsSupport::AsyncWait(
+ Handle handle,
+ MojoWaitFlags flags,
+ AsyncWaitCallback* callback) {
+ Waiter* waiter = new Waiter();
+ waiter->handle = handle;
+ waiter->flags = flags;
+ waiter->callback = callback;
waiters_.push_back(waiter);
- return true;
+ return waiter;
}
-void SimpleBindingsSupport::CancelWait(AsyncWaitCallback* callback) {
- std::list<Waiter>::iterator it = waiters_.begin();
+void SimpleBindingsSupport::CancelWait(AsyncWaitID async_wait_id) {
+ Waiter* waiter = static_cast<Waiter*>(async_wait_id);
+
+ WaiterList::iterator it = waiters_.begin();
while (it != waiters_.end()) {
- if (it->callback == callback) {
- std::list<Waiter>::iterator doomed = it++;
+ if (*it == waiter) {
+ WaiterList::iterator doomed = it++;
waiters_.erase(doomed);
} else {
++it;
}
}
+
+ delete waiter;
}
void SimpleBindingsSupport::Process() {
typedef std::pair<AsyncWaitCallback*, MojoResult> Result;
std::list<Result> results;
- // TODO(darin): Honor given deadline.
-
- std::list<Waiter>::iterator it = waiters_.begin();
+ WaiterList::iterator it = waiters_.begin();
while (it != waiters_.end()) {
- const Waiter& waiter = *it;
+ Waiter* waiter = *it;
MojoResult result;
- if (IsReady(waiter.handle, waiter.flags, &result)) {
- results.push_back(std::make_pair(waiter.callback, result));
- std::list<Waiter>::iterator doomed = it++;
+ if (IsReady(waiter->handle, waiter->flags, &result)) {
+ results.push_back(std::make_pair(waiter->callback, result));
+ WaiterList::iterator doomed = it++;
waiters_.erase(doomed);
+ delete waiter;
} else {
++it;
}
diff --git a/mojo/public/tests/simple_bindings_support.h b/mojo/public/tests/simple_bindings_support.h
index c22de82..59131ba 100644
--- a/mojo/public/tests/simple_bindings_support.h
+++ b/mojo/public/tests/simple_bindings_support.h
@@ -17,11 +17,10 @@ class SimpleBindingsSupport : public BindingsSupport {
SimpleBindingsSupport();
virtual ~SimpleBindingsSupport();
- virtual bool AsyncWait(Handle handle,
- MojoWaitFlags flags,
- MojoDeadline deadline,
- AsyncWaitCallback* callback) MOJO_OVERRIDE;
- virtual void CancelWait(AsyncWaitCallback* callback) MOJO_OVERRIDE;
+ virtual AsyncWaitID AsyncWait(Handle handle,
+ MojoWaitFlags flags,
+ AsyncWaitCallback* callback) MOJO_OVERRIDE;
+ virtual void CancelWait(AsyncWaitID async_wait_id) MOJO_OVERRIDE;
// This method is called by unit tests to check the status of any handles
// that we are asynchronously waiting on and to dispatch callbacks for any
@@ -34,11 +33,11 @@ class SimpleBindingsSupport : public BindingsSupport {
struct Waiter {
Handle handle;
MojoWaitFlags flags;
- MojoDeadline deadline;
AsyncWaitCallback* callback;
};
- std::list<Waiter> waiters_;
+ typedef std::list<Waiter*> WaiterList;
+ WaiterList waiters_;
};
} // namespace test
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc
index c2e2f90..6a4be90 100644
--- a/mojo/shell/context.cc
+++ b/mojo/shell/context.cc
@@ -18,9 +18,11 @@ Context::Context()
scoped_ptr<net::NetworkDelegate>(new NetworkDelegate()),
storage_.profile_path()) {
system::CoreImpl::Init();
+ BindingsSupport::Set(&bindings_support_impl_);
}
Context::~Context() {
+ BindingsSupport::Set(NULL);
}
} // namespace shell
diff --git a/mojo/shell/context.h b/mojo/shell/context.h
index f2dec12..16c04b4 100644
--- a/mojo/shell/context.h
+++ b/mojo/shell/context.h
@@ -5,6 +5,7 @@
#ifndef MOJO_SHELL_CONTEXT_H_
#define MOJO_SHELL_CONTEXT_H_
+#include "mojo/common/bindings_support_impl.h"
#include "mojo/shell/loader.h"
#include "mojo/shell/storage.h"
#include "mojo/shell/task_runners.h"
@@ -34,6 +35,7 @@ class Context {
TaskRunners task_runners_;
Storage storage_;
Loader loader_;
+ common::BindingsSupportImpl bindings_support_impl_;
#if defined(OS_ANDROID)
base::android::ScopedJavaGlobalRef<jobject> activity_;