summaryrefslogtreecommitdiffstats
path: root/third_party/mojo
diff options
context:
space:
mode:
authorviettrungluu <viettrungluu@chromium.org>2015-02-09 18:03:35 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-10 02:04:27 +0000
commit17e878ce6362ffe65a0893b601960f86556d6237 (patch)
tree4699c82c1395d5fbc33063c932522bd3f03f53d1 /third_party/mojo
parentc2a67e9610872a125819c8d4544b720606346a94 (diff)
downloadchromium_src-17e878ce6362ffe65a0893b601960f86556d6237.zip
chromium_src-17e878ce6362ffe65a0893b601960f86556d6237.tar.gz
chromium_src-17e878ce6362ffe65a0893b601960f86556d6237.tar.bz2
Update mojo sdk to rev 8af2ccff2eee4bfca1043015abee30482a030b30
Also apply mojo 8fda9302f51f99dc25e6e0c95cfd0a04e1adc802 (https://codereview.chromium.org/902783004/). Also apply mojo e62ed5fbf8bb4d7cfa87f499b1d1b50bdf8e0b3b (https://codereview.chromium.org/905253005/). Also apply dcf5a5e1dbccb91f774d545b5f31d06042d8a8e3 (https://codereview.chromium.org/909903003/). Also apply 9f87aeadbda22441b7d469e596f7bd7d0d73e2a8 (https://codereview.chromium.org/908973002/). (Reland of https://crrev.com/2e86fb9356e3a693762d3c86c70e63951bd9d1be a.k.a. refs/heads/master@{#315432}.) TBR=jamesr@chromium.org NOPRESUBMIT=true CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win8_chromium_gn_dbg,win8_chromium_gn_rel Review URL: https://codereview.chromium.org/910883002 Cr-Commit-Position: refs/heads/master@{#315471}
Diffstat (limited to 'third_party/mojo')
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.cc74
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.h33
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder_internal.h9
-rw-r--r--third_party/mojo/src/mojo/edk/js/BUILD.gn18
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_endpoint.cc4
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_info.cc3
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.cc67
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.h28
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc28
-rw-r--r--third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc33
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.cc22
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.h34
-rw-r--r--third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc4
-rw-r--r--third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc22
-rw-r--r--third_party/mojo/src/mojo/edk/system/slave_connection_manager.h32
-rw-r--r--third_party/mojo/src/mojo/public/VERSION2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn1
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc12
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc128
-rw-r--r--third_party/mojo/src/mojo/public/go/system/core.go28
-rw-r--r--third_party/mojo/src/mojo/public/go/system/data_pipe.go18
-rw-r--r--third_party/mojo/src/mojo/public/go/system/handle.go4
-rw-r--r--third_party/mojo/src/mojo/public/go/system/message_pipe.go8
-rw-r--r--third_party/mojo/src/mojo/public/go/system/mojo_types.go52
-rw-r--r--third_party/mojo/src/mojo/public/go/system/shared_buffer.go9
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom4
-rw-r--r--third_party/mojo/src/mojo/public/js/connection.js15
-rw-r--r--third_party/mojo/src/mojo/public/mojo_application.gni10
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py68
-rw-r--r--third_party/mojo/src/mojo/public/tools/BUILD.gn15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl13
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl16
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl25
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl7
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl5
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl50
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl54
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl10
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl43
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl4
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl22
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/enum.tmpl20
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl14
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl30
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl219
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py9
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py189
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py34
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl3
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/mojom.gni11
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/data.py3
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py27
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py14
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py90
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py37
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py42
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/download_shell_binary.py55
66 files changed, 1475 insertions, 401 deletions
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
index 0150dcb..d0a5135 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
@@ -13,7 +13,6 @@
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/embedder/platform_support.h"
#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/channel_manager.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/core.h"
@@ -55,9 +54,15 @@ namespace internal {
PlatformSupport* g_platform_support = nullptr;
system::Core* g_core = nullptr;
system::ChannelManager* g_channel_manager = nullptr;
+MasterProcessDelegate* g_master_process_delegate = nullptr;
+SlaveProcessDelegate* g_slave_process_delegate = nullptr;
} // namespace internal
+Configuration* GetConfiguration() {
+ return system::GetMutableConfiguration();
+}
+
void Init(scoped_ptr<PlatformSupport> platform_support) {
DCHECK(platform_support);
@@ -72,8 +77,27 @@ void Init(scoped_ptr<PlatformSupport> platform_support) {
new system::ChannelManager(internal::g_platform_support);
}
-Configuration* GetConfiguration() {
- return system::GetMutableConfiguration();
+void InitMaster(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ MasterProcessDelegate* master_process_delegate,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner) {
+ // |Init()| must have already been called.
+ DCHECK(internal::g_core);
+
+ // TODO(vtl): This is temporary. We really want to construct a
+ // |MasterConnectionManager| here, which will in turn hold on to the delegate.
+ internal::g_master_process_delegate = master_process_delegate;
+}
+
+void InitSlave(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ SlaveProcessDelegate* slave_process_delegate,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ ScopedPlatformHandle platform_handle) {
+ // |Init()| must have already been called.
+ DCHECK(internal::g_core);
+
+ // TODO(vtl): This is temporary. We really want to construct a
+ // |SlaveConnectionManager| here, which will in turn hold on to the delegate.
+ internal::g_slave_process_delegate = slave_process_delegate;
}
// TODO(vtl): Write tests for this.
@@ -83,18 +107,16 @@ ScopedMessagePipeHandle CreateChannelOnIOThread(
DCHECK(platform_handle.is_valid());
DCHECK(channel_info);
- scoped_refptr<system::ChannelEndpoint> channel_endpoint;
+ *channel_info = new ChannelInfo(MakeChannelId());
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
+ internal::g_channel_manager->CreateChannelOnIOThread(
+ (*channel_info)->channel_id, platform_handle.Pass());
- DCHECK(internal::g_core);
ScopedMessagePipeHandle rv(
MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
-
- *channel_info = new ChannelInfo(MakeChannelId());
- internal::g_channel_manager->CreateChannelOnIOThread(
- (*channel_info)->channel_id, platform_handle.Pass(), channel_endpoint);
-
+ CHECK(rv.is_valid());
+ // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it
+ // once that's fixed.
return rv.Pass();
}
@@ -107,31 +129,19 @@ ScopedMessagePipeHandle CreateChannel(
DCHECK(io_thread_task_runner);
DCHECK(!callback.is_null());
- scoped_refptr<system::ChannelEndpoint> channel_endpoint;
+ system::ChannelId channel_id = MakeChannelId();
+ scoped_ptr<ChannelInfo> channel_info(new ChannelInfo(channel_id));
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
+ internal::g_channel_manager->CreateChannel(
+ channel_id, platform_handle.Pass(), io_thread_task_runner,
+ base::Bind(callback, base::Unretained(channel_info.release())),
+ callback_thread_task_runner);
- DCHECK(internal::g_core);
ScopedMessagePipeHandle rv(
MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
-
- // We'll have to set |channel_info->channel_id| on the I/O thread.
- scoped_ptr<ChannelInfo> channel_info(new ChannelInfo());
-
- if (rv.is_valid()) {
- 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 ? callback_thread_task_runner
- : io_thread_task_runner)
- ->PostTask(FROM_HERE, base::Bind(callback, channel_info.release()));
- }
-
+ CHECK(rv.is_valid());
+ // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it
+ // once that's fixed.
return rv.Pass();
}
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h
index cc0ad26..4898ae1 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.h
@@ -18,15 +18,42 @@ namespace mojo {
namespace embedder {
struct Configuration;
+class MasterProcessDelegate;
class PlatformSupport;
+class SlaveProcessDelegate;
+
+// 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();
// 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, 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();
+// Initializes a master process. To be called after |Init()|.
+// |master_process_delegate| should live forever (or until after
+// |mojo::embedder::test::Shutdown()|); its methods will be called using
+// |delegate_thread_task_runner|, which must be the task runner for the thread
+// calling |InitMaster()|. |io_thread_task_runner| should be the task runner for
+// some I/O thread; this should be the same as that provided to
+// |CreateChannel()| (or on which |CreateChannelOnIOThread()| is called).
+// TODO(vtl): Remove the |io_thread_task_runner| argument from
+// |CreateChannel()| (and eventually |CreateChannel()| altogether) and require
+// that either this or |InitSlave()| be called. Currently, |CreateChannel()| can
+// be used with different I/O threads, but this capability will be removed.
+MOJO_SYSTEM_IMPL_EXPORT void InitMaster(
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ MasterProcessDelegate* master_process_delegate,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner);
+
+// Initializes a slave process. Similar to |InitMaster()| (see above).
+// |platform_handle| should be connected to the handle passed to |AddSlave()|.
+// TODO(vtl): |AddSlave()| doesn't exist yet.
+MOJO_SYSTEM_IMPL_EXPORT void InitSlave(
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ SlaveProcessDelegate* slave_process_delegate,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ ScopedPlatformHandle platform_handle);
// A "channel" is a connection on top of an OS "pipe", on top of which Mojo
// message pipes (etc.) can be multiplexed. It must "live" on some I/O thread.
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 536e0db..7d90148 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
@@ -26,6 +26,9 @@ typedef uint64_t ChannelId;
namespace embedder {
class PlatformSupport;
+// TODO(vtl): Remove these (see below).
+class MasterProcessDelegate;
+class SlaveProcessDelegate;
// 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
@@ -49,6 +52,12 @@ extern system::Core* g_core;
// (|mojo::embedder::CreateChannel()|, etc.).
extern system::ChannelManager* g_channel_manager;
+// TODO(vtl): Remove these: We'll eventually really want to hold on to a
+// |MasterConnectionManager*| or a |SlaveConnectionManager*|. For now, keep
+// these around as globals to avoid triggering leak detectors.
+extern MasterProcessDelegate* g_master_process_delegate;
+extern SlaveProcessDelegate* g_slave_process_delegate;
+
} // namespace internal
} // namepace embedder
diff --git a/third_party/mojo/src/mojo/edk/js/BUILD.gn b/third_party/mojo/src/mojo/edk/js/BUILD.gn
index 9a066d3..ed1b81f 100644
--- a/third_party/mojo/src/mojo/edk/js/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/js/BUILD.gn
@@ -4,6 +4,20 @@
import("../mojo_edk.gni")
+# TODO(hansmuller): The organization of tests in this directory is weird:
+# * Really, js_unittests tests public stuff, so that should live in public
+# and be reworked as some sort of apptest.
+# * Both js_unittests and js_integration_tests should auto-generate their
+# tests somehow. The .cc files are just test runner stubs, including
+# explicit lists of .js files.
+group("tests") {
+ testonly = true
+ deps = [
+ "test:js_unittests",
+ "test:js_integration_tests",
+ ]
+}
+
mojo_edk_source_set("js") {
sources = [
"core.cc",
@@ -50,7 +64,5 @@ mojo_edk_source_set("js_unittests") {
"mojo/edk/test:test_support",
]
- mojo_sdk_deps = [
- "mojo/public/cpp/system",
- ]
+ mojo_sdk_deps = [ "mojo/public/cpp/system" ]
}
diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
index 8ef1f40..0e071d8 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
@@ -82,8 +82,8 @@ void ChannelEndpoint::AttachAndRun(Channel* channel,
remote_id_ = remote_id;
while (!channel_message_queue_.IsEmpty()) {
- LOG_IF(WARNING, !WriteMessageNoLock(channel_message_queue_.GetMessage()))
- << "Failed to write enqueue message to channel";
+ bool ok = WriteMessageNoLock(channel_message_queue_.GetMessage());
+ LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel";
}
if (!client_) {
diff --git a/third_party/mojo/src/mojo/edk/system/channel_info.cc b/third_party/mojo/src/mojo/edk/system/channel_info.cc
index 6d23215..e2c69e6 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_info.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_info.cc
@@ -6,6 +6,9 @@
#include <algorithm>
+#include "base/task_runner.h"
+#include "mojo/edk/system/channel.h"
+
namespace mojo {
namespace system {
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 c2fe8a5..634accc 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.cc
@@ -9,6 +9,9 @@
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/task_runner.h"
+#include "mojo/edk/system/channel.h"
+#include "mojo/edk/system/channel_endpoint.h"
+#include "mojo/edk/system/message_pipe_dispatcher.h"
namespace mojo {
namespace system {
@@ -38,33 +41,21 @@ ChannelManager::~ChannelManager() {
ShutdownChannelHelper(map_elem.second);
}
-void ChannelManager::CreateChannelOnIOThread(
+scoped_refptr<MessagePipeDispatcher> 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_);
- CHECK(channel_infos_.find(channel_id) == channel_infos_.end());
- channel_infos_[channel_id] =
- ChannelInfo(channel, base::MessageLoopProxy::current());
- }
- channel->SetChannelManager(this);
+ embedder::ScopedPlatformHandle platform_handle) {
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint;
+ scoped_refptr<system::MessagePipeDispatcher> dispatcher =
+ system::MessagePipeDispatcher::CreateRemoteMessagePipe(
+ &bootstrap_channel_endpoint);
+ CreateChannelOnIOThreadHelper(channel_id, platform_handle.Pass(),
+ bootstrap_channel_endpoint);
+ return dispatcher;
}
-void ChannelManager::CreateChannel(
+scoped_refptr<MessagePipeDispatcher> 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) {
@@ -72,12 +63,17 @@ void ChannelManager::CreateChannel(
DCHECK(!callback.is_null());
// (|callback_thread_task_runner| may be null.)
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint;
+ scoped_refptr<system::MessagePipeDispatcher> dispatcher =
+ system::MessagePipeDispatcher::CreateRemoteMessagePipe(
+ &bootstrap_channel_endpoint);
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));
+ return dispatcher;
}
scoped_refptr<Channel> ChannelManager::GetChannel(ChannelId channel_id) const {
@@ -103,14 +99,37 @@ void ChannelManager::ShutdownChannel(ChannelId channel_id) {
ShutdownChannelHelper(channel_info);
}
+void ChannelManager::CreateChannelOnIOThreadHelper(
+ 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_);
+ CHECK(channel_infos_.find(channel_id) == channel_infos_.end());
+ channel_infos_[channel_id] =
+ ChannelInfo(channel, base::MessageLoopProxy::current());
+ }
+ channel->SetChannelManager(this);
+}
+
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);
+ CreateChannelOnIOThreadHelper(channel_id, platform_handle.Pass(),
+ bootstrap_channel_endpoint);
if (callback_thread_task_runner)
callback_thread_task_runner->PostTask(FROM_HERE, callback);
else
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 35a4f27..da3e030 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.h
@@ -7,12 +7,12 @@
#include <stdint.h>
+#include "base/callback_forward.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_info.h"
namespace base {
@@ -27,6 +27,10 @@ class PlatformSupport;
namespace system {
+class Channel;
+class ChannelEndpoint;
+class MessagePipeDispatcher;
+
// 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.
typedef uint64_t ChannelId;
@@ -49,27 +53,21 @@ class MOJO_SYSTEM_IMPL_EXPORT 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(
+ scoped_refptr<MessagePipeDispatcher> CreateChannelOnIOThread(
ChannelId channel_id,
- embedder::ScopedPlatformHandle platform_handle,
- scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint);
+ embedder::ScopedPlatformHandle platform_handle);
// 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| is null else by posted 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(
+ scoped_refptr<MessagePipeDispatcher> 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);
@@ -92,6 +90,14 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
void ShutdownChannel(ChannelId channel_id);
private:
+ // Used by |CreateChannelOnIOThread()| and |CreateChannelHelper()|. Called on
+ // the I/O thread.
+ void CreateChannelOnIOThreadHelper(
+ ChannelId channel_id,
+ embedder::ScopedPlatformHandle platform_handle,
+ scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint);
+
+ // Used by |CreateChannel()|. Called on the I/O thread.
void CreateChannelHelper(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
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 c5aa503..86ab4a0 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
@@ -48,12 +48,9 @@ TEST_F(ChannelManagerTest, Basic) {
embedder::PlatformChannelPair channel_pair;
- 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<MessagePipeDispatcher> d =
+ cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle());
scoped_refptr<Channel> ch = cm.GetChannel(id);
EXPECT_TRUE(ch);
@@ -77,19 +74,13 @@ TEST_F(ChannelManagerTest, TwoChannels) {
embedder::PlatformChannelPair channel_pair;
- 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<MessagePipeDispatcher> d1 =
+ cm.CreateChannelOnIOThread(id1, channel_pair.PassServerHandle());
- scoped_refptr<ChannelEndpoint> cep2;
- scoped_refptr<MessagePipeDispatcher> d2 =
- MessagePipeDispatcher::CreateRemoteMessagePipe(&cep2);
const ChannelId id2 = 2;
- cm.CreateChannelOnIOThread(id2, channel_pair.PassClientHandle(), cep2);
- cep2 = nullptr;
+ scoped_refptr<MessagePipeDispatcher> d2 =
+ cm.CreateChannelOnIOThread(id2, channel_pair.PassClientHandle());
scoped_refptr<Channel> ch1 = cm.GetChannel(id1);
EXPECT_TRUE(ch1);
@@ -173,12 +164,9 @@ TEST_F(ChannelManagerTest, CallsFromOtherThread) {
embedder::PlatformChannelPair channel_pair;
- 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<MessagePipeDispatcher> d =
+ cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle());
base::RunLoop run_loop;
OtherThread thread(base::MessageLoopProxy::current(), &cm, id,
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 2894c65..f1939a0 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
@@ -87,7 +87,8 @@ void ConnectSlave(MasterConnectionManager* master,
embedder::PlatformChannelPair platform_channel_pair;
master->AddSlave(make_scoped_ptr(new TestSlaveInfo(slave_name)),
platform_channel_pair.PassServerHandle());
- slave->Init(slave_process_delegate, platform_channel_pair.PassClientHandle());
+ slave->Init(base::MessageLoop::current()->task_runner(),
+ slave_process_delegate, platform_channel_pair.PassClientHandle());
}
class MockMasterProcessDelegate : public embedder::MasterProcessDelegate {
@@ -191,7 +192,8 @@ class ConnectionManagerTest : public testing::Test {
TEST_F(ConnectionManagerTest, BasicConnectSlaves) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave1_process_delegate;
SlaveConnectionManager slave1;
@@ -250,7 +252,8 @@ TEST_F(ConnectionManagerTest, BasicConnectSlaves) {
TEST_F(ConnectionManagerTest, ShutdownMasterBeforeSlave) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
@@ -277,7 +280,8 @@ TEST_F(ConnectionManagerTest, ShutdownMasterBeforeSlave) {
TEST_F(ConnectionManagerTest, SlaveCancelConnect) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave1_process_delegate;
SlaveConnectionManager slave1;
@@ -306,7 +310,8 @@ TEST_F(ConnectionManagerTest, SlaveCancelConnect) {
// Tests that pending connections are removed on error.
TEST_F(ConnectionManagerTest, ErrorRemovePending) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave1_process_delegate;
SlaveConnectionManager slave1;
@@ -340,7 +345,8 @@ TEST_F(ConnectionManagerTest, ErrorRemovePending) {
TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
@@ -371,7 +377,8 @@ TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) {
TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave1_process_delegate;
SlaveConnectionManager slave1;
@@ -422,7 +429,8 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
TEST_F(ConnectionManagerTest, ConnectMasterToSlave) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
@@ -452,7 +460,8 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSlave) {
TEST_F(ConnectionManagerTest, ConnectMasterToSelf) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
EXPECT_TRUE(master.AllowConnect(connection_id));
@@ -478,7 +487,8 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSelf) {
TEST_F(ConnectionManagerTest, MasterCancelConnect) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
@@ -501,7 +511,8 @@ TEST_F(ConnectionManagerTest, MasterCancelConnect) {
TEST_F(ConnectionManagerTest, AddSlaveThenImmediateShutdown) {
MasterConnectionManager master;
- master.Init(&master_process_delegate());
+ master.Init(base::MessageLoop::current()->task_runner(),
+ &master_process_delegate());
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
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 4d7deae..b401bcd 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
@@ -220,16 +220,13 @@ struct MasterConnectionManager::PendingConnectionInfo {
// MasterConnectionManager -----------------------------------------------------
MasterConnectionManager::MasterConnectionManager()
- : creation_thread_task_runner_(base::MessageLoop::current()->task_runner()),
- master_process_delegate_(),
+ : master_process_delegate_(),
private_thread_("MasterConnectionManagerPrivateThread"),
next_process_identifier_(kFirstSlaveProcessIdentifier) {
- DCHECK(creation_thread_task_runner_);
- AssertOnCreationThread(); // Just make sure this assertion works correctly.
}
MasterConnectionManager::~MasterConnectionManager() {
- AssertOnCreationThread();
+ DCHECK(!delegate_thread_task_runner_);
DCHECK(!master_process_delegate_);
DCHECK(!private_thread_.message_loop());
DCHECK(helpers_.empty());
@@ -237,19 +234,23 @@ MasterConnectionManager::~MasterConnectionManager() {
}
void MasterConnectionManager::Init(
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
embedder::MasterProcessDelegate* master_process_delegate) {
- AssertOnCreationThread();
+ DCHECK(delegate_thread_task_runner);
DCHECK(master_process_delegate);
+ DCHECK(!delegate_thread_task_runner_);
DCHECK(!master_process_delegate_);
DCHECK(!private_thread_.message_loop());
+ delegate_thread_task_runner_ = delegate_thread_task_runner;
+ AssertOnDelegateThread();
master_process_delegate_ = master_process_delegate;
CHECK(private_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
}
void MasterConnectionManager::Shutdown() {
- AssertOnCreationThread();
+ AssertOnDelegateThread();
DCHECK(master_process_delegate_);
DCHECK(private_thread_.message_loop());
@@ -261,6 +262,7 @@ void MasterConnectionManager::Shutdown() {
DCHECK(helpers_.empty());
DCHECK(pending_connections_.empty());
master_process_delegate_ = nullptr;
+ delegate_thread_task_runner_ = nullptr;
}
void MasterConnectionManager::AddSlave(
@@ -547,16 +549,16 @@ void MasterConnectionManager::CallOnSlaveDisconnect(
scoped_ptr<embedder::SlaveInfo> slave_info) {
AssertOnPrivateThread();
DCHECK(master_process_delegate_);
- creation_thread_task_runner_->PostTask(
+ delegate_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&embedder::MasterProcessDelegate::OnSlaveDisconnect,
base::Unretained(master_process_delegate_),
base::Passed(&slave_info)));
}
-void MasterConnectionManager::AssertOnCreationThread() const {
+void MasterConnectionManager::AssertOnDelegateThread() const {
DCHECK(base::MessageLoop::current());
DCHECK_EQ(base::MessageLoop::current()->task_runner(),
- creation_thread_task_runner_);
+ delegate_thread_task_runner_);
}
void MasterConnectionManager::AssertNotOnPrivateThread() const {
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 978d9fe..5bdb810 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
@@ -35,10 +35,10 @@ const ProcessIdentifier kMasterProcessIdentifier = 1;
// The |ConnectionManager| implementation for the master process.
//
-// Objects of this class must be created, initialized (via |Init()|), shut down
-// (via |Shutdown()|), and destroyed on the same thread (the "creation thread").
-// Otherwise, its public methods are thread-safe (except that they may not be
-// called from its internal, private thread).
+// Objects of this class may be created and destroyed on any thread. However,
+// |Init()| and |Shutdown()| must be called on the "delegate thread". Otherwise,
+// its public methods are thread-safe (except that they may not be called from
+// its internal, private thread).
class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
: public ConnectionManager {
public:
@@ -48,10 +48,11 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
~MasterConnectionManager() override;
// No other methods may be called until after this has been called.
- // |master_process_delegate| must stay alive at least until after |Shutdown()|
- // has been called; its methods will be called on this object's creation
- // thread.
- void Init(embedder::MasterProcessDelegate* master_process_delegate);
+ // |delegate_thread_task_runner| should be the task runner for the "delegate
+ // thread", on which |master_process_delegate|'s methods will be called. Both
+ // must stay alive at least until after |Shutdown()| has been called.
+ void Init(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ embedder::MasterProcessDelegate* master_process_delegate);
// No other methods may be called after this is (or while it is being) called.
void Shutdown();
@@ -96,10 +97,10 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
// Posts a call to |master_process_delegate_->OnSlaveDisconnect()|.
void CallOnSlaveDisconnect(scoped_ptr<embedder::SlaveInfo> slave_info);
- // Asserts that the current thread is the creation thread. (This actually
- // checks the current message loop, which is what we depend on, not the thread
- // per se.)
- void AssertOnCreationThread() const;
+ // Asserts that the current thread is the delegate thread. (This actually
+ // checks the current message loop.)
+ // TODO(vtl): Probably we should actually check the thread.
+ void AssertOnDelegateThread() const;
// Asserts that the current thread is *not* |private_thread_| (no-op if
// DCHECKs are not enabled). This should only be called while
@@ -111,12 +112,11 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
// (i.e., after |Init()| but before |Shutdown()|).
void AssertOnPrivateThread() const;
- const scoped_refptr<base::TaskRunner> creation_thread_task_runner_;
-
- // This is set in |Init()| before |private_thread_| exists and only cleared in
- // |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on
+ // These are set in |Init()| before |private_thread_| exists and only cleared
+ // in |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on
// |private_thread_|. (Note that |master_process_delegate_| may only be called
- // from the creation thread.)
+ // from the delegate thread.)
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner_;
embedder::MasterProcessDelegate* master_process_delegate_;
// This is a private I/O thread on which this class does the bulk of its work.
diff --git a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc b/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc
index 5f0f2e9..ce96f24 100644
--- a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc
+++ b/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc
@@ -46,8 +46,8 @@ bool ProxyMessagePipeEndpoint::OnPeerClose() {
void ProxyMessagePipeEndpoint::EnqueueMessage(
scoped_ptr<MessageInTransit> message) {
DCHECK(channel_endpoint_);
- LOG_IF(WARNING, !channel_endpoint_->EnqueueMessage(message.Pass()))
- << "Failed to write enqueue message to channel";
+ bool ok = channel_endpoint_->EnqueueMessage(message.Pass());
+ LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel";
}
void ProxyMessagePipeEndpoint::Close() {
diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
index 2427823..de8d17f 100644
--- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
@@ -17,20 +17,17 @@ namespace system {
// SlaveConnectionManager ------------------------------------------------------
SlaveConnectionManager::SlaveConnectionManager()
- : creation_thread_task_runner_(base::MessageLoop::current()->task_runner()),
- slave_process_delegate_(),
+ : slave_process_delegate_(),
private_thread_("SlaveConnectionManagerPrivateThread"),
awaiting_ack_type_(NOT_AWAITING_ACK),
ack_result_(),
ack_peer_process_identifier_(),
ack_platform_handle_(),
event_(false, false) { // Auto-reset, not initially signalled.
- DCHECK(creation_thread_task_runner_);
- AssertOnCreationThread(); // Just make sure this assertion works correctly.
}
SlaveConnectionManager::~SlaveConnectionManager() {
- AssertOnCreationThread();
+ DCHECK(!delegate_thread_task_runner_);
DCHECK(!slave_process_delegate_);
DCHECK(!private_thread_.message_loop());
DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK);
@@ -40,14 +37,18 @@ SlaveConnectionManager::~SlaveConnectionManager() {
}
void SlaveConnectionManager::Init(
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
embedder::SlaveProcessDelegate* slave_process_delegate,
embedder::ScopedPlatformHandle platform_handle) {
- AssertOnCreationThread();
+ DCHECK(delegate_thread_task_runner);
DCHECK(slave_process_delegate);
DCHECK(platform_handle.is_valid());
+ DCHECK(!delegate_thread_task_runner_);
DCHECK(!slave_process_delegate_);
DCHECK(!private_thread_.message_loop());
+ delegate_thread_task_runner_ = delegate_thread_task_runner;
+ AssertOnDelegateThread();
slave_process_delegate_ = slave_process_delegate;
CHECK(private_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
@@ -59,7 +60,7 @@ void SlaveConnectionManager::Init(
}
void SlaveConnectionManager::Shutdown() {
- AssertOnCreationThread();
+ AssertOnDelegateThread();
DCHECK(slave_process_delegate_);
DCHECK(private_thread_.message_loop());
@@ -69,6 +70,7 @@ void SlaveConnectionManager::Shutdown() {
base::Unretained(this)));
private_thread_.Stop();
slave_process_delegate_ = nullptr;
+ delegate_thread_task_runner_ = nullptr;
}
bool SlaveConnectionManager::AllowConnect(
@@ -287,15 +289,15 @@ void SlaveConnectionManager::OnError(Error error) {
raw_channel_.reset();
DCHECK(slave_process_delegate_);
- creation_thread_task_runner_->PostTask(
+ delegate_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&embedder::SlaveProcessDelegate::OnMasterDisconnect,
base::Unretained(slave_process_delegate_)));
}
-void SlaveConnectionManager::AssertOnCreationThread() const {
+void SlaveConnectionManager::AssertOnDelegateThread() const {
DCHECK(base::MessageLoop::current());
DCHECK_EQ(base::MessageLoop::current()->task_runner(),
- creation_thread_task_runner_);
+ delegate_thread_task_runner_);
}
void SlaveConnectionManager::AssertNotOnPrivateThread() const {
diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
index e773448..731d9db 100644
--- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
@@ -31,10 +31,10 @@ namespace system {
// The |ConnectionManager| implementation for slave processes.
//
-// Objects of this class must created, initialized (via |Init()|), shut down
-// (via |Shutdown()|), and destroyed on the same thread (the "creation thread").
-// Otherwise, its public methods are thread-safe (except that they may not be
-// called from its internal, private thread).
+// Objects of this class may be created and destroyed on any thread. However,
+// |Init()| and |Shutdown()| must be called on the "delegate thread". Otherwise,
+// its public methods are thread-safe (except that they may not be called from
+// its internal, private thread).
class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
: public ConnectionManager,
public RawChannel::Delegate {
@@ -45,10 +45,11 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
~SlaveConnectionManager() override;
// No other methods may be called until after this has been called.
- // |slave_process_delegate| must stay alive at least until after |Shutdown()|
- // has been called; its methods will be called on this object's creation
- // thread.
- void Init(embedder::SlaveProcessDelegate* slave_process_delegate,
+ // |delegate_thread_task_runner| should be the task runner for the "delegate
+ // thread", on which |slave_process_delegate|'s methods will be called. Both
+ // must stay alive at least until after |Shutdown()| has been called.
+ void Init(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ embedder::SlaveProcessDelegate* slave_process_delegate,
embedder::ScopedPlatformHandle platform_handle);
// No other methods may be called after this is (or while it is being) called.
@@ -80,10 +81,10 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
embedder::ScopedPlatformHandleVectorPtr platform_handles) override;
void OnError(Error error) override;
- // Asserts that the current thread is the creation thread. (This actually
- // checks the current message loop, which is what we depend on, not the thread
- // per se.)
- void AssertOnCreationThread() const;
+ // Asserts that the current thread is the delegate thread. (This actually
+ // checks the current message loop.)
+ // TODO(vtl): Probably we should actually check the thread.
+ void AssertOnDelegateThread() const;
// Asserts that the current thread is *not* |private_thread_| (no-op if
// DCHECKs are not enabled). This should only be called while
@@ -95,12 +96,11 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
// (i.e., after |Init()| but before |Shutdown()|).
void AssertOnPrivateThread() const;
- const scoped_refptr<base::TaskRunner> creation_thread_task_runner_;
-
- // These is set in |Init()| before |private_thread_| exists and only cleared
+ // These are set in |Init()| before |private_thread_| exists and only cleared
// in |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on
// |private_thread_|. (Note that |slave_process_delegate_| may only be called
- // from the creation thread.)
+ // from the delegate thread.)
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner_;
embedder::SlaveProcessDelegate* slave_process_delegate_;
// This is a private I/O thread on which this class does the bulk of its work.
diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION
index 63d6820..58655cc 100644
--- a/third_party/mojo/src/mojo/public/VERSION
+++ b/third_party/mojo/src/mojo/public/VERSION
@@ -1 +1 @@
-8d45c89c30b230843c5bd6dd0693a555750946c0 \ No newline at end of file
+8af2ccff2eee4bfca1043015abee30482a030b30 \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
index b065d90..d1d723a 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
@@ -42,6 +42,8 @@ const char* ValidationErrorToString(ValidationError error) {
return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID";
case VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP:
return "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP";
+ case VALIDATION_ERROR_UNKOWN_UNION_TAG:
+ return "VALIDATION_ERROR_UNKOWN_UNION_TAG";
}
return "Unknown error";
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
index 2abb1b7..4facf6e 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -46,7 +46,9 @@ enum ValidationError {
VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID,
// Two parallel arrays which are supposed to represent a map have different
// lengths.
- VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP
+ VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP,
+ // Attempted to deserialize a tagged union with an unknown tag.
+ VALIDATION_ERROR_UNKOWN_UNION_TAG
};
const char* ValidationErrorToString(ValidationError error);
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
index 0051270..b267e4e 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -24,6 +24,7 @@ mojo_sdk_source_set("tests") {
"string_unittest.cc",
"struct_unittest.cc",
"type_conversion_unittest.cc",
+ "union_unittest.cc",
"validation_unittest.cc",
]
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
index 4359be8..f2e693d 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -46,6 +46,18 @@ class SerializationWarningTest : public testing::Test {
template <typename T>
void TestWarning(StructPtr<T> obj,
mojo::internal::ValidationError expected_warning) {
+ TestStructWarningImpl<T>(obj.Pass(), expected_warning);
+ }
+
+ template <typename T>
+ void TestWarning(InlinedStructPtr<T> obj,
+ mojo::internal::ValidationError expected_warning) {
+ TestStructWarningImpl<T>(obj.Pass(), expected_warning);
+ }
+
+ template <typename T, typename TPtr>
+ void TestStructWarningImpl(TPtr obj,
+ mojo::internal::ValidationError expected_warning) {
warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
mojo::internal::FixedBuffer buf(GetSerializedSize_(obj));
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
index a8d8a95..f811a22 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/environment/environment.h"
@@ -118,19 +119,79 @@ TEST(UnionTest, SerializationPod) {
EXPECT_EQ(pod2->which(), PodUnion::Tag::F_INT8);
}
-TEST(UnionTest, StringGetterSetter) {
+TEST(UnionTest, ValidationJustWorksPod) {
PodUnionPtr pod(PodUnion::New());
+ pod->set_f_int8(10);
+
+ size_t size = GetSerializedSize_(pod);
+ EXPECT_EQ(16U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data;
+ Serialize_(pod.Pass(), &buf, &data);
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_TRUE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, NullValidation) {
+ void* buf = nullptr;
+ mojo::internal::BoundsChecker bounds_checker(buf, 0, 0);
+ EXPECT_TRUE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
+}
+
+TEST(UnionTest, OutOfAlignmentValidation) {
+ Environment environment;
+ size_t size = sizeof(internal::PodUnion_Data);
+ // Get an aligned object and shift the alignment.
+ mojo::internal::FixedBuffer aligned_buf(size + 1);
+ void* raw_buf = aligned_buf.Leak();
+ char* buf = reinterpret_cast<char*>(raw_buf) + 1;
+
+ internal::PodUnion_Data* data =
+ reinterpret_cast<internal::PodUnion_Data*>(buf);
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, OOBValidation) {
+ Environment environment;
+ size_t size = sizeof(internal::PodUnion_Data) - 1;
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ void* raw_buf = buf.Leak();
+ EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, UnknownTagValidation) {
+ Environment environment;
+ size_t size = sizeof(internal::PodUnion_Data);
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
+ data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF);
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ void* raw_buf = buf.Leak();
+ EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, StringGetterSetter) {
+ ObjectUnionPtr pod(ObjectUnion::New());
String hello("hello world");
pod->set_f_string(hello);
EXPECT_EQ(hello, pod->get_f_string());
EXPECT_TRUE(pod->is_f_string());
- EXPECT_EQ(pod->which(), PodUnion::Tag::F_STRING);
+ EXPECT_EQ(pod->which(), ObjectUnion::Tag::F_STRING);
}
TEST(UnionTest, StringEquals) {
- PodUnionPtr pod1(PodUnion::New());
- PodUnionPtr pod2(PodUnion::New());
+ ObjectUnionPtr pod1(ObjectUnion::New());
+ ObjectUnionPtr pod2(ObjectUnion::New());
pod1->set_f_string("hello world");
pod2->set_f_string("hello world");
@@ -141,32 +202,77 @@ TEST(UnionTest, StringEquals) {
}
TEST(UnionTest, StringClone) {
- PodUnionPtr pod(PodUnion::New());
+ ObjectUnionPtr pod(ObjectUnion::New());
String hello("hello world");
pod->set_f_string(hello);
- PodUnionPtr pod_clone = pod.Clone();
+ ObjectUnionPtr pod_clone = pod.Clone();
EXPECT_EQ(hello, pod_clone->get_f_string());
EXPECT_TRUE(pod_clone->is_f_string());
- EXPECT_EQ(pod_clone->which(), PodUnion::Tag::F_STRING);
+ EXPECT_EQ(pod_clone->which(), ObjectUnion::Tag::F_STRING);
}
TEST(UnionTest, StringSerialization) {
- PodUnionPtr pod1(PodUnion::New());
+ ObjectUnionPtr pod1(ObjectUnion::New());
String hello("hello world");
pod1->set_f_string(hello);
size_t size = GetSerializedSize_(pod1);
mojo::internal::FixedBuffer buf(size);
- internal::PodUnion_Data* data;
+ internal::ObjectUnion_Data* data;
Serialize_(pod1.Pass(), &buf, &data);
- PodUnionPtr pod2;
+ ObjectUnionPtr pod2;
Deserialize_(data, &pod2);
EXPECT_EQ(hello, pod2->get_f_string());
EXPECT_TRUE(pod2->is_f_string());
- EXPECT_EQ(pod2->which(), PodUnion::Tag::F_STRING);
+ EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING);
+}
+
+TEST(UnionTest, StringValidationNull) {
+ Environment environment;
+ size_t size = sizeof(internal::ObjectUnion_Data);
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
+ data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+ data->data.unknown = 0x0;
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ void* raw_buf = buf.Leak();
+ EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, StringValidationPointerOverflow) {
+ Environment environment;
+ size_t size = sizeof(internal::ObjectUnion_Data);
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
+ data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+ data->data.unknown = 0xFFFFFFFFFFFFFFFF;
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ void* raw_buf = buf.Leak();
+ EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+TEST(UnionTest, StringValidationValidateString) {
+ Environment environment;
+ size_t size = 32;
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
+ data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+
+ data->data.f_f_string = 8;
+ char* ptr = reinterpret_cast<char*>(&data->data.f_f_string);
+ mojo::internal::ArrayHeader* array_header =
+ reinterpret_cast<mojo::internal::ArrayHeader*>(ptr + *ptr);
+ array_header->num_bytes = 20; // This should go out of bounds.
+ array_header->num_elements = 20;
+ mojo::internal::BoundsChecker bounds_checker(data, 32, 0);
+ void* raw_buf = buf.Leak();
+ EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
}
} // namespace test
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/go/system/core.go b/third_party/mojo/src/mojo/public/go/system/core.go
index e1b8cd4..da6313e 100644
--- a/third_party/mojo/src/mojo/public/go/system/core.go
+++ b/third_party/mojo/src/mojo/public/go/system/core.go
@@ -9,6 +9,7 @@ package system
import "C"
import (
"reflect"
+ "sync"
"unsafe"
)
@@ -57,8 +58,21 @@ type Core interface {
// coreImpl is an implementation of the Mojo system APIs.
type coreImpl struct {
+ // Protects from making parallel non-blocking mojo cgo calls.
+ mu sync.Mutex
}
+// GetCore returns singleton instance of the Mojo system APIs implementation.
+//
+// The implementation uses cgo to call native mojo APIs implementation. Each cgo
+// call uses a separate thread for execution. To limit the number of used
+// threads all non-blocking system calls (i.e. all system calls except |Wait|
+// and |WaitMany|) on this implementation and on handles returned by this
+// implementation are protected by a mutex so that if you make two parallel
+// system calls one will wait for another to finish before executing.
+// However, |Wait| and |WaitMany| are not protected by a mutex and each parallel
+// call will use a separate thread. To reduce number of threads used for |Wait|
+// calls prefer to use |WaitMany|.
func GetCore() Core {
return &core
}
@@ -68,10 +82,13 @@ func (impl *coreImpl) acquireCHandle(handle C.MojoHandle) UntypedHandle {
}
func (impl *coreImpl) AcquireNativeHandle(handle MojoHandle) UntypedHandle {
- return &untypedHandleImpl{baseHandle{handle}}
+ return &untypedHandleImpl{baseHandle{impl, handle}}
}
func (impl *coreImpl) GetTimeTicksNow() MojoTimeTicks {
+ impl.mu.Lock()
+ defer impl.mu.Unlock()
+
return MojoTimeTicks(C.MojoGetTimeTicksNow())
}
@@ -108,6 +125,9 @@ func (impl *coreImpl) WaitMany(handles []Handle, signals []MojoHandleSignals, de
}
func (impl *coreImpl) CreateDataPipe(opts *DataPipeOptions) (MojoResult, ProducerHandle, ConsumerHandle) {
+ impl.mu.Lock()
+ defer impl.mu.Unlock()
+
cParams := C.MallocCreateDataPipeParams()
defer C.FreeCreateDataPipeParams(cParams)
result := C.MojoCreateDataPipe(opts.cValue(cParams.opts), cParams.producer, cParams.consumer)
@@ -117,6 +137,9 @@ func (impl *coreImpl) CreateDataPipe(opts *DataPipeOptions) (MojoResult, Produce
}
func (impl *coreImpl) CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, MessagePipeHandle, MessagePipeHandle) {
+ impl.mu.Lock()
+ defer impl.mu.Unlock()
+
cParams := C.MallocCreateMessagePipeParams()
defer C.FreeCreateMessagePipeParams(cParams)
result := C.MojoCreateMessagePipe(opts.cValue(cParams.opts), cParams.handle0, cParams.handle1)
@@ -126,6 +149,9 @@ func (impl *coreImpl) CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, M
}
func (impl *coreImpl) CreateSharedBuffer(opts *SharedBufferOptions, numBytes uint64) (MojoResult, SharedBufferHandle) {
+ impl.mu.Lock()
+ defer impl.mu.Unlock()
+
cParams := C.MallocCreateSharedBufferParams()
defer C.FreeCreateSharedBufferParams(cParams)
result := C.MojoCreateSharedBuffer(opts.cValue(cParams.opts), C.uint64_t(numBytes), cParams.handle)
diff --git a/third_party/mojo/src/mojo/public/go/system/data_pipe.go b/third_party/mojo/src/mojo/public/go/system/data_pipe.go
index b79a1e0..a433074 100644
--- a/third_party/mojo/src/mojo/public/go/system/data_pipe.go
+++ b/third_party/mojo/src/mojo/public/go/system/data_pipe.go
@@ -86,6 +86,9 @@ type dataPipeConsumer struct {
}
func (h *dataPipeConsumer) ReadData(flags MojoReadDataFlags) (MojoResult, []byte) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocReadDataParams()
defer C.FreeReadDataParams(cParams)
*cParams.num_bytes = 0
@@ -103,6 +106,9 @@ func (h *dataPipeConsumer) ReadData(flags MojoReadDataFlags) (MojoResult, []byte
}
func (h *dataPipeConsumer) BeginReadData(numBytes int, flags MojoReadDataFlags) (MojoResult, []byte) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocTwoPhaseActionParams()
defer C.FreeTwoPhaseActionParams(cParams)
*cParams.num_bytes = C.uint32_t(numBytes)
@@ -112,6 +118,9 @@ func (h *dataPipeConsumer) BeginReadData(numBytes int, flags MojoReadDataFlags)
}
func (h *dataPipeConsumer) EndReadData(numBytesRead int) MojoResult {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
return MojoResult(C.MojoEndReadData(h.mojoHandle.cValue(), C.uint32_t(numBytesRead)))
}
@@ -120,6 +129,9 @@ type dataPipeProducer struct {
}
func (h *dataPipeProducer) WriteData(data []byte, flags MojoWriteDataFlags) (MojoResult, int) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocWriteDataParams(C.uint32_t(len(data)))
defer C.FreeWriteDataParams(cParams)
*cParams.num_bytes = C.uint32_t(len(data))
@@ -130,6 +142,9 @@ func (h *dataPipeProducer) WriteData(data []byte, flags MojoWriteDataFlags) (Moj
}
func (h *dataPipeProducer) BeginWriteData(numBytes int, flags MojoWriteDataFlags) (MojoResult, []byte) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocTwoPhaseActionParams()
defer C.FreeTwoPhaseActionParams(cParams)
*cParams.num_bytes = C.uint32_t(numBytes)
@@ -139,5 +154,8 @@ func (h *dataPipeProducer) BeginWriteData(numBytes int, flags MojoWriteDataFlags
}
func (h *dataPipeProducer) EndWriteData(numBytesWritten int) MojoResult {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
return MojoResult(C.MojoEndWriteData(h.mojoHandle.cValue(), C.uint32_t(numBytesWritten)))
}
diff --git a/third_party/mojo/src/mojo/public/go/system/handle.go b/third_party/mojo/src/mojo/public/go/system/handle.go
index 6f020cf..189c8dd1 100644
--- a/third_party/mojo/src/mojo/public/go/system/handle.go
+++ b/third_party/mojo/src/mojo/public/go/system/handle.go
@@ -61,6 +61,7 @@ type UntypedHandle interface {
}
type baseHandle struct {
+ core *coreImpl
mojoHandle MojoHandle
}
@@ -69,6 +70,9 @@ func (h *baseHandle) invalidate() {
}
func (h *baseHandle) Close() MojoResult {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
mojoHandle := h.mojoHandle
h.invalidate()
return MojoResult(C.MojoClose(mojoHandle.cValue()))
diff --git a/third_party/mojo/src/mojo/public/go/system/message_pipe.go b/third_party/mojo/src/mojo/public/go/system/message_pipe.go
index 3188ecf..79f0ae9 100644
--- a/third_party/mojo/src/mojo/public/go/system/message_pipe.go
+++ b/third_party/mojo/src/mojo/public/go/system/message_pipe.go
@@ -32,6 +32,9 @@ type messagePipe struct {
}
func (h *messagePipe) ReadMessage(flags MojoReadMessageFlags) (MojoResult, []byte, []UntypedHandle) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocReadMessageParams()
defer C.FreeReadMessageParams(cParams)
*cParams.num_bytes = 0
@@ -52,12 +55,15 @@ func (h *messagePipe) ReadMessage(flags MojoReadMessageFlags) (MojoResult, []byt
cHandles := *(*[]MojoHandle)(newUnsafeSlice(unsafe.Pointer(cArrays.handles), handlesLen))
handles := []UntypedHandle{}
for i := 0; i < handlesLen; i++ {
- handles = append(handles, &untypedHandleImpl{baseHandle{cHandles[i]}})
+ handles = append(handles, h.core.AcquireNativeHandle(cHandles[i]))
}
return MojoResult(result), bytes, handles
}
func (h *messagePipe) WriteMessage(bytes []byte, handles []UntypedHandle, flags MojoWriteMessageFlags) MojoResult {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cArrays := C.MallocMessageArrays(C.uint32_t(len(bytes)), C.uint32_t(len(handles)))
defer C.FreeMessageArrays(cArrays)
cBytes := *(*[]byte)(newUnsafeSlice(unsafe.Pointer(cArrays.bytes), len(bytes)))
diff --git a/third_party/mojo/src/mojo/public/go/system/mojo_types.go b/third_party/mojo/src/mojo/public/go/system/mojo_types.go
index 9ed47b0..afb9df3 100644
--- a/third_party/mojo/src/mojo/public/go/system/mojo_types.go
+++ b/third_party/mojo/src/mojo/public/go/system/mojo_types.go
@@ -36,43 +36,43 @@ const (
MOJO_DEADLINE_INDEFINITE MojoDeadline = math.MaxUint64
MOJO_HANDLE_INVALID MojoHandle = 0
MOJO_RESULT_OK MojoResult = 0
- MOJO_RESULT_CANCELLED = -1
- MOJO_RESULT_UNKNOWN = -2
- MOJO_RESULT_INVALID_ARGUMENT = -3
- MOJO_RESULT_DEADLINE_EXCEEDED = -4
- MOJO_RESULT_NOT_FOUND = -5
- MOJO_RESULT_ALREADY_EXISTS = -6
- MOJO_RESULT_PERMISSION_DENIED = -7
- MOJO_RESULT_RESOURCE_EXHAUSTED = -8
- MOJO_RESULT_FAILED_PRECONDITION = -9
- MOJO_RESULT_ABORTED = -10
- MOJO_RESULT_OUT_OF_RANGE = -11
- MOJO_RESULT_UNIMPLEMENTED = -12
- MOJO_RESULT_INTERNAL = -13
- MOJO_RESULT_UNAVAILABLE = -14
- MOJO_RESULT_DATA_LOSS = -15
- MOJO_RESULT_BUSY = -16
- MOJO_RESULT_SHOULD_WAIT = -17
+ MOJO_RESULT_CANCELLED MojoResult = -1
+ MOJO_RESULT_UNKNOWN MojoResult = -2
+ MOJO_RESULT_INVALID_ARGUMENT MojoResult = -3
+ MOJO_RESULT_DEADLINE_EXCEEDED MojoResult = -4
+ MOJO_RESULT_NOT_FOUND MojoResult = -5
+ MOJO_RESULT_ALREADY_EXISTS MojoResult = -6
+ MOJO_RESULT_PERMISSION_DENIED MojoResult = -7
+ MOJO_RESULT_RESOURCE_EXHAUSTED MojoResult = -8
+ MOJO_RESULT_FAILED_PRECONDITION MojoResult = -9
+ MOJO_RESULT_ABORTED MojoResult = -10
+ MOJO_RESULT_OUT_OF_RANGE MojoResult = -11
+ MOJO_RESULT_UNIMPLEMENTED MojoResult = -12
+ MOJO_RESULT_INTERNAL MojoResult = -13
+ MOJO_RESULT_UNAVAILABLE MojoResult = -14
+ MOJO_RESULT_DATA_LOSS MojoResult = -15
+ MOJO_RESULT_BUSY MojoResult = -16
+ MOJO_RESULT_SHOULD_WAIT MojoResult = -17
MOJO_HANDLE_SIGNAL_NONE MojoHandleSignals = 0
- MOJO_HANDLE_SIGNAL_READABLE = 1 << 0
- MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1
- MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2
+ MOJO_HANDLE_SIGNAL_READABLE MojoHandleSignals = 1 << 0
+ MOJO_HANDLE_SIGNAL_WRITABLE MojoHandleSignals = 1 << 1
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED MojoHandleSignals = 1 << 2
MOJO_WRITE_MESSAGE_FLAG_NONE MojoWriteMessageFlags = 0
MOJO_READ_MESSAGE_FLAG_NONE MojoReadMessageFlags = 0
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0
+ MOJO_READ_MESSAGE_FLAG_MAY_DISCARD MojoReadMessageFlags = 1 << 0
MOJO_READ_DATA_FLAG_NONE MojoReadDataFlags = 0
- MOJO_READ_DATA_FLAG_ALL_OR_NONE = 1 << 0
- MOJO_READ_DATA_FLAG_DISCARD = 1 << 1
- MOJO_READ_DATA_FLAG_QUERY = 1 << 2
- MOJO_READ_DATA_FLAG_PEEK = 1 << 3
+ MOJO_READ_DATA_FLAG_ALL_OR_NONE MojoReadDataFlags = 1 << 0
+ MOJO_READ_DATA_FLAG_DISCARD MojoReadDataFlags = 1 << 1
+ MOJO_READ_DATA_FLAG_QUERY MojoReadDataFlags = 1 << 2
+ MOJO_READ_DATA_FLAG_PEEK MojoReadDataFlags = 1 << 3
MOJO_WRITE_DATA_FLAG_NONE MojoWriteDataFlags = 0
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE MojoWriteDataFlags = 1 << 0
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE MojoCreateDataPipeOptionsFlags = 0
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD = 1 << 0
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD MojoCreateDataPipeOptionsFlags = 1 << 0
MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE MojoCreateMessagePipeOptionsFlags = 0
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE MojoCreateSharedBufferOptionsFlags = 0
diff --git a/third_party/mojo/src/mojo/public/go/system/shared_buffer.go b/third_party/mojo/src/mojo/public/go/system/shared_buffer.go
index a8bdbfa..927c7ea 100644
--- a/third_party/mojo/src/mojo/public/go/system/shared_buffer.go
+++ b/third_party/mojo/src/mojo/public/go/system/shared_buffer.go
@@ -31,6 +31,9 @@ type sharedBuffer struct {
}
func (h *sharedBuffer) DuplicateBufferHandle(opts *DuplicateBufferHandleOptions) (MojoResult, SharedBufferHandle) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocDuplicateBufferHandleParams()
defer C.FreeDuplicateBufferHandleParams(cParams)
result := C.MojoDuplicateBufferHandle(h.mojoHandle.cValue(), opts.cValue(cParams.opts), cParams.duplicate)
@@ -38,6 +41,9 @@ func (h *sharedBuffer) DuplicateBufferHandle(opts *DuplicateBufferHandleOptions)
}
func (h *sharedBuffer) MapBuffer(offset uint64, numBytes int, flags MojoMapBufferFlags) (MojoResult, []byte) {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
cParams := C.MallocMapBufferParams()
defer C.FreeMapBufferParams(cParams)
result := C.MojoMapBuffer(h.mojoHandle.cValue(), C.uint64_t(offset), C.uint64_t(numBytes), cParams.buffer, flags.cValue())
@@ -48,5 +54,8 @@ func (h *sharedBuffer) MapBuffer(offset uint64, numBytes int, flags MojoMapBuffe
}
func (h *sharedBuffer) UnmapBuffer(buffer []byte) MojoResult {
+ h.core.mu.Lock()
+ defer h.core.mu.Unlock()
+
return MojoResult(C.MojoUnmapBuffer(unsafe.Pointer(&buffer[0])))
}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
index 2b99728..f68b113 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -19,6 +19,7 @@ mojom("test_interfaces") {
"sample_service.mojom",
"serialization_test_structs.mojom",
"test_structs.mojom",
+ "test_unions.mojom",
"validation_test_interfaces.mojom",
]
}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
index 5f50ccd..eae8ce6 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
@@ -17,9 +17,9 @@ union PodUnion {
float f_float;
double f_double;
bool f_bool;
- string f_string;
};
-struct SomeStruct {
+union ObjectUnion {
+ int8 f_int8;
string f_string;
};
diff --git a/third_party/mojo/src/mojo/public/js/connection.js b/third_party/mojo/src/mojo/public/js/connection.js
index 223e711..4a7a8b8 100644
--- a/third_party/mojo/src/mojo/public/js/connection.js
+++ b/third_party/mojo/src/mojo/public/js/connection.js
@@ -140,10 +140,13 @@ define("mojo/public/js/connection", [
}
// Return a handle for a message pipe that's connected to a stub for
- // localInterface. The stub delegates to impl. Used by generated code for
- // outgoing interface parameters: the caller specifies impl, and the generated
- // code sends the handle returned by this function.
- function bindImpl(impl, localInterface) {
+ // localInterface. Used by generated code for outgoing interface
+ // parameters: the caller is given the generated stub via
+ // |stubCallback(stub)| and the generated code sends the handle
+ // returned by this function. The caller is responsible for managing
+ // the lifetime of the stub and for setting it's implementation
+ // delegate with: StubBindings(stub).delegate = myImpl;
+ function bindImpl(stubCallback, localInterface) {
var messagePipe = core.createMessagePipe();
if (messagePipe.result != core.RESULT_OK)
throw new Error("createMessagePipe failed " + messagePipe.result);
@@ -152,8 +155,8 @@ define("mojo/public/js/connection", [
var router = new Router(messagePipe.handle0);
var connection = new BaseConnection(stub, undefined, router);
StubBindings(stub).connection = connection;
- if (impl)
- StubBindings(stub).delegate = impl;
+ if (stubCallback)
+ stubCallback(stub);
return messagePipe.handle1;
}
diff --git a/third_party/mojo/src/mojo/public/mojo_application.gni b/third_party/mojo/src/mojo/public/mojo_application.gni
index 19abf74..7661c88 100644
--- a/third_party/mojo/src/mojo/public/mojo_application.gni
+++ b/third_party/mojo/src/mojo/public/mojo_application.gni
@@ -74,16 +74,14 @@ template("mojo_native_application") {
}
# Copy the prebuilt mojo_shell if using it.
- if (defined(invoker.datadeps)) {
- datadeps = invoker.datadeps
+ if (defined(invoker.data_deps)) {
+ data_deps = invoker.data_deps
if (use_prebuilt_mojo_shell) {
- datadeps += [ copy_mojo_shell ]
+ data_deps += [ copy_mojo_shell ]
}
} else {
if (use_prebuilt_mojo_shell) {
- datadeps = [
- copy_mojo_shell,
- ]
+ data_deps = [ copy_mojo_shell ]
}
}
deps = rebase_path([
diff --git a/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py b/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
index 7b8edf6..35b8ff2 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
+++ b/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
@@ -146,7 +146,6 @@ class MojoInterfaceType(type):
class MyInterface(object):
__metaclass__ = MojoInterfaceType
DESCRIPTOR = {
- 'client': MyInterfaceClient,
'methods': [
{
'name': 'FireAndForget',
@@ -181,13 +180,10 @@ class MojoInterfaceType(type):
methods = [_MethodDescriptor(x) for x in descriptor.get('methods', [])]
for method in methods:
dictionary[method.name] = _NotImplemented
- client_class_getter = descriptor.get('client', None)
fully_qualified_name = descriptor['fully_qualified_name']
- interface_manager = InterfaceManager(fully_qualified_name, methods,
- client_class_getter)
+ interface_manager = InterfaceManager(fully_qualified_name, methods)
dictionary.update({
- 'client': None,
'manager': None,
'_interface_manager': interface_manager,
})
@@ -244,24 +240,13 @@ class InterfaceManager(object):
over a pipe.
"""
- def __init__(self, name, methods, client_class_getter):
+ def __init__(self, name, methods):
self.name = name
self.methods = methods
self.interface_class = None
- self._client_class_getter = client_class_getter
- self._client_manager = None
- self._client_manager_computed = False
self._proxy_class = None
self._stub_class = None
- @property
- def client_manager(self):
- if not self._client_manager_computed:
- self._client_manager_computed = True
- if self._client_class_getter:
- self._client_manager = self._client_class_getter().manager
- return self._client_manager
-
def Proxy(self, handle):
router = messaging.Router(handle)
error_handler = _ProxyErrorHandler()
@@ -282,9 +267,6 @@ class InterfaceManager(object):
retainer.release()
error_handler.AddCallback(Cleanup)
- if self.client_manager:
- impl.client = self.client_manager._InternalProxy(router, error_handler)
-
# Give an instance manager to the implementation to allow it to close
# the connection.
impl.manager = InstanceManager(router, error_handler)
@@ -292,15 +274,14 @@ class InterfaceManager(object):
router.Start()
def _InternalProxy(self, router, error_handler):
+ if error_handler is None:
+ error_handler = _ProxyErrorHandler()
+
if not self._proxy_class:
dictionary = {
'__module__': __name__,
'__init__': _ProxyInit,
}
- if self.client_manager:
- dictionary['client'] = property(_ProxyGetClient, _ProxySetClient)
- dictionary['manager'] = None
- dictionary['_client_manager'] = self.client_manager
for method in self.methods:
dictionary[method.name] = _ProxyMethodCall(method)
self._proxy_class = type('%sProxy' % self.name,
@@ -335,15 +316,18 @@ class InstanceManager(object):
def __init__(self, router, error_handler):
self._router = router
self._error_handler = error_handler
+ assert self._error_handler is not None
def Close(self):
+ self._error_handler.OnClose()
self._router.Close()
def PassMessagePipe(self):
+ self._error_handler.OnClose()
return self._router.PassMessagePipe()
def AddOnErrorCallback(self, callback):
- self._error_handler.AddCallback(lambda _: callback())
+ self._error_handler.AddCallback(lambda _: callback(), False)
class _MethodDescriptor(object):
@@ -373,21 +357,32 @@ def _ConstructParameterStruct(descriptor, name, suffix):
class _ProxyErrorHandler(messaging.ConnectionErrorHandler):
def __init__(self):
messaging.ConnectionErrorHandler.__init__(self)
- self._callbacks = set()
+ self._callbacks = dict()
def OnError(self, result):
+ if self._callbacks is None:
+ return
exception = messaging.MessagingException('Mojo error: %d' % result)
- for callback in list(self._callbacks):
+ for (callback, _) in self._callbacks.iteritems():
callback(exception)
self._callbacks = None
- def AddCallback(self, callback):
+ def OnClose(self):
+ if self._callbacks is None:
+ return
+ exception = messaging.MessagingException('Router has been closed.')
+ for (callback, call_on_close) in self._callbacks.iteritems():
+ if call_on_close:
+ callback(exception)
+ self._callbacks = None
+
+ def AddCallback(self, callback, call_on_close=True):
if self._callbacks is not None:
- self._callbacks.add(callback)
+ self._callbacks[callback] = call_on_close
def RemoveCallback(self, callback):
if self._callbacks:
- self._callbacks.remove(callback)
+ del self._callbacks[callback]
class _Retainer(object):
@@ -457,19 +452,6 @@ def _StructNe(self, other):
def _ProxyInit(self, router, error_handler):
self._router = router
self._error_handler = error_handler
- self._client = None
-
-
-# pylint: disable=W0212
-def _ProxyGetClient(self):
- return self._client
-
-
-# pylint: disable=W0212
-def _ProxySetClient(self, client):
- self._client = client
- stub = self._client_manager._Stub(client)
- self._router.SetIncomingMessageReceiver(stub)
# pylint: disable=W0212
diff --git a/third_party/mojo/src/mojo/public/tools/BUILD.gn b/third_party/mojo/src/mojo/public/tools/BUILD.gn
index 12cca6d..103c259 100644
--- a/third_party/mojo/src/mojo/public/tools/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/tools/BUILD.gn
@@ -10,11 +10,20 @@ if (use_prebuilt_mojo_shell) {
if (is_win) {
filename += ".exe"
}
+ if (is_android) {
+ filename = "MojoShell.apk"
+ }
sources = [
"prebuilt/$filename",
]
- outputs = [
- "$root_out_dir/$filename",
- ]
+ if (is_android) {
+ outputs = [
+ "$root_out_dir/apks/$filename",
+ ]
+ } else {
+ outputs = [
+ "$root_out_dir/$filename",
+ ]
+ }
}
}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
index 116e86a..d9a398a 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
@@ -32,6 +32,11 @@ namespace {{namespace}} {
class {{struct.name}};
{%- endfor %}
+{#--- Wrapper forward declarations for unions #}
+{% for union in unions %}
+class {{union.name}};
+{%- endfor %}
+
namespace internal {
{#--- Internal forward declarations #}
@@ -39,6 +44,10 @@ namespace internal {
class {{struct.name}}_Data;
{%- endfor %}
+{% for union in unions %}
+class {{union.name}}_Data;
+{%- endfor %}
+
#pragma pack(push, 1)
{#--- Class declarations #}
@@ -46,6 +55,10 @@ class {{struct.name}}_Data;
{% include "struct_declaration.tmpl" %}
{%- endfor %}
+{% for union in unions %}
+{% include "union_declaration.tmpl" %}
+{%- endfor %}
+
#pragma pack(pop)
} // namespace internal
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
index 1ddcc45..863d18f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -8,6 +8,7 @@
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4056)
+#pragma warning(disable:4065)
#pragma warning(disable:4756)
#endif
@@ -63,6 +64,11 @@ const uint32_t {{method_name}} = {{method.ordinal}};
{%- include "struct_definition.tmpl" %}
{%- endfor %}
+{#--- Union definitions #}
+{% for union in unions %}
+{%- include "union_definition.tmpl" %}
+{%- endfor %}
+
} // namespace internal
{#--- Struct Constants #}
@@ -77,6 +83,11 @@ const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{cons
{%- include "wrapper_class_definition.tmpl" %}
{%- endfor %}
+{#--- Union builder definitions #}
+{%- for union in unions %}
+{%- include "wrapper_union_class_definition.tmpl" %}
+{%- endfor %}
+
{#--- Interface definitions #}
{%- for interface in interfaces %}
{%- include "interface_definition.tmpl" %}
@@ -87,6 +98,11 @@ const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{cons
{%- include "struct_serialization_definition.tmpl" %}
{%- endfor %}
+{#--- Union Serialization Helpers #}
+{%- for union in unions %}
+{%- include "union_serialization_definition.tmpl" %}
+{%- endfor %}
+
{%- for namespace in namespaces_as_array|reverse %}
} // namespace {{namespace}}
{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 25449b7..0312002 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -53,6 +53,16 @@ using {{struct.name}}Ptr = mojo::StructPtr<{{struct.name}}>;
{% endif %}
{% endfor %}
+{#--- Union Forward Declarations -#}
+{% for union in unions %}
+class {{union.name}};
+{% if union|should_inline_union %}
+typedef mojo::InlinedStructPtr<{{union.name}}> {{union.name}}Ptr;
+{% else %}
+typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
+{% endif %}
+{%- endfor %}
+
{#--- NOTE: Non-inlined structs may have pointers to inlined structs, so we #}
{#--- need to fully define inlined structs ahead of the others. #}
@@ -70,6 +80,11 @@ using {{struct.name}}Ptr = mojo::StructPtr<{{struct.name}}>;
{% endif %}
{%- endfor %}
+{#--- Unions #}
+{% for union in unions %}
+{% include "wrapper_union_class_declaration.tmpl" %}
+{%- endfor %}
+
{#--- Interfaces -#}
{% for interface in interfaces %}
{% include "interface_declaration.tmpl" %}
@@ -95,10 +110,18 @@ using {{struct.name}}Ptr = mojo::StructPtr<{{struct.name}}>;
{% include "interface_response_validator_declaration.tmpl" %}
{%- endfor %}
+{%- import "serialization_macros.tmpl" as serialization_macros %}
{#--- Struct Serialization Helpers -#}
{% if structs %}
{% for struct in structs %}
-{% include "struct_serialization_declaration.tmpl" %}
+{{ serialization_macros.declare_serialization(struct.name) }}
+{%- endfor %}
+{%- endif %}
+
+{#--- Union Serialization Helpers -#}
+{% if unions %}
+{% for union in unions %}
+{{ serialization_macros.declare_serialization(union.name) }}
{%- endfor %}
{%- endif %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
index 5de77d3..0892b64 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
@@ -29,5 +29,5 @@ class {{class_name}} {
header_.num_fields = {{struct.packed.packed_fields|length}};
}
};
-static_assert(sizeof({{class_name}}) == {{struct.packed|struct_size}},
+static_assert(sizeof({{class_name}}) == {{struct.versions[-1].num_bytes}},
"Bad sizeof({{class_name}})");
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl
new file mode 100644
index 0000000..2be038c
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl
@@ -0,0 +1,7 @@
+{%- macro declare_serialization(name) %}
+size_t GetSerializedSize_(const {{name}}Ptr& input);
+void Serialize_({{name}}Ptr input, mojo::internal::Buffer* buffer,
+ internal::{{name}}_Data** output);
+void Deserialize_(internal::{{name}}_Data* input,
+ {{name}}Ptr* output);
+{%- endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
index 34c0f11..ee8934e 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -18,5 +18,5 @@ class {{class_name}} {
{{class_name}}();
~{{class_name}}() = delete;
};
-static_assert(sizeof({{class_name}}) == {{struct.packed|struct_size}},
+static_assert(sizeof({{class_name}}) == {{struct.versions[-1].num_bytes}},
"Bad sizeof({{class_name}})");
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
deleted file mode 100644
index 604be86..0000000
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
+++ /dev/null
@@ -1,5 +0,0 @@
-size_t GetSerializedSize_(const {{struct.name}}Ptr& input);
-void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer,
- internal::{{struct.name}}_Data** output);
-void Deserialize_(internal::{{struct.name}}_Data* input,
- {{struct.name}}Ptr* output);
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
new file mode 100644
index 0000000..6e6fe95
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -0,0 +1,50 @@
+{%- set class_name = union.name ~ "_Data" -%}
+{%- set enum_name = union.name ~ "_Tag" -%}
+{%- import "struct_macros.tmpl" as struct_macros %}
+
+class {{class_name}} {
+ public:
+ static {{class_name}}* New(mojo::internal::Buffer* buf);
+
+ static bool Validate(const void* data,
+ mojo::internal::BoundsChecker* bounds_checker);
+
+ enum class {{enum_name}} : uint32_t {
+{% for field in union.fields %}
+ {{field.name|upper}},
+{%- endfor %}
+ };
+
+ // A note on layout:
+ // "Each non-static data member is allocated as if it were the sole member of
+ // a struct." - Section 9.5.2 ISO/IEC 14882:2011 (The C++ Spec)
+ union MOJO_ALIGNAS(8) Union_ {
+{%- for field in union.fields %}
+{%- if field.kind|is_string_kind %}
+ uint64_t f_{{field.name}};
+{%- elif field.kind.spec == 'b' %}
+ uint8_t f_{{field.name}} : 1;
+{%- elif field.kind|is_enum_kind %}
+ int32_t f_{{field.name}};
+{%- else %}
+ {{field.kind|cpp_pod_type}} f_{{field.name}};
+{%- endif %}
+{%- endfor %}
+ uint64_t unknown;
+ };
+
+ uint32_t reserved;
+ {{enum_name}} tag;
+ Union_ data;
+
+ void EncodePointersAndHandles(std::vector<mojo::Handle>* handles);
+ void DecodePointersAndHandles(std::vector<mojo::Handle>* handles);
+
+ private:
+ {{class_name}}();
+ ~{{class_name}}() = delete;
+};
+static_assert(sizeof({{class_name}}) == 16,
+ "Bad sizeof({{class_name}})");
+static_assert(sizeof({{class_name}}::Union_) == 8,
+ "Bad sizeof({{class_name}}::Union_)");
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
new file mode 100644
index 0000000..9f6f02f
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -0,0 +1,54 @@
+{%- import "validation_macros.tmpl" as validation_macros %}
+{%- set class_name = union.name ~ "_Data" %}
+{%- set enum_name = union.name ~ "_Tag" -%}
+
+// static
+{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) {
+ return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
+}
+
+// static
+bool {{class_name}}::Validate(const void* data,
+ mojo::internal::BoundsChecker* bounds_checker) {
+ if (!data) {
+ return true;
+ }
+
+ if (!mojo::internal::IsAligned(data)) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_MISALIGNED_OBJECT);
+ return false;
+ }
+
+ if (!bounds_checker->ClaimMemory(data, sizeof({{class_name}}))) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
+ return false;
+ }
+ const {{class_name}}* object = static_cast<const {{class_name}}*>(data);
+ MOJO_ALLOW_UNUSED_LOCAL(object);
+
+ switch (object->tag) {
+{% for field in union.fields %}
+ case {{enum_name}}::{{field.name|upper}}:
+{{ validation_macros.validate_union_field(field, union)|indent(6) }}
+{%- endfor %}
+ default:
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNKOWN_UNION_TAG,
+ "unknown tag in {{union.name}}");
+ return false;
+ }
+}
+
+{{class_name}}::{{class_name}}() {
+}
+
+void {{class_name}}::EncodePointersAndHandles(
+ std::vector<mojo::Handle>* handles) {
+ // TODO(azani): Implement pointers and handles.
+}
+
+void {{class_name}}::DecodePointersAndHandles(
+ std::vector<mojo::Handle>* handles) {
+ // TODO(azani): Implement pointers and handles.
+}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
index a29df07..8b82f7f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -30,9 +30,10 @@ void Serialize_({{union.name}}Ptr input, mojo::internal::Buffer* buf,
{% for field in union.fields %}
case {{union.name}}::Tag::{{field.name|upper}}:
{% if field.kind|is_string_kind %}
- Serialize_(input_acc.data()->{{field.name}}, buf, &result->data.{{field.name}}.ptr);
+ {{field.kind|cpp_field_type}}* {{field.name}}_ptr = reinterpret_cast<{{field.kind|cpp_field_type}}*>(&result->data.f_{{field.name}});
+ Serialize_(*(input_acc.data()->{{field.name}}), buf, &{{field.name}}_ptr->ptr);
{% else %}
- result->data.{{field.name}} = input_acc.data()->{{field.name}};
+ result->data.f_{{field.name}} = input_acc.data()->{{field.name}};
{%- endif %}
break;
{%- endfor %}
@@ -53,9 +54,10 @@ void Deserialize_(internal::{{union.name}}_Data* input,
case {{union.name}}::Tag::{{field.name|upper}}:
{% if field.kind|is_string_kind %}
result_acc.SwitchActive({{union.name}}::Tag::{{field.name|upper}});
- Deserialize_(input->data.{{field.name}}.ptr, &result_acc.data()->{{field.name}});
+ {{field.kind|cpp_field_type}}* {{field.name}}_ptr = reinterpret_cast<{{field.kind|cpp_field_type}}*>(&input->data.f_{{field.name}});
+ Deserialize_({{field.name}}_ptr->ptr, result_acc.data()->{{field.name}});
{% else %}
- result->set_{{field.name}}(input->data.{{field.name}});
+ result->set_{{field.name}}(input->data.f_{{field.name}});
{%- endif %}
break;
{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl
new file mode 100644
index 0000000..5a328f9
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl
@@ -0,0 +1,43 @@
+{%- macro validate_not_null_ptr(field_expr, field, object_name) %}
+if (!{{field_expr}}->offset) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ "null {{field.name}} field in {{object_name}}");
+ return false;
+}
+{%- endmacro %}
+
+{%- macro validate_encoded_ptr(field_expr) %}
+if (!mojo::internal::ValidateEncodedPointer(&{{field_expr}}->offset)) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER);
+ return false;
+}
+{%- endmacro %}
+
+{%- macro validate_array_or_string(field_expr, field) -%}
+if (!{{field.kind|cpp_wrapper_type}}::Data_::Validate<
+ {{field.kind|get_array_validate_params}}>(
+ mojo::internal::DecodePointerRaw(&{{field_expr}}->offset),
+ bounds_checker)) {
+ return false;
+}
+{%- endmacro %}
+
+{%- macro validate_union_field(field, union) %}
+{%- set field_expr = "(reinterpret_cast<const "
+ ~ field.kind|cpp_field_type
+ ~ "*>(&object->data.f_"
+ ~ field.name
+ ~ "))" -%}
+{%- if field.kind|is_object_kind -%}
+{%- if not field.kind|is_nullable_kind -%}
+{{ validate_not_null_ptr(field_expr, field, union.name) }}
+{%- endif %}
+{{ validate_encoded_ptr(field_expr) }}
+{%- endif %}
+
+{%- if field.kind|is_array_kind or field.kind|is_string_kind -%}
+{{ validate_array_or_string(field_expr, field) }}
+{%- endif %}
+return true;
+{%- endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
index 0420c8d..107de09 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -39,7 +39,11 @@ class {{union.name}} {
Union_() {}
~Union_() {}
{% for field in union.fields %}
+{% if field.kind|is_object_kind -%}
+ {{field.kind|cpp_wrapper_type}}* {{field.name}};
+{% else -%}
{{field.kind|cpp_wrapper_type}} {{field.name}};
+{% endif -%}
{%- endfor %}
};
void SwitchActive(Tag new_active);
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
index bab528c..b5e9c23 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
@@ -21,7 +21,11 @@
switch (tag_) {
{% for field in union.fields %}
case Tag::{{field.name|upper}}:
+{% if field.kind|is_object_kind %}
+ rv->set_{{field.name}}(*(data_.{{field.name}}));
+{%- else %}
rv->set_{{field.name}}(data_.{{field.name}});
+{%- endif %}
break;
{%- endfor %}
};
@@ -37,7 +41,11 @@ bool {{union.name}}::Equals(const {{union.name}}& other) const {
switch (tag_) {
{% for field in union.fields %}
case Tag::{{field.name|upper}}:
- return mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(data_.{{field.name}}, other.get_{{field.name}}());
+{% if field.kind|is_object_kind %}
+ return mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(*(data_.{{field.name}}), *(other.data_.{{field.name}}));
+{%- else %}
+ return mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(data_.{{field.name}}, other.data_.{{field.name}});
+{%- endif %}
{%- endfor %}
};
@@ -51,12 +59,20 @@ bool {{union.name}}::is_{{field.name}}() const {
{{field.kind|cpp_result_type}} {{union.name}}::get_{{field.name}}() const {
MOJO_DCHECK(tag_ == Tag::{{field.name|upper}});
+{% if field.kind|is_object_kind %}
+ return *(data_.{{field.name}});
+{%- else %}
return data_.{{field.name}};
+{%- endif %}
}
void {{union.name}}::set_{{field.name}}({{field.kind|cpp_const_wrapper_type}} {{field.name}}) {
SwitchActive(Tag::{{field.name|upper}});
+{% if field.kind|is_string_kind %}
+ *(data_.{{field.name}}) = {{field.name}};
+{%- else %}
data_.{{field.name}} = {{field.name}};
+{%- endif %}
}
{%- endfor %}
@@ -74,7 +90,7 @@ void {{union.name}}::SetActive(Tag new_active) {
{% for field in union.fields %}
case Tag::{{field.name|upper}}:
{% if field.kind|is_string_kind %}
- new (&data_.{{field.name}}) String();
+ data_.{{field.name}} = new String();
{%- endif %}
break;
{%- endfor %}
@@ -88,7 +104,7 @@ void {{union.name}}::DestroyActive() {
{% for field in union.fields %}
case Tag::{{field.name|upper}}:
{% if field.kind|is_string_kind %}
- data_.{{field.name}}.~String();
+ delete data_.{{field.name}};
{%- endif %}
break;
{%- endfor %}
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 f65298f..93a3e42 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
@@ -74,7 +74,7 @@ if (decoder{{level+1}} == null) {
{%- macro struct_def(struct) %}
class {{struct|name}} extends bindings.Struct {
- static const int kStructSize = {{struct.packed|struct_size}};
+ static const int kStructSize = {{struct.versions[-1].num_bytes}};
static const bindings.DataHeader kDefaultStructInfo =
const bindings.DataHeader(kStructSize, {{struct.packed.packed_fields|length}});
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/enum.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/enum.tmpl
new file mode 100644
index 0000000..8bc882f
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/enum.tmpl
@@ -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.
+
+{% macro define(enum) %}
+type {{enum|name}} int32
+
+const (
+{% for field in enum.fields %}
+{% if field.value %}
+ {{enum|name}}_{{field|name}} = {{field.value|expression_to_text}}
+{% elif loop.first %}
+ {{enum|name}}_{{field|name}} = 0
+{% else %}
+ {{enum|name}}_{{field|name}} = {{enum|name}}_{{enum.fields[loop.index0 - 1]|name}} + 1;
+{% endif %}
+{% endfor %}
+)
+
+{% endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
new file mode 100644
index 0000000..484845d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
@@ -0,0 +1,14 @@
+// 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 "struct.tmpl" as struct_macros %}
+
+{% macro define(interface) %}
+{% for method in interface.methods %}
+{{struct_macros.define(method|struct_from_method, False)}}
+{%- if method.response_parameters %}
+{{struct_macros.define(method|response_struct_from_method, False)}}
+{% endif %}
+{% endfor %}
+{% endmacro %} \ No newline at end of file
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
index 8c58c4c..3769585 100644
--- 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
@@ -9,3 +9,33 @@
//
package {{package}}
+
+import (
+ "fmt"
+
+ "mojo/public/go/bindings"
+ "mojo/public/go/system"
+)
+
+var _ = fmt.Errorf
+var _ = bindings.NewEncoder
+var _ = system.GetCore
+
+{% import "enum.tmpl" as enum_macros %}
+{% import "interface.tmpl" as interface_macros %}
+{% import "struct.tmpl" as struct_macros %}
+
+{#- Enum definitions #}
+{% for enum in enums %}
+{{enum_macros.define(enum)}}
+{%- endfor %}
+
+{#- Interface definitions #}
+{% for interface in interfaces %}
+{{interface_macros.define(interface)}}
+{%- endfor %}
+
+{#- Struct definitions #}
+{% for struct in structs %}
+{{struct_macros.define(struct)}}
+{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
new file mode 100644
index 0000000..eb6b121
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
@@ -0,0 +1,219 @@
+// 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.
+
+{% macro define(struct, exported=True) %}
+type {{struct|name(exported)}} struct {
+{% for packed_field in struct.packed.packed_fields %}
+ {{packed_field.field|name(exported)}} {{packed_field.field.kind|go_type}}
+{% endfor %}
+}
+
+func (s *{{struct|name(exported)}}) Encode(encoder *bindings.Encoder) error {
+ encoder.StartStruct({{struct.versions[-1].num_bytes}}, {{struct.packed.packed_fields|length}})
+{% for byte in struct.bytes %}
+{% for packed_field in byte.packed_fields %}
+ {{encode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent()}}
+{% endfor %}
+{% endfor %}
+ if err := encoder.Finish(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (s *{{struct|name(exported)}}) Decode(decoder *bindings.Decoder) error {
+{% if struct.bytes %}
+ numFields, err := decoder.StartStruct()
+{% else %}
+ _, err := decoder.StartStruct()
+{% endif %}
+ if err != nil {
+ return err
+ }
+{% for byte in struct.bytes %}
+{% for packed_field in byte.packed_fields %}
+ if numFields > {{packed_field.ordinal}} {
+ {{decode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent(2)}}
+ }
+{% endfor %}
+{% endfor %}
+ if err := decoder.Finish(); err != nil {
+ return err
+ }
+ return nil
+}
+
+{% endmacro %}
+
+
+
+{% macro encode(value, kind, level=0) %}
+{% if kind|is_nullable %}
+if {{value}} == nil {
+{% if kind|is_handle %}
+ encoder.WriteInvalidHandle()
+{% else %}
+ encoder.WriteNullPointer()
+{% endif %}
+} else {
+ {{encodeNonNullable('(*'~value~')', kind, level)|tab_indent()}}
+}
+{% else -%}
+{{encodeNonNullable(value, kind, level)}}
+{%- endif %}
+{% endmacro %}
+
+
+
+{% macro encodeNonNullable(value, kind, level=0) %}
+{% if kind|is_pointer %}
+if err := encoder.WritePointer(); err != nil {
+ return err
+}
+{% endif %}
+{% if kind|is_struct %}
+if err := {{value}}.Encode(encoder); err != nil {
+ return err
+}
+{% elif kind|is_array %}
+encoder.StartArray(uint32(len({{value}})), {{kind.kind|bit_size}})
+for _, elem{{level}} := range {{value}} {
+ {{encode('elem'~level, kind.kind, level+1)|tab_indent()}}
+}
+if err := encoder.Finish(); err != nil {
+ return err
+}
+{% elif kind|is_map %}
+encoder.StartMap()
+{
+ var keys{{level}} {{kind.key_kind|array|go_type}}
+ var values{{level}} {{kind.value_kind|array|go_type}}
+ for key{{level}}, value{{level}} := range {{value}} {
+ keys{{level}} = append(keys{{level}}, key{{level}})
+ values{{level}} = append(values{{level}}, value{{level}})
+ }
+ {{encode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}}
+ {{encode('values'~level, kind.value_kind|array, level+1)|tab_indent()}}
+}
+if err := encoder.Finish(); err != nil {
+ return err
+}
+{% elif kind|is_enum %}
+if err := encoder.WriteInt32(int32({{value}})); err != nil {
+ return err
+}
+{% else %}
+if err := encoder.Write{{kind|encode_suffix}}({{value}}); err != nil {
+ return err
+}
+{% endif %}
+{% endmacro %}
+
+
+
+{% macro decode(value, kind, level=0) %}
+{% if kind|is_pointer %}
+pointer{{level}}, err := decoder.ReadPointer()
+if err != nil {
+ return err
+}
+if pointer{{level}} == 0 {
+{% if kind|is_nullable %}
+ {{value}} = nil
+} else {
+ {{value}} = new({{kind|go_type(False)}})
+ {{decodePointerValue('(*'~value~')', kind, level)|tab_indent()}}
+}
+{% else %}
+ return fmt.Errorf("unexpected null pointer")
+} else {
+ {{decodePointerValue(value, kind, level)|tab_indent()}}
+}
+{% endif %}
+{% elif kind|is_handle %}
+handle{{level}}, err := decoder.Read{{kind|decode_suffix}}()
+if err != nil {
+ return err
+}
+if handle{{level}}.IsValid() {
+ {{value}} = {% if kind|is_nullable %}&{% endif %}handle{{level}}
+} else {
+{% if kind|is_nullable %}
+ {{value}} = nil
+{% else %}
+ return fmt.Errorf("unexpected invalid handle")
+{% endif %}
+}
+{% elif kind|is_enum %}
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
+if err != nil {
+ return err
+}
+{{value}} = {% if kind|is_nullable %}&{% endif %}{{kind|go_type(False)}}(value{{level}})
+{% else %}
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
+if err != nil {
+ return err
+}
+{{value}} = {% if kind|is_nullable %}&{% endif %}value{{level}}
+{% endif %}
+{% endmacro %}
+
+
+
+{% macro decodePointerValue(value, kind, level=0) %}
+{% if kind|is_struct %}
+if err := {{value}}.Decode(decoder); err != nil {
+ return err
+}
+{% elif kind|is_array %}
+len{{level}}, err := decoder.StartArray({{kind.kind|bit_size}})
+if err != nil {
+ return err
+}
+{% if kind.length %}
+if len{{level}} != {{kind.length}} {
+ return fmt.Errorf("invalid array length: expected %d, got %d", {{kind.length}}, len{{level}})
+}
+{% else %}
+{{value}} = make({{kind|go_type(False)}}, len{{level}})
+{% endif %}
+for i{{level}} := uint32(0); i{{level}} < len{{level}}; i{{level}}++ {
+ {{decode(value~'[i'~level~']', kind.kind, level+1)|tab_indent()}}
+}
+if err := decoder.Finish(); err != nil {
+ return err
+}
+{% elif kind|is_map %}
+if err := decoder.StartMap(); err != nil {
+ return err
+}
+var keys{{level}} {{kind.key_kind|array|go_type}}
+{
+ {{decode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}}
+}
+var values{{level}} {{kind.value_kind|array|go_type}}
+{
+ {{decode('values'~level, kind.value_kind|array, level+1)|tab_indent()}}
+}
+if len(keys{{level}}) != len(values{{level}}) {
+ return fmt.Errorf("Number of keys %d is different from number of values %d", len(keys{{level}}), len(values{{level}}))
+}
+if err := decoder.Finish(); err != nil {
+ return err
+}
+len{{level}} := len(keys{{level}})
+map{{level}} := make({{kind|go_type(False)}})
+for i{{level}} := 0; i{{level}} < len{{level}}; i{{level}}++ {
+ map{{level}}[keys{{level}}[i{{level}}]] = values{{level}}[i{{level}}]
+}
+{{value}} = map{{level}}
+{% else %}
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
+if err != nil {
+ return err
+}
+{{value}} = value{{level}}
+{% endif %}
+{% endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
index 0abdac4..333e0da 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
@@ -110,7 +110,7 @@ if (decoder{{level+1}} == null) {
{% macro struct_def(struct, inner_class=False) %}
{{'static' if inner_class else 'public'}} final class {{struct|name}} extends org.chromium.mojo.bindings.Struct {
- private static final int STRUCT_SIZE = {{struct.packed|struct_size}};
+ private static final int STRUCT_SIZE = {{struct.versions[-1].num_bytes}};
private static final DataHeader DEFAULT_STRUCT_INFO = new DataHeader(STRUCT_SIZE, {{struct.packed.packed_fields|length}});
{% for constant in struct.constants %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 34bba30..8b7e219 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -283,6 +283,9 @@ def ShouldInlineStruct(struct):
return False
return True
+def ShouldInlineUnion(union):
+ return not any(mojom.IsMoveOnlyKind(field.kind) for field in union.fields)
+
def GetArrayValidateParams(kind):
if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and
not mojom.IsStringKind(kind)):
@@ -314,8 +317,6 @@ def GetMapValidateParams(value_kind):
'true' if element_is_nullable else 'false',
GetArrayValidateParams(value_kind))
-_HEADER_SIZE = 8
-
class Generator(generator.Generator):
cpp_filters = {
@@ -334,6 +335,7 @@ class Generator(generator.Generator):
"get_pad": pack.GetPad,
"has_callbacks": mojom.HasCallbacks,
"should_inline": ShouldInlineStruct,
+ "should_inline_union": ShouldInlineUnion,
"is_array_kind": mojom.IsArrayKind,
"is_cloneable_kind": mojom.IsCloneableKind,
"is_enum_kind": mojom.IsEnumKind,
@@ -347,11 +349,13 @@ class Generator(generator.Generator):
"is_string_kind": mojom.IsStringKind,
"is_struct_kind": mojom.IsStructKind,
"is_struct_with_handles": IsStructWithHandles,
+ "is_union_kind": mojom.IsUnionKind,
"struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
"struct_from_method": generator.GetStructFromMethod,
"response_struct_from_method": generator.GetResponseStructFromMethod,
"stylize_method": generator.StudlyCapsToCamel,
"to_all_caps": generator.CamelCaseToAllCaps,
+ "under_to_camel": generator.UnderToCamel,
}
def GetJinjaExports(self):
@@ -363,6 +367,7 @@ class Generator(generator.Generator):
"kinds": self.module.kinds,
"enums": self.module.enums,
"structs": self.GetStructs(),
+ "unions": self.module.unions,
"interfaces": self.module.interfaces,
}
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 d971b53..2b562f2 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
@@ -13,8 +13,6 @@ from mojom.generate.template_expander import UseJinja
GENERATOR_PREFIX = 'dart'
-_HEADER_SIZE = 8
-
_kind_to_dart_default_value = {
mojom.BOOL: "false",
mojom.INT8: "0",
@@ -209,14 +207,6 @@ def GetNameForElement(element):
def GetInterfaceResponseName(method):
return UpperCamelCase(method.name + 'Response')
-def GetResponseStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetResponseStructFromMethod(method))
-
-def GetStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetStructFromMethod(method))
-
def GetDartTrueFalse(value):
return 'true' if value else 'false'
@@ -379,9 +369,8 @@ class Generator(generator.Generator):
'dart_type': DartDeclType,
'name': GetNameForElement,
'interface_response_name': GetInterfaceResponseName,
- 'response_struct_from_method': GetResponseStructFromMethod,
- 'struct_from_method': GetStructFromMethod,
- 'struct_size': lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
+ 'response_struct_from_method': generator.GetResponseStructFromMethod,
+ 'struct_from_method': generator.GetStructFromMethod,
}
def GetParameters(self):
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
index 3f7c938..1196276 100644
--- 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
@@ -4,12 +4,148 @@
'''Generates Go source files from a mojom.Module.'''
+from itertools import chain
import os
+import re
from mojom.generate.template_expander import UseJinja
import mojom.generate.generator as generator
import mojom.generate.module as mojom
+import mojom.generate.pack as pack
+
+class KindInfo(object):
+ def __init__(self, go_type, encode_suffix, decode_suffix, bit_size):
+ self.go_type = go_type
+ self.encode_suffix = encode_suffix
+ self.decode_suffix = decode_suffix
+ self.bit_size = bit_size
+
+_kind_infos = {
+ mojom.BOOL: KindInfo('bool', 'Bool', 'Bool', 1),
+ mojom.INT8: KindInfo('int8', 'Int8', 'Int8', 8),
+ mojom.UINT8: KindInfo('uint8', 'Uint8', 'Uint8', 8),
+ mojom.INT16: KindInfo('int16', 'Int16', 'Int16', 16),
+ mojom.UINT16: KindInfo('uint16', 'Uint16', 'Uint16', 16),
+ mojom.INT32: KindInfo('int32', 'Int32', 'Int32', 32),
+ mojom.UINT32: KindInfo('uint32', 'Uint32', 'Uint32', 32),
+ mojom.FLOAT: KindInfo('float32', 'Float32', 'Float32', 32),
+ mojom.HANDLE: KindInfo(
+ 'system.Handle', 'Handle', 'Handle', 32),
+ mojom.DCPIPE: KindInfo(
+ 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32),
+ mojom.DPPIPE: KindInfo(
+ 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32),
+ mojom.MSGPIPE: KindInfo(
+ 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32),
+ mojom.SHAREDBUFFER: KindInfo(
+ 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32),
+ mojom.NULLABLE_HANDLE: KindInfo(
+ 'system.Handle', 'Handle', 'Handle', 32),
+ mojom.NULLABLE_DCPIPE: KindInfo(
+ 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32),
+ mojom.NULLABLE_DPPIPE: KindInfo(
+ 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32),
+ mojom.NULLABLE_MSGPIPE: KindInfo(
+ 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32),
+ mojom.NULLABLE_SHAREDBUFFER: KindInfo(
+ 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32),
+ mojom.INT64: KindInfo('int64', 'Int64', 'Int64', 64),
+ mojom.UINT64: KindInfo('uint64', 'Uint64', 'Uint64', 64),
+ mojom.DOUBLE: KindInfo('float64', 'Float64', 'Float64', 64),
+ mojom.STRING: KindInfo('string', 'String', 'String', 64),
+ mojom.NULLABLE_STRING: KindInfo('string', 'String', 'String', 64),
+}
+
+def GetBitSize(kind):
+ if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct)):
+ return 64
+ if isinstance(kind, (mojom.InterfaceRequest, mojom.Interface)):
+ kind = mojom.MSGPIPE
+ if isinstance(kind, mojom.Enum):
+ kind = mojom.INT32
+ return _kind_infos[kind].bit_size
+
+def GetGoType(kind, nullable = True):
+ if nullable and mojom.IsNullableKind(kind):
+ return '*%s' % GetNonNullableGoType(kind)
+ return GetNonNullableGoType(kind)
+
+def GetNonNullableGoType(kind):
+ if mojom.IsStructKind(kind):
+ return '%s' % FormatName(kind.name)
+ if mojom.IsArrayKind(kind):
+ if kind.length:
+ return '[%s]%s' % (kind.length, GetGoType(kind.kind))
+ return '[]%s' % GetGoType(kind.kind)
+ if mojom.IsMapKind(kind):
+ return 'map[%s]%s' % (GetGoType(kind.key_kind), GetGoType(kind.value_kind))
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return GetGoType(mojom.MSGPIPE)
+ if mojom.IsEnumKind(kind):
+ return GetNameForNestedElement(kind)
+ return _kind_infos[kind].go_type
+
+def NameToComponent(name):
+ # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
+ # HTTP_Entry2_FooBar)
+ name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
+ # insert '_' between non upper and start of upper blocks (e.g.,
+ # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
+ name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
+ return [x.lower() for x in name.split('_')]
+
+def UpperCamelCase(name):
+ return ''.join([x.capitalize() for x in NameToComponent(name)])
+
+def FormatName(name, exported=True):
+ if exported:
+ return UpperCamelCase(name)
+ # Leave '_' symbols for unexported names.
+ return name[0].lower() + name[1:]
+
+def GetNameForNestedElement(element):
+ if element.parent_kind:
+ return "%s_%s" % (GetNameForElement(element.parent_kind),
+ FormatName(element.name))
+ return FormatName(element.name)
+
+def GetNameForElement(element, exported=True):
+ if (mojom.IsInterfaceKind(element) or mojom.IsStructKind(element) or
+ isinstance(element, (mojom.EnumField,
+ mojom.Field,
+ mojom.Method,
+ mojom.Parameter))):
+ return FormatName(element.name, exported)
+ if isinstance(element, (mojom.Enum,
+ mojom.Constant,
+ mojom.ConstantValue)):
+ return GetNameForNestedElement(element)
+ raise Exception('Unexpected element: %s' % element)
+
+def ExpressionToText(token):
+ if isinstance(token, mojom.EnumValue):
+ return "%s_%s" % (GetNameForNestedElement(token.enum),
+ FormatName(token.name, True))
+ if isinstance(token, mojom.ConstantValue):
+ return GetNameForNestedElement(token)
+ if isinstance(token, mojom.Constant):
+ return ExpressionToText(token.value)
+ return token
+
+def DecodeSuffix(kind):
+ if mojom.IsEnumKind(kind):
+ return DecodeSuffix(mojom.INT32)
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return DecodeSuffix(mojom.MSGPIPE)
+ return _kind_infos[kind].decode_suffix
+
+def EncodeSuffix(kind):
+ if mojom.IsEnumKind(kind):
+ return EncodeSuffix(mojom.INT32)
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return EncodeSuffix(mojom.MSGPIPE)
+ return _kind_infos[kind].encode_suffix
def GetPackage(module):
if module.namespace:
@@ -22,12 +158,63 @@ def GetPackagePath(module):
path = os.path.join(path, i)
return path
+def GetStructFromMethod(method):
+ params_class = "%s_%s_Params" % (GetNameForElement(method.interface),
+ GetNameForElement(method))
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.parameters:
+ struct.AddField("in%s" % GetNameForElement(param),
+ param.kind, param.ordinal)
+ struct.packed = pack.PackedStruct(struct)
+ struct.bytes = pack.GetByteLayout(struct.packed)
+ struct.versions = pack.GetVersionInfo(struct.packed)
+ return struct
+
+def GetResponseStructFromMethod(method):
+ params_class = "%s_%s_ResponseParams" % (GetNameForElement(method.interface),
+ GetNameForElement(method))
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.response_parameters:
+ struct.AddField("out%s" % GetNameForElement(param),
+ param.kind, param.ordinal)
+ struct.packed = pack.PackedStruct(struct)
+ struct.bytes = pack.GetByteLayout(struct.packed)
+ struct.versions = pack.GetVersionInfo(struct.packed)
+ return struct
+
class Generator(generator.Generator):
- go_filters = {}
+ go_filters = {
+ 'array': lambda kind: mojom.Array(kind),
+ 'bit_size': GetBitSize,
+ 'decode_suffix': DecodeSuffix,
+ 'encode_suffix': EncodeSuffix,
+ 'go_type': GetGoType,
+ 'expression_to_text': ExpressionToText,
+ 'is_array': mojom.IsArrayKind,
+ 'is_enum': mojom.IsEnumKind,
+ 'is_handle': mojom.IsAnyHandleKind,
+ 'is_map': mojom.IsMapKind,
+ 'is_none_or_empty': lambda array: array == None or len(array) == 0,
+ 'is_nullable': mojom.IsNullableKind,
+ 'is_pointer': mojom.IsObjectKind,
+ 'is_struct': mojom.IsStructKind,
+ 'name': GetNameForElement,
+ 'response_struct_from_method': GetResponseStructFromMethod,
+ 'struct_from_method': GetStructFromMethod,
+ 'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines())
+ }
+
+ def GetAllEnums(self):
+ data = [self.module] + self.GetStructs() + self.module.interfaces
+ enums = [x.enums for x in data]
+ return [i for i in chain.from_iterable(enums)]
def GetParameters(self):
return {
+ 'enums': self.GetAllEnums(),
+ 'interfaces': self.module.interfaces,
'package': GetPackage(self.module),
+ 'structs': self.GetStructs(),
}
@UseJinja('go_templates/source.tmpl', filters=go_filters)
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 ad8980d..f279ef8 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
@@ -23,8 +23,6 @@ from mojom.generate.template_expander import UseJinja
GENERATOR_PREFIX = 'java'
-_HEADER_SIZE = 8
-
_spec_to_java_type = {
mojom.BOOL.spec: 'boolean',
mojom.DCPIPE.spec: 'org.chromium.mojo.system.DataPipe.ConsumerHandle',
@@ -348,14 +346,6 @@ def IsPointerArrayKind(kind):
sub_kind = kind.kind
return mojom.IsObjectKind(sub_kind)
-def GetResponseStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetResponseStructFromMethod(method))
-
-def GetStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetStructFromMethod(method))
-
def GetConstantsMainEntityName(module):
if module.attributes and 'JavaConstantsClassName' in module.attributes:
return ParseStringAttribute(module.attributes['JavaConstantsClassName'])
@@ -420,9 +410,8 @@ class Generator(generator.Generator):
'method_ordinal_name': GetMethodOrdinalName,
'name': GetNameForElement,
'new_array': NewArray,
- 'response_struct_from_method': GetResponseStructFromMethod,
- 'struct_from_method': GetStructFromMethod,
- 'struct_size': lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
+ 'response_struct_from_method': generator.GetResponseStructFromMethod,
+ 'struct_from_method': generator.GetStructFromMethod,
}
def GetJinjaExports(self):
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
index f8a7057..d4d4ed7 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
@@ -191,14 +191,6 @@ def GetFieldGroup(byte):
assert len(byte.packed_fields) == 1
return GetFieldDescriptor(byte.packed_fields[0])
-def GetResponseStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetResponseStructFromMethod(method))
-
-def GetStructFromMethod(method):
- return generator.GetDataHeader(
- False, generator.GetStructFromMethod(method))
-
def ComputeStaticValues(module):
in_progress = set()
computed = set()
@@ -287,8 +279,8 @@ class Generator(generator.Generator):
'field_group': GetFieldGroup,
'fully_qualified_name': GetFullyQualifiedName,
'name': GetNameForElement,
- 'response_struct_from_method': GetResponseStructFromMethod,
- 'struct_from_method': GetStructFromMethod,
+ 'response_struct_from_method': generator.GetResponseStructFromMethod,
+ 'struct_from_method': generator.GetStructFromMethod,
}
@UseJinja('python_templates/module.py.tmpl', filters=python_filters)
@@ -296,7 +288,7 @@ class Generator(generator.Generator):
return {
'enums': self.module.enums,
'imports': self.GetImports(),
- 'interfaces': self.GetQualifiedInterfaces(),
+ 'interfaces': self.module.interfaces,
'module': ComputeStaticValues(self.module),
'namespace': self.module.namespace,
'structs': self.GetStructs(),
@@ -312,26 +304,6 @@ class Generator(generator.Generator):
each['python_module'] = MojomToPythonImport(each['module_name'])
return self.module.imports
- def GetQualifiedInterfaces(self):
- """
- Returns the list of interfaces of the module. Each interface that has a
- client will have a reference to the representation of the client interface
- in the 'qualified_client' field.
- """
- interfaces = self.module.interfaces
- all_interfaces = [] + interfaces
- for each in self.GetImports():
- all_interfaces += [data.KindFromImport(x, each) for x in
- each['module'].interfaces];
- interfaces_by_name = dict((x.name, x) for x in all_interfaces)
- for interface in interfaces:
- if interface.client:
- assert interface.client in interfaces_by_name, (
- 'Unable to find interface %s declared as client of %s.' %
- (interface.client, interface.name))
- interface.qualified_client = interfaces_by_name[interface.client]
- return sorted(interfaces, key=lambda i: (bool(i.client), i.name))
-
def GetJinjaParameters(self):
return {
'lstrip_blocks': True,
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl
index 1e9f0bd..a475a58 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl
@@ -36,9 +36,6 @@ class {{struct|name}}(object):
class {{interface|name}}(object):
__metaclass__ = _reflection.MojoInterfaceType
DESCRIPTOR = {
-{% if interface.client %}
- 'client': lambda: {{interface.qualified_client|fully_qualified_name}},
-{% endif %}
'fully_qualified_name': '{% if namespace %}{{namespace|replace(".","::")}}::{% endif %}{{interface|fully_qualified_name|replace(".","::")}}',
'methods': [
{% for method in interface.methods %}
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 3e0ca4f..3b2874f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
+++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
@@ -61,19 +61,28 @@ template("mojom") {
"$generator_root/generators/cpp_templates/module.h.tmpl",
"$generator_root/generators/cpp_templates/module-internal.h.tmpl",
"$generator_root/generators/cpp_templates/params_definition.tmpl",
+ "$generator_root/generators/cpp_templates/serialization_macros.tmpl",
"$generator_root/generators/cpp_templates/struct_declaration.tmpl",
"$generator_root/generators/cpp_templates/struct_definition.tmpl",
- "$generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
"$generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
"$generator_root/generators/cpp_templates/struct_macros.tmpl",
"$generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
"$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
+ "$generator_root/generators/cpp_templates/union_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/union_definition.tmpl",
+ "$generator_root/generators/cpp_templates/union_serialization_definition.tmpl",
+ "$generator_root/generators/cpp_templates/validation_macros.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_union_class_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_union_class_definition.tmpl",
"$generator_root/generators/dart_templates/enum_definition.tmpl",
"$generator_root/generators/dart_templates/interface_definition.tmpl",
"$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/enum.tmpl",
+ "$generator_root/generators/go_templates/interface.tmpl",
"$generator_root/generators/go_templates/source.tmpl",
+ "$generator_root/generators/go_templates/struct.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",
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 3a41593..3d0ac2e 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
@@ -364,6 +364,7 @@ def ConstantFromData(module, data, parent_kind):
scope = (module.namespace, )
# TODO(mpcomplete): maybe we should only support POD kinds.
constant.kind = KindFromData(module.kinds, data['kind'], scope)
+ constant.parent_kind = parent_kind
constant.value = FixupExpression(module, data.get('value'), scope, None)
value = mojom.ConstantValue(module, parent_kind, constant)
@@ -409,7 +410,7 @@ def ModuleFromData(data):
module.structs = map(
lambda struct: StructFromData(module, struct), data['structs'])
module.unions = map(
- lambda union: UnionFromData(module, struct), data.get('unions', []))
+ lambda union: UnionFromData(module, union), data.get('unions', []))
module.interfaces = map(
lambda interface: InterfaceFromData(module, interface),
data['interfaces'])
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 401c399..ffb64e7 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
@@ -12,14 +12,20 @@ import module as mojom
import mojom.fileutil as fileutil
import pack
+def _GetDataHeader(exported, struct):
+ struct.packed = pack.PackedStruct(struct)
+ struct.bytes = pack.GetByteLayout(struct.packed)
+ struct.versions = pack.GetVersionInfo(struct.packed)
+ struct.exported = exported
+ return struct
+
def GetStructFromMethod(method):
"""Converts a method's parameters into the fields of a struct."""
params_class = "%s_%s_Params" % (method.interface.name, method.name)
struct = mojom.Struct(params_class, module=method.interface.module)
for param in method.parameters:
struct.AddField(param.name, param.kind, param.ordinal)
- struct.packed = pack.PackedStruct(struct)
- return struct
+ return _GetDataHeader(False, struct)
def GetResponseStructFromMethod(method):
"""Converts a method's response_parameters into the fields of a struct."""
@@ -27,14 +33,7 @@ def GetResponseStructFromMethod(method):
struct = mojom.Struct(params_class, module=method.interface.module)
for param in method.response_parameters:
struct.AddField(param.name, param.kind, param.ordinal)
- struct.packed = pack.PackedStruct(struct)
- return struct
-
-def GetDataHeader(exported, struct):
- struct.packed = pack.PackedStruct(struct)
- struct.bytes = pack.GetByteLayout(struct.packed)
- struct.exported = exported
- return struct
+ return _GetDataHeader(False, struct)
def ExpectedArraySize(kind):
if mojom.IsArrayKind(kind):
@@ -48,6 +47,10 @@ def CamelCaseToAllCaps(camel_case):
return '_'.join(
word for word in re.split(r'([A-Z][^A-Z]+)', camel_case) if word).upper()
+def UnderToCamel(under):
+ """Converts underscore_separated strings to CamelCase strings."""
+ return ''.join(word.capitalize() for word in under.split('_'))
+
def WriteFile(contents, full_path):
# Make sure the containing directory exists.
full_dir = os.path.dirname(full_path)
@@ -71,10 +74,10 @@ class Generator(object):
result.append(GetStructFromMethod(method))
if method.response_parameters != None:
result.append(GetResponseStructFromMethod(method))
- return map(partial(GetDataHeader, False), result)
+ return result
def GetStructs(self):
- return map(partial(GetDataHeader, True), self.module.structs)
+ return map(partial(_GetDataHeader, True), self.module.structs)
# Prepend the filename with a directory that matches the directory of the
# original .mojom file, relative to the import root.
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 8a0f56b..c2e59a6 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
@@ -171,10 +171,11 @@ class EnumValue(NamedValue):
class Constant(object):
- def __init__(self, name=None, kind=None, value=None):
+ def __init__(self, name=None, kind=None, value=None, parent_kind=None):
self.name = name
self.kind = kind
self.value = value
+ self.parent_kind = parent_kind
class Field(object):
@@ -464,6 +465,10 @@ def IsStructKind(kind):
return isinstance(kind, Struct)
+def IsUnionKind(kind):
+ return isinstance(kind, Union)
+
+
def IsArrayKind(kind):
return isinstance(kind, Array)
@@ -494,7 +499,7 @@ def IsMapKind(kind):
def IsObjectKind(kind):
return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind) or
- IsMapKind(kind))
+ IsMapKind(kind) or IsUnionKind(kind))
def IsNonInterfaceHandleKind(kind):
@@ -512,7 +517,8 @@ def IsAnyHandleKind(kind):
def IsMoveOnlyKind(kind):
- return IsObjectKind(kind) or IsAnyHandleKind(kind)
+ return (not IsStringKind(kind) and IsObjectKind(kind)) or \
+ IsAnyHandleKind(kind)
def IsCloneableKind(kind):
@@ -525,7 +531,7 @@ def IsCloneableKind(kind):
return True
if IsArrayKind(kind):
return ContainsHandles(kind.kind, visited_kinds)
- if IsStructKind(kind):
+ if IsStructKind(kind) or IsUnionKind(kind):
for field in kind.fields:
if ContainsHandles(field.kind, visited_kinds):
return True
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 37d79eb..c67488c 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
@@ -11,6 +11,9 @@ import module as mojom
# ps.packed_fields will access a list of PackedField objects, each of which
# will have an offset, a size and a bit (for mojom.BOOLs).
+# Size of struct header in bytes: num_bytes [4B] + version [4B].
+HEADER_SIZE = 8
+
class PackedField(object):
kind_to_size = {
mojom.BOOL: 1,
@@ -42,8 +45,8 @@ class PackedField(object):
def GetSizeForKind(cls, kind):
if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct)):
return 8
- if isinstance(kind, mojom.Interface) or \
- isinstance(kind, mojom.InterfaceRequest):
+ if (isinstance(kind, mojom.Interface) or
+ isinstance(kind, mojom.InterfaceRequest)):
kind = mojom.MSGPIPE
if isinstance(kind, mojom.Enum):
# TODO(mpcomplete): what about big enums?
@@ -68,16 +71,16 @@ class PackedField(object):
self.min_version = None
-# Returns the pad necessary to reserve space for alignment of |size|.
def GetPad(offset, size):
+ """Returns the pad necessary to reserve space for alignment of |size|."""
return (size - (offset % size)) % size
-# Returns a 2-tuple of the field offset and bit (for BOOLs)
def GetFieldOffset(field, last_field):
- if field.field.kind == mojom.BOOL and \
- last_field.field.kind == mojom.BOOL and \
- last_field.bit < 7:
+ """Returns a 2-tuple of the field offset and bit (for BOOLs)."""
+ if (field.field.kind == mojom.BOOL and
+ last_field.field.kind == mojom.BOOL and
+ last_field.bit < 7):
return (last_field.offset, last_field.bit + 1)
offset = last_field.offset + last_field.size
@@ -85,17 +88,32 @@ def GetFieldOffset(field, last_field):
return (offset + pad, 0)
+def GetPayloadSizeUpToField(field):
+ """Returns the payload size (not including struct header) if |field| is the
+ last field.
+ """
+ if not field:
+ return 0
+ offset = field.offset + field.size
+ pad = GetPad(offset, 8)
+ return offset + pad
+
+
class PackedStruct(object):
def __init__(self, struct):
self.struct = struct
+ # |packed_fields| contains all the fields, in increasing offset order.
self.packed_fields = []
+ # |packed_fields_in_ordinal_order| refers to the same fields as
+ # |packed_fields|, but in ordinal order.
+ self.packed_fields_in_ordinal_order = []
# No fields.
if (len(struct.fields) == 0):
return
# Start by sorting by ordinal.
- src_fields = []
+ src_fields = self.packed_fields_in_ordinal_order
ordinal = 0
for index, field in enumerate(struct.fields):
if field.ordinal is not None:
@@ -148,7 +166,6 @@ class PackedStruct(object):
src_field = src_fields[0]
src_field.offset = 0
src_field.bit = 0
- # dst_fields will contain each of the fields, in increasing offset order.
dst_fields = self.packed_fields
dst_fields.append(src_field)
@@ -170,14 +187,6 @@ class PackedStruct(object):
src_field.offset, src_field.bit = GetFieldOffset(src_field, last_field)
dst_fields.append(src_field)
- def GetTotalSize(self):
- if not self.packed_fields:
- return 0
- last_field = self.packed_fields[-1]
- offset = last_field.offset + last_field.size
- pad = GetPad(offset, 8)
- return offset + pad
-
class ByteInfo(object):
def __init__(self):
@@ -186,7 +195,9 @@ class ByteInfo(object):
def GetByteLayout(packed_struct):
- bytes = [ByteInfo() for i in xrange(packed_struct.GetTotalSize())]
+ total_payload_size = GetPayloadSizeUpToField(
+ packed_struct.packed_fields[-1] if packed_struct.packed_fields else None)
+ bytes = [ByteInfo() for i in xrange(total_payload_size)]
limit_of_previous_field = 0
for packed_field in packed_struct.packed_fields:
@@ -203,3 +214,46 @@ def GetByteLayout(packed_struct):
assert not (byte.is_padding and byte.packed_fields)
return bytes
+
+
+class VersionInfo(object):
+ def __init__(self, version, num_fields, num_bytes):
+ self.version = version
+ self.num_fields = num_fields
+ self.num_bytes = num_bytes
+
+
+def GetVersionInfo(packed_struct):
+ """Get version information for a struct.
+
+ Args:
+ packed_struct: A PackedStruct instance.
+
+ Returns:
+ A non-empty list of VersionInfo instances, sorted by version in increasing
+ order.
+ Note: The version numbers may not be consecutive.
+ """
+ versions = []
+ last_version = 0
+ last_num_fields = 0
+ last_payload_size = 0
+
+ for packed_field in packed_struct.packed_fields_in_ordinal_order:
+ if packed_field.min_version != last_version:
+ versions.append(
+ VersionInfo(last_version, last_num_fields,
+ last_payload_size + HEADER_SIZE))
+ last_version = packed_field.min_version
+
+ last_num_fields += 1
+ # The fields are iterated in ordinal order here. However, the size of a
+ # version is determined by the last field of that version in pack order,
+ # instead of ordinal order. Therefore, we need to calculate the max value.
+ last_payload_size = max(GetPayloadSizeUpToField(packed_field),
+ last_payload_size)
+
+ assert len(versions) == 0 or last_num_fields != versions[-1].num_fields
+ versions.append(VersionInfo(last_version, last_num_fields,
+ last_payload_size + HEADER_SIZE))
+ return versions
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py
new file mode 100644
index 0000000..a684773
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py
@@ -0,0 +1,37 @@
+# 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.
+
+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 generator
+
+
+class StringManipulationTest(unittest.TestCase):
+ """generator contains some string utilities, this tests only those."""
+
+ def testUnderToCamel(self):
+ """Tests UnderToCamel which converts underscore_separated to CamelCase."""
+ self.assertEquals("CamelCase", generator.UnderToCamel("camel_case"))
+ self.assertEquals("CamelCase", generator.UnderToCamel("CAMEL_CASE"))
+
+if __name__ == "__main__":
+ unittest.main()
+
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
index 329e242..c140003 100644
--- 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
@@ -52,3 +52,45 @@ class PackTest(unittest.TestCase):
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)
+
+ def testGetVersionInfoEmptyStruct(self):
+ """Tests that pack.GetVersionInfo() never returns an empty list, even for
+ empty structs.
+ """
+ struct = mojom.Struct('test')
+ ps = pack.PackedStruct(struct)
+
+ versions = pack.GetVersionInfo(ps)
+ self.assertEquals(1, len(versions))
+ self.assertEquals(0, versions[0].version)
+ self.assertEquals(0, versions[0].num_fields)
+ self.assertEquals(8, versions[0].num_bytes)
+
+ def testGetVersionInfoComplexOrder(self):
+ """Tests pack.GetVersionInfo() using a struct whose definition order,
+ ordinal order and pack order for fields are all different.
+ """
+ struct = mojom.Struct('test')
+ struct.AddField('field_3', mojom.BOOL, ordinal=3,
+ attributes={'MinVersion': 3})
+ struct.AddField('field_0', mojom.INT32, ordinal=0)
+ struct.AddField('field_1', mojom.INT64, ordinal=1,
+ attributes={'MinVersion': 2})
+ struct.AddField('field_2', mojom.INT64, ordinal=2,
+ attributes={'MinVersion': 3})
+ ps = pack.PackedStruct(struct)
+
+ versions = pack.GetVersionInfo(ps)
+ self.assertEquals(3, len(versions))
+
+ self.assertEquals(0, versions[0].version)
+ self.assertEquals(1, versions[0].num_fields)
+ self.assertEquals(16, versions[0].num_bytes)
+
+ self.assertEquals(2, versions[1].version)
+ self.assertEquals(2, versions[1].num_fields)
+ self.assertEquals(24, versions[1].num_bytes)
+
+ self.assertEquals(3, versions[2].version)
+ self.assertEquals(4, versions[2].num_fields)
+ self.assertEquals(32, versions[2].num_bytes)
diff --git a/third_party/mojo/src/mojo/public/tools/download_shell_binary.py b/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
index b46139e..ee74231 100755
--- a/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
+++ b/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
@@ -10,25 +10,23 @@ import sys
import tempfile
import zipfile
+BINARY_FOR_PLATFORM = {
+ "linux-x64" : "mojo_shell",
+ "android-arm" : "MojoShell.apk"
+}
+
if not sys.platform.startswith("linux"):
print "Not supported for your platform"
sys.exit(0)
+CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
+PREBUILT_FILE_PATH = os.path.join(CURRENT_PATH, "prebuilt")
-def download(tools_directory):
- current_path = os.path.dirname(os.path.realpath(__file__))
- find_depot_tools_path = os.path.join(current_path, tools_directory)
- sys.path.insert(0, find_depot_tools_path)
- # pylint: disable=F0401
- import find_depot_tools
-
- prebuilt_file_path = os.path.join(current_path, "prebuilt")
- stamp_path = os.path.join(prebuilt_file_path, "VERSION")
- depot_tools_path = find_depot_tools.add_depot_tools_to_path()
- gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
+def download(tools_directory):
+ stamp_path = os.path.join(PREBUILT_FILE_PATH, "VERSION")
- version_path = os.path.join(current_path, "../VERSION")
+ version_path = os.path.join(CURRENT_PATH, "../VERSION")
with open(version_path) as version_file:
version = version_file.read().strip()
@@ -38,13 +36,27 @@ def download(tools_directory):
if current_version == version:
return 0 # Already have the right version.
except IOError:
- pass # If the stamp file does not exist we need to download a new binary.
+ pass # If the stamp file does not exist we need to download new binaries.
- platform = "linux-x64" # TODO: configurate
- basename = platform + ".zip"
+ for platform in ["linux-x64", "android-arm"]:
+ download_version_for_platform(version, platform, tools_directory)
+
+ with open(stamp_path, 'w') as stamp_file:
+ stamp_file.write(version)
+ return 0
+def download_version_for_platform(version, platform, tools_directory):
+ find_depot_tools_path = os.path.join(CURRENT_PATH, tools_directory)
+ sys.path.insert(0, find_depot_tools_path)
+ # pylint: disable=F0401
+ import find_depot_tools
+
+ basename = platform + ".zip"
gs_path = "gs://mojo/shell/" + version + "/" + basename
+ depot_tools_path = find_depot_tools.add_depot_tools_to_path()
+ gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
+
with tempfile.NamedTemporaryFile() as temp_zip_file:
# We're downloading from a public bucket which does not need authentication,
# but the user might have busted credential files somewhere such as ~/.boto
@@ -70,19 +82,16 @@ def download(tools_directory):
print e.output
sys.exit(1)
+ binary_name = BINARY_FOR_PLATFORM[platform]
with zipfile.ZipFile(temp_zip_file.name) as z:
- zi = z.getinfo("mojo_shell")
+ zi = z.getinfo(binary_name)
mode = zi.external_attr >> 16
- z.extract(zi, prebuilt_file_path)
- os.chmod(os.path.join(prebuilt_file_path, "mojo_shell"), mode)
-
- with open(stamp_path, 'w') as stamp_file:
- stamp_file.write(version)
- return 0
+ z.extract(zi, PREBUILT_FILE_PATH)
+ os.chmod(os.path.join(PREBUILT_FILE_PATH, binary_name), mode)
def main():
- parser = argparse.ArgumentParser(description="Download mojo_shell binary "
+ parser = argparse.ArgumentParser(description="Download mojo_shell binaries "
"from google storage")
parser.add_argument("--tools-directory",
dest="tools_directory",