summaryrefslogtreecommitdiffstats
path: root/third_party/mojo
diff options
context:
space:
mode:
authorviettrungluu <viettrungluu@chromium.org>2015-02-06 15:15:32 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-06 23:16:17 +0000
commitc2e11810044fe5ff1c1b8588103671925a5b74fe (patch)
tree21d27627d9f117013d375c6977e8a1bbf23fad9c /third_party/mojo
parent37bacf082d54dafe0dc8b6d1ba10e294374f8036 (diff)
downloadchromium_src-c2e11810044fe5ff1c1b8588103671925a5b74fe.zip
chromium_src-c2e11810044fe5ff1c1b8588103671925a5b74fe.tar.gz
chromium_src-c2e11810044fe5ff1c1b8588103671925a5b74fe.tar.bz2
Update mojo sdk to rev 8d45c89c30b230843c5bd6dd0693a555750946c0
[Taken over from blundell's https://codereview.chromium.org/901843003/, PS3.] Adapt to de-clienting of Surface. Have nacl_listener pass a SimplePlatformSupport instance to mojo::embedder::Init to satisfy the DCHECK introduced in https://codereview.chromium.org/898623002/diff/40001/mojo/edk/embedder/embedder.cc. [Additional fix backported from https://codereview.chromium.org/898423002/.] Fix mojo::embedder::CreateChannel(): the evaluation order between the channel_info->channel_id and channel_info.release() is undefined. TBR=blundell@chromium.org NOPRESUBMIT=true Review URL: https://codereview.chromium.org/904103003 Cr-Commit-Position: refs/heads/master@{#315128}
Diffstat (limited to 'third_party/mojo')
-rw-r--r--third_party/mojo/src/mojo/edk/DEPS7
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/DEPS11
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/channel_init.cc17
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/channel_init.h5
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.cc89
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.h14
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder_internal.h7
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc8
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/test_embedder.cc5
-rw-r--r--third_party/mojo/src/mojo/edk/js/DEPS5
-rw-r--r--third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom3
-rw-r--r--third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc32
-rw-r--r--third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js26
-rw-r--r--third_party/mojo/src/mojo/edk/system/BUILD.gn10
-rw-r--r--third_party/mojo/src/mojo/edk/system/DEPS3
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel.h7
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.cc71
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.h96
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc116
-rw-r--r--third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc46
-rw-r--r--third_party/mojo/src/mojo/edk/system/core.cc6
-rw-r--r--third_party/mojo/src/mojo/edk/system/core.h26
-rw-r--r--third_party/mojo/src/mojo/edk/system/core_test_base.cc3
-rw-r--r--third_party/mojo/src/mojo/edk/system/core_test_base.h3
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.cc13
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.h3
-rw-r--r--third_party/mojo/src/mojo/edk/test/BUILD.gn14
-rw-r--r--third_party/mojo/src/mojo/public/DEPS6
-rw-r--r--third_party/mojo/src/mojo/public/VERSION2
-rw-r--r--third_party/mojo/src/mojo/public/c/DEPS16
-rw-r--r--third_party/mojo/src/mojo/public/c/gles2/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/c/system/buffer.h4
-rw-r--r--third_party/mojo/src/mojo/public/c/system/data_pipe.h8
-rw-r--r--third_party/mojo/src/mojo/public/c/system/functions.h13
-rw-r--r--third_party/mojo/src/mojo/public/c/system/message_pipe.h50
-rw-r--r--third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc3
-rw-r--r--third_party/mojo/src/mojo/public/c/system/types.h3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/DEPS18
-rw-r--r--third_party/mojo/src/mojo/public/cpp/README.md2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/DEPS11
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/application_impl.h17
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/service_registry.cc4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/DEPS5
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/string.h3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h1
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/DEPS4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/environment/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/environment/lib/DEPS4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/test_support/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/utility/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/utility/run_loop.h15
-rw-r--r--third_party/mojo/src/mojo/public/dart/DEPS4
-rw-r--r--third_party/mojo/src/mojo/public/dart/core.dart1
-rw-r--r--third_party/mojo/src/mojo/public/dart/rules.gni112
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/application.dart2
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/codec.dart148
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart15
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/message.dart39
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/message_pipe.dart6
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/proxy.dart8
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/service_provider.dart3
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/stub.dart12
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/timer_impl.dart333
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/decoder.go57
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/encoder.go21
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/invalid_handle.go97
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/util.go20
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom32
-rw-r--r--third_party/mojo/src/mojo/public/tests/DEPS3
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl6
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl11
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py8
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py51
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py12
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/mojom.gni44
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py11
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/fileutil.py18
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py81
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py4
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py96
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py42
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/parse/translate.py95
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/fileutil_unittest.py55
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py4
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py54
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py7
91 files changed, 1453 insertions, 932 deletions
diff --git a/third_party/mojo/src/mojo/edk/DEPS b/third_party/mojo/src/mojo/edk/DEPS
deleted file mode 100644
index 9a51b60..0000000
--- a/third_party/mojo/src/mojo/edk/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
- "-mojo",
- "+mojo/edk",
- "+mojo/public",
-
- "+third_party/ashmem",
-]
diff --git a/third_party/mojo/src/mojo/edk/embedder/DEPS b/third_party/mojo/src/mojo/edk/embedder/DEPS
deleted file mode 100644
index c3a0d22..0000000
--- a/third_party/mojo/src/mojo/edk/embedder/DEPS
+++ /dev/null
@@ -1,11 +0,0 @@
-include_rules = [
- "+mojo/edk/system/system_impl_export.h",
-]
-
-specific_include_rules = {
- # Implementation files may freely access mojo/edk/system, but we don't want to
- # leak implementation details through the headers.
- ".*\.cc": [
- "+mojo/edk/system",
- ]
-}
diff --git a/third_party/mojo/src/mojo/edk/embedder/channel_init.cc b/third_party/mojo/src/mojo/edk/embedder/channel_init.cc
index 9a0bfce..0b6d76c 100644
--- a/third_party/mojo/src/mojo/edk/embedder/channel_init.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/channel_init.cc
@@ -15,6 +15,9 @@ ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {
}
ChannelInit::~ChannelInit() {
+ // TODO(vtl): This is likely leaky in common scenarios (we're on the main
+ // thread, which outlives the I/O thread, and we're destroyed after the I/O
+ // thread is destroyed.
if (channel_info_)
DestroyChannel(channel_info_);
}
@@ -22,14 +25,12 @@ ChannelInit::~ChannelInit() {
ScopedMessagePipeHandle ChannelInit::Init(
base::PlatformFile file,
scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- DCHECK(!io_thread_task_runner_); // Should only init once.
- io_thread_task_runner_ = io_thread_task_runner;
ScopedMessagePipeHandle message_pipe =
- CreateChannel(
- ScopedPlatformHandle(PlatformHandle(file)), io_thread_task_runner,
- base::Bind(&ChannelInit::OnCreatedChannel, weak_factory_.GetWeakPtr(),
- io_thread_task_runner),
- base::MessageLoop::current()->message_loop_proxy()).Pass();
+ CreateChannel(ScopedPlatformHandle(PlatformHandle(file)),
+ io_thread_task_runner,
+ base::Bind(&ChannelInit::OnCreatedChannel,
+ weak_factory_.GetWeakPtr()),
+ base::MessageLoop::current()->task_runner()).Pass();
return message_pipe.Pass();
}
@@ -40,7 +41,6 @@ void ChannelInit::WillDestroySoon() {
// static
void ChannelInit::OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- scoped_refptr<base::TaskRunner> io_thread,
ChannelInfo* channel) {
// If |self| was already destroyed, shut the channel down.
if (!self) {
@@ -48,6 +48,7 @@ void ChannelInit::OnCreatedChannel(base::WeakPtr<ChannelInit> self,
return;
}
+ DCHECK(!self->channel_info_);
self->channel_info_ = channel;
}
diff --git a/third_party/mojo/src/mojo/edk/embedder/channel_init.h b/third_party/mojo/src/mojo/edk/embedder/channel_init.h
index 59b6694..478da41 100644
--- a/third_party/mojo/src/mojo/edk/embedder/channel_init.h
+++ b/third_party/mojo/src/mojo/edk/embedder/channel_init.h
@@ -28,7 +28,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelInit {
~ChannelInit();
// Initializes the channel. This takes ownership of |file|. Returns the
- // primordial MessagePipe for the channel.
+ // primordial |MessagePipe| for the channel.
mojo::ScopedMessagePipeHandle Init(
base::PlatformFile file,
scoped_refptr<base::TaskRunner> io_thread_task_runner);
@@ -41,11 +41,8 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelInit {
// established. (This is a static method that takes a weak pointer to self,
// since we want to destroy the channel even if we're destroyed.)
static void OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- scoped_refptr<base::TaskRunner> io_thread,
ChannelInfo* channel);
- scoped_refptr<base::TaskRunner> io_thread_task_runner_;
-
// If non-null the channel has been established.
ChannelInfo* channel_info_;
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
index 1d12c1e..0150dcb 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
@@ -4,6 +4,7 @@
#include "mojo/edk/embedder/embedder.h"
+#include "base/atomicops.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
@@ -25,42 +26,25 @@ namespace embedder {
namespace {
-// Helper for |CreateChannel...()|. Returns 0 on failure. Called on the channel
-// creation thread.
-system::ChannelId MakeChannel(
- ScopedPlatformHandle platform_handle,
- scoped_refptr<system::ChannelEndpoint> channel_endpoint) {
- DCHECK(platform_handle.is_valid());
-
- // Create and initialize a |system::Channel|.
- DCHECK(internal::g_core);
- scoped_refptr<system::Channel> channel =
- new system::Channel(internal::g_core->platform_support());
- channel->Init(system::RawChannel::Create(platform_handle.Pass()));
- channel->SetBootstrapEndpoint(channel_endpoint);
-
- DCHECK(internal::g_channel_manager);
- return internal::g_channel_manager->AddChannel(
- channel, base::MessageLoopProxy::current());
-}
-
-// Helper for |CreateChannel()|. Called on the channel creation thread.
-void CreateChannelHelper(
- ScopedPlatformHandle platform_handle,
- scoped_ptr<ChannelInfo> channel_info,
- scoped_refptr<system::ChannelEndpoint> channel_endpoint,
- DidCreateChannelCallback callback,
- scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
- channel_info->channel_id =
- MakeChannel(platform_handle.Pass(), channel_endpoint);
-
- // Hand the channel back to the embedder.
- if (callback_thread_task_runner) {
- callback_thread_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, channel_info.release()));
- } else {
- callback.Run(channel_info.release());
- }
+// TODO(vtl): For now, we need this to be thread-safe (since theoretically we
+// currently support multiple channel creation threads -- possibly one per
+// channel). Eventually, we won't need it to be thread-safe (we'll require a
+// single I/O thread), and eventually we won't need it at all. Remember to
+// remove the base/atomicops.h include.
+system::ChannelId MakeChannelId() {
+ // Note that |AtomicWord| is signed.
+ static base::subtle::AtomicWord counter = 0;
+
+ base::subtle::AtomicWord new_counter_value =
+ base::subtle::NoBarrier_AtomicIncrement(&counter, 1);
+ // Don't allow the counter to wrap. Note that any (strictly) positive value is
+ // a valid |ChannelId| (and |NoBarrier_AtomicIncrement()| returns the value
+ // post-increment).
+ CHECK_GT(new_counter_value, 0);
+ // Use "negative" values for these IDs, so that we'll also be able to use
+ // "positive" "process identifiers" (see connection_manager.h) as IDs (and
+ // they won't conflict).
+ return static_cast<system::ChannelId>(-new_counter_value);
}
} // namespace
@@ -68,16 +52,24 @@ void CreateChannelHelper(
namespace internal {
// Declared in embedder_internal.h.
+PlatformSupport* g_platform_support = nullptr;
system::Core* g_core = nullptr;
system::ChannelManager* g_channel_manager = nullptr;
} // namespace internal
void Init(scoped_ptr<PlatformSupport> platform_support) {
+ DCHECK(platform_support);
+
+ DCHECK(!internal::g_platform_support);
+ internal::g_platform_support = platform_support.release();
+
DCHECK(!internal::g_core);
- internal::g_core = new system::Core(platform_support.Pass());
+ internal::g_core = new system::Core(internal::g_platform_support);
+
DCHECK(!internal::g_channel_manager);
- internal::g_channel_manager = new system::ChannelManager();
+ internal::g_channel_manager =
+ new system::ChannelManager(internal::g_platform_support);
}
Configuration* GetConfiguration() {
@@ -99,8 +91,9 @@ ScopedMessagePipeHandle CreateChannelOnIOThread(
ScopedMessagePipeHandle rv(
MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
- *channel_info =
- new ChannelInfo(MakeChannel(platform_handle.Pass(), channel_endpoint));
+ *channel_info = new ChannelInfo(MakeChannelId());
+ internal::g_channel_manager->CreateChannelOnIOThread(
+ (*channel_info)->channel_id, platform_handle.Pass(), channel_endpoint);
return rv.Pass();
}
@@ -126,14 +119,16 @@ ScopedMessagePipeHandle CreateChannel(
scoped_ptr<ChannelInfo> channel_info(new ChannelInfo());
if (rv.is_valid()) {
- io_thread_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&CreateChannelHelper, base::Passed(&platform_handle),
- base::Passed(&channel_info), channel_endpoint, callback,
- callback_thread_task_runner));
+ system::ChannelId channel_id = MakeChannelId();
+ channel_info->channel_id = channel_id;
+ internal::g_channel_manager->CreateChannel(
+ channel_id, platform_handle.Pass(), channel_endpoint,
+ io_thread_task_runner,
+ base::Bind(callback, base::Unretained(channel_info.release())),
+ callback_thread_task_runner);
} else {
- (callback_thread_task_runner.get() ? callback_thread_task_runner
- : io_thread_task_runner)
+ (callback_thread_task_runner ? callback_thread_task_runner
+ : io_thread_task_runner)
->PostTask(FROM_HERE, base::Bind(callback, channel_info.release()));
}
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h
index 987c6879..cc0ad26 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.h
@@ -20,13 +20,12 @@ namespace embedder {
struct Configuration;
class PlatformSupport;
-// Must be called first, or just after setting configuration parameters,
-// to initialize the (global, singleton) system.
+// Must be called first, or just after setting configuration parameters, to
+// initialize the (global, singleton) system.
MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr<PlatformSupport> platform_support);
-// Returns the global configuration. In general there should be no need to
-// change the configuration, but if you do so this must be done before calling
-// |Init()|.
+// Returns the global configuration. In general, you should not need to change
+// the configuration, but if you do you must do it before calling |Init()|.
MOJO_SYSTEM_IMPL_EXPORT Configuration* GetConfiguration();
// A "channel" is a connection on top of an OS "pipe", on top of which Mojo
@@ -64,8 +63,6 @@ MOJO_SYSTEM_IMPL_EXPORT Configuration* GetConfiguration();
//
// The destruction functions are similarly synchronous and asynchronous,
// respectively, and take the |ChannelInfo*| produced by the creation functions.
-//
-// TODO(vtl): Figure out channel teardown.
// Creates a channel; must only be called from the I/O thread. |platform_handle|
// should be a handle to a connected OS "pipe". Eventually (even on failure),
@@ -95,6 +92,9 @@ CreateChannel(ScopedPlatformHandle platform_handle,
// should be the value provided to the callback to |CreateChannel()| (or
// returned by |CreateChannelOnIOThread()|). If called from the I/O thread, this
// will complete synchronously (in particular, it will post no tasks).
+// TODO(vtl): If called from some other thread, it'll post tasks to the I/O
+// thread. This is obviously potentially problematic if you want to shut the I/O
+// thread down.
MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel(ChannelInfo* channel_info);
// Inform the channel that it will soon be destroyed (doing so is optional).
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
index ab8388a..536e0db 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
@@ -19,12 +19,14 @@ class ChannelManager;
class Core;
// Repeat a typedef in mojo/edk/system/channel_manager.h, to avoid including it.
-typedef uintptr_t ChannelId;
+typedef uint64_t ChannelId;
} // namespace system
namespace embedder {
+class PlatformSupport;
+
// This is a type that's opaque to users of the embedder API (which only
// gives/takes |ChannelInfo*|s). We make it a struct to make it
// template-friendly.
@@ -37,6 +39,9 @@ struct ChannelInfo {
namespace internal {
+// Instance of |PlatformSupport| to use.
+extern PlatformSupport* g_platform_support;
+
// Instance of |Core| used by the system functions (|Mojo...()|).
extern system::Core* g_core;
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
index ed4ea2e..fd1c04c 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
@@ -44,7 +44,7 @@ class ScopedTestChannel {
ScopedPlatformHandle platform_handle)
: io_thread_task_runner_(io_thread_task_runner),
bootstrap_message_pipe_(MOJO_HANDLE_INVALID),
- did_create_channel_event_(true, false),
+ did_create_channel_event_(true, false), // Manual reset.
channel_info_(nullptr) {
bootstrap_message_pipe_ =
CreateChannel(platform_handle.Pass(), io_thread_task_runner_,
@@ -58,7 +58,11 @@ class ScopedTestChannel {
// Destructor: Shuts down the channel. (As noted above, for this to happen,
// the I/O thread must be alive and pumping messages.)
- ~ScopedTestChannel() { DestroyChannel(channel_info_); }
+ ~ScopedTestChannel() {
+ // |WaitForChannelCreationCompletion()| must be called before destruction.
+ CHECK(did_create_channel_event_.IsSignaled());
+ DestroyChannel(channel_info_);
+ }
// Waits for channel creation to be completed.
void WaitForChannelCreationCompletion() { did_create_channel_event_.Wait(); }
diff --git a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc b/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
index defab41..3412626 100644
--- a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
@@ -54,6 +54,11 @@ bool Shutdown() {
bool rv = system::internal::ShutdownCheckNoLeaks(internal::g_core);
delete internal::g_core;
internal::g_core = nullptr;
+
+ CHECK(internal::g_platform_support);
+ delete internal::g_platform_support;
+ internal::g_platform_support = nullptr;
+
return rv;
}
diff --git a/third_party/mojo/src/mojo/edk/js/DEPS b/third_party/mojo/src/mojo/edk/js/DEPS
deleted file mode 100644
index c350edf..0000000
--- a/third_party/mojo/src/mojo/edk/js/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
- "+base",
- "+gin",
- "+v8",
-]
diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom
index 69f67b6..688b22b 100644
--- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom
+++ b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom
@@ -44,8 +44,9 @@ interface CppSide {
BackPointerResponse(EchoArgsList arg);
};
-[Client=CppSide]
interface JsSide {
+ SetCppSide(CppSide cpp);
+
Ping();
Echo(int32 numIterations, EchoArgs arg);
BitFlip(EchoArgs arg);
diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc
index 1da70c2..3675f97 100644
--- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc
+++ b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc
@@ -193,11 +193,11 @@ void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) {
// run_loop().
class CppSideConnection : public js_to_cpp::CppSide {
public:
- CppSideConnection() :
- run_loop_(NULL),
- js_side_(NULL),
- mishandled_messages_(0) {
- }
+ CppSideConnection()
+ : run_loop_(nullptr),
+ js_side_(nullptr),
+ mishandled_messages_(0),
+ binding_(this) {}
~CppSideConnection() override {}
void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
@@ -206,6 +206,12 @@ class CppSideConnection : public js_to_cpp::CppSide {
void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; }
js_to_cpp::JsSide* js_side() { return js_side_; }
+ void Bind(InterfaceRequest<js_to_cpp::CppSide> request) {
+ binding_.Bind(request.Pass());
+ // Keep the pipe open even after validation errors.
+ binding_.internal_router()->EnableTestingMode();
+ }
+
// js_to_cpp::CppSide:
void StartTest() override { NOTREACHED(); }
@@ -229,6 +235,7 @@ class CppSideConnection : public js_to_cpp::CppSide {
base::RunLoop* run_loop_;
js_to_cpp::JsSide* js_side_;
int mishandled_messages_;
+ mojo::Binding<js_to_cpp::CppSide> binding_;
private:
DISALLOW_COPY_AND_ASSIGN(CppSideConnection);
@@ -363,21 +370,22 @@ class JsToCppTest : public testing::Test {
void RunTest(const std::string& test, CppSideConnection* cpp_side) {
cpp_side->set_run_loop(&run_loop_);
- MessagePipe pipe;
- js_to_cpp::JsSidePtr js_side =
- MakeProxy<js_to_cpp::JsSide>(pipe.handle0.Pass());
- js_side.set_client(cpp_side);
-
- js_side.internal_state()->router_for_testing()->EnableTestingMode();
+ js_to_cpp::JsSidePtr js_side;
+ auto js_side_proxy = GetProxy(&js_side);
cpp_side->set_js_side(js_side.get());
+ js_to_cpp::CppSidePtr cpp_side_ptr;
+ cpp_side->Bind(GetProxy(&cpp_side_ptr));
+
+ js_side->SetCppSide(cpp_side_ptr.Pass());
gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
gin::ArrayBufferAllocator::SharedInstance());
gin::IsolateHolder instance;
MojoRunnerDelegate delegate;
gin::ShellRunner runner(&delegate, instance.isolate());
- delegate.Start(&runner, pipe.handle1.release().value(), test);
+ delegate.Start(&runner, js_side_proxy.PassMessagePipe().release().value(),
+ test);
run_loop_.Run();
}
diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js
index 140ad4c..ddecc4b 100644
--- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js
+++ b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js
@@ -5,11 +5,13 @@
define('mojo/edk/js/tests/js_to_cpp_tests', [
'console',
'mojo/edk/js/tests/js_to_cpp.mojom',
+ 'mojo/public/js/bindings',
'mojo/public/js/connection',
'mojo/public/js/connector',
'mojo/public/js/core',
-], function (console, jsToCpp, connection, connector, core) {
- var retainedConnection;
+], function (console, jsToCpp, bindings, connection, connector, core) {
+ var retainedJsSide;
+ var retainedJsSideStub;
var sampleData;
var sampleMessage;
var BAD_VALUE = 13;
@@ -25,6 +27,11 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [
JsSideConnection.prototype =
Object.create(jsToCpp.JsSide.stubClass.prototype);
+ JsSideConnection.prototype.setCppSide = function(cppSide) {
+ this.cppSide_ = cppSide;
+ this.cppSide_.startTest();
+ };
+
JsSideConnection.prototype.ping = function (arg) {
this.cppSide_.pingResponse();
};
@@ -203,13 +210,7 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [
}, null);
}
- function createCppSideConnection(handle, stubClass, proxyClass) {
- var c = new connection.Connection(handle, stubClass, proxyClass);
- c.local.cppSide_ = c.remote;
- return c;
- }
-
- return function(handle) {
+ return function(jsSideRequestHandle) {
var i;
sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes);
for (i = 0; i < sampleData.length; ++i) {
@@ -219,8 +220,9 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [
for (i = 0; i < sampleMessage.length; ++i) {
sampleMessage[i] = 255 - i;
}
- retainedConnection = createCppSideConnection(
- handle, JsSideConnection,jsToCpp.CppSide.proxyClass);
- retainedConnection.remote.startTest();
+ retainedJsSideStub =
+ connection.bindHandleToStub(jsSideRequestHandle, jsToCpp.JsSide);
+ retainedJsSide = new JsSideConnection;
+ bindings.StubBindings(retainedJsSideStub).delegate = retainedJsSide;
};
});
diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn
index 12fa225..d9dc930 100644
--- a/third_party/mojo/src/mojo/edk/system/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/system/BUILD.gn
@@ -123,6 +123,14 @@ component("system") {
allow_circular_includes_from = [ "../embedder" ]
}
+group("tests") {
+ testonly = true
+ deps = [
+ ":mojo_system_unittests",
+ ":mojo_message_pipe_perftests",
+ ]
+}
+
mojo_edk_source_set("test_utils") {
testonly = true
@@ -137,7 +145,6 @@ mojo_edk_source_set("test_utils") {
]
}
-# GYP version: mojo/edk/mojo_edk.gyp:mojo_system_unittests
test("mojo_system_unittests") {
sources = [
"../test/multiprocess_test_helper_unittest.cc",
@@ -184,7 +191,6 @@ test("mojo_system_unittests") {
allow_circular_includes_from = [ "../embedder:embedder_unittests" ]
}
-# GYP version: mojo/edk/mojo_edk.gyp:mojo_message_pipe_perftests
test("mojo_message_pipe_perftests") {
sources = [
"message_pipe_perftest.cc",
diff --git a/third_party/mojo/src/mojo/edk/system/DEPS b/third_party/mojo/src/mojo/edk/system/DEPS
deleted file mode 100644
index 4ef4138..0000000
--- a/third_party/mojo/src/mojo/edk/system/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+crypto",
-]
diff --git a/third_party/mojo/src/mojo/edk/system/channel.h b/third_party/mojo/src/mojo/edk/system/channel.h
index 3961859..93ba87a 100644
--- a/third_party/mojo/src/mojo/edk/system/channel.h
+++ b/third_party/mojo/src/mojo/edk/system/channel.h
@@ -54,8 +54,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
: public base::RefCountedThreadSafe<Channel>,
public RawChannel::Delegate {
public:
- // |platform_support| (typically owned by |Core|) must remain alive until
- // after |Shutdown()| is called.
+ // |platform_support| must remain alive until after |Shutdown()| is called.
explicit Channel(embedder::PlatformSupport* platform_support);
// This must be called on the creation thread before any other methods are
@@ -65,7 +64,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Sets the channel manager associated with this channel. This should be set
// at most once and only called before |WillShutdownSoon()| (and
- // |Shutdown()|).
+ // |Shutdown()|). (This is called by the channel manager when adding a
+ // channel; this should not be called before the channel is managed by the
+ // channel manager.)
void SetChannelManager(ChannelManager* channel_manager);
// This must be called on the creation thread before destruction (which can
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.cc b/third_party/mojo/src/mojo/edk/system/channel_manager.cc
index 4e58f89..c2fe8a5 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.cc
@@ -5,8 +5,10 @@
#include "mojo/edk/system/channel_manager.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/task_runner.h"
namespace mojo {
namespace system {
@@ -26,7 +28,8 @@ void ShutdownChannelHelper(const ChannelInfo& channel_info) {
} // namespace
-ChannelManager::ChannelManager() {
+ChannelManager::ChannelManager(embedder::PlatformSupport* platform_support)
+ : platform_support_(platform_support) {
}
ChannelManager::~ChannelManager() {
@@ -35,24 +38,57 @@ ChannelManager::~ChannelManager() {
ShutdownChannelHelper(map_elem.second);
}
-ChannelId ChannelManager::AddChannel(
- scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner) {
- ChannelId channel_id = GetChannelId(channel.get());
+void ChannelManager::CreateChannelOnIOThread(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint) {
+ DCHECK_NE(channel_id, kInvalidChannelId);
+ DCHECK(platform_handle.is_valid());
+ DCHECK(bootstrap_channel_endpoint);
+
+ // Create and initialize a |system::Channel|.
+ scoped_refptr<system::Channel> channel =
+ new system::Channel(platform_support_);
+ channel->Init(system::RawChannel::Create(platform_handle.Pass()));
+ channel->SetBootstrapEndpoint(bootstrap_channel_endpoint);
{
base::AutoLock locker(lock_);
- DCHECK(channel_infos_.find(channel_id) == channel_infos_.end());
+ CHECK(channel_infos_.find(channel_id) == channel_infos_.end());
channel_infos_[channel_id] =
- ChannelInfo(channel, channel_thread_task_runner);
+ ChannelInfo(channel, base::MessageLoopProxy::current());
}
channel->SetChannelManager(this);
+}
+
+void ChannelManager::CreateChannel(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ base::Closure callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
+ DCHECK(io_thread_task_runner);
+ DCHECK(!callback.is_null());
+ // (|callback_thread_task_runner| may be null.)
- return channel_id;
+ io_thread_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&ChannelManager::CreateChannelHelper, base::Unretained(this),
+ channel_id, base::Passed(&platform_handle),
+ bootstrap_channel_endpoint, callback,
+ callback_thread_task_runner));
+}
+
+scoped_refptr<Channel> ChannelManager::GetChannel(ChannelId channel_id) const {
+ base::AutoLock locker(lock_);
+ auto it = channel_infos_.find(channel_id);
+ DCHECK(it != channel_infos_.end());
+ return it->second.channel;
}
void ChannelManager::WillShutdownChannel(ChannelId channel_id) {
- GetChannelInfo(channel_id).channel->WillShutdownSoon();
+ GetChannel(channel_id)->WillShutdownSoon();
}
void ChannelManager::ShutdownChannel(ChannelId channel_id) {
@@ -67,11 +103,18 @@ void ChannelManager::ShutdownChannel(ChannelId channel_id) {
ShutdownChannelHelper(channel_info);
}
-ChannelInfo ChannelManager::GetChannelInfo(ChannelId channel_id) {
- base::AutoLock locker(lock_);
- auto it = channel_infos_.find(channel_id);
- DCHECK(it != channel_infos_.end());
- return it->second;
+void ChannelManager::CreateChannelHelper(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
+ base::Closure callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
+ CreateChannelOnIOThread(channel_id, platform_handle.Pass(),
+ bootstrap_channel_endpoint);
+ if (callback_thread_task_runner)
+ callback_thread_task_runner->PostTask(FROM_HERE, callback);
+ else
+ callback.Run();
}
} // namespace system
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.h b/third_party/mojo/src/mojo/edk/system/channel_manager.h
index bb6371b..35a4f27 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.h
@@ -11,35 +11,71 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "base/task_runner.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_info.h"
+namespace base {
+class TaskRunner;
+}
+
namespace mojo {
+
+namespace embedder {
+class PlatformSupport;
+}
+
namespace system {
// IDs for |Channel|s managed by a |ChannelManager|. (IDs should be thought of
// as specific to a given |ChannelManager|.) 0 is never a valid ID.
-//
-// Note: We currently just use the pointer of the |Channel| casted to a
-// |uintptr_t|, but we reserve the right to change this.
-typedef uintptr_t ChannelId;
+typedef uint64_t ChannelId;
+
+const ChannelId kInvalidChannelId = 0;
// This class manages and "owns" |Channel|s (which typically connect to other
-// processes) for a given process. This class is thread-safe.
+// processes) for a given process. This class is thread-safe, except as
+// specifically noted.
class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
public:
- ChannelManager();
+ // |*platform_support| must remain alive longer than this object.
+ explicit ChannelManager(embedder::PlatformSupport* platform_support);
~ChannelManager();
- // Adds |channel| to the set of |Channel|s managed by this |ChannelManager|;
- // |channel_thread_task_runner| should be the task runner for |channel|'s
- // creation (a.k.a. I/O) thread. |channel| should either already be
- // initialized. It should not be managed by any |ChannelManager| yet. Returns
- // the ID for the added channel.
- ChannelId AddChannel(
- scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner);
+ // Creates a |Channel| and adds it to the set of channels managed by this
+ // |ChannelManager|. |channel_id| should be a valid |ChannelId| (i.e.,
+ // nonzero) not "assigned" to any other |Channel| being managed by this
+ // |ChannelManager|.
+ // TODO(vtl): Currently, this should be called on any I/O thread (which will
+ // become the new channel's "channel thread"). Eventually, the channel manager
+ // will have an assigned I/O thread, on which this must be called.
+ // TODO(vtl): Probably this should return a message pipe dispatcher (for the
+ // bootstrap message pipe) instead.
+ void CreateChannelOnIOThread(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint);
+
+ // Like |CreateChannelOnIOThread()|, but may be called from any thread. On
+ // completion, will call |callback| ("on" |io_thread_task_runner| if
+ // |callback_thread_task_runner| is null else by posting to using
+ // |callback_thread_task_runner|). Note: This will always post a task to the
+ // I/O thread, even if |io_thread_task_runner| is the task runner for the
+ // current thread.
+ // TODO(vtl): The |io_thread_task_runner| argument is temporary (we should use
+ // the channel manager's I/O thread).
+ // TODO(vtl): Probably this should return a message pipe dispatcher (for the
+ // bootstrap message pipe) instead.
+ void CreateChannel(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ base::Closure callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+
+ // Gets the |Channel| with the given ID (which must exist).
+ scoped_refptr<Channel> GetChannel(ChannelId channel_id) const;
// Informs the channel manager (and thus channel) that it will be shutdown
// soon (by calling |ShutdownChannel()|). Calling this is optional (and may in
@@ -50,28 +86,26 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
// Shuts down the channel specified by the given ID. It is up to the caller to
// guarantee that this is only called once per channel (that was added using
- // |AddChannel()|). If called from the chanel's creation thread (i.e.,
- // |base::MessageLoopProxy::current()| is the channel thread's |TaskRunner|),
- // this will complete synchronously.
+ // |CreateChannelOnIOThread()|). If called from the channel's creation thread
+ // (i.e., |base::MessageLoopProxy::current()| is the channel thread's
+ // |TaskRunner|), this will complete synchronously.
void ShutdownChannel(ChannelId channel_id);
private:
- // Gets the ID for a given channel.
- //
- // Note: This is currently a static method and thus may be called under
- // |lock_|. If this is ever made non-static (i.e., made specific to a given
- // |ChannelManager|), those call sites may have to changed.
- static ChannelId GetChannelId(const Channel* channel) {
- return reinterpret_cast<ChannelId>(channel);
- }
-
- // Gets the |ChannelInfo| for the channel specified by the given ID. (This
- // should *not* be called under lock.)
- ChannelInfo GetChannelInfo(ChannelId channel_id);
+ void CreateChannelHelper(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
+ base::Closure callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+
+ embedder::PlatformSupport* const platform_support_;
// Note: |Channel| methods should not be called under |lock_|.
- base::Lock lock_; // Protects the members below.
+ mutable base::Lock lock_; // Protects the members below.
+ // TODO(vtl): Once we give the |ChannelManager| one single I/O thread, we can
+ // get rid of |ChannelInfo| (and just have ref pointers to |Channel|s).
base::hash_map<ChannelId, ChannelInfo> channel_infos_;
DISALLOW_COPY_AND_ASSIGN(ChannelManager);
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
index 52f3f0e..c5aa503 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
@@ -17,6 +17,8 @@
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/channel.h"
+#include "mojo/edk/system/channel_endpoint.h"
+#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
@@ -42,19 +44,20 @@ class ChannelManagerTest : public testing::Test {
};
TEST_F(ChannelManagerTest, Basic) {
- ChannelManager cm;
-
- // Hang on to a ref to the |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to it.
- scoped_refptr<Channel> ch(new Channel(platform_support()));
- ASSERT_TRUE(ch->HasOneRef());
+ ChannelManager cm(platform_support());
embedder::PlatformChannelPair channel_pair;
- ch->Init(RawChannel::Create(channel_pair.PassServerHandle()));
- ChannelId id = cm.AddChannel(ch, base::MessageLoopProxy::current());
- EXPECT_NE(id, 0u);
- // |ChannelManager| should take a ref.
+ scoped_refptr<ChannelEndpoint> cep;
+ scoped_refptr<MessagePipeDispatcher> d =
+ MessagePipeDispatcher::CreateRemoteMessagePipe(&cep);
+ const ChannelId id = 1;
+ cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle(), cep);
+ cep = nullptr;
+
+ scoped_refptr<Channel> ch = cm.GetChannel(id);
+ EXPECT_TRUE(ch);
+ // |ChannelManager| should have a ref.
EXPECT_FALSE(ch->HasOneRef());
cm.WillShutdownChannel(id);
@@ -65,30 +68,34 @@ TEST_F(ChannelManagerTest, Basic) {
// On the "I/O" thread, so shutdown should happen synchronously.
// |ChannelManager| should have given up its ref.
EXPECT_TRUE(ch->HasOneRef());
+
+ EXPECT_EQ(MOJO_RESULT_OK, d->Close());
}
TEST_F(ChannelManagerTest, TwoChannels) {
- ChannelManager cm;
-
- // Hang on to a ref to each |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to them.
- scoped_refptr<Channel> ch1(new Channel(platform_support()));
- ASSERT_TRUE(ch1->HasOneRef());
- scoped_refptr<Channel> ch2(new Channel(platform_support()));
- ASSERT_TRUE(ch2->HasOneRef());
+ ChannelManager cm(platform_support());
embedder::PlatformChannelPair channel_pair;
- ch1->Init(RawChannel::Create(channel_pair.PassServerHandle()));
- ch2->Init(RawChannel::Create(channel_pair.PassClientHandle()));
- ChannelId id1 = cm.AddChannel(ch1, base::MessageLoopProxy::current());
- EXPECT_NE(id1, 0u);
- EXPECT_FALSE(ch1->HasOneRef());
+ scoped_refptr<ChannelEndpoint> cep1;
+ scoped_refptr<MessagePipeDispatcher> d1 =
+ MessagePipeDispatcher::CreateRemoteMessagePipe(&cep1);
+ const ChannelId id1 = 1;
+ cm.CreateChannelOnIOThread(id1, channel_pair.PassServerHandle(), cep1);
+ cep1 = nullptr;
+
+ scoped_refptr<ChannelEndpoint> cep2;
+ scoped_refptr<MessagePipeDispatcher> d2 =
+ MessagePipeDispatcher::CreateRemoteMessagePipe(&cep2);
+ const ChannelId id2 = 2;
+ cm.CreateChannelOnIOThread(id2, channel_pair.PassClientHandle(), cep2);
+ cep2 = nullptr;
- ChannelId id2 = cm.AddChannel(ch2, base::MessageLoopProxy::current());
- EXPECT_NE(id2, 0u);
- EXPECT_NE(id2, id1);
- EXPECT_FALSE(ch2->HasOneRef());
+ scoped_refptr<Channel> ch1 = cm.GetChannel(id1);
+ EXPECT_TRUE(ch1);
+
+ scoped_refptr<Channel> ch2 = cm.GetChannel(id2);
+ EXPECT_TRUE(ch2);
// Calling |WillShutdownChannel()| multiple times (on |id1|) is okay.
cm.WillShutdownChannel(id1);
@@ -100,45 +107,47 @@ TEST_F(ChannelManagerTest, TwoChannels) {
EXPECT_TRUE(ch1->HasOneRef());
cm.ShutdownChannel(id2);
EXPECT_TRUE(ch2->HasOneRef());
+
+ EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
+ EXPECT_EQ(MOJO_RESULT_OK, d2->Close());
}
class OtherThread : public base::SimpleThread {
public:
- // Note: We rely on the main thread keeping *exactly one* reference to
- // |channel|.
+ // Note: There should be no other refs to the channel identified by
+ // |channel_id| outside the channel manager.
OtherThread(scoped_refptr<base::TaskRunner> task_runner,
ChannelManager* channel_manager,
- Channel* channel,
+ ChannelId channel_id,
base::Closure quit_closure)
: base::SimpleThread("other_thread"),
task_runner_(task_runner),
channel_manager_(channel_manager),
- channel_(channel),
+ channel_id_(channel_id),
quit_closure_(quit_closure) {}
~OtherThread() override {}
private:
void Run() override {
- // See comment above constructor.
- ASSERT_TRUE(channel_->HasOneRef());
+ // TODO(vtl): Once we have a way of creating a channel from off the I/O
+ // thread, do that here instead.
- ChannelId id = channel_manager_->AddChannel(make_scoped_refptr(channel_),
- task_runner_);
- EXPECT_NE(id, 0u);
- // |ChannelManager| should take a ref.
- EXPECT_FALSE(channel_->HasOneRef());
+ // You can use any unique, nonzero value as the ID.
+ scoped_refptr<Channel> ch = channel_manager_->GetChannel(channel_id_);
+ // |ChannelManager| should have a ref.
+ EXPECT_FALSE(ch->HasOneRef());
- channel_manager_->WillShutdownChannel(id);
+ channel_manager_->WillShutdownChannel(channel_id_);
// |ChannelManager| should still have a ref.
- EXPECT_FALSE(channel_->HasOneRef());
+ EXPECT_FALSE(ch->HasOneRef());
- channel_manager_->ShutdownChannel(id);
+ channel_manager_->ShutdownChannel(channel_id_);
// This doesn't happen synchronously, so we "wait" until it does.
- // TODO(vtl): Possibly |Channel| should provide some notification of being
+ // TODO(vtl): Probably |Channel| should provide some notification of being
// shut down.
base::TimeTicks start_time(base::TimeTicks::Now());
for (;;) {
- if (channel_->HasOneRef())
+ if (ch->HasOneRef())
break;
// Check, instead of assert, since if things go wrong, dying is more
@@ -153,29 +162,32 @@ class OtherThread : public base::SimpleThread {
scoped_refptr<base::TaskRunner> task_runner_;
ChannelManager* channel_manager_;
- Channel* channel_;
+ ChannelId channel_id_;
base::Closure quit_closure_;
DISALLOW_COPY_AND_ASSIGN(OtherThread);
};
TEST_F(ChannelManagerTest, CallsFromOtherThread) {
- ChannelManager cm;
-
- // Hang on to a ref to the |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to it.
- scoped_refptr<Channel> ch(new Channel(platform_support()));
- ASSERT_TRUE(ch->HasOneRef());
+ ChannelManager cm(platform_support());
embedder::PlatformChannelPair channel_pair;
- ch->Init(RawChannel::Create(channel_pair.PassServerHandle()));
+
+ scoped_refptr<ChannelEndpoint> cep;
+ scoped_refptr<MessagePipeDispatcher> d =
+ MessagePipeDispatcher::CreateRemoteMessagePipe(&cep);
+ const ChannelId id = 1;
+ cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle(), cep);
+ cep = nullptr;
base::RunLoop run_loop;
- OtherThread thread(base::MessageLoopProxy::current(), &cm, ch.get(),
+ OtherThread thread(base::MessageLoopProxy::current(), &cm, id,
run_loop.QuitClosure());
thread.Start();
run_loop.Run();
thread.Join();
+
+ EXPECT_EQ(MOJO_RESULT_OK, d->Close());
}
} // namespace
diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
index f46c386..2894c65 100644
--- a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
@@ -58,6 +58,11 @@ bool ArePlatformHandlesConnected(const embedder::PlatformHandle& h1,
return true;
}
+bool IsValidSlaveProcessIdentifier(ProcessIdentifier process_identifier) {
+ return process_identifier != kInvalidProcessIdentifier &&
+ process_identifier != kMasterProcessIdentifier;
+}
+
class TestSlaveInfo : public embedder::SlaveInfo {
public:
explicit TestSlaveInfo(const std::string& name) : name_(name) {}
@@ -200,13 +205,15 @@ TEST_F(ConnectionManagerTest, BasicConnectSlaves) {
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
- ProcessIdentifier peer1;
+ ProcessIdentifier peer1 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h1;
EXPECT_TRUE(slave1.Connect(connection_id, &peer1, &h1));
+ EXPECT_TRUE(IsValidSlaveProcessIdentifier(peer1));
EXPECT_TRUE(h1.is_valid());
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_TRUE(slave2.Connect(connection_id, &peer2, &h2));
+ EXPECT_TRUE(IsValidSlaveProcessIdentifier(peer2));
EXPECT_TRUE(h2.is_valid());
// TODO(vtl): If/when I add the ability to get one's own process identifier,
@@ -285,9 +292,10 @@ TEST_F(ConnectionManagerTest, SlaveCancelConnect) {
EXPECT_TRUE(slave2.AllowConnect(connection_id));
EXPECT_TRUE(slave1.CancelConnect(connection_id));
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_FALSE(slave2.Connect(connection_id, &peer2, &h2));
+ EXPECT_EQ(kInvalidProcessIdentifier, peer2);
EXPECT_FALSE(h2.is_valid());
slave1.Shutdown();
@@ -320,9 +328,10 @@ TEST_F(ConnectionManagerTest, ErrorRemovePending) {
master_process_delegate().RunUntilNotified();
EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls());
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_FALSE(slave2.Connect(connection_id, &peer2, &h2));
+ EXPECT_EQ(kInvalidProcessIdentifier, peer2);
EXPECT_FALSE(h2.is_valid());
slave2.Shutdown();
@@ -343,13 +352,15 @@ TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) {
// Currently, the connect-to-self case is signalled by the master not sending
// back a handle.
- ProcessIdentifier peer1;
+ ProcessIdentifier peer1 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h1;
EXPECT_TRUE(slave.Connect(connection_id, &peer1, &h1));
+ EXPECT_TRUE(IsValidSlaveProcessIdentifier(peer1));
EXPECT_FALSE(h1.is_valid());
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_TRUE(slave.Connect(connection_id, &peer2, &h2));
+ EXPECT_TRUE(IsValidSlaveProcessIdentifier(peer2));
EXPECT_FALSE(h2.is_valid());
EXPECT_EQ(peer1, peer2);
@@ -374,10 +385,10 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
- ProcessIdentifier peer1;
+ ProcessIdentifier peer1 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h1;
EXPECT_TRUE(slave1.Connect(connection_id, &peer1, &h1));
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_TRUE(slave2.Connect(connection_id, &peer2, &h2));
@@ -395,9 +406,9 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
h1.reset();
h2.reset();
- ProcessIdentifier second_peer2;
+ ProcessIdentifier second_peer2 = kInvalidProcessIdentifier;
EXPECT_TRUE(slave2.Connect(connection_id, &second_peer2, &h2));
- ProcessIdentifier second_peer1;
+ ProcessIdentifier second_peer1 = kInvalidProcessIdentifier;
EXPECT_TRUE(slave1.Connect(connection_id, &second_peer1, &h1));
EXPECT_EQ(peer1, second_peer1);
@@ -421,13 +432,15 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSlave) {
EXPECT_TRUE(master.AllowConnect(connection_id));
EXPECT_TRUE(slave.AllowConnect(connection_id));
- ProcessIdentifier master_peer;
+ ProcessIdentifier master_peer = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle master_h;
EXPECT_TRUE(master.Connect(connection_id, &master_peer, &master_h));
+ EXPECT_TRUE(IsValidSlaveProcessIdentifier(master_peer));
EXPECT_TRUE(master_h.is_valid());
- ProcessIdentifier slave_peer;
+ ProcessIdentifier slave_peer = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle slave_h;
EXPECT_TRUE(slave.Connect(connection_id, &slave_peer, &slave_h));
+ EXPECT_EQ(kMasterProcessIdentifier, slave_peer);
EXPECT_TRUE(slave_h.is_valid());
EXPECT_NE(master_peer, slave_peer);
@@ -447,13 +460,15 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSelf) {
// Currently, the connect-to-self case is signalled by the master not sending
// back a handle.
- ProcessIdentifier peer1;
+ ProcessIdentifier peer1 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h1;
EXPECT_TRUE(master.Connect(connection_id, &peer1, &h1));
+ EXPECT_EQ(kMasterProcessIdentifier, peer1);
EXPECT_FALSE(h1.is_valid());
- ProcessIdentifier peer2;
+ ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_TRUE(master.Connect(connection_id, &peer2, &h2));
+ EXPECT_EQ(kMasterProcessIdentifier, peer2);
EXPECT_FALSE(h2.is_valid());
EXPECT_EQ(peer1, peer2);
@@ -474,9 +489,10 @@ TEST_F(ConnectionManagerTest, MasterCancelConnect) {
EXPECT_TRUE(slave.AllowConnect(connection_id));
EXPECT_TRUE(master.CancelConnect(connection_id));
- ProcessIdentifier peer;
+ ProcessIdentifier peer = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h;
EXPECT_FALSE(slave.Connect(connection_id, &peer, &h));
+ EXPECT_EQ(kInvalidProcessIdentifier, peer);
EXPECT_FALSE(h.is_valid());
slave.Shutdown();
diff --git a/third_party/mojo/src/mojo/edk/system/core.cc b/third_party/mojo/src/mojo/edk/system/core.cc
index 6189e50..4460088 100644
--- a/third_party/mojo/src/mojo/edk/system/core.cc
+++ b/third_party/mojo/src/mojo/edk/system/core.cc
@@ -78,8 +78,8 @@ namespace system {
// held.
// TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter.
-Core::Core(scoped_ptr<embedder::PlatformSupport> platform_support)
- : platform_support_(platform_support.Pass()) {
+Core::Core(embedder::PlatformSupport* platform_support)
+ : platform_support_(platform_support) {
}
Core::~Core() {
@@ -469,7 +469,7 @@ MojoResult Core::CreateSharedBuffer(
return result;
scoped_refptr<SharedBufferDispatcher> dispatcher;
- result = SharedBufferDispatcher::Create(platform_support(), validated_options,
+ result = SharedBufferDispatcher::Create(platform_support_, validated_options,
num_bytes, &dispatcher);
if (result != MOJO_RESULT_OK) {
DCHECK(!dispatcher);
diff --git a/third_party/mojo/src/mojo/edk/system/core.h b/third_party/mojo/src/mojo/edk/system/core.h
index 0ff9c01..7833193c 100644
--- a/third_party/mojo/src/mojo/edk/system/core.h
+++ b/third_party/mojo/src/mojo/edk/system/core.h
@@ -39,7 +39,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// ---------------------------------------------------------------------------
// These methods are only to be used by via the embedder API (and internally):
- explicit Core(scoped_ptr<embedder::PlatformSupport> platform_support);
+
+ // |*platform_support| must outlive this object.
+ explicit Core(embedder::PlatformSupport* platform_support);
virtual ~Core();
// Adds |dispatcher| to the handle table, returning the handle for it. Returns
@@ -59,12 +61,19 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
base::Callback<void(MojoResult)> callback);
embedder::PlatformSupport* platform_support() const {
- return platform_support_.get();
+ return platform_support_;
}
// ---------------------------------------------------------------------------
- // System calls implementation:
+ // The following methods are essentially implementations of the Mojo Core
+ // functions of the Mojo API, with the C interface translated to C++ by
+ // "mojo/edk/embedder/entrypoints.cc". The best way to understand the contract
+ // of these methods is to look at the header files defining the corresponding
+ // API functions, referenced below.
+
+ // These methods correspond to the API functions defined in
+ // "mojo/public/c/system/functions.h":
MojoTimeTicks GetTimeTicksNow();
MojoResult Close(MojoHandle handle);
MojoResult Wait(MojoHandle handle,
@@ -77,6 +86,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoDeadline deadline,
UserPointer<uint32_t> result_index,
UserPointer<MojoHandleSignalsState> signals_states);
+
+ // These methods correspond to the API functions defined in
+ // "mojo/public/c/system/message_pipe.h":
MojoResult CreateMessagePipe(
UserPointer<const MojoCreateMessagePipeOptions> options,
UserPointer<MojoHandle> message_pipe_handle0,
@@ -93,6 +105,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
UserPointer<MojoHandle> handles,
UserPointer<uint32_t> num_handles,
MojoReadMessageFlags flags);
+
+ // These methods correspond to the API functions defined in
+ // "mojo/public/c/system/data_pipe.h":
MojoResult CreateDataPipe(
UserPointer<const MojoCreateDataPipeOptions> options,
UserPointer<MojoHandle> data_pipe_producer_handle,
@@ -117,6 +132,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoReadDataFlags flags);
MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
uint32_t num_bytes_read);
+
+ // These methods correspond to the API functions defined in
+ // "mojo/public/c/system/buffer.h":
MojoResult CreateSharedBuffer(
UserPointer<const MojoCreateSharedBufferOptions> options,
uint64_t num_bytes,
@@ -146,7 +164,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
uint32_t* result_index,
HandleSignalsState* signals_states);
- const scoped_ptr<embedder::PlatformSupport> platform_support_;
+ embedder::PlatformSupport* const platform_support_;
// TODO(vtl): |handle_table_lock_| should be a reader-writer lock (if only we
// had them).
diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.cc b/third_party/mojo/src/mojo/edk/system/core_test_base.cc
index b81a051..7196886d 100644
--- a/third_party/mojo/src/mojo/edk/system/core_test_base.cc
+++ b/third_party/mojo/src/mojo/edk/system/core_test_base.cc
@@ -9,7 +9,6 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/dispatcher.h"
@@ -173,7 +172,7 @@ CoreTestBase::~CoreTestBase() {
}
void CoreTestBase::SetUp() {
- core_ = new Core(make_scoped_ptr(new embedder::SimplePlatformSupport()));
+ core_ = new Core(&platform_support_);
}
void CoreTestBase::TearDown() {
diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.h b/third_party/mojo/src/mojo/edk/system/core_test_base.h
index c2b5ee2..26b7925 100644
--- a/third_party/mojo/src/mojo/edk/system/core_test_base.h
+++ b/third_party/mojo/src/mojo/edk/system/core_test_base.h
@@ -5,9 +5,9 @@
#ifndef MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
#define MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
-#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/public/c/system/types.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,6 +38,7 @@ class CoreTestBase : public testing::Test {
Core* core() { return core_; }
private:
+ embedder::SimplePlatformSupport platform_support_;
Core* core_;
DISALLOW_COPY_AND_ASSIGN(CoreTestBase);
diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
index b78dfb6..4d7deae 100644
--- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
@@ -20,9 +20,14 @@
namespace mojo {
namespace system {
-const ProcessIdentifier kFirstProcessIdentifier = 1;
-const ProcessIdentifier kMasterProcessIdentifier =
- static_cast<ProcessIdentifier>(-1);
+const ProcessIdentifier kFirstSlaveProcessIdentifier = 2;
+
+static_assert(kMasterProcessIdentifier != kInvalidProcessIdentifier,
+ "Bad master process identifier");
+static_assert(kFirstSlaveProcessIdentifier != kInvalidProcessIdentifier,
+ "Bad first slave process identifier");
+static_assert(kMasterProcessIdentifier != kFirstSlaveProcessIdentifier,
+ "Master and first slave process identifiers are the same");
// MasterConnectionManager::Helper ---------------------------------------------
@@ -218,7 +223,7 @@ MasterConnectionManager::MasterConnectionManager()
: creation_thread_task_runner_(base::MessageLoop::current()->task_runner()),
master_process_delegate_(),
private_thread_("MasterConnectionManagerPrivateThread"),
- next_process_identifier_(kFirstProcessIdentifier) {
+ next_process_identifier_(kFirstSlaveProcessIdentifier) {
DCHECK(creation_thread_task_runner_);
AssertOnCreationThread(); // Just make sure this assertion works correctly.
}
diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
index dcec9c2..978d9fe 100644
--- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
@@ -30,6 +30,9 @@ class SlaveInfo;
namespace system {
+// The master process will always have this "process identifier".
+const ProcessIdentifier kMasterProcessIdentifier = 1;
+
// The |ConnectionManager| implementation for the master process.
//
// Objects of this class must be created, initialized (via |Init()|), shut down
diff --git a/third_party/mojo/src/mojo/edk/test/BUILD.gn b/third_party/mojo/src/mojo/edk/test/BUILD.gn
index b130440..3a15663 100644
--- a/third_party/mojo/src/mojo/edk/test/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/test/BUILD.gn
@@ -76,6 +76,20 @@ mojo_edk_source_set("test_support_impl") {
# Public SDK test targets follow. These targets are not defined within the
# public SDK itself as running the unittests requires the EDK.
+# TODO(vtl): These don't really belong here. (They should be converted to
+# apptests, but even apart from that these targets belong somewhere else.)
+
+group("public_tests") {
+ testonly = true
+ deps = [
+ ":mojo_public_application_unittests",
+ ":mojo_public_bindings_unittests",
+ ":mojo_public_environment_unittests",
+ ":mojo_public_system_perftests",
+ ":mojo_public_system_unittests",
+ ":mojo_public_utility_unittests",
+ ]
+}
test("mojo_public_application_unittests") {
deps = [
diff --git a/third_party/mojo/src/mojo/public/DEPS b/third_party/mojo/src/mojo/public/DEPS
deleted file mode 100644
index 0c679b9..0000000
--- a/third_party/mojo/src/mojo/public/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
- "-base",
- "-build",
- "-mojo",
- "+mojo/public",
-]
diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION
index 55ad309..63d6820 100644
--- a/third_party/mojo/src/mojo/public/VERSION
+++ b/third_party/mojo/src/mojo/public/VERSION
@@ -1 +1 @@
-126532ce21c5c3c55a1e1693731411cb60169efd \ No newline at end of file
+8d45c89c30b230843c5bd6dd0693a555750946c0 \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/c/DEPS b/third_party/mojo/src/mojo/public/c/DEPS
deleted file mode 100644
index 5272770..0000000
--- a/third_party/mojo/src/mojo/public/c/DEPS
+++ /dev/null
@@ -1,16 +0,0 @@
-include_rules = [
- # Require explicit dependencies in each directory.
- "-mojo/public",
- # But everyone can depend on the C system headers.
- "+mojo/public/c/system",
-]
-
-specific_include_rules = {
- r".*_(unit|perf)test\.cc": [
- "+testing",
- # Our test harness is C++, so allow the use of C++:
- "+mojo/public/cpp/system",
- "+mojo/public/cpp/test_support",
- "+mojo/public/cpp/utility",
- ],
-}
diff --git a/third_party/mojo/src/mojo/public/c/gles2/DEPS b/third_party/mojo/src/mojo/public/c/gles2/DEPS
deleted file mode 100644
index 3887457..0000000
--- a/third_party/mojo/src/mojo/public/c/gles2/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/c/environment",
-]
diff --git a/third_party/mojo/src/mojo/public/c/system/buffer.h b/third_party/mojo/src/mojo/public/c/system/buffer.h
index 97bc340..45d2c2d 100644
--- a/third_party/mojo/src/mojo/public/c/system/buffer.h
+++ b/third_party/mojo/src/mojo/public/c/system/buffer.h
@@ -169,9 +169,9 @@ MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle,
MojoMapBufferFlags flags);
// Unmaps a buffer pointer that was mapped by |MojoMapBuffer()|. |buffer| must
-// have been the result of |MojoMapBuffer()| (not some pointer strictly inside
+// have been the result of |MojoMapBuffer()| (not some other pointer inside
// the mapped memory), and the entire mapping will be removed (partial unmapping
-// is not supported). A mapping may only be unmapped exactly once.
+// is not supported). A mapping may only be unmapped once.
//
// Returns:
// |MOJO_RESULT_OK| on success.
diff --git a/third_party/mojo/src/mojo/public/c/system/data_pipe.h b/third_party/mojo/src/mojo/public/c/system/data_pipe.h
index 089ead3..86126c1 100644
--- a/third_party/mojo/src/mojo/public/c/system/data_pipe.h
+++ b/third_party/mojo/src/mojo/public/c/system/data_pipe.h
@@ -81,8 +81,8 @@ const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE = 1 << 0;
// elements.
// |MOJO_READ_DATA_FLAG_QUERY| - Query the number of elements available to
// read. For use with |MojoReadData()| only. Mutually exclusive with
-// |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is
-// ignored if this flag is set.
+// |MOJO_READ_DATA_FLAG_DISCARD|, and |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+// is ignored if this flag is set.
// |MOJO_READ_DATA_FLAG_PEEK| - Read elements without removing them. For use
// with |MojoReadData()| only. Mutually exclusive with
// |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_QUERY|.
@@ -264,8 +264,8 @@ MOJO_SYSTEM_EXPORT MojoResult
// available to future reads.
//
// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to
-// |*num_bytes| (which again be a multiple of the element size) bytes of data,
-// setting |*num_bytes| to the amount actually discarded. If flags has
+// |*num_bytes| (which again must be a multiple of the element size) bytes of
+// data, setting |*num_bytes| to the amount actually discarded. If flags has
// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly
// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY|
// must not be set, and |elements| is ignored (and should typically be set to
diff --git a/third_party/mojo/src/mojo/public/c/system/functions.h b/third_party/mojo/src/mojo/public/c/system/functions.h
index 5e0a0c4..c53a4ed 100644
--- a/third_party/mojo/src/mojo/public/c/system/functions.h
+++ b/third_party/mojo/src/mojo/public/c/system/functions.h
@@ -9,8 +9,6 @@
#ifndef MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_
#define MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_
-// Note: This header should be compilable as C.
-
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/c/system/types.h"
@@ -25,9 +23,12 @@ extern "C" {
// operation's success/failure. E.g., a separate |flags| parameter may control
// whether a given "in/out" parameter is used for input, output, or both.)
-// Platform-dependent monotonically increasing tick count representing "right
-// now." The resolution of this clock is ~1-15ms. Resolution varies depending
-// on hardware/operating system configuration.
+// Returns the time, in microseconds, since some undefined point in the past.
+// The values are only meaningful relative to other values that were obtained
+// from the same device without an intervening system restart. Such values are
+// guaranteed to be monotonically-increasing with the passage of real time.
+// Although the units are microseconds, the resolution of the clock may vary and
+// is typically in the range of ~1-15 ms.
MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void);
// Closes the given |handle|.
@@ -71,7 +72,7 @@ MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle);
// end of a message pipe and the other end is closed).
//
// If there are multiple waiters (on different threads, obviously) waiting on
-// the same handle and signal, and that signal becomes is satisfied, all waiters
+// the same handle and signal, and that signal becomes satisfied, all waiters
// will be awoken.
MOJO_SYSTEM_EXPORT MojoResult
MojoWait(MojoHandle handle,
diff --git a/third_party/mojo/src/mojo/public/c/system/message_pipe.h b/third_party/mojo/src/mojo/public/c/system/message_pipe.h
index 97d8887..d42c3fc 100644
--- a/third_party/mojo/src/mojo/public/c/system/message_pipe.h
+++ b/third_party/mojo/src/mojo/public/c/system/message_pipe.h
@@ -90,8 +90,6 @@ extern "C" {
// |*options| is invalid).
// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
// been reached.
-//
-// TODO(vtl): Add an options struct pointer argument.
MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe(
const struct MojoCreateMessagePipeOptions* options, // Optional.
MojoHandle* message_pipe_handle0, // Out.
@@ -118,7 +116,7 @@ MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe(
// latter case).
// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
// Note that closing an endpoint is not necessarily synchronous (e.g.,
-// across processes), so this function may be succeed even if the other
+// across processes), so this function may succeed even if the other
// endpoint has been closed (in which case the message would be dropped).
// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|.
// |MOJO_RESULT_BUSY| if some handle to be sent is currently in use.
@@ -133,37 +131,37 @@ MOJO_SYSTEM_EXPORT MojoResult
uint32_t num_handles,
MojoWriteMessageFlags flags);
-// Reads a message from the message pipe endpoint given by
-// |message_pipe_handle|; also usable to query the size of the next message or
-// discard the next message. |bytes|/|*num_bytes| indicate the buffer/buffer
-// size to receive the message data (if any) and |handles|/|*num_handles|
-// indicate the buffer/maximum handle count to receive the attached handles (if
-// any).
-//
-// |num_bytes| and |num_handles| are optional "in-out" parameters. If non-null,
-// on return |*num_bytes| and |*num_handles| will usually indicate the number
-// of bytes and number of attached handles in the "next" message, respectively,
-// whether that message was read or not. (If null, the number of bytes/handles
-// is treated as zero.)
+// Reads the next message from a message pipe, or indicates the size of the
+// message if it cannot fit in the provided buffers. The message will be read
+// in its entirety or not at all; if it is not, it will remain enqueued unless
+// the |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| flag was passed. At most one
+// message will be consumed from the queue, and the return value will indicate
+// whether a message was successfully read.
//
-// If |bytes| is null, then |*num_bytes| must be zero, and similarly for
-// |handles| and |*num_handles|.
+// |num_bytes| and |num_handles| are optional in/out parameters that on input
+// must be set to the sizes of the |bytes| and |handles| arrays, and on output
+// will be set to the actual number of bytes or handles contained in the
+// message (even if the message was not retrieved due to being too large).
+// Either |num_bytes| or |num_handles| may be null if the message is not
+// expected to contain the corresponding type of data, but such a call would
+// fail with |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message in fact did
+// contain that type of data.
//
-// Partial reads are NEVER done. Either a full read is done and |MOJO_RESULT_OK|
-// returned, or the read is NOT done and |MOJO_RESULT_RESOURCE_EXHAUSTED| is
-// returned (if |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| was set, the message is
-// also discarded in this case).
+// |bytes| and |handles| will receive the contents of the message, if it is
+// retrieved. Either or both may be null, in which case the corresponding size
+// parameter(s) must also be set to zero or passed as null.
//
// Returns:
// |MOJO_RESULT_OK| on success (i.e., a message was actually read).
// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid.
// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
-// |MOJO_RESULT_RESOURCE_EXHAUSTED| if one of the buffers to receive the
-// message/attached handles (|bytes|/|*num_bytes| or
-// |handles|/|*num_handles|) was too small. (TODO(vtl): Reconsider this
-// error code; should distinguish this from the hitting-system-limits
-// case.)
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message was too large to fit in the
+// provided buffer(s). The message will have been left in the queue or
+// discarded, depending on flags.
// |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read.
+//
+// TODO(vtl): Reconsider the |MOJO_RESULT_RESOURCE_EXHAUSTED| error code; should
+// distinguish this from the hitting-system-limits case.
MOJO_SYSTEM_EXPORT MojoResult
MojoReadMessage(MojoHandle message_pipe_handle,
void* bytes, // Optional out.
diff --git a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
index 2f3ef62..71e61f4 100644
--- a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
+++ b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
@@ -109,6 +109,9 @@ TEST(CoreTest, BasicMessagePipe) {
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
EXPECT_EQ(kSignalAll, state.satisfiable_signals);
+ // Last parameter is optional.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, NULL));
+
// Try to read.
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
diff --git a/third_party/mojo/src/mojo/public/c/system/types.h b/third_party/mojo/src/mojo/public/c/system/types.h
index a88b024..9f85fbb 100644
--- a/third_party/mojo/src/mojo/public/c/system/types.h
+++ b/third_party/mojo/src/mojo/public/c/system/types.h
@@ -17,7 +17,8 @@
// TODO(vtl): Notes: Use of undefined flags will lead to undefined behavior
// (typically they'll be ignored), not necessarily an error.
-// |MojoTimeTicks|: Used to specify time ticks. Value is in microseconds.
+// |MojoTimeTicks|: A time delta, in microseconds, the meaning of which is
+// source-dependent.
typedef int64_t MojoTimeTicks;
diff --git a/third_party/mojo/src/mojo/public/cpp/DEPS b/third_party/mojo/src/mojo/public/cpp/DEPS
deleted file mode 100644
index 74acd7c..0000000
--- a/third_party/mojo/src/mojo/public/cpp/DEPS
+++ /dev/null
@@ -1,18 +0,0 @@
-include_rules = [
- # Require explicit dependencies in each directory.
- "-mojo/public",
- # But everyone can depend on the C and C++ system headers.
- "+mojo/public/c/system",
- "+mojo/public/cpp/system",
- # Ditto for the C environment headers (but not the C++ environment, since it
- # has dependencies of its own).
- "+mojo/public/c/environment",
-]
-
-specific_include_rules = {
- r".*_(unit|perf)test\.cc": [
- "+testing",
- "+mojo/public/cpp/test_support",
- "+mojo/public/cpp/utility",
- ],
-}
diff --git a/third_party/mojo/src/mojo/public/cpp/README.md b/third_party/mojo/src/mojo/public/cpp/README.md
index 8f03d98..4404c24 100644
--- a/third_party/mojo/src/mojo/public/cpp/README.md
+++ b/third_party/mojo/src/mojo/public/cpp/README.md
@@ -8,7 +8,7 @@ subdirectories of the same name, under mojo/public/c/). Typically, these
wrappers provide increased convenience and/or type-safety.
Other subdirectories provide support (static) libraries of various sorts. In
-this case, the organization is to have the public interface for the library in
+this case, the organization is to have the public interface for the library
defined in header files in the subdirectory itself and the implementation of the
library at a lower level, under a lib (sub)subdirectory. A developer should be
able to substitute their own implementation of any such support library, and
diff --git a/third_party/mojo/src/mojo/public/cpp/application/DEPS b/third_party/mojo/src/mojo/public/cpp/application/DEPS
deleted file mode 100644
index 503eebc..0000000
--- a/third_party/mojo/src/mojo/public/cpp/application/DEPS
+++ /dev/null
@@ -1,11 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/bindings",
- "+mojo/public/cpp/environment",
- "+mojo/public/interfaces/application",
- "+mojo/public/interfaces/service_provider",
-]
-specific_include_rules = {
- r"application_test_base\.h": [
- "+testing/gtest/include/gtest",
- ],
-} \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
index bb92307..46d368d 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
@@ -79,20 +79,15 @@ class ApplicationImpl : public Application {
// Block until the Application is initialized, if it is not already.
void WaitForInitialize();
- // Unbinds the Shell and Application connections. Must be called after
- // Initialize.
+ // Unbinds the Shell and Application connections. Can be used to re-bind the
+ // handles to another implementation of ApplicationImpl, for instance when
+ // running apptests.
void UnbindConnections(InterfaceRequest<Application>* application_request,
ShellPtr* shell);
// Quits the main run loop for this application.
static void Terminate();
- protected:
- // Application implementation.
- void AcceptConnection(const String& requestor_url,
- InterfaceRequest<ServiceProvider> services,
- ServiceProviderPtr exposed_services) override;
-
private:
class ShellPtrWatcher;
@@ -103,11 +98,15 @@ class ApplicationImpl : public Application {
Terminate();
}
+ // Application implementation.
+ void AcceptConnection(const String& requestor_url,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services) override;
+
void RequestQuit() override;
typedef std::vector<internal::ServiceRegistry*> ServiceRegistryList;
- bool initialized_;
ServiceRegistryList incoming_service_registries_;
ServiceRegistryList outgoing_service_registries_;
ApplicationDelegate* delegate_;
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/DEPS b/third_party/mojo/src/mojo/public/cpp/application/lib/DEPS
deleted file mode 100644
index a04ed0f..0000000
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/utility",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
index 4d1f8dc..c66dbb5 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
+++ b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
@@ -26,8 +26,7 @@ class ApplicationImpl::ShellPtrWatcher : public ErrorHandler {
ApplicationImpl::ApplicationImpl(ApplicationDelegate* delegate,
InterfaceRequest<Application> request)
- : initialized_(false),
- delegate_(delegate),
+ : delegate_(delegate),
binding_(this, request.Pass()),
shell_watch_(nullptr) {
}
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
index 72058a4..ba6dd3f 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
+++ b/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
@@ -42,7 +42,7 @@ class ShellAndArgumentGrabber : public Application {
void WaitForInitialize() {
// Initialize is always the first call made on Application.
- binding_.WaitForIncomingMethodCall();
+ MOJO_CHECK(binding_.WaitForIncomingMethodCall());
}
private:
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/service_registry.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/service_registry.cc
index d934a16..01c6c70 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/service_registry.cc
+++ b/third_party/mojo/src/mojo/public/cpp/application/lib/service_registry.cc
@@ -18,8 +18,10 @@ ServiceRegistry::ServiceRegistry(
InterfaceRequest<ServiceProvider> local_services)
: application_impl_(application_impl),
url_(url),
- local_binding_(this, local_services.Pass()),
+ local_binding_(this),
remote_service_provider_(remote_services.Pass()) {
+ if (local_services.is_pending())
+ local_binding_.Bind(local_services.Pass());
}
ServiceRegistry::ServiceRegistry()
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/DEPS b/third_party/mojo/src/mojo/public/cpp/bindings/DEPS
deleted file mode 100644
index 2a0496e..0000000
--- a/third_party/mojo/src/mojo/public/cpp/bindings/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/environment",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/DEPS b/third_party/mojo/src/mojo/public/cpp/bindings/lib/DEPS
deleted file mode 100644
index b809b58..0000000
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/bindings",
- "+mojo/public/cpp/environment",
- "+mojo/public/cpp/system",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/string.h b/third_party/mojo/src/mojo/public/cpp/bindings/string.h
index ba0d8fa8..e0ed4ba 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/string.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/string.h
@@ -13,6 +13,9 @@
namespace mojo {
+// A UTF-8 encoded character string that can be null. Provides functions that
+// are similar to std::string, along with access to the underlying std::string
+// object.
class String {
public:
typedef internal::String_Data Data_;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h b/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
index a420fa5..04a8130 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
@@ -25,6 +25,7 @@ class StructHelper {
} // namespace internal
+// Smart pointer wrapping a mojom structure with move-only semantics.
template <typename Struct>
class StructPtr {
MOJO_MOVE_ONLY_TYPE(StructPtr)
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/DEPS b/third_party/mojo/src/mojo/public/cpp/bindings/tests/DEPS
deleted file mode 100644
index b99d520..0000000
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/environment",
- "+mojo/public/interfaces/bindings/tests",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/DEPS b/third_party/mojo/src/mojo/public/cpp/environment/DEPS
deleted file mode 100644
index 04346d9..0000000
--- a/third_party/mojo/src/mojo/public/cpp/environment/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/bindings/callback.h",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/DEPS b/third_party/mojo/src/mojo/public/cpp/environment/lib/DEPS
deleted file mode 100644
index 1889e1f..0000000
--- a/third_party/mojo/src/mojo/public/cpp/environment/lib/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/environment",
- "+mojo/public/cpp/utility",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/test_support/DEPS b/third_party/mojo/src/mojo/public/cpp/test_support/DEPS
deleted file mode 100644
index 6dc5394..0000000
--- a/third_party/mojo/src/mojo/public/cpp/test_support/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/c/test_support",
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/utility/DEPS b/third_party/mojo/src/mojo/public/cpp/utility/DEPS
deleted file mode 100644
index a9dfbd1..0000000
--- a/third_party/mojo/src/mojo/public/cpp/utility/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/bindings/callback.h"
-]
diff --git a/third_party/mojo/src/mojo/public/cpp/utility/run_loop.h b/third_party/mojo/src/mojo/public/cpp/utility/run_loop.h
index 5ebe63e..4673eaa 100644
--- a/third_party/mojo/src/mojo/public/cpp/utility/run_loop.h
+++ b/third_party/mojo/src/mojo/public/cpp/utility/run_loop.h
@@ -15,6 +15,8 @@ namespace mojo {
class RunLoopHandler;
+// Watches handles for signals and calls event handlers when they occur. Also
+// executes delayed tasks. This class should only be used by a single thread.
class RunLoop {
public:
RunLoop();
@@ -31,8 +33,17 @@ class RunLoop {
// created.
static RunLoop* current();
- // Registers a RunLoopHandler for the specified handle. Only one handler can
- // be registered for a specified handle.
+ // Registers a RunLoopHandler for the specified handle. It is an error to
+ // register more than one handler for a handle, and crashes the process.
+ //
+ // The handler's OnHandleReady() method is invoked after one of the signals in
+ // |handle_signals| occurs. Note that the handler remains registered until
+ // explicitly removed or an error occurs.
+ //
+ // The handler's OnHandleError() method is invoked if the deadline elapses, an
+ // error is detected, or the RunLoop is being destroyed. The handler is
+ // automatically unregistered before calling OnHandleError(), so it will not
+ // receive any further notifications.
void AddHandler(RunLoopHandler* handler,
const Handle& handle,
MojoHandleSignals handle_signals,
diff --git a/third_party/mojo/src/mojo/public/dart/DEPS b/third_party/mojo/src/mojo/public/dart/DEPS
deleted file mode 100644
index 53d0007..0000000
--- a/third_party/mojo/src/mojo/public/dart/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+dart",
- "+base",
-] \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/dart/core.dart b/third_party/mojo/src/mojo/public/dart/core.dart
index ecd671d..6cdbe26 100644
--- a/third_party/mojo/src/mojo/public/dart/core.dart
+++ b/third_party/mojo/src/mojo/public/dart/core.dart
@@ -16,6 +16,5 @@ part 'src/event_stream.dart';
part 'src/handle.dart';
part 'src/handle_watcher.dart';
part 'src/message_pipe.dart';
-part 'src/timer_impl.dart';
part 'src/timer_queue.dart';
part 'src/types.dart';
diff --git a/third_party/mojo/src/mojo/public/dart/rules.gni b/third_party/mojo/src/mojo/public/dart/rules.gni
new file mode 100644
index 0000000..aea59e3
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/dart/rules.gni
@@ -0,0 +1,112 @@
+# Copyright 2015 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.
+
+# Rules to generate python packaged applications for Dart
+
+import("../mojo_sdk.gni")
+
+template("dart_package") {
+ action(target_name) {
+ script = rebase_path("mojo/public/tools/gn/zip.py", ".", mojo_root)
+
+ inputs = invoker.sources
+
+ deps = []
+ zip_inputs = []
+
+ if (defined(invoker.deps)) {
+ deps += invoker.deps
+ foreach(d, invoker.deps) {
+ dep_name = get_label_info(d, "name")
+ dep_target_out_dir = get_label_info(d, "target_out_dir")
+ zip_inputs += [ "$dep_target_out_dir/$dep_name.dartzip" ]
+ }
+ }
+
+ if (defined(invoker.datadeps)) {
+ datadeps = invoker.datadeps
+ }
+
+ output = "$target_out_dir/$target_name.dartzip"
+ outputs = [
+ output,
+ ]
+
+ rebase_base_dir =
+ rebase_path(get_label_info(":$target_name", "dir"), root_build_dir)
+ rebase_inputs = rebase_path(inputs, root_build_dir)
+ rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir)
+ rebase_output = rebase_path(output, root_build_dir)
+ args = [
+ "--base-dir=$rebase_base_dir",
+ "--inputs=$rebase_inputs",
+ "--zip-inputs=$rebase_zip_inputs",
+ "--output=$rebase_output",
+ ]
+ }
+}
+
+# Use this template to generate a .mojo dart application. One of the source
+# files should be named main.dart and contain a main function as the
+# entry point. Dependencies of dart_packaged_application targets should be
+# either mojom targets (and specified using the mojom_deps variable) or
+# dart_package targets.
+template("dart_packaged_application") {
+ package_name = "${target_name}_package"
+ package_output = "$target_out_dir/$package_name.dartzip"
+
+ if (defined(invoker.output_name)) {
+ mojo_output = "$root_out_dir/" + invoker.output_name + ".mojo"
+ } else {
+ mojo_output = "$root_out_dir/" + target_name + ".mojo"
+ }
+
+ dart_package(package_name) {
+ sources = invoker.sources
+ if (defined(invoker.deps)) {
+ deps = invoker.deps
+ }
+ if (defined(invoker.mojom_deps)) {
+ mojom_deps = invoker.mojom_deps
+ }
+ if (defined(invoker.datadeps)) {
+ datadeps = invoker.datadeps
+ }
+ }
+
+ action(target_name) {
+ script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_root)
+
+ input = package_output
+ inputs = [
+ input,
+ ]
+
+ output = mojo_output
+ outputs = [
+ output,
+ ]
+
+ deps = [
+ ":$package_name",
+ ]
+ if (defined(invoker.deps)) {
+ deps += invoker.deps
+ }
+ if (defined(invoker.mojom_deps)) {
+ deps += invoker.mojom_deps
+ }
+ if (defined(invoker.datadeps)) {
+ datadeps = invoker.datadeps
+ }
+
+ rebase_input = rebase_path(input, root_build_dir)
+ rebase_output = rebase_path(output, root_build_dir)
+ args = [
+ "--input=$rebase_input",
+ "--output=$rebase_output",
+ "--line=#!mojo mojo:dart_content_handler",
+ ]
+ }
+}
diff --git a/third_party/mojo/src/mojo/public/dart/src/application.dart b/third_party/mojo/src/mojo/public/dart/src/application.dart
index 55002f5e..2819625 100644
--- a/third_party/mojo/src/mojo/public/dart/src/application.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/application.dart
@@ -33,7 +33,7 @@ class _ApplicationImpl extends application_mojom.Application {
void requestQuit() => _application._requestQuitAndClose();
- void close() => shell.close();
+ void close({bool nodefer: false}) => shell.close();
}
// TODO(zra): Better documentation and examples.
diff --git a/third_party/mojo/src/mojo/public/dart/src/codec.dart b/third_party/mojo/src/mojo/public/dart/src/codec.dart
index 7ad8370..268daee 100644
--- a/third_party/mojo/src/mojo/public/dart/src/codec.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/codec.dart
@@ -18,6 +18,12 @@ const int kElementNullable = (1 << 1);
bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
+class MojoCodecError {
+ final String message;
+ MojoCodecError(this.message);
+ String toString() => message;
+}
+
class _EncoderBuffer {
ByteData buffer;
List<core.MojoHandle> handles;
@@ -88,7 +94,7 @@ class Encoder {
void encodeUint8(int value, int offset) {
if (value < 0) {
- throw '$kErrorUnsigned: $val';
+ throw new MojoCodecError('$kErrorUnsigned: $val');
}
_buffer.buffer.setUint8(_base + offset, value);
}
@@ -98,7 +104,7 @@ class Encoder {
void encodeUint16(int value, int offset) {
if (value < 0) {
- throw '$kErrorUnsigned: $val';
+ throw new MojoCodecError('$kErrorUnsigned: $val');
}
_buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
@@ -108,7 +114,7 @@ class Encoder {
void encodeUint32(int value, int offset) {
if (value < 0) {
- throw '$kErrorUnsigned: $val';
+ throw new MojoCodecError('$kErrorUnsigned: $val');
}
_buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
@@ -118,7 +124,7 @@ class Encoder {
void encodeUint64(int value, int offset) {
if (value < 0) {
- throw '$kErrorUnsigned: $val';
+ throw new MojoCodecError('$kErrorUnsigned: $val');
}
_buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
@@ -176,14 +182,16 @@ class Encoder {
void encodeNullPointer(int offset, bool nullable) {
if (!nullable) {
- throw 'Trying to encode a null pointer for a non-nullable type';
+ throw new MojoCodecError(
+ 'Trying to encode a null pointer for a non-nullable type');
}
_buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN);
}
void encodeInvalideHandle(int offset, bool nullable) {
if (!nullable) {
- throw 'Trying to encode a null pointer for a non-nullable type';
+ throw new MojoCodecError(
+ 'Trying to encode a null pointer for a non-nullable type');
}
_buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN);
}
@@ -207,7 +215,8 @@ class Encoder {
int elementSize, int length, int offset, int expectedLength) {
if ((expectedLength != kUnspecifiedArrayLength) &&
(expectedLength != length)) {
- throw 'Trying to encode a fixed array of incorrect length';
+ throw new MojoCodecError(
+ 'Trying to encode a fixed array of incorrect length');
}
return encoderForArrayByTotalSize(length * elementSize, length, offset);
}
@@ -226,7 +235,8 @@ class Encoder {
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(expectedLength != value.length)) {
- throw 'Trying to encode a fixed array of incorrect size.';
+ throw new MojoCodecError(
+ 'Trying to encode a fixed array of incorrect size.');
}
var bytes = new Uint8List((value.length + 7) ~/ kAlignment);
for (int i = 0; i < bytes.length; ++i) {
@@ -411,34 +421,34 @@ class Encoder {
}
void appendInt8Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Int8List.fromList(value)));
+ appendBytes(new Uint8List.view(new Int8List.fromList(value).buffer));
void appendUint8Array(List<int> value) =>
appendBytes(new Uint8List.fromList(value));
void appendInt16Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Int16List.fromList(value)));
+ appendBytes(new Uint8List.view(new Int16List.fromList(value).buffer));
void appendUint16Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Uint16List.fromList(value)));
+ appendBytes(new Uint8List.view(new Uint16List.fromList(value).buffer));
void appendInt32Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Int32List.fromList(value)));
+ appendBytes(new Uint8List.view(new Int32List.fromList(value).buffer));
void appendUint32Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Uint32List.fromList(value)));
+ appendBytes(new Uint8List.view(new Uint32List.fromList(value).buffer));
void appendInt64Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Int64List.fromList(value)));
+ appendBytes(new Uint8List.view(new Int64List.fromList(value).buffer));
void appendUint64Array(List<int> value) =>
- appendBytes(new Uint8List.view(new Uint64List.fromList(value)));
+ appendBytes(new Uint8List.view(new Uint64List.fromList(value).buffer));
void appendFloatArray(List<int> value) =>
- appendBytes(new Uint8List.view(new Float32List.fromList(value)));
+ appendBytes(new Uint8List.view(new Float32List.fromList(value).buffer));
void appendDoubleArray(List<int> value) =>
- appendBytes(new Uint8List.view(new Float64List.fromList(value)));
+ appendBytes(new Uint8List.view(new Float64List.fromList(value).buffer));
Encoder encoderForMap(int offset) {
encodePointerToNextUnclaimed(offset);
@@ -447,16 +457,59 @@ class Encoder {
}
+class _Validator {
+ final int _maxMemory;
+ final int _numberOfHandles;
+ int _minNextClaimedHandle = 0;
+ int _minNextMemory = 0;
+
+ _Validator(this._maxMemory, this._numberOfHandles);
+
+ void claimHandle(int handle) {
+ if (handle < _minNextClaimedHandle) {
+ throw new MojoCodecError('Trying to access handle out of order.');
+ }
+ if (handle >= _numberOfHandles) {
+ throw new MojoCodecError('Trying to access non present handle.');
+ }
+ _minNextClaimedHandle = handle + 1;
+ }
+
+ void claimMemory(int start, int end) {
+ if ((start % kAlignment) != 0) {
+ throw new MojoCodecError('Incorrect starting alignment: $start.');
+ }
+ if (start < _minNextMemory) {
+ throw new MojoCodecError('Trying to access memory out of order.');
+ }
+ if (end < start) {
+ throw new MojoCodecError('Incorrect memory range.');
+ }
+ if (end > _maxMemory) {
+ throw new MojoCodecError('Trying to access out of range memory.');
+ }
+ _minNextMemory = align(end);
+ }
+}
+
+
class Decoder {
+ _Validator _validator;
Message _message;
int _base = 0;
- Decoder(this._message, [this._base = 0]);
+ Decoder(this._message, [this._base = 0, this._validator = null]) {
+ if (_validator == null) {
+ _validator = new _Validator(
+ _message.buffer.lengthInBytes, _message.handles.length);
+ }
+ }
- Decoder getDecoderAtPosition(int offset) => new Decoder(_message, offset);
+ Decoder getDecoderAtPosition(int offset) =>
+ new Decoder(_message, offset, _validator);
- factory Decoder.atOffset(Decoder d, int offset) =>
- new Decoder(d._message, offset);
+ factory Decoder.atOffset(Decoder d, int offset, _Validator validator) =>
+ new Decoder(d._message, offset, validator);
ByteData get _buffer => _message.buffer;
List<core.MojoHandle> get _handles => _message.handles;
@@ -487,10 +540,12 @@ class Decoder {
int index = decodeInt32(offset);
if (index == -1) {
if (!nullable) {
- throw 'Trying to decode an invalid handle from a non-nullable type.';
+ throw new MojoCodecError(
+ 'Trying to decode an invalid handle from a non-nullable type.');
}
return new core.MojoHandle(core.MojoHandle.INVALID);
}
+ _validator.claimHandle(index);
return _handles[index];
}
@@ -524,17 +579,26 @@ class Decoder {
int pointerOffset = decodeUint64(offset);
if (pointerOffset == 0) {
if (!nullable) {
- throw 'Trying to decode a null pointer for a non-nullable type';
+ throw new MojoCodecError(
+ 'Trying to decode a null pointer for a non-nullable type');
}
return null;
}
int newPosition = (basePosition + pointerOffset);
- return new Decoder.atOffset(this, newPosition);
+ return new Decoder.atOffset(this, newPosition, _validator);
}
DataHeader decodeDataHeader() {
+ _validator.claimMemory(_base, _base + DataHeader.kHeaderSize);
int size = decodeUint32(DataHeader.kSizeOffset);
int numFields = decodeUint32(DataHeader.kNumFieldsOffset);
+ if (size < 0) {
+ throw new MojoCodecError('Negative size.');
+ }
+ if (numFields < 0) {
+ throw new MojoCodecError('Negative number of fields.');
+ }
+ _validator.claimMemory(_base + DataHeader.kHeaderSize, _base + size);
return new DataHeader(size, numFields);
}
@@ -542,11 +606,13 @@ class Decoder {
DataHeader decodeDataHeaderForBoolArray(int expectedLength) {
var header = decodeDataHeader();
if (header.size < DataHeader.kHeaderSize + (header.numFields + 7) ~/ 8) {
- throw 'Array header is incorrect';
+ throw new MojoCodecError('Array header is incorrect');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(header.numFields != expectedLength)) {
- throw 'Incorrect array length';
+ throw new MojoCodecError(
+ 'Incorrect array length. Expected $expectedLength, but got '
+ '${header.numFields}.');
}
return header;
}
@@ -576,11 +642,14 @@ class Decoder {
DataHeader decodeDataHeaderForArray(int elementSize, int expectedLength) {
var header = decodeDataHeader();
if (header.size < DataHeader.kHeaderSize + header.numFields * elementSize) {
- throw 'Array header is incorrect: $header, elementSize = $elementSize';
+ throw new MojoCodecError(
+ 'Array header is incorrect: $header, elementSize = $elementSize');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(header.numFields != expectedLength)) {
- throw 'Incorrect array length.';
+ throw new MojoCodecError(
+ 'Incorrect array length. Expected $expectedLength, but got '
+ '${header.numFields}');
}
return header;
}
@@ -588,11 +657,11 @@ class Decoder {
DataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
decodeDataHeaderForArray(kPointerSize, expectedLength);
- List<int> decodeArray(Function arrayViewer,
- int elementSize,
- int offset,
- int nullability,
- int expectedLength) {
+ List decodeArray(Function arrayViewer,
+ int elementSize,
+ int offset,
+ int nullability,
+ int expectedLength) {
Decoder d = decodePointer(offset, isArrayNullable(nullability));
if (d == null) {
return null;
@@ -728,4 +797,17 @@ class Decoder {
}
return _stringOfUtf8(bytes);
}
+
+ DataHeader decodeDataHeaderForMap() {
+ var header = decodeDataHeader();
+ if (header.size != kMapStructHeader.size) {
+ throw new MojoCodecError(
+ 'Incorrect header for map. The size is incorrect.');
+ }
+ if (header.numFields != kMapStructHeader.numFields) {
+ throw new MojoCodecError(
+ 'Incorrect header for map. The number of fields is incorrect.');
+ }
+ return header;
+ }
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart b/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart
index 3d14f6c..da688d4 100644
--- a/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart
@@ -19,11 +19,6 @@ class _MojoHandleWatcherNatives {
// The MojoHandleWatcher sends a stream of events to application isolates that
// register Mojo handles with it. Application isolates make the following calls:
//
-// Start() - Starts up the MojoHandleWatcher isolate. Should be called only once
-// per VM process.
-//
-// Stop() - Causes the MojoHandleWatcher isolate to exit.
-//
// add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add
// 'handle' to the set of handles it watches, and to notify the calling
// isolate only for the events specified by 'signals' using the send port
@@ -291,7 +286,9 @@ class MojoHandleWatcher {
return new MojoResult(result);
}
- static Future<Isolate> Start() {
+ // Starts up the MojoHandleWatcher isolate. Should be called only once
+ // per VM process.
+ static Future<Isolate> _start() {
// Make a control message pipe,
MojoMessagePipe pipe = new MojoMessagePipe();
int consumerHandle = pipe.endpoints[0].handle.h;
@@ -305,7 +302,9 @@ class MojoHandleWatcher {
return Isolate.spawn(_handleWatcherIsolate, consumerHandle);
}
- static void Stop() {
+ // Causes the MojoHandleWatcher isolate to exit. Should be called only
+ // once per VM process.
+ static void _stop() {
// Create a port for notification that the handle watcher has shutdown.
var shutdownReceivePort = new ReceivePort();
var shutdownSendPort = shutdownReceivePort.sendPort;
@@ -339,7 +338,7 @@ class MojoHandleWatcher {
return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
}
- static MojoResult timer(SendPort port, int deadline) {
+ static MojoResult timer(Object ignored, SendPort port, int deadline) {
// The deadline will be unwrapped before sending to the handle watcher.
return _sendControlData(
new MojoHandle(deadline), port, _encodeCommand(TIMER));
diff --git a/third_party/mojo/src/mojo/public/dart/src/message.dart b/third_party/mojo/src/mojo/public/dart/src/message.dart
index 2cdda8a..918d219 100644
--- a/third_party/mojo/src/mojo/public/dart/src/message.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/message.dart
@@ -35,12 +35,18 @@ class MessageHeader {
MessageHeader.fromMessage(Message message) {
var decoder = new Decoder(message);
_header = decoder.decodeDataHeader();
+ if (_header.size < kSimpleMessageSize) {
+ throw new MojoCodecError(
+ 'Incorrect message size. Got: ${_header.size} '
+ 'wanted $kSimpleMessageSize');
+ }
type = decoder.decodeUint32(kMessageTypeOffset);
flags = decoder.decodeUint32(kMessageFlagsOffset);
if (mustHaveRequestId(flags)) {
if (_header.size < kMessageWithRequestIdSize) {
- throw 'Incorrect message size. Got: ${_header.size} ' +
- 'wanted $kMessageWithRequestIdSize';
+ throw new MojoCodecError(
+ 'Incorrect message size. Got: ${_header.size} '
+ 'wanted $kMessageWithRequestIdSize');
}
requestId = decoder.decodeUint64(kMessageRequestIdOffset);
} else {
@@ -63,6 +69,35 @@ class MessageHeader {
ServiceMessage get serviceMessage => new ServiceMessage(this);
String toString() => "MessageHeader($_header, $type, $flags, $requestId)";
+
+ bool validateHeaderFlags(expectedFlags) =>
+ (flags & (kMessageExpectsResponse | kMessageIsResponse)) == expectedFlags;
+
+ bool validateHeader(int expectedType, int expectedFlags) =>
+ (type == expectedType) && validateHeaderFlags(expectedFlags);
+
+ static void _validateDataHeader(DataHeader dataHeader) {
+ if (dataHeader.numFields < kSimpleMessageNumFields) {
+ throw 'Incorrect number of fields, expecting at least '
+ '$kSimpleMessageNumFields, but got: ${dataHeader.numFields}.';
+ }
+ if (dataHeader.size < kSimpleMessageSize) {
+ throw 'Incorrect message size, expecting at least $kSimpleMessageSize, '
+ 'but got: ${dataHeader.size}';
+ }
+ if ((dataHeader.numFields == kSimpleMessageSize) &&
+ (dataHeader.size != kSimpleMessageSize)) {
+ throw 'Incorrect message size for a message with $kSimpleMessageNumFields'
+ ' fields, expecting $kSimpleMessageSize, '
+ 'but got ${dataHeader.size}';
+ }
+ if ((dataHeader.numFields == kMessageWithRequestIdNumFields) &&
+ (dataHeader.size != kMessageWithRequestIdSize)) {
+ throw 'Incorrect message size for a message with '
+ '$kMessageWithRequestIdNumFields fields, expecting '
+ '$kMessageWithRequestIdSize, but got ${dataHeader.size}';
+ }
+ }
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/message_pipe.dart b/third_party/mojo/src/mojo/public/dart/src/message_pipe.dart
index 325be42..7733d33 100644
--- a/third_party/mojo/src/mojo/public/dart/src/message_pipe.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/message_pipe.dart
@@ -49,9 +49,11 @@ class MojoMessagePipeEndpoint {
return status;
}
+ int dataLengthInBytes = (data == null) ? 0 : data.lengthInBytes;
+
// If numBytes has the default value, use the full length of the data.
- int dataNumBytes = (numBytes == -1) ? data.lengthInBytes : numBytes;
- if (dataNumBytes > data.lengthInBytes) {
+ int dataNumBytes = (numBytes == -1) ? dataLengthInBytes : numBytes;
+ if (dataNumBytes > dataLengthInBytes) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/proxy.dart b/third_party/mojo/src/mojo/public/dart/src/proxy.dart
index f662f3a..1186232 100644
--- a/third_party/mojo/src/mojo/public/dart/src/proxy.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/proxy.dart
@@ -47,8 +47,8 @@ abstract class Proxy extends core.MojoEventStreamListener {
var header = new MessageHeader(name);
var serviceMessage = message.serializeWithHeader(header);
endpoint.write(serviceMessage.buffer,
- serviceMessage.buffer.lengthInBytes,
- serviceMessage.handles);
+ serviceMessage.buffer.lengthInBytes,
+ serviceMessage.handles);
if (!endpoint.status.isOk) {
throw "message pipe write failed";
}
@@ -66,8 +66,8 @@ abstract class Proxy extends core.MojoEventStreamListener {
var header = new MessageHeader.withRequestId(name, flags, id);
var serviceMessage = message.serializeWithHeader(header);
endpoint.write(serviceMessage.buffer,
- serviceMessage.buffer.lengthInBytes,
- serviceMessage.handles);
+ serviceMessage.buffer.lengthInBytes,
+ serviceMessage.handles);
if (!endpoint.status.isOk) {
throw "message pipe write failed";
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/service_provider.dart b/third_party/mojo/src/mojo/public/dart/src/service_provider.dart
index deac6bc..6b07f2e 100644
--- a/third_party/mojo/src/mojo/public/dart/src/service_provider.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/service_provider.dart
@@ -30,10 +30,11 @@ class ServiceProvider extends service_provider.ServiceProvider {
_proxy.connectToService(name, pipe.endpoints[1]);
}
- close() {
+ close({bool nodefer : false}) {
if (_proxy != null) {
_proxy.close();
_proxy = null;
}
+ super.close(nodefer: nodefer);
}
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/stub.dart b/third_party/mojo/src/mojo/public/dart/src/stub.dart
index b4ab293..8238736 100644
--- a/third_party/mojo/src/mojo/public/dart/src/stub.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/stub.dart
@@ -20,6 +20,9 @@ abstract class Stub extends core.MojoEventStreamListener {
// Query how many bytes are available.
var result = endpoint.query();
assert(result.status.isOk || result.status.isResourceExhausted);
+ if (result.bytesRead == 0) {
+ throw new MojoCodecError('Unexpected empty message.');
+ }
// Read the data and view as a message.
var bytes = new ByteData(result.bytesRead);
@@ -41,7 +44,7 @@ abstract class Stub extends core.MojoEventStreamListener {
response.buffer.lengthInBytes,
response.handles);
if (!endpoint.status.isOk) {
- throw "message pipe write failed: ${endpoint.status}";
+ throw 'message pipe write failed: ${endpoint.status}';
}
if (_isClosing && (_outstandingResponseFutures == 0)) {
// This was the final response future for which we needed to send
@@ -63,9 +66,12 @@ abstract class Stub extends core.MojoEventStreamListener {
throw 'Unexpected write signal in client.';
}
- void close() {
+ // NB: |nodefer| should only be true when calling close() while handling an
+ // exception thrown from handleRead(), e.g. when we receive a malformed
+ // message.
+ void close({bool nodefer : false}) {
if (!isOpen) return;
- if (isInHandler || (_outstandingResponseFutures > 0)) {
+ if (!nodefer && (isInHandler || (_outstandingResponseFutures > 0))) {
// Either close() is being called from within handleRead() or
// handleWrite(), or close() is being called while there are outstanding
// response futures. Defer the actual close until all response futures
diff --git a/third_party/mojo/src/mojo/public/dart/src/timer_impl.dart b/third_party/mojo/src/mojo/public/dart/src/timer_impl.dart
deleted file mode 100644
index 61fee6d..0000000
--- a/third_party/mojo/src/mojo/public/dart/src/timer_impl.dart
+++ /dev/null
@@ -1,333 +0,0 @@
-// 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.
-
-// This code is adapted from the Timer implementation in the standalone Dart VM
-// for use in the Mojo embedder.
-
-part of core;
-
-// Timer heap implemented as a array-based binary heap[0].
-// This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
-// `add`.
-//
-// To ensure the timers are ordered by insertion time, the _Timer class has a
-// `_id` field set when added to the heap.
-//
-// [0] http://en.wikipedia.org/wiki/Binary_heap
-class _TimerHeap {
- List<_Timer> _list;
- int _used = 0;
-
- _TimerHeap([int initSize = 7])
- : _list = new List<_Timer>(initSize);
-
- bool get isEmpty => _used == 0;
- bool get isNotEmpty => _used > 0;
-
- _Timer get first => _list[0];
-
- bool isFirst(_Timer timer) => timer._indexOrNext == 0;
-
- void add(_Timer timer) {
- if (_used == _list.length) {
- _resize();
- }
- timer._indexOrNext = _used++;
- _list[timer._indexOrNext] = timer;
- _bubbleUp(timer);
- }
-
- _Timer removeFirst() {
- var f = first;
- remove(f);
- return f;
- }
-
- void remove(_Timer timer) {
- _used--;
- timer._id = -1;
- if (isEmpty) {
- _list[0] = null;
- timer._indexOrNext = null;
- return;
- }
- var last = _list[_used];
- if (!identical(last, timer)) {
- last._indexOrNext = timer._indexOrNext;
- _list[last._indexOrNext] = last;
- if (last._compareTo(timer) < 0) {
- _bubbleUp(last);
- } else {
- _bubbleDown(last);
- }
- }
- _list[_used] = null;
- timer._indexOrNext = null;
- }
-
- void _resize() {
- var newList = new List(_list.length * 2 + 1);
- newList.setRange(0, _used, _list);
- _list = newList;
- }
-
- void _bubbleUp(_Timer timer) {
- while (!isFirst(timer)) {
- Timer parent = _parent(timer);
- if (timer._compareTo(parent) < 0) {
- _swap(timer, parent);
- } else {
- break;
- }
- }
- }
-
- void _bubbleDown(_Timer timer) {
- while (true) {
- int leftIndex = _leftChildIndex(timer._indexOrNext);
- int rightIndex = _rightChildIndex(timer._indexOrNext);
- _Timer newest = timer;
- if (leftIndex < _used && _list[leftIndex]._compareTo(newest) < 0) {
- newest = _list[leftIndex];
- }
- if (rightIndex < _used && _list[rightIndex]._compareTo(newest) < 0) {
- newest = _list[rightIndex];
- }
- if (identical(newest, timer)) {
- // We are where we should be, break.
- break;
- }
- _swap(newest, timer);
- }
- }
-
- void _swap(_Timer first, _Timer second) {
- int tmp = first._indexOrNext;
- first._indexOrNext = second._indexOrNext;
- second._indexOrNext = tmp;
- _list[first._indexOrNext] = first;
- _list[second._indexOrNext] = second;
- }
-
- Timer _parent(_Timer timer) => _list[_parentIndex(timer._indexOrNext)];
- Timer _leftChild(_Timer timer) => _list[_leftChildIndex(timer._indexOrNext)];
- Timer _rightChild(_Timer timer) =>
- _list[_rightChildIndex(timer._indexOrNext)];
-
- static int _parentIndex(int index) => (index - 1) ~/ 2;
- static int _leftChildIndex(int index) => 2 * index + 1;
- static int _rightChildIndex(int index) => 2 * index + 2;
-}
-
-class _Timer implements Timer {
- // Disables the timer.
- static const int _NO_TIMER = -1;
-
- // Timers are ordered by wakeup time.
- static _TimerHeap _heap = new _TimerHeap();
- static _Timer _firstZeroTimer;
- static _Timer _lastZeroTimer;
- static int _idCount = 0;
-
- static RawReceivePort _receivePort;
- static SendPort _sendPort;
- static bool _handlingCallbacks = false;
-
- Function _callback;
- int _milliSeconds;
- int _wakeupTime = 0;
- var _indexOrNext;
- int _id = -1;
-
- static Timer _createTimer(void callback(Timer timer),
- int milliSeconds,
- bool repeating) {
- _Timer timer = new _Timer._internal();
- timer._callback = callback;
- if (milliSeconds > 0) {
- // Add one because DateTime.now() is assumed to round down
- // to nearest millisecond, not up, so that time + duration is before
- // duration milliseconds from now. Using micosecond timers like
- // Stopwatch allows detecting that the timer fires early.
- timer._wakeupTime =
- new DateTime.now().millisecondsSinceEpoch + 1 + milliSeconds;
- }
- timer._milliSeconds = repeating ? milliSeconds : -1;
- if (timer._addTimerToHeap()) {
- // The new timer is the first in queue. Update event handler.
- _notifyEventHandler();
- }
- return timer;
- }
-
- factory _Timer(int milliSeconds, void callback(Timer timer)) {
- return _createTimer(callback, milliSeconds, false);
- }
-
- factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) {
- return _createTimer(callback, milliSeconds, true);
- }
-
- _Timer._internal() {}
-
- bool get _isInHeap => _id >= 0;
-
- void _clear() {
- _callback = null;
- }
-
- int _compareTo(_Timer other) {
- int c = _wakeupTime - other._wakeupTime;
- if (c != 0) return c;
- return _id - other._id;
- }
-
- bool get _repeating => _milliSeconds >= 0;
-
- bool get isActive => _callback != null;
-
- // Cancels a set timer. The timer is removed from the timer list and if
- // the given timer is the earliest timer the native timer is reset.
- void cancel() {
- _clear();
- if (!_isInHeap) return;
- assert(_wakeupTime != 0);
- bool update = (_firstZeroTimer == null) && _heap.isFirst(this);
- _heap.remove(this);
- if (update) {
- _notifyEventHandler();
- }
- }
-
- void _advanceWakeupTime() {
- assert(_milliSeconds >= 0);
- _wakeupTime += _milliSeconds;
- }
-
- // Adds a timer to the timer list. Timers with the same wakeup time are
- // enqueued in order and notified in FIFO order.
- bool _addTimerToHeap() {
- if (_wakeupTime == 0) {
- if (_firstZeroTimer == null) {
- _lastZeroTimer = this;
- _firstZeroTimer = this;
- return true;
- } else {
- _lastZeroTimer._indexOrNext = this;
- _lastZeroTimer = this;
- return false;
- }
- } else {
- _id = _idCount++;
- _heap.add(this);
- return _firstZeroTimer == null && _heap.isFirst(this);
- }
- }
-
-
- static void _notifyEventHandler() {
- if (_handlingCallbacks) {
- // While we are already handling callbacks we will not notify the event
- // handler. _handleTimeout will call _notifyEventHandler once all pending
- // timers are processed.
- return;
- }
-
- if (_firstZeroTimer == null && _heap.isEmpty) {
- // No pending timers: Close the receive port and let the event handler
- // know.
- if (_receivePort != null) {
- MojoHandleWatcher.timer(_sendPort, _NO_TIMER);
- _shutdownTimerHandler();
- }
- } else {
- if (_receivePort == null) {
- // Create a receive port and register a message handler for the timer
- // events.
- _createTimerHandler();
- }
- if (_firstZeroTimer != null) {
- _sendPort.send(null);
- } else {
- MojoHandleWatcher.timer(_sendPort, _heap.first._wakeupTime);
- }
- }
- }
-
- static void _handleTimeout(_) {
- int currentTime = new DateTime.now().millisecondsSinceEpoch;
- // Collect all pending timers.
- var timer = _firstZeroTimer;
- var nextTimer = _lastZeroTimer;
- _firstZeroTimer = null;
- _lastZeroTimer = null;
- while (_heap.isNotEmpty && _heap.first._wakeupTime <= currentTime) {
- var next = _heap.removeFirst();
- if (timer == null) {
- nextTimer = next;
- timer = next;
- } else {
- nextTimer._indexOrNext = next;
- nextTimer = next;
- }
- }
-
- // Trigger all of the pending timers. New timers added as part of the
- // callbacks will be enqueued now and notified in the next spin at the
- // earliest.
- _handlingCallbacks = true;
- try {
- while (timer != null) {
- var next = timer._indexOrNext;
- timer._indexOrNext = null;
- // One of the timers in the pending_timers list can cancel
- // one of the later timers which will set the callback to
- // null.
- if (timer._callback != null) {
- var callback = timer._callback;
- if (!timer._repeating) {
- // Mark timer as inactive.
- timer._callback = null;
- }
- callback(timer);
- // Re-insert repeating timer if not canceled.
- if (timer._repeating && timer._callback != null) {
- timer._advanceWakeupTime();
- timer._addTimerToHeap();
- }
- }
- timer = next;
- }
- } finally {
- _handlingCallbacks = false;
- _notifyEventHandler();
- }
- }
-
- // Creates a receive port and registers the timer handler on that
- // receive port.
- static void _createTimerHandler() {
- if(_receivePort == null) {
- _receivePort = new RawReceivePort(_handleTimeout);
- _sendPort = _receivePort.sendPort;
- }
- }
-
- static void _shutdownTimerHandler() {
- _receivePort.close();
- _receivePort = null;
- _sendPort = null;
- }
-}
-
-// Provide a closure which will allocate a Timer object to be able to hook
-// up the Timer interface in dart:isolate with the implementation here.
-_getTimerFactoryClosure() {
- return (int milliSeconds, void callback(Timer timer), bool repeating) {
- if (repeating) {
- return new _Timer.periodic(milliSeconds, callback);
- }
- return new _Timer(milliSeconds, callback);
- };
-}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/decoder.go b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
index 2dccd0a..3f3cce9 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/decoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
@@ -185,6 +185,7 @@ func (d *Decoder) ReadUint8() (uint8, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 8); err != nil {
return 0, err
}
+ d.state().alignOffsetToBytes()
value := d.buf[d.state().offset]
d.state().skipBytes(1)
d.state().elementsProcessed++
@@ -202,6 +203,7 @@ func (d *Decoder) ReadUint16() (uint16, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 16); err != nil {
return 0, err
}
+ d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 2)
value := binary.LittleEndian.Uint16(d.buf[d.state().offset:])
d.state().skipBytes(2)
@@ -220,6 +222,7 @@ func (d *Decoder) ReadUint32() (uint32, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 32); err != nil {
return 0, err
}
+ d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 4)
value := binary.LittleEndian.Uint32(d.buf[d.state().offset:])
d.state().skipBytes(4)
@@ -238,6 +241,7 @@ func (d *Decoder) ReadUint64() (uint64, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
return 0, err
}
+ d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 8)
value := binary.LittleEndian.Uint64(d.buf[d.state().offset:])
d.state().skipBytes(8)
@@ -300,16 +304,59 @@ func (d *Decoder) ReadPointer() (uint64, error) {
if newEnd%8 != 0 {
return 0, fmt.Errorf("incorrect pointer data alignment: %d", newEnd)
}
- d.claimData(d.end - int(newEnd))
+ d.claimData(int(newEnd) - d.end)
return pointer, nil
}
-// ReadMessagePipeHandle reads a message pipe handle.
-func (d *Decoder) ReadMessagePipeHandle() (system.MessagePipeHandle, error) {
+// ReadUntypedHandle reads an untyped handle.
+func (d *Decoder) ReadUntypedHandle() (system.UntypedHandle, error) {
handleIndex, err := d.ReadUint32()
if err != nil {
return nil, err
}
- untypedHandle, err := d.claimHandle(int(handleIndex))
- return untypedHandle.ToMessagePipeHandle(), err
+ if handleIndex == ^uint32(0) {
+ return &InvalidHandle{}, nil
+ }
+ return d.claimHandle(int(handleIndex))
+}
+
+// ReadHandle reads a handle.
+func (d *Decoder) ReadHandle() (system.Handle, error) {
+ return d.ReadUntypedHandle()
+}
+
+// ReadMessagePipeHandle reads a message pipe handle.
+func (d *Decoder) ReadMessagePipeHandle() (system.MessagePipeHandle, error) {
+ if handle, err := d.ReadUntypedHandle(); err != nil {
+ return nil, err
+ } else {
+ return handle.ToMessagePipeHandle(), nil
+ }
+}
+
+// ReadConsumerHandle reads a data pipe consumer handle.
+func (d *Decoder) ReadConsumerHandle() (system.ConsumerHandle, error) {
+ if handle, err := d.ReadUntypedHandle(); err != nil {
+ return nil, err
+ } else {
+ return handle.ToConsumerHandle(), nil
+ }
+}
+
+// ReadProducerHandle reads a data pipe producer handle.
+func (d *Decoder) ReadProducerHandle() (system.ProducerHandle, error) {
+ if handle, err := d.ReadUntypedHandle(); err != nil {
+ return nil, err
+ } else {
+ return handle.ToProducerHandle(), nil
+ }
+}
+
+// ReadSharedBufferHandle reads a shared buffer handle.
+func (d *Decoder) ReadSharedBufferHandle() (system.SharedBufferHandle, error) {
+ if handle, err := d.ReadUntypedHandle(); err != nil {
+ return nil, err
+ } else {
+ return handle.ToSharedBufferHandle(), nil
+ }
}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/encoder.go b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
index 210d9b0..5ea1a50 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/encoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
@@ -36,6 +36,13 @@ type encodingState struct {
elementsProcessed uint32
}
+func (s *encodingState) alignOffsetToBytes() {
+ if s.bitOffset > 0 {
+ s.offset++
+ s.bitOffset = 0
+ }
+}
+
func (s *encodingState) skipBits(count uint32) {
s.bitOffset += count
s.offset += int(s.bitOffset >> 3) // equal to s.bitOffset / 8
@@ -63,16 +70,6 @@ type Encoder struct {
stateStack []encodingState
}
-func align(size, alignment int) int {
- return ((size - 1) | (alignment - 1)) + 1
-}
-
-// bytesForBits returns minimum number of bytes required to store provided
-// number of bits.
-func bytesForBits(bits uint64) int {
- return int((bits + 7) / 8)
-}
-
func ensureElementBitSizeAndCapacity(state *encodingState, bitSize uint32) error {
if state == nil {
return fmt.Errorf("empty state stack")
@@ -213,6 +210,7 @@ func (e *Encoder) WriteUint8(value uint8) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 8); err != nil {
return err
}
+ e.state().alignOffsetToBytes()
e.buf[e.state().offset] = value
e.state().skipBytes(1)
e.state().elementsProcessed++
@@ -229,6 +227,7 @@ func (e *Encoder) WriteUint16(value uint16) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 16); err != nil {
return err
}
+ e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 2)
binary.LittleEndian.PutUint16(e.buf[e.state().offset:], value)
e.state().skipBytes(2)
@@ -246,6 +245,7 @@ func (e *Encoder) WriteUint32(value uint32) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 32); err != nil {
return err
}
+ e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 4)
binary.LittleEndian.PutUint32(e.buf[e.state().offset:], value)
e.state().skipBytes(4)
@@ -263,6 +263,7 @@ func (e *Encoder) WriteUint64(value uint64) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
return err
}
+ e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 8)
binary.LittleEndian.PutUint64(e.buf[e.state().offset:], value)
e.state().skipBytes(8)
diff --git a/third_party/mojo/src/mojo/public/go/bindings/invalid_handle.go b/third_party/mojo/src/mojo/public/go/bindings/invalid_handle.go
new file mode 100644
index 0000000..1acc645
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/bindings/invalid_handle.go
@@ -0,0 +1,97 @@
+// Copyright 2015 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.
+
+package bindings
+
+import (
+ "mojo/public/go/system"
+)
+
+// InvalidHandle is a handle that will always be invalid.
+type InvalidHandle struct {
+}
+
+func (h *InvalidHandle) Close() system.MojoResult {
+ return system.MOJO_RESULT_INVALID_ARGUMENT
+}
+
+func (h *InvalidHandle) IsValid() bool {
+ return false
+}
+
+func (h *InvalidHandle) NativeHandle() system.MojoHandle {
+ return system.MOJO_HANDLE_INVALID
+}
+
+func (h *InvalidHandle) ReleaseNativeHandle() system.MojoHandle {
+ return system.MOJO_HANDLE_INVALID
+}
+
+func (h *InvalidHandle) ToUntypedHandle() system.UntypedHandle {
+ return h
+}
+
+func (h *InvalidHandle) Wait(signals system.MojoHandleSignals, deadline system.MojoDeadline) (system.MojoResult, system.MojoHandleSignalsState) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, system.MojoHandleSignalsState{}
+}
+
+func (h *InvalidHandle) ToConsumerHandle() system.ConsumerHandle {
+ return h
+}
+
+func (h *InvalidHandle) ToProducerHandle() system.ProducerHandle {
+ return h
+}
+
+func (h *InvalidHandle) ToMessagePipeHandle() system.MessagePipeHandle {
+ return h
+}
+
+func (h *InvalidHandle) ToSharedBufferHandle() system.SharedBufferHandle {
+ return h
+}
+
+func (h *InvalidHandle) ReadData(flags system.MojoReadDataFlags) (system.MojoResult, []byte) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil
+}
+
+func (h *InvalidHandle) BeginReadData(numBytes int, flags system.MojoReadDataFlags) (system.MojoResult, []byte) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil
+}
+
+func (h *InvalidHandle) EndReadData(numBytesRead int) system.MojoResult {
+ return system.MOJO_RESULT_INVALID_ARGUMENT
+}
+
+func (h *InvalidHandle) WriteData(data []byte, flags system.MojoWriteDataFlags) (system.MojoResult, int) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, 0
+}
+
+func (h *InvalidHandle) BeginWriteData(numBytes int, flags system.MojoWriteDataFlags) (system.MojoResult, []byte) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil
+}
+
+func (h *InvalidHandle) EndWriteData(numBytesWritten int) system.MojoResult {
+ return system.MOJO_RESULT_INVALID_ARGUMENT
+}
+
+func (h *InvalidHandle) ReadMessage(flags system.MojoReadMessageFlags) (system.MojoResult, []byte, []system.UntypedHandle) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil, nil
+}
+
+func (h *InvalidHandle) WriteMessage(bytes []byte, handles []system.UntypedHandle, flags system.MojoWriteMessageFlags) system.MojoResult {
+ return system.MOJO_RESULT_INVALID_ARGUMENT
+}
+
+func (h *InvalidHandle) DuplicateBufferHandle(opts *system.DuplicateBufferHandleOptions) (system.MojoResult, system.SharedBufferHandle) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil
+}
+
+func (h *InvalidHandle) MapBuffer(offset uint64, numBytes int, flags system.MojoMapBufferFlags) (system.MojoResult, []byte) {
+ return system.MOJO_RESULT_INVALID_ARGUMENT, nil
+}
+
+func (h *InvalidHandle) UnmapBuffer(buffer []byte) system.MojoResult {
+ return system.MOJO_RESULT_INVALID_ARGUMENT
+}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/util.go b/third_party/mojo/src/mojo/public/go/bindings/util.go
new file mode 100644
index 0000000..8d51ddb
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/bindings/util.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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.
+
+package bindings
+
+func align(size, alignment int) int {
+ return ((size - 1) | (alignment - 1)) + 1
+}
+
+// bytesForBits returns minimum number of bytes required to store provided
+// number of bits.
+func bytesForBits(bits uint64) int {
+ return int((bits + 7) / 8)
+}
+
+// StringPointer converts provided string to *string.
+func StringPointer(s string) *string {
+ return &s
+}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
index 40fa9a6..dc4f05e 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
@@ -22,7 +22,7 @@ struct EmptyStruct {
// Used to verify that struct fields which don't specify a default are
// initialized to: false for bool, 0 for numbers, and null for strings,
-// handles, and structs. The "?" nullable suffix shouldn't have any
+// handles, and structs. The "?" nullable suffix shouldn't have any
// impact on initial field values.
struct NoDefaultFieldValues {
@@ -58,7 +58,7 @@ struct NoDefaultFieldValues {
};
// Used to verify that struct fields with an explicit default value
-// are initialized correctly. The "?" nullable suffix shouldn't have any
+// are initialized correctly. The "?" nullable suffix shouldn't have any
// impact on initial field values.
struct DefaultFieldValues {
@@ -140,6 +140,18 @@ struct MapValueTypes {
map<string, array<map<string, string>>> f8;
};
+// Used to verify that various array types can be encoded and decoded
+// successfully.
+
+struct ArrayValueTypes {
+ array<int8> f0;
+ array<int16> f1;
+ array<int32> f2;
+ array<int64> f3;
+ array<float> f4;
+ array<double> f5;
+};
+
// Used to verify that various float and double values can be encoded and
// decoded correctly.
@@ -189,18 +201,18 @@ struct IntegerNumberValues {
const int32 V13 = 1234567890;
const int32 V14 = 2147483647;
- // The limits for JavaScript integers are +/- (2^53 - 1).
+ // The limits for JavaScript integers are +/- (2^53 - 1).
const int64 V15 = -9007199254740991; // Number.MIN_SAFE_INTEGER
const int64 V16 = -1;
const int64 V17 = 0;
const int64 V18 = 1234567890123456;
const int64 V19 = 9007199254740991; // Number.MAX_SAFE_INTEGER
- int8 f0 = V0;
+ int8 f0 = V0;
int8 f1 = V1;
- int8 f2 = V2;
- int8 f3 = V3;
- int8 f4 = V4;
+ int8 f2 = V2;
+ int8 f3 = V3;
+ int8 f4 = V4;
int16 f5 = V5;
int16 f6 = V6;
@@ -237,14 +249,14 @@ struct UnsignedNumberValues {
const uint32 V7 = 1234567890;
const uint32 V8 = 0xFFFFFFFF;
- // The limits for JavaScript integers are +/- (2^53 - 1).
+ // The limits for JavaScript integers are +/- (2^53 - 1).
const uint64 V9 = 0;
const uint64 V10 = 1234567890123456;
const uint64 V11 = 9007199254740991; // Number.MAX_SAFE_INTEGER
- uint8 f0 = V0;
+ uint8 f0 = V0;
uint8 f1 = V1;
- uint8 f2 = V2;
+ uint8 f2 = V2;
uint16 f3 = V3;
uint16 f4 = V4;
diff --git a/third_party/mojo/src/mojo/public/tests/DEPS b/third_party/mojo/src/mojo/public/tests/DEPS
deleted file mode 100644
index 0669117..0000000
--- a/third_party/mojo/src/mojo/public/tests/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+mojo",
-]
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
index 952c0dc..a73ad8e 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
@@ -17,7 +17,7 @@ abstract class {{interface|name}} implements core.Listener {
{{interface|name}}.unbound() :
stub = new {{interface|name}}Stub.unbound();
- void close() => stub.close();
+ void close({bool nodefer : false}) => stub.close(nodefer: nodefer);
StreamSubscription<int> listen() => stub.listen();
@@ -76,7 +76,7 @@ class {{interface|name}}Proxy extends bindings.Proxy implements {{interface|name
{%- endif %}
{%- endfor %}
default:
- throw new Exception("Unexpected message name");
+ throw new bindings.MojoCodecError("Unexpected message name");
break;
}
}
@@ -183,7 +183,7 @@ class {{interface|name}}Stub extends bindings.Stub {
break;
{%- endfor %}
default:
- throw new Exception("Unexpected message name");
+ throw new bindings.MojoCodecError("Unexpected message name");
break;
}
return null;
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
index f5b62a9..f65298f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
@@ -50,12 +50,13 @@ if (decoder{{level+1}} == null) {
List<{{kind.key_kind|dart_type}}> keys{{level}};
List<{{kind.value_kind|dart_type}}> values{{level}};
{
- {{decode('keys'~level, kind.key_kind|array, 'DataHeader.HEADER_SIZE', 0, level+1)|indent(4)}}
+ {{decode('keys'~level, kind.key_kind|array, 'bindings.DataHeader.kHeaderSize', 0, level+1)|indent(4)}}
}
{
{{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'bindings.DataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1)|indent(4)}}
}
- {{variable}} = new Map<{{kind.key_kind|dart_type}}, {{kind.value_kind|dart_type}}>.fromIterables(keys, values);
+ {{variable}} = new Map<{{kind.key_kind|dart_type}}, {{kind.value_kind|dart_type}}>.fromIterables(
+ keys{{level}}, values{{level}});
{%- else %}
var si{{level+1}} = decoder{{level+1}}.decodeDataHeaderForPointerArray({{kind|array_expected_length}});
{{variable}} = new {{kind|dart_type}}(si{{level+1}}.numFields);
@@ -105,11 +106,13 @@ class {{struct|name}} extends bindings.Struct {
return null;
}
{{struct|name}} result = new {{struct|name}}();
-{%- if not struct.bytes %}
- decoder0.decodeDataHeader();
-{%- else %}
+
var mainDataHeader = decoder0.decodeDataHeader();
-{%- endif %}
+ if ((mainDataHeader.size < kStructSize) ||
+ (mainDataHeader.numFields < {{struct.packed.packed_fields|length}})) {
+ throw new bindings.MojoCodecError('Malformed header');
+ }
+
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
if (mainDataHeader.numFields > {{packed_field.ordinal}}) {
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl
new file mode 100644
index 0000000..8c58c4c
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl
@@ -0,0 +1,11 @@
+// Copyright 2015 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.
+
+// This file is autogenerated by:
+// mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+// {{module.path}}
+//
+
+package {{package}}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
index 3251095..d971b53 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
@@ -69,9 +69,9 @@ _kind_to_dart_decl_type = {
_spec_to_decode_method = {
mojom.BOOL.spec: 'decodeBool',
- mojom.DCPIPE.spec: 'decodeHandle',
+ mojom.DCPIPE.spec: 'decodeConsumerHandle',
mojom.DOUBLE.spec: 'decodeDouble',
- mojom.DPPIPE.spec: 'decodeHandle',
+ mojom.DPPIPE.spec: 'decodeProducerHandle',
mojom.FLOAT.spec: 'decodeFloat',
mojom.HANDLE.spec: 'decodeHandle',
mojom.INT16.spec: 'decodeInt16',
@@ -95,9 +95,9 @@ _spec_to_decode_method = {
_spec_to_encode_method = {
mojom.BOOL.spec: 'encodeBool',
- mojom.DCPIPE.spec: 'encodeHandle',
+ mojom.DCPIPE.spec: 'encodeConsumerHandle',
mojom.DOUBLE.spec: 'encodeDouble',
- mojom.DPPIPE.spec: 'encodeHandle',
+ mojom.DPPIPE.spec: 'encodeProducerHandle',
mojom.FLOAT.spec: 'encodeFloat',
mojom.HANDLE.spec: 'encodeHandle',
mojom.INT16.spec: 'encodeInt16',
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
new file mode 100644
index 0000000..3f7c938
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
@@ -0,0 +1,51 @@
+# Copyright 2015 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.
+
+'''Generates Go source files from a mojom.Module.'''
+
+import os
+
+from mojom.generate.template_expander import UseJinja
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+
+def GetPackage(module):
+ if module.namespace:
+ return module.namespace.split('.')[-1]
+ return 'mojom'
+
+def GetPackagePath(module):
+ path = 'mojom'
+ for i in module.namespace.split('.'):
+ path = os.path.join(path, i)
+ return path
+
+class Generator(generator.Generator):
+ go_filters = {}
+
+ def GetParameters(self):
+ return {
+ 'package': GetPackage(self.module),
+ }
+
+ @UseJinja('go_templates/source.tmpl', filters=go_filters)
+ def GenerateSource(self):
+ return self.GetParameters()
+
+ def GenerateFiles(self, args):
+ self.Write(self.GenerateSource(), os.path.join("go", "src", "gen",
+ GetPackagePath(self.module), '%s.go' % self.module.name))
+
+ def GetJinjaParameters(self):
+ return {
+ 'lstrip_blocks': True,
+ 'trim_blocks': True,
+ }
+
+ def GetGlobals(self):
+ return {
+ 'namespace': self.module.namespace,
+ 'module': self.module,
+ }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 276d5af..ad8980d 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -15,6 +15,7 @@ import zipfile
from jinja2 import contextfilter
+import mojom.fileutil as fileutil
import mojom.generate.generator as generator
import mojom.generate.module as mojom
from mojom.generate.template_expander import UseJinja
@@ -212,7 +213,7 @@ def EncodeMethod(context, kind, variable, offset, bit):
return 'encode(%s)' % ', '.join(params)
def GetPackage(module):
- if 'JavaPackage' in module.attributes:
+ if module.attributes and 'JavaPackage' in module.attributes:
return ParseStringAttribute(module.attributes['JavaPackage'])
# Default package.
if module.namespace:
@@ -356,7 +357,7 @@ def GetStructFromMethod(method):
False, generator.GetStructFromMethod(method))
def GetConstantsMainEntityName(module):
- if 'JavaConstantsClassName' in module.attributes:
+ if module.attributes and 'JavaConstantsClassName' in module.attributes:
return ParseStringAttribute(module.attributes['JavaConstantsClassName'])
# This constructs the name of the embedding classes for module level constants
# by extracting the mojom's filename and prepending it to Constants.
@@ -471,12 +472,7 @@ class Generator(generator.Generator):
return exports
def DoGenerateFiles(self):
- if not os.path.exists(self.output_dir):
- try:
- os.makedirs(self.output_dir)
- except:
- # Ignore errors on directory creation.
- pass
+ fileutil.EnsureDirectoryExists(self.output_dir)
# Keep this above the others as .GetStructs() changes the state of the
# module, annotating structs with required information.
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
index 6fc89c1..3e0ca4f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
+++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
@@ -73,6 +73,7 @@ template("mojom") {
"$generator_root/generators/dart_templates/module.lib.tmpl",
"$generator_root/generators/dart_templates/module_definition.tmpl",
"$generator_root/generators/dart_templates/struct_definition.tmpl",
+ "$generator_root/generators/go_templates/source.tmpl",
"$generator_root/generators/java_templates/constant_definition.tmpl",
"$generator_root/generators/java_templates/constants.java.tmpl",
"$generator_root/generators/java_templates/enum.java.tmpl",
@@ -93,6 +94,7 @@ template("mojom") {
"$generator_root/generators/python_templates/module.py.tmpl",
"$generator_root/generators/mojom_cpp_generator.py",
"$generator_root/generators/mojom_dart_generator.py",
+ "$generator_root/generators/mojom_go_generator.py",
"$generator_root/generators/mojom_js_generator.py",
"$generator_root/generators/mojom_java_generator.py",
"$generator_root/generators/mojom_python_generator.py",
@@ -117,6 +119,7 @@ template("mojom") {
]
generator_dart_outputs =
[ "{{source_gen_dir}}/{{source_name_part}}.mojom.dart" ]
+ generator_dart_zip_output = "$target_out_dir/$target_name.dartzip"
generator_java_outputs =
[ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ]
generator_js_outputs = [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ]
@@ -209,7 +212,10 @@ template("mojom") {
if (defined(invoker.deps)) {
deps += invoker.deps
}
- data_deps = [ ":${target_name}_python" ]
+ data_deps = [
+ ":${target_name}_python",
+ ":${target_name}_dart",
+ ]
if (defined(invoker.mojo_sdk_deps)) {
foreach(sdk_dep, invoker.mojo_sdk_deps) {
# Check that the SDK dep was not mistakenly given as an absolute path.
@@ -277,6 +283,42 @@ template("mojom") {
]
}
+ action("${target_name}_dart") {
+ script = rebase_path("mojo/public/tools/gn/zip.py", ".", mojo_root)
+
+ inputs = process_file_template(invoker.sources, generator_dart_outputs)
+
+ deps = []
+ zip_inputs = []
+
+ foreach(d, all_deps) {
+ # Resolve the name, so that a target //mojo/something becomes
+ # //mojo/something:something and we can append "_dart" to get the dart
+ # dependency name.
+ full_name = get_label_info(d, "label_no_toolchain")
+ dep_name = get_label_info(d, "name")
+ dep_target_out_dir = get_label_info(d, "target_out_dir")
+ deps += [ "${full_name}_dart" ]
+ zip_inputs += [ "$dep_target_out_dir/$dep_name.dartzip" ]
+ }
+
+ output = generator_dart_zip_output
+ outputs = [
+ output,
+ ]
+
+ rebase_base_dir = rebase_path("$root_build_dir/gen/", root_build_dir)
+ rebase_inputs = rebase_path(inputs, root_build_dir)
+ rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir)
+ rebase_output = rebase_path(output, root_build_dir)
+ args = [
+ "--base-dir=$rebase_base_dir",
+ "--inputs=$rebase_inputs",
+ "--zip-inputs=$rebase_zip_inputs",
+ "--output=$rebase_output",
+ ]
+ }
+
if (is_android) {
import("//build/config/android/rules.gni")
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py
index 2d1802c..0498838 100755
--- a/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -34,6 +34,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
"pylib"))
from mojom.error import Error
+import mojom.fileutil as fileutil
from mojom.generate.data import OrderedModuleFromData
from mojom.parse.parser import Parse
from mojom.parse.translate import Translate
@@ -50,9 +51,12 @@ def LoadGenerators(generators_string):
if generator_name.lower() == "c++":
generator_name = os.path.join(script_dir, "generators",
"mojom_cpp_generator.py")
- if generator_name.lower() == "dart":
+ elif generator_name.lower() == "dart":
generator_name = os.path.join(script_dir, "generators",
"mojom_dart_generator.py")
+ elif generator_name.lower() == "go":
+ generator_name = os.path.join(script_dir, "generators",
+ "mojom_go_generator.py")
elif generator_name.lower() == "javascript":
generator_name = os.path.join(script_dir, "generators",
"mojom_js_generator.py")
@@ -191,7 +195,7 @@ def main():
help="output directory for generated files")
parser.add_argument("-g", "--generators", dest="generators_string",
metavar="GENERATORS",
- default="c++,dart,javascript,java,python",
+ default="c++,dart,go,javascript,java,python",
help="comma-separated list of generators")
parser.add_argument("--debug_print_intermediate", action="store_true",
help="print the intermediate representation")
@@ -204,8 +208,7 @@ def main():
generator_modules = LoadGenerators(args.generators_string)
- if not os.path.exists(args.output_dir):
- os.makedirs(args.output_dir)
+ fileutil.EnsureDirectoryExists(args.output_dir)
processor = MojomProcessor(lambda filename: filename in args.filename)
for filename in args.filename:
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/fileutil.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/fileutil.py
new file mode 100644
index 0000000..b321e9f
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/fileutil.py
@@ -0,0 +1,18 @@
+# Copyright 2015 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.
+
+import errno
+import os.path
+
+def EnsureDirectoryExists(path, always_try_to_create=False):
+ """A wrapper for os.makedirs that does not error if the directory already
+ exists. A different process could be racing to create this directory."""
+
+ if not os.path.exists(path) or always_try_to_create:
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ # There may have been a race to create this directory.
+ if e.errno != errno.EEXIST:
+ raise
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py
index 6d34a40..3a41593 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py
@@ -42,6 +42,10 @@ def istr(index, string):
rv.__index__ = index
return rv
+def AddOptional(dictionary, key, value):
+ if value is not None:
+ dictionary[key] = value;
+
builtin_values = frozenset([
"double.INFINITY",
"double.NEGATIVE_INFINITY",
@@ -186,15 +190,19 @@ def ImportFromData(module, data):
return import_item
def StructToData(struct):
- return {
+ data = {
istr(0, 'name'): struct.name,
- istr(1, 'fields'): map(FieldToData, struct.fields)
+ istr(1, 'fields'): map(FieldToData, struct.fields),
+ # TODO(yzshen): EnumToData() and ConstantToData() are missing.
+ istr(2, 'enums'): [],
+ istr(3, 'constants'): []
}
+ AddOptional(data, istr(4, 'attributes'), struct.attributes)
+ return data
def StructFromData(module, data):
struct = mojom.Struct(module=module)
struct.name = data['name']
- struct.attributes = data['attributes']
struct.spec = 'x:' + module.namespace + '.' + struct.name
module.kinds[struct.spec] = struct
struct.enums = map(lambda enum:
@@ -203,13 +211,16 @@ def StructFromData(module, data):
ConstantFromData(module, constant, struct), data['constants'])
# Stash fields data here temporarily.
struct.fields_data = data['fields']
+ struct.attributes = data.get('attributes')
return struct
def UnionToData(union):
- return {
+ data = {
istr(0, 'name'): union.name,
istr(1, 'fields'): map(FieldToData, union.fields)
}
+ AddOptional(data, istr(2, 'attributes'), union.attributes)
+ return data
def UnionFromData(module, data):
union = mojom.Union(module=module)
@@ -218,6 +229,7 @@ def UnionFromData(module, data):
module.kinds[union.spec] = union
# Stash fields data here temporarily.
union.fields_data = data['fields']
+ union.attributes = data.get('attributes')
return union
def FieldToData(field):
@@ -225,10 +237,9 @@ def FieldToData(field):
istr(0, 'name'): field.name,
istr(1, 'kind'): KindToData(field.kind)
}
- if field.ordinal != None:
- data[istr(2, 'ordinal')] = field.ordinal
- if field.default != None:
- data[istr(3, 'default')] = field.default
+ AddOptional(data, istr(2, 'ordinal'), field.ordinal)
+ AddOptional(data, istr(3, 'default'), field.default)
+ AddOptional(data, istr(4, 'attributes'), field.attributes)
return data
def FieldFromData(module, data, struct):
@@ -239,6 +250,7 @@ def FieldFromData(module, data, struct):
field.ordinal = data.get('ordinal')
field.default = FixupExpression(
module, data.get('default'), (module.namespace, struct.name), field.kind)
+ field.attributes = data.get('attributes')
return field
def ParameterToData(parameter):
@@ -246,10 +258,9 @@ def ParameterToData(parameter):
istr(0, 'name'): parameter.name,
istr(1, 'kind'): parameter.kind.spec
}
- if parameter.ordinal != None:
- data[istr(2, 'ordinal')] = parameter.ordinal
- if parameter.default != None:
- data[istr(3, 'default')] = parameter.default
+ AddOptional(data, istr(2, 'ordinal'), parameter.ordinal)
+ AddOptional(data, istr(3, 'default'), parameter.default)
+ AddOptional(data, istr(4, 'attributes'), parameter.attributes)
return data
def ParameterFromData(module, data, interface):
@@ -259,6 +270,7 @@ def ParameterFromData(module, data, interface):
module.kinds, data['kind'], (module.namespace, interface.name))
parameter.ordinal = data.get('ordinal')
parameter.default = data.get('default')
+ parameter.attributes = data.get('attributes')
return parameter
def MethodToData(method):
@@ -266,36 +278,39 @@ def MethodToData(method):
istr(0, 'name'): method.name,
istr(1, 'parameters'): map(ParameterToData, method.parameters)
}
- if method.ordinal != None:
- data[istr(2, 'ordinal')] = method.ordinal
- if method.response_parameters != None:
- data[istr(3, 'response_parameters')] = map(
+ if method.response_parameters is not None:
+ data[istr(2, 'response_parameters')] = map(
ParameterToData, method.response_parameters)
+ AddOptional(data, istr(3, 'ordinal'), method.ordinal)
+ AddOptional(data, istr(4, 'attributes'), method.attributes)
return data
def MethodFromData(module, data, interface):
method = mojom.Method(interface, data['name'], ordinal=data.get('ordinal'))
- method.default = data.get('default')
method.parameters = map(lambda parameter:
ParameterFromData(module, parameter, interface), data['parameters'])
if data.has_key('response_parameters'):
method.response_parameters = map(
lambda parameter: ParameterFromData(module, parameter, interface),
data['response_parameters'])
+ method.attributes = data.get('attributes')
return method
def InterfaceToData(interface):
- return {
+ data = {
istr(0, 'name'): interface.name,
- istr(1, 'client'): interface.client,
- istr(2, 'methods'): map(MethodToData, interface.methods)
+ istr(1, 'methods'): map(MethodToData, interface.methods),
+ # TODO(yzshen): EnumToData() and ConstantToData() are missing.
+ istr(2, 'enums'): [],
+ istr(3, 'constants'): []
}
+ AddOptional(data, istr(4, 'attributes'), interface.attributes)
+ return data
def InterfaceFromData(module, data):
interface = mojom.Interface(module=module)
interface.name = data['name']
interface.spec = 'x:' + module.namespace + '.' + interface.name
- interface.client = data['client'] if data.has_key('client') else None
module.kinds[interface.spec] = interface
interface.enums = map(lambda enum:
EnumFromData(module, enum, interface), data['enums'])
@@ -303,6 +318,7 @@ def InterfaceFromData(module, data):
ConstantFromData(module, constant, interface), data['constants'])
# Stash methods data here temporarily.
interface.methods_data = data['methods']
+ interface.attributes = data.get('attributes')
return interface
def EnumFieldFromData(module, enum, data, parent_kind):
@@ -314,10 +330,11 @@ def EnumFieldFromData(module, enum, data, parent_kind):
# vice versa?
if parent_kind:
field.value = FixupExpression(
- module, data['value'], (module.namespace, parent_kind.name), enum)
+ module, data.get('value'), (module.namespace, parent_kind.name), enum)
else:
field.value = FixupExpression(
- module, data['value'], (module.namespace, ), enum)
+ module, data.get('value'), (module.namespace, ), enum)
+ field.attributes = data.get('attributes')
value = mojom.EnumValue(module, enum, field)
module.values[value.GetSpec()] = value
return field
@@ -330,10 +347,11 @@ def EnumFromData(module, data, parent_kind):
name = parent_kind.name + '.' + name
enum.spec = 'x:%s.%s' % (module.namespace, name)
enum.parent_kind = parent_kind
-
enum.fields = map(
lambda field: EnumFieldFromData(module, enum, field, parent_kind),
data['fields'])
+ enum.attributes = data.get('attributes')
+
module.kinds[enum.spec] = enum
return enum
@@ -353,13 +371,20 @@ def ConstantFromData(module, data, parent_kind):
return constant
def ModuleToData(module):
- return {
+ data = {
istr(0, 'name'): module.name,
istr(1, 'namespace'): module.namespace,
- istr(2, 'structs'): map(StructToData, module.structs),
- istr(3, 'interfaces'): map(InterfaceToData, module.interfaces),
+ # TODO(yzshen): Imports information is missing.
+ istr(2, 'imports'): [],
+ istr(3, 'structs'): map(StructToData, module.structs),
istr(4, 'unions'): map(UnionToData, module.unions),
+ istr(5, 'interfaces'): map(InterfaceToData, module.interfaces),
+ # TODO(yzshen): EnumToData() and ConstantToData() are missing.
+ istr(6, 'enums'): [],
+ istr(7, 'constants'): []
}
+ AddOptional(data, istr(8, 'attributes'), module.attributes)
+ return data
def ModuleFromData(data):
module = mojom.Module()
@@ -371,12 +396,12 @@ def ModuleFromData(data):
module.name = data['name']
module.namespace = data['namespace']
- module.attributes = data['attributes']
# Imports must come first, because they add to module.kinds which is used
# by by the others.
module.imports = map(
lambda import_data: ImportFromData(module, import_data),
data['imports'])
+ module.attributes = data.get('attributes')
# First pass collects kinds.
module.enums = map(
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
index af14ead..401c399 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -9,6 +9,7 @@ import os.path
import re
import module as mojom
+import mojom.fileutil as fileutil
import pack
def GetStructFromMethod(method):
@@ -50,8 +51,7 @@ def CamelCaseToAllCaps(camel_case):
def WriteFile(contents, full_path):
# Make sure the containing directory exists.
full_dir = os.path.dirname(full_path)
- if not os.path.exists(full_dir):
- os.makedirs(full_dir)
+ fileutil.EnsureDirectoryExists(full_dir)
# Dump the data to disk.
with open(full_path, "w+") as f:
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index 8e52924..8a0f56b 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -130,6 +130,10 @@ PRIMITIVES = (
)
+ATTRIBUTE_MIN_VERSION = 'MinVersion'
+ATTRIBUTE_CLIENT = 'Client'
+
+
class NamedValue(object):
def __init__(self, module, parent_kind, name):
self.module = module
@@ -174,11 +178,18 @@ class Constant(object):
class Field(object):
- def __init__(self, name=None, kind=None, ordinal=None, default=None):
+ def __init__(self, name=None, kind=None, ordinal=None, default=None,
+ attributes=None):
self.name = name
self.kind = kind
self.ordinal = ordinal
self.default = default
+ self.attributes = attributes
+
+ @property
+ def min_version(self):
+ return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
+ if self.attributes else None
class Struct(ReferenceKind):
@@ -186,8 +197,9 @@ class Struct(ReferenceKind):
ReferenceKind.AddSharedProperty('module')
ReferenceKind.AddSharedProperty('imported_from')
ReferenceKind.AddSharedProperty('fields')
+ ReferenceKind.AddSharedProperty('attributes')
- def __init__(self, name=None, module=None):
+ def __init__(self, name=None, module=None, attributes=None):
if name is not None:
spec = 'x:' + name
else:
@@ -197,9 +209,10 @@ class Struct(ReferenceKind):
self.module = module
self.imported_from = None
self.fields = []
+ self.attributes = attributes
- def AddField(self, name, kind, ordinal=None, default=None):
- field = Field(name, kind, ordinal, default)
+ def AddField(self, name, kind, ordinal=None, default=None, attributes=None):
+ field = Field(name, kind, ordinal, default, attributes)
self.fields.append(field)
return field
@@ -209,8 +222,9 @@ class Union(ReferenceKind):
ReferenceKind.AddSharedProperty('module')
ReferenceKind.AddSharedProperty('imported_from')
ReferenceKind.AddSharedProperty('fields')
+ ReferenceKind.AddSharedProperty('attributes')
- def __init__(self, name=None, module=None):
+ def __init__(self, name=None, module=None, attributes=None):
if name is not None:
spec = 'x:' + name
else:
@@ -220,9 +234,10 @@ class Union(ReferenceKind):
self.module = module
self.imported_from = None
self.fields = []
+ self.attributes = attributes
- def AddField(self, name, kind, ordinal=None):
- field = Field(name, kind, ordinal, default=None)
+ def AddField(self, name, kind, ordinal=None, attributes=None):
+ field = Field(name, kind, ordinal, None, attributes)
self.fields.append(field)
return field
@@ -287,42 +302,57 @@ class InterfaceRequest(ReferenceKind):
class Parameter(object):
- def __init__(self, name=None, kind=None, ordinal=None, default=None):
+ def __init__(self, name=None, kind=None, ordinal=None, default=None,
+ attributes=None):
self.name = name
self.ordinal = ordinal
self.kind = kind
self.default = default
+ self.attributes = attributes
+
+ @property
+ def min_version(self):
+ return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
+ if self.attributes else None
class Method(object):
- def __init__(self, interface, name, ordinal=None):
+ def __init__(self, interface, name, ordinal=None, attributes=None):
self.interface = interface
self.name = name
self.ordinal = ordinal
self.parameters = []
self.response_parameters = None
+ self.attributes = attributes
- def AddParameter(self, name, kind, ordinal=None, default=None):
- parameter = Parameter(name, kind, ordinal, default)
+ def AddParameter(self, name, kind, ordinal=None, default=None,
+ attributes=None):
+ parameter = Parameter(name, kind, ordinal, default, attributes)
self.parameters.append(parameter)
return parameter
- def AddResponseParameter(self, name, kind, ordinal=None, default=None):
+ def AddResponseParameter(self, name, kind, ordinal=None, default=None,
+ attributes=None):
if self.response_parameters == None:
self.response_parameters = []
- parameter = Parameter(name, kind, ordinal, default)
+ parameter = Parameter(name, kind, ordinal, default, attributes)
self.response_parameters.append(parameter)
return parameter
+ @property
+ def min_version(self):
+ return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
+ if self.attributes else None
+
class Interface(ReferenceKind):
ReferenceKind.AddSharedProperty('module')
ReferenceKind.AddSharedProperty('name')
ReferenceKind.AddSharedProperty('imported_from')
- ReferenceKind.AddSharedProperty('client')
ReferenceKind.AddSharedProperty('methods')
+ ReferenceKind.AddSharedProperty('attributes')
- def __init__(self, name=None, client=None, module=None):
+ def __init__(self, name=None, module=None, attributes=None):
if name is not None:
spec = 'x:' + name
else:
@@ -331,23 +361,33 @@ class Interface(ReferenceKind):
self.module = module
self.name = name
self.imported_from = None
- self.client = client
self.methods = []
+ self.attributes = attributes
- def AddMethod(self, name, ordinal=None):
- method = Method(self, name, ordinal=ordinal)
+ def AddMethod(self, name, ordinal=None, attributes=None):
+ method = Method(self, name, ordinal, attributes)
self.methods.append(method)
return method
+ @property
+ def client(self):
+ return self.attributes.get(ATTRIBUTE_CLIENT) if self.attributes else None
+
class EnumField(object):
- def __init__(self, name=None, value=None):
+ def __init__(self, name=None, value=None, attributes=None):
self.name = name
self.value = value
+ self.attributes = attributes
+
+ @property
+ def min_version(self):
+ return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
+ if self.attributes else None
class Enum(Kind):
- def __init__(self, name=None, module=None):
+ def __init__(self, name=None, module=None, attributes=None):
self.module = module
self.name = name
self.imported_from = None
@@ -357,10 +397,11 @@ class Enum(Kind):
spec = None
Kind.__init__(self, spec)
self.fields = []
+ self.attributes = attributes
class Module(object):
- def __init__(self, name=None, namespace=None):
+ def __init__(self, name=None, namespace=None, attributes=None):
self.name = name
self.path = name
self.namespace = namespace
@@ -368,19 +409,20 @@ class Module(object):
self.unions = []
self.interfaces = []
self.kinds = {}
+ self.attributes = attributes
- def AddInterface(self, name):
- interface = Interface(name, module=self)
+ def AddInterface(self, name, attributes=None):
+ interface = Interface(name, self, attributes)
self.interfaces.append(interface)
return interface
- def AddStruct(self, name):
- struct = Struct(name, module=self)
+ def AddStruct(self, name, attributes=None):
+ struct = Struct(name, self, attributes)
self.structs.append(struct)
return struct
- def AddUnion(self, name):
- union = Union(name, module=self)
+ def AddUnion(self, name, attributes=None):
+ union = Union(name, self, attributes)
self.unions.append(union)
return union
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
index 8f7bb3b..37d79eb 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
@@ -65,6 +65,7 @@ class PackedField(object):
self.size = self.GetSizeForKind(field.kind)
self.offset = None
self.bit = None
+ self.min_version = None
# Returns the pad necessary to reserve space for alignment of |size|.
@@ -103,6 +104,47 @@ class PackedStruct(object):
ordinal += 1
src_fields.sort(key=lambda field: field.ordinal)
+ # Set |min_version| for each field.
+ #
+ # TODO(yzshen): We are in the middle of converting the |num_fields| field in
+ # encoded structs to |version|. In order to make code using |num_fields| and
+ # |version| work together, for structs without any [MinVersion] annotation,
+ # each field will be treated as if [MinVersion=ordinal+1] is set:
+ #
+ # struct Foo {
+ # int32 field_0;
+ # int32 field_1;
+ # }
+ #
+ # is treated as:
+ #
+ # struct Foo {
+ # [MinVersion=1] int32 field_0;
+ # [MinVersion=2] int32 field_1;
+ # }
+ #
+ # This way |num_fields| is the same value as |version|.
+ #
+ # This trick needs to be removed once the conversion is done.
+
+ if any(packed_field.field.min_version is not None
+ for packed_field in src_fields):
+ # This struct has fields that explicitly set [MinVersion]. Assume that it
+ # is only handled by code that understands versioning.
+ next_min_version = 0
+ for packed_field in src_fields:
+ if packed_field.field.min_version is None:
+ assert next_min_version == 0
+ else:
+ assert packed_field.field.min_version >= next_min_version
+ next_min_version = packed_field.field.min_version
+ packed_field.min_version = next_min_version
+ else:
+ next_min_version = 1
+ for packed_field in src_fields:
+ packed_field.min_version = next_min_version
+ next_min_version += 1
+
src_field = src_fields[0]
src_field.offset = 0
src_field.bit = 0
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
index 88bd269..8fbc86d 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
@@ -55,9 +55,13 @@ def _MapKind(kind):
return map_to_kind[kind]
return 'x:' + kind
+def _AddOptional(dictionary, key, value):
+ if value is not None:
+ dictionary[key] = value;
+
def _AttributeListToDict(attribute_list):
if attribute_list is None:
- return {}
+ return None
assert isinstance(attribute_list, ast.AttributeList)
# TODO(vtl): Check for duplicate keys here.
return dict([(attribute.key, attribute.value)
@@ -66,12 +70,17 @@ def _AttributeListToDict(attribute_list):
def _EnumToDict(enum):
def EnumValueToDict(enum_value):
assert isinstance(enum_value, ast.EnumValue)
- return {'name': enum_value.name,
- 'value': enum_value.value}
+ data = {'name': enum_value.name}
+ _AddOptional(data, 'value', enum_value.value)
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(enum_value.attribute_list))
+ return data
assert isinstance(enum, ast.Enum)
- return {'name': enum.name,
+ data = {'name': enum.name,
'fields': map(EnumValueToDict, enum.enum_value_list)}
+ _AddOptional(data, 'attributes', _AttributeListToDict(enum.attribute_list))
+ return data
def _ConstToDict(const):
assert isinstance(const, ast.Const)
@@ -88,71 +97,90 @@ class _MojomBuilder(object):
def StructToDict(struct):
def StructFieldToDict(struct_field):
assert isinstance(struct_field, ast.StructField)
- return {'name': struct_field.name,
- 'kind': _MapKind(struct_field.typename),
- 'ordinal': struct_field.ordinal.value \
- if struct_field.ordinal else None,
- 'default': struct_field.default_value}
+ data = {'name': struct_field.name,
+ 'kind': _MapKind(struct_field.typename)}
+ _AddOptional(data, 'ordinal',
+ struct_field.ordinal.value
+ if struct_field.ordinal else None)
+ _AddOptional(data, 'default', struct_field.default_value)
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(struct_field.attribute_list))
+ return data
assert isinstance(struct, ast.Struct)
- return {'name': struct.name,
- 'attributes': _AttributeListToDict(struct.attribute_list),
+ data = {'name': struct.name,
'fields': _MapTreeForType(StructFieldToDict, struct.body,
ast.StructField),
'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum),
'constants': _MapTreeForType(_ConstToDict, struct.body,
ast.Const)}
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(struct.attribute_list))
+ return data
def UnionToDict(union):
def UnionFieldToDict(union_field):
assert isinstance(union_field, ast.UnionField)
- return {'name': union_field.name,
- 'kind': _MapKind(union_field.typename),
- 'ordinal': union_field.ordinal.value \
- if union_field.ordinal else None}
+ data = {'name': union_field.name,
+ 'kind': _MapKind(union_field.typename)}
+ _AddOptional(data, 'ordinal',
+ union_field.ordinal.value
+ if union_field.ordinal else None)
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(union_field.attribute_list))
+ return data
+
assert isinstance(union, ast.Union)
- return {'name': union.name,
+ data = {'name': union.name,
'fields': _MapTreeForType(UnionFieldToDict, union.body,
ast.UnionField)}
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(union.attribute_list))
+ return data
def InterfaceToDict(interface):
def MethodToDict(method):
def ParameterToDict(param):
assert isinstance(param, ast.Parameter)
- return {'name': param.name,
- 'kind': _MapKind(param.typename),
- 'ordinal': param.ordinal.value if param.ordinal else None}
+ data = {'name': param.name,
+ 'kind': _MapKind(param.typename)}
+ _AddOptional(data, 'ordinal',
+ param.ordinal.value if param.ordinal else None)
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(param.attribute_list))
+ return data
assert isinstance(method, ast.Method)
- rv = {'name': method.name,
- 'parameters': map(ParameterToDict, method.parameter_list),
- 'ordinal': method.ordinal.value if method.ordinal else None}
+ data = {'name': method.name,
+ 'parameters': map(ParameterToDict, method.parameter_list)}
if method.response_parameter_list is not None:
- rv['response_parameters'] = map(ParameterToDict,
- method.response_parameter_list)
- return rv
+ data['response_parameters'] = map(ParameterToDict,
+ method.response_parameter_list)
+ _AddOptional(data, 'ordinal',
+ method.ordinal.value if method.ordinal else None)
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(method.attribute_list))
+ return data
assert isinstance(interface, ast.Interface)
- attributes = _AttributeListToDict(interface.attribute_list)
- return {'name': interface.name,
- 'attributes': attributes,
- 'client': attributes.get('Client'),
+ data = {'name': interface.name,
'methods': _MapTreeForType(MethodToDict, interface.body,
ast.Method),
'enums': _MapTreeForType(_EnumToDict, interface.body, ast.Enum),
'constants': _MapTreeForType(_ConstToDict, interface.body,
ast.Const)}
+ _AddOptional(data, 'attributes',
+ _AttributeListToDict(interface.attribute_list))
+ return data
assert isinstance(tree, ast.Mojom)
self.mojom['name'] = name
self.mojom['namespace'] = tree.module.name[1] if tree.module else ''
self.mojom['imports'] = \
[{'filename': imp.import_filename} for imp in tree.import_list]
- self.mojom['attributes'] = \
- _AttributeListToDict(tree.module.attribute_list) if tree.module else {}
self.mojom['structs'] = \
_MapTreeForType(StructToDict, tree.definition_list, ast.Struct)
- self.mojom['union'] = \
+ self.mojom['unions'] = \
_MapTreeForType(UnionToDict, tree.definition_list, ast.Union)
self.mojom['interfaces'] = \
_MapTreeForType(InterfaceToDict, tree.definition_list, ast.Interface)
@@ -160,6 +188,9 @@ class _MojomBuilder(object):
_MapTreeForType(_EnumToDict, tree.definition_list, ast.Enum)
self.mojom['constants'] = \
_MapTreeForType(_ConstToDict, tree.definition_list, ast.Const)
+ _AddOptional(self.mojom, 'attributes',
+ _AttributeListToDict(tree.module.attribute_list)
+ if tree.module else None)
return self.mojom
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/fileutil_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/fileutil_unittest.py
new file mode 100644
index 0000000..d56faad
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/fileutil_unittest.py
@@ -0,0 +1,55 @@
+# Copyright 2015 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.
+
+import imp
+import os.path
+import shutil
+import sys
+import tempfile
+import unittest
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("mojom")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
+from mojom import fileutil
+
+
+class FileUtilTest(unittest.TestCase):
+
+ def testEnsureDirectoryExists(self):
+ """Test that EnsureDirectoryExists fuctions correctly."""
+
+ temp_dir = tempfile.mkdtemp()
+ try:
+ self.assertTrue(os.path.exists(temp_dir))
+
+ # Directory does not exist, yet.
+ full = os.path.join(temp_dir, "foo", "bar")
+ self.assertFalse(os.path.exists(full))
+
+ # Create the directory.
+ fileutil.EnsureDirectoryExists(full)
+ self.assertTrue(os.path.exists(full))
+
+ # Trying to create it again does not cause an error.
+ fileutil.EnsureDirectoryExists(full)
+ self.assertTrue(os.path.exists(full))
+
+ # Bypass check for directory existence to tickle error handling that
+ # occurs in response to a race.
+ fileutil.EnsureDirectoryExists(full, always_try_to_create=True)
+ self.assertTrue(os.path.exists(full))
+ finally:
+ shutil.rmtree(temp_dir)
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py
index 9ad63c1..90c90e3 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py
@@ -32,7 +32,6 @@ class DataTest(unittest.TestCase):
module = mojom.Module('test_module', 'test_namespace')
struct_data = {
'name': 'SomeStruct',
- 'attributes': [],
'enums': [],
'constants': [],
'fields': [
@@ -41,9 +40,6 @@ class DataTest(unittest.TestCase):
{'name': 'field3', 'kind': 'i32', 'default': 15}]}
struct = data.StructFromData(module, struct_data)
- del struct_data['attributes']
- del struct_data['enums']
- del struct_data['constants']
struct.fields = map(lambda field:
data.FieldFromData(module, field, struct), struct.fields_data)
self.assertEquals(struct_data, data.StructToData(struct))
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py
new file mode 100644
index 0000000..329e242
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py
@@ -0,0 +1,54 @@
+# Copyright 2015 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.
+
+import imp
+import os.path
+import sys
+import unittest
+
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+
+try:
+ imp.find_module("mojom")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
+from mojom.generate import pack
+from mojom.generate import module as mojom
+
+
+# TODO(yzshen): Move tests in pack_tests.py here.
+class PackTest(unittest.TestCase):
+
+ def testMinVersion(self):
+ """Tests that |min_version| is properly set for packed fields."""
+ struct = mojom.Struct('test')
+ struct.AddField('field_2', mojom.BOOL, 2)
+ struct.AddField('field_0', mojom.INT32, 0)
+ struct.AddField('field_1', mojom.INT64, 1)
+ ps = pack.PackedStruct(struct)
+
+ self.assertEquals("field_0", ps.packed_fields[0].field.name)
+ self.assertEquals("field_2", ps.packed_fields[1].field.name)
+ self.assertEquals("field_1", ps.packed_fields[2].field.name)
+
+ self.assertEquals(1, ps.packed_fields[0].min_version)
+ self.assertEquals(3, ps.packed_fields[1].min_version)
+ self.assertEquals(2, ps.packed_fields[2].min_version)
+
+ struct.fields[0].attributes = {'MinVersion': 1}
+ ps = pack.PackedStruct(struct)
+
+ self.assertEquals(0, ps.packed_fields[0].min_version)
+ self.assertEquals(1, ps.packed_fields[1].min_version)
+ self.assertEquals(0, ps.packed_fields[2].min_version)
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py
index 20704dc..29dd906 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py
@@ -54,11 +54,10 @@ class TranslateTest(unittest.TestCase):
ast.UnionField("b", None, None, "string")]))])
expected = [{
"name": "SomeUnion",
- "fields": [
- {"kind": "i32", "name": "a", "ordinal": None},
- {"kind": "s", "name": "b", "ordinal": None}]}]
+ "fields": [{"kind": "i32", "name": "a"},
+ {"kind": "s", "name": "b"}]}]
actual = translate.Translate(tree, "mojom_tree")
- self.assertEquals(actual["union"], expected)
+ self.assertEquals(actual["unions"], expected)
if __name__ == "__main__":