summaryrefslogtreecommitdiffstats
path: root/extensions/browser/mojo
diff options
context:
space:
mode:
authorsammc <sammc@chromium.org>2014-10-23 18:46:40 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-24 01:47:03 +0000
commit680be408457f4272b468e72468eb22e1c0f0b67a (patch)
tree9b0581a0cdd4faf690443e1e28030cd64d99e864 /extensions/browser/mojo
parent51307ca7a09f7be8da0572a7eff2b8e47bdb8d78 (diff)
downloadchromium_src-680be408457f4272b468e72468eb22e1c0f0b67a.zip
chromium_src-680be408457f4272b468e72468eb22e1c0f0b67a.tar.gz
chromium_src-680be408457f4272b468e72468eb22e1c0f0b67a.tar.bz2
Move stash_backend into extensions/browser/mojo.
Review URL: https://codereview.chromium.org/638273004 Cr-Commit-Position: refs/heads/master@{#301024}
Diffstat (limited to 'extensions/browser/mojo')
-rw-r--r--extensions/browser/mojo/stash_backend.cc73
-rw-r--r--extensions/browser/mojo/stash_backend.h45
-rw-r--r--extensions/browser/mojo/stash_backend_unittest.cc174
3 files changed, 292 insertions, 0 deletions
diff --git a/extensions/browser/mojo/stash_backend.cc b/extensions/browser/mojo/stash_backend.cc
new file mode 100644
index 0000000..da4842d
--- /dev/null
+++ b/extensions/browser/mojo/stash_backend.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 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 "extensions/browser/mojo/stash_backend.h"
+
+namespace extensions {
+
+// An implementation of StashService that forwards calls to a StashBackend.
+class StashServiceImpl : public mojo::InterfaceImpl<StashService> {
+ public:
+ explicit StashServiceImpl(base::WeakPtr<StashBackend> backend);
+ ~StashServiceImpl() override;
+
+ // mojo::InterfaceImpl<StashService> overrides.
+ void AddToStash(mojo::Array<StashedObjectPtr> stash) override;
+ void RetrieveStash(
+ const mojo::Callback<void(mojo::Array<StashedObjectPtr> stash)>& callback)
+ override;
+
+ private:
+ base::WeakPtr<StashBackend> backend_;
+
+ DISALLOW_COPY_AND_ASSIGN(StashServiceImpl);
+};
+
+StashBackend::StashBackend() : weak_factory_(this) {
+}
+
+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());
+ }
+}
+
+mojo::Array<StashedObjectPtr> StashBackend::RetrieveStash() {
+ if (stashed_objects_.is_null())
+ stashed_objects_.resize(0);
+ return stashed_objects_.Pass();
+}
+
+void StashBackend::BindToRequest(mojo::InterfaceRequest<StashService> request) {
+ mojo::BindToRequest(new StashServiceImpl(weak_factory_.GetWeakPtr()),
+ &request);
+}
+
+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 extensions
diff --git a/extensions/browser/mojo/stash_backend.h b/extensions/browser/mojo/stash_backend.h
new file mode 100644
index 0000000..b90e43d
--- /dev/null
+++ b/extensions/browser/mojo/stash_backend.h
@@ -0,0 +1,45 @@
+// Copyright 2014 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 EXTENSIONS_BROWSER_MOJO_STASH_BACKEND_H_
+#define EXTENSIONS_BROWSER_MOJO_STASH_BACKEND_H_
+
+#include <vector>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "extensions/common/mojo/stash.mojom.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace extensions {
+
+// A backend that provides access to StashService for a single extension.
+class StashBackend {
+ public:
+ StashBackend();
+ ~StashBackend();
+
+ // Creates a StashService that forwards calls to this StashBackend and bind it
+ // to |request|.
+ void BindToRequest(mojo::InterfaceRequest<StashService> request);
+
+ // Adds the StashedObjects contained within |stash| to the stash.
+ void AddToStash(mojo::Array<StashedObjectPtr> stash);
+
+ // Returns all StashedObjects added to the stash since the last call to
+ // RetrieveStash.
+ mojo::Array<StashedObjectPtr> RetrieveStash();
+
+ private:
+ // The objects that have been stashed.
+ mojo::Array<StashedObjectPtr> stashed_objects_;
+
+ base::WeakPtrFactory<StashBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(StashBackend);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_MOJO_STASH_BACKEND_H_
diff --git a/extensions/browser/mojo/stash_backend_unittest.cc b/extensions/browser/mojo/stash_backend_unittest.cc
new file mode 100644
index 0000000..0a0244b
--- /dev/null
+++ b/extensions/browser/mojo/stash_backend_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2014 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/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "extensions/browser/mojo/stash_backend.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class StashServiceTest : public testing::Test, public mojo::ErrorHandler {
+ public:
+ enum Event {
+ EVENT_NONE,
+ EVENT_STASH_RETRIEVED,
+ };
+
+ StashServiceTest() {}
+
+ virtual void SetUp() override {
+ expecting_error_ = false;
+ expected_event_ = EVENT_NONE;
+ stash_backend_.reset(new StashBackend);
+ stash_backend_->BindToRequest(mojo::GetProxy(&stash_service_));
+ stash_service_.set_error_handler(this);
+ }
+
+ void OnConnectionError() override { FAIL() << "Unexpected connection error"; }
+
+ mojo::Array<StashedObjectPtr> RetrieveStash() {
+ mojo::Array<StashedObjectPtr> stash;
+ stash_service_->RetrieveStash(base::Bind(
+ &StashServiceTest::StashRetrieved, base::Unretained(this), &stash));
+ WaitForEvent(EVENT_STASH_RETRIEVED);
+ return stash.Pass();
+ }
+
+ void StashRetrieved(mojo::Array<StashedObjectPtr>* output,
+ mojo::Array<StashedObjectPtr> stash) {
+ *output = stash.Pass();
+ EventReceived(EVENT_STASH_RETRIEVED);
+ }
+
+ void WaitForEvent(Event event) {
+ expected_event_ = event;
+ base::RunLoop run_loop;
+ stop_run_loop_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ void EventReceived(Event event) {
+ if (event == expected_event_ && !stop_run_loop_.is_null())
+ stop_run_loop_.Run();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ base::Closure stop_run_loop_;
+ scoped_ptr<StashBackend> stash_backend_;
+ Event expected_event_;
+ bool expecting_error_;
+ mojo::InterfacePtr<StashService> stash_service_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StashServiceTest);
+};
+
+// Test that adding stashed objects in multiple calls can all be retrieved by a
+// Retrieve call.
+TEST_F(StashServiceTest, AddTwiceAndRetrieve) {
+ mojo::Array<StashedObjectPtr> stashed_objects;
+ StashedObjectPtr stashed_object(StashedObject::New());
+ stashed_object->id = "test type";
+ stashed_object->data.push_back(1);
+ stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
+ stashed_objects.push_back(stashed_object.Pass());
+ stash_service_->AddToStash(stashed_objects.Pass());
+ stashed_object = StashedObject::New();
+ stashed_object->id = "test type2";
+ stashed_object->data.push_back(2);
+ stashed_object->data.push_back(3);
+ stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
+ stashed_objects.push_back(stashed_object.Pass());
+ stash_service_->AddToStash(stashed_objects.Pass());
+ stashed_objects = RetrieveStash();
+ ASSERT_EQ(2u, stashed_objects.size());
+ EXPECT_EQ("test type", stashed_objects[0]->id);
+ EXPECT_EQ(0u, stashed_objects[0]->stashed_handles.size());
+ EXPECT_EQ(1u, stashed_objects[0]->data.size());
+ EXPECT_EQ(1, stashed_objects[0]->data[0]);
+ EXPECT_EQ("test type2", stashed_objects[1]->id);
+ EXPECT_EQ(0u, stashed_objects[1]->stashed_handles.size());
+ EXPECT_EQ(2u, stashed_objects[1]->data.size());
+ EXPECT_EQ(2, stashed_objects[1]->data[0]);
+ EXPECT_EQ(3, stashed_objects[1]->data[1]);
+}
+
+// Test that handles survive a round-trip through the stash.
+TEST_F(StashServiceTest, StashAndRetrieveHandles) {
+ mojo::Array<StashedObjectPtr> stashed_objects;
+ StashedObjectPtr stashed_object(StashedObject::New());
+ stashed_object->id = "test type";
+ stashed_object->data.push_back(1);
+
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ mojo::ScopedDataPipeProducerHandle producer;
+ MojoCreateDataPipeOptions options = {
+ sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1,
+ };
+ mojo::CreateDataPipe(&options, &producer, &consumer);
+ uint32_t num_bytes = 1;
+ MojoResult result = mojo::WriteDataRaw(
+ producer.get(), "1", &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ ASSERT_EQ(1u, num_bytes);
+
+ stashed_object->stashed_handles.push_back(
+ mojo::ScopedHandle::From(producer.Pass()));
+ stashed_object->stashed_handles.push_back(
+ mojo::ScopedHandle::From(consumer.Pass()));
+ stashed_objects.push_back(stashed_object.Pass());
+ stash_service_->AddToStash(stashed_objects.Pass());
+ stashed_objects = RetrieveStash();
+ ASSERT_EQ(1u, stashed_objects.size());
+ EXPECT_EQ("test type", stashed_objects[0]->id);
+ ASSERT_EQ(2u, stashed_objects[0]->stashed_handles.size());
+
+ consumer = mojo::ScopedDataPipeConsumerHandle::From(
+ stashed_objects[0]->stashed_handles[1].Pass());
+ result = mojo::Wait(
+ consumer.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ char data = '\0';
+ result = mojo::ReadDataRaw(
+ consumer.get(), &data, &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ ASSERT_EQ(1u, num_bytes);
+ EXPECT_EQ('1', data);
+}
+
+TEST_F(StashServiceTest, RetrieveWithoutStashing) {
+ mojo::Array<StashedObjectPtr> stashed_objects = RetrieveStash();
+ ASSERT_TRUE(!stashed_objects.is_null());
+ EXPECT_EQ(0u, stashed_objects.size());
+}
+
+// Test that a stash service discards stashed objects when the backend no longer
+// exists.
+TEST_F(StashServiceTest, ServiceWithDeletedBackend) {
+ stash_backend_.reset();
+ stash_service_.set_error_handler(this);
+
+ mojo::Array<StashedObjectPtr> stashed_objects;
+ StashedObjectPtr stashed_object(StashedObject::New());
+ stashed_object->id = "test type";
+ stashed_object->data.push_back(1);
+ mojo::MessagePipe message_pipe;
+ stashed_object->stashed_handles.push_back(
+ mojo::ScopedHandle::From(message_pipe.handle0.Pass()));
+ stashed_objects.push_back(stashed_object.Pass());
+ stash_service_->AddToStash(stashed_objects.Pass());
+ stashed_objects = RetrieveStash();
+ ASSERT_EQ(0u, stashed_objects.size());
+ // Check that the stashed handle has been closed.
+ MojoResult result =
+ mojo::Wait(message_pipe.handle1.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+}
+
+} // namespace extensions