Chromium Code Reviews| Index: extensions/browser/mojo/stash_backend.cc |
| diff --git a/extensions/browser/mojo/stash_backend.cc b/extensions/browser/mojo/stash_backend.cc |
| index da4842d3340035a88ce8c840ebb327c7705c2eb1..5f8f03b3a57351958d3004a8fa3ebfcbc44bf6fb 100644 |
| --- a/extensions/browser/mojo/stash_backend.cc |
| +++ b/extensions/browser/mojo/stash_backend.cc |
| @@ -4,7 +4,11 @@ |
| #include "extensions/browser/mojo/stash_backend.h" |
| +#include "base/bind.h" |
| +#include "third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h" |
| + |
| namespace extensions { |
| +namespace { |
| // An implementation of StashService that forwards calls to a StashBackend. |
| class StashServiceImpl : public mojo::InterfaceImpl<StashService> { |
| @@ -24,7 +28,66 @@ class StashServiceImpl : public mojo::InterfaceImpl<StashService> { |
| DISALLOW_COPY_AND_ASSIGN(StashServiceImpl); |
| }; |
| -StashBackend::StashBackend() : weak_factory_(this) { |
| +StashServiceImpl::StashServiceImpl(base::WeakPtr<StashBackend> backend) |
| + : backend_(backend) { |
| +} |
| + |
| +StashServiceImpl::~StashServiceImpl() { |
| +} |
| + |
| +void StashServiceImpl::AddToStash( |
| + mojo::Array<StashedObjectPtr> stashed_objects) { |
| + if (!backend_) |
| + return; |
| + backend_->AddToStash(stashed_objects.Pass()); |
| +} |
| + |
| +void StashServiceImpl::RetrieveStash( |
| + const mojo::Callback<void(mojo::Array<StashedObjectPtr>)>& callback) { |
| + if (!backend_) { |
| + callback.Run(mojo::Array<StashedObjectPtr>(0)); |
| + return; |
| + } |
| + callback.Run(backend_->RetrieveStash()); |
| +} |
| + |
| +} // namespace |
| + |
| +// A stash entry for a stashed object. This handles notifications if a handle |
| +// within the stashed object is readable. |
| +class StashBackend::StashEntry { |
| + public: |
| + // Construct an StashEntry for |stashed_object|. If |on_handle_readable| is |
|
Anand Mistry (off Chromium)
2015/02/05 11:10:33
s/an/a
Sam McNally
2015/02/05 23:35:31
Done.
|
| + // non-null, it will be invoked when any handle on |stashed_object| is |
| + // readable. |
| + StashEntry(StashedObjectPtr stashed_object, |
| + const base::Closure& on_handle_readable); |
| + ~StashEntry(); |
| + |
| + // Returns the stashed object. |
| + StashedObjectPtr Release(); |
| + |
| + // Cancels notifications for handles becoming readable. |
| + void CancelHandleNotifications(); |
| + |
| + private: |
| + // Invoked when a handle within |stashed_object_| is readable. |
| + void OnHandleReady(MojoResult result); |
| + |
| + // The waiters that are waiting for handles to be readable. |
| + std::vector<linked_ptr<mojo::AsyncWaiter>> waiters_; |
| + |
| + StashedObjectPtr stashed_object_; |
| + |
| + // If non-null, a callback to call when a handle contained within |
| + // |stashed_object_| is readable. |
| + const base::Closure on_handle_readable_; |
| +}; |
| + |
| +StashBackend::StashBackend(const base::Closure& on_handle_readable) |
| + : on_handle_readable_(on_handle_readable), |
| + has_notified_(false), |
| + weak_factory_(this) { |
| } |
| StashBackend::~StashBackend() { |
| @@ -32,14 +95,22 @@ StashBackend::~StashBackend() { |
| void StashBackend::AddToStash(mojo::Array<StashedObjectPtr> stashed_objects) { |
| for (size_t i = 0; i < stashed_objects.size(); i++) { |
| - stashed_objects_.push_back(stashed_objects[i].Pass()); |
| + stashed_objects_.push_back(linked_ptr<StashEntry>(new StashEntry( |
| + stashed_objects[i].Pass(), |
| + has_notified_ ? base::Closure() |
| + : base::Bind(&StashBackend::OnHandleReady, |
| + weak_factory_.GetWeakPtr())))); |
| } |
| } |
| mojo::Array<StashedObjectPtr> StashBackend::RetrieveStash() { |
| - if (stashed_objects_.is_null()) |
| - stashed_objects_.resize(0); |
| - return stashed_objects_.Pass(); |
| + has_notified_ = false; |
| + mojo::Array<StashedObjectPtr> result(0); |
| + for (auto& entry : stashed_objects_) { |
| + result.push_back(entry->Release()); |
| + } |
| + stashed_objects_.clear(); |
| + return result.Pass(); |
| } |
| void StashBackend::BindToRequest(mojo::InterfaceRequest<StashService> request) { |
| @@ -47,27 +118,47 @@ void StashBackend::BindToRequest(mojo::InterfaceRequest<StashService> request) { |
| &request); |
| } |
| -StashServiceImpl::StashServiceImpl(base::WeakPtr<StashBackend> backend) |
| - : backend_(backend) { |
| +void StashBackend::OnHandleReady() { |
| + DCHECK(!has_notified_); |
| + has_notified_ = true; |
| + for (auto& entry : stashed_objects_) { |
| + entry->CancelHandleNotifications(); |
| + } |
| + if (!on_handle_readable_.is_null()) |
| + on_handle_readable_.Run(); |
| } |
| -StashServiceImpl::~StashServiceImpl() { |
| +StashBackend::StashEntry::StashEntry(StashedObjectPtr stashed_object, |
| + const base::Closure& on_handle_readable) |
| + : stashed_object_(stashed_object.Pass()), |
| + on_handle_readable_(on_handle_readable) { |
| + if (on_handle_readable_.is_null() || !stashed_object_->monitor_handles) |
| + return; |
| + |
| + for (size_t i = 0; i < stashed_object_->stashed_handles.size(); i++) { |
| + waiters_.push_back(linked_ptr<mojo::AsyncWaiter>(new mojo::AsyncWaiter( |
| + stashed_object_->stashed_handles[i].get(), MOJO_HANDLE_SIGNAL_READABLE, |
| + base::Bind(&StashBackend::StashEntry::OnHandleReady, |
| + base::Unretained(this))))); |
| + } |
| } |
| -void StashServiceImpl::AddToStash( |
| - mojo::Array<StashedObjectPtr> stashed_objects) { |
| - if (!backend_) |
| - return; |
| - backend_->AddToStash(stashed_objects.Pass()); |
| +StashBackend::StashEntry::~StashEntry() { |
| } |
| -void StashServiceImpl::RetrieveStash( |
| - const mojo::Callback<void(mojo::Array<StashedObjectPtr>)>& callback) { |
| - if (!backend_) { |
| - callback.Run(mojo::Array<StashedObjectPtr>(0)); |
| +StashedObjectPtr StashBackend::StashEntry::Release() { |
| + waiters_.clear(); |
| + return stashed_object_.Pass(); |
| +} |
| + |
| +void StashBackend::StashEntry::CancelHandleNotifications() { |
| + waiters_.clear(); |
| +} |
| + |
| +void StashBackend::StashEntry::OnHandleReady(MojoResult result) { |
| + if (result != MOJO_RESULT_OK) |
| return; |
| - } |
| - callback.Run(backend_->RetrieveStash()); |
| + on_handle_readable_.Run(); |
| } |
| } // namespace extensions |