Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / extensions / browser / mojo / stash_backend.cc
blob5bab69c3ef832ede6e61e0b07b80513fb7c55830
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/mojo/stash_backend.h"
7 #include "base/bind.h"
8 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
9 #include "third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h"
11 namespace extensions {
12 namespace {
14 // An implementation of StashService that forwards calls to a StashBackend.
15 class StashServiceImpl : public StashService {
16 public:
17 StashServiceImpl(mojo::InterfaceRequest<StashService> request,
18 base::WeakPtr<StashBackend> backend);
19 ~StashServiceImpl() override;
21 // StashService overrides.
22 void AddToStash(mojo::Array<StashedObjectPtr> stash) override;
23 void RetrieveStash(
24 const mojo::Callback<void(mojo::Array<StashedObjectPtr> stash)>& callback)
25 override;
27 private:
28 mojo::StrongBinding<StashService> binding_;
29 base::WeakPtr<StashBackend> backend_;
31 DISALLOW_COPY_AND_ASSIGN(StashServiceImpl);
34 StashServiceImpl::StashServiceImpl(mojo::InterfaceRequest<StashService> request,
35 base::WeakPtr<StashBackend> backend)
36 : binding_(this, request.Pass()), backend_(backend) {
39 StashServiceImpl::~StashServiceImpl() {
42 void StashServiceImpl::AddToStash(
43 mojo::Array<StashedObjectPtr> stashed_objects) {
44 if (!backend_)
45 return;
46 backend_->AddToStash(stashed_objects.Pass());
49 void StashServiceImpl::RetrieveStash(
50 const mojo::Callback<void(mojo::Array<StashedObjectPtr>)>& callback) {
51 if (!backend_) {
52 callback.Run(mojo::Array<StashedObjectPtr>(0));
53 return;
55 callback.Run(backend_->RetrieveStash());
58 } // namespace
60 // A stash entry for a stashed object. This handles notifications if a handle
61 // within the stashed object is readable.
62 class StashBackend::StashEntry {
63 public:
64 // Construct a StashEntry for |stashed_object|. If |on_handle_readable| is
65 // non-null, it will be invoked when any handle on |stashed_object| is
66 // readable.
67 StashEntry(StashedObjectPtr stashed_object,
68 const base::Closure& on_handle_readable);
69 ~StashEntry();
71 // Returns the stashed object.
72 StashedObjectPtr Release();
74 // Cancels notifications for handles becoming readable.
75 void CancelHandleNotifications();
77 private:
78 // Invoked when a handle within |stashed_object_| is readable.
79 void OnHandleReady(MojoResult result);
81 // The waiters that are waiting for handles to be readable.
82 ScopedVector<mojo::AsyncWaiter> waiters_;
84 StashedObjectPtr stashed_object_;
86 // If non-null, a callback to call when a handle contained within
87 // |stashed_object_| is readable.
88 const base::Closure on_handle_readable_;
91 StashBackend::StashBackend(const base::Closure& on_handle_readable)
92 : on_handle_readable_(on_handle_readable),
93 has_notified_(false),
94 weak_factory_(this) {
97 StashBackend::~StashBackend() {
100 void StashBackend::AddToStash(mojo::Array<StashedObjectPtr> stashed_objects) {
101 for (size_t i = 0; i < stashed_objects.size(); i++) {
102 stashed_objects_.push_back(
103 new StashEntry(stashed_objects[i].Pass(),
104 has_notified_ ? base::Closure()
105 : base::Bind(&StashBackend::OnHandleReady,
106 weak_factory_.GetWeakPtr())));
110 mojo::Array<StashedObjectPtr> StashBackend::RetrieveStash() {
111 has_notified_ = false;
112 mojo::Array<StashedObjectPtr> result(0);
113 for (auto& entry : stashed_objects_) {
114 result.push_back(entry->Release());
116 stashed_objects_.clear();
117 return result.Pass();
120 void StashBackend::BindToRequest(mojo::InterfaceRequest<StashService> request) {
121 new StashServiceImpl(request.Pass(), weak_factory_.GetWeakPtr());
124 void StashBackend::OnHandleReady() {
125 DCHECK(!has_notified_);
126 has_notified_ = true;
127 for (auto& entry : stashed_objects_) {
128 entry->CancelHandleNotifications();
130 if (!on_handle_readable_.is_null())
131 on_handle_readable_.Run();
134 StashBackend::StashEntry::StashEntry(StashedObjectPtr stashed_object,
135 const base::Closure& on_handle_readable)
136 : stashed_object_(stashed_object.Pass()),
137 on_handle_readable_(on_handle_readable) {
138 if (on_handle_readable_.is_null() || !stashed_object_->monitor_handles)
139 return;
141 for (size_t i = 0; i < stashed_object_->stashed_handles.size(); i++) {
142 waiters_.push_back(new mojo::AsyncWaiter(
143 stashed_object_->stashed_handles[i].get(), MOJO_HANDLE_SIGNAL_READABLE,
144 base::Bind(&StashBackend::StashEntry::OnHandleReady,
145 base::Unretained(this))));
149 StashBackend::StashEntry::~StashEntry() {
152 StashedObjectPtr StashBackend::StashEntry::Release() {
153 waiters_.clear();
154 return stashed_object_.Pass();
157 void StashBackend::StashEntry::CancelHandleNotifications() {
158 waiters_.clear();
161 void StashBackend::StashEntry::OnHandleReady(MojoResult result) {
162 if (result != MOJO_RESULT_OK)
163 return;
164 on_handle_readable_.Run();
167 } // namespace extensions