summaryrefslogtreecommitdiff
path: root/chromium/mojo
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-03-12 09:13:00 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-03-16 09:58:26 +0000
commit03561cae90f1d99b5c54b1ef3be69f10e882b25e (patch)
treecc5f0958e823c044e7ae51cc0117fe51432abe5e /chromium/mojo
parentfa98118a45f7e169f8846086dc2c22c49a8ba310 (diff)
downloadqtwebengine-chromium-03561cae90f1d99b5c54b1ef3be69f10e882b25e.tar.gz
BASELINE: Update Chromium to 88.0.4324.208
Change-Id: I3ae87d23e4eff4b4a469685658740a213600c667 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/mojo')
-rw-r--r--chromium/mojo/BUILD.gn1
-rw-r--r--chromium/mojo/DIR_METADATA11
-rw-r--r--chromium/mojo/OWNERS2
-rw-r--r--chromium/mojo/core/BUILD.gn36
-rw-r--r--chromium/mojo/core/channel.h5
-rw-r--r--chromium/mojo/core/channel_fuzzer.cc2
-rw-r--r--chromium/mojo/core/channel_posix.cc128
-rw-r--r--chromium/mojo/core/channel_unittest.cc2
-rw-r--r--chromium/mojo/core/core.cc2
-rw-r--r--chromium/mojo/core/core_test_base.h1
-rw-r--r--chromium/mojo/core/core_unittest.cc3
-rw-r--r--chromium/mojo/core/data_pipe_unittest.cc35
-rw-r--r--chromium/mojo/core/embedder/embedder.cc19
-rw-r--r--chromium/mojo/core/embedder/embedder.h8
-rw-r--r--chromium/mojo/core/embedder/scoped_ipc_support.cc2
-rw-r--r--chromium/mojo/core/embedder_unittest.cc3
-rw-r--r--chromium/mojo/core/invitation_unittest.cc2
-rw-r--r--chromium/mojo/core/message_pipe_dispatcher.cc79
-rw-r--r--chromium/mojo/core/message_pipe_perftest.cc3
-rw-r--r--chromium/mojo/core/message_pipe_unittest.cc1
-rw-r--r--chromium/mojo/core/multiprocess_message_pipe_unittest.cc1
-rw-r--r--chromium/mojo/core/node_channel.cc4
-rw-r--r--chromium/mojo/core/node_channel_fuzzer.cc2
-rw-r--r--chromium/mojo/core/node_channel_unittest.cc2
-rw-r--r--chromium/mojo/core/node_controller.cc16
-rw-r--r--chromium/mojo/core/node_controller.h9
-rw-r--r--chromium/mojo/core/node_controller_unittest.cc42
-rw-r--r--chromium/mojo/core/ports/node.cc3
-rw-r--r--chromium/mojo/core/test/BUILD.gn12
-rw-r--r--chromium/mojo/core/test_utils.cc74
-rw-r--r--chromium/mojo/core/test_utils.h59
-rw-r--r--chromium/mojo/core/trap_unittest.cc2
-rw-r--r--chromium/mojo/public/DEPS1
-rw-r--r--chromium/mojo/public/c/system/types.h12
-rw-r--r--chromium/mojo/public/cpp/base/BUILD.gn2
-rw-r--r--chromium/mojo/public/cpp/base/big_buffer.h2
-rw-r--r--chromium/mojo/public/cpp/base/file_unittest.cc96
-rw-r--r--chromium/mojo/public/cpp/base/read_only_file_mojom_traits.cc101
-rw-r--r--chromium/mojo/public/cpp/base/read_only_file_mojom_traits.h29
-rw-r--r--chromium/mojo/public/cpp/base/values_mojom_traits.cc4
-rw-r--r--chromium/mojo/public/cpp/base/values_unittest.cc19
-rw-r--r--chromium/mojo/public/cpp/bindings/BUILD.gn4
-rw-r--r--chromium/mojo/public/cpp/bindings/README.md2
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_binding.h20
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_receiver.h20
-rw-r--r--chromium/mojo/public/cpp/bindings/connector.h4
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.cc23
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message.cc29
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/tracing_helper.h20
-rw-r--r--chromium/mojo/public/cpp/bindings/pending_receiver.h2
-rw-r--r--chromium/mojo/public/cpp/bindings/receiver.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/service_factory.cc68
-rw-r--r--chromium/mojo/public/cpp/bindings/service_factory.h85
-rw-r--r--chromium/mojo/public/cpp/bindings/struct_ptr.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/BUILD.gn2
-rw-r--r--chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h2
-rw-r--r--chromium/mojo/public/cpp/platform/BUILD.gn16
-rw-r--r--chromium/mojo/public/cpp/system/platform_handle.cc24
-rw-r--r--chromium/mojo/public/cpp/system/platform_handle.h49
-rw-r--r--chromium/mojo/public/cpp/system/simple_watcher.cc48
-rw-r--r--chromium/mojo/public/cpp/system/simple_watcher.h4
-rw-r--r--chromium/mojo/public/cpp/test_support/lib/test_utils.cc2
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/BUILD.gn4
-rw-r--r--chromium/mojo/public/js/BUILD.gn131
-rw-r--r--chromium/mojo/public/js/bindings_lite.js89
-rw-r--r--chromium/mojo/public/js/bindings_module_export.js.part3
-rw-r--r--chromium/mojo/public/js/bindings_module_preamble.js.part4
-rw-r--r--chromium/mojo/public/js/bindings_uncompiled_module_export.js.part1
-rw-r--r--chromium/mojo/public/js/interface_support.js8
-rw-r--r--chromium/mojo/public/js/interface_support_preamble.js.part8
-rw-r--r--chromium/mojo/public/js/lib/interface_endpoint_client.js15
-rw-r--r--chromium/mojo/public/js/mojo_bindings_resources.grd49
-rw-r--r--chromium/mojo/public/js/mojo_internal_preamble.js.part27
-rw-r--r--chromium/mojo/public/mojom/base/BUILD.gn21
-rw-r--r--chromium/mojo/public/mojom/base/big_string.mojom1
-rw-r--r--chromium/mojo/public/mojom/base/file.mojom1
-rw-r--r--chromium/mojo/public/mojom/base/process_id.mojom1
-rw-r--r--chromium/mojo/public/mojom/base/read_only_file.mojom20
-rw-r--r--chromium/mojo/public/mojom/base/time.mojom2
-rw-r--r--chromium/mojo/public/mojom/base/token.mojom1
-rw-r--r--chromium/mojo/public/mojom/base/values.mojom3
-rw-r--r--chromium/mojo/public/tools/bindings/BUILD.gn9
-rw-r--r--chromium/mojo/public/tools/bindings/README.md25
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl5
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/enum_definition_for_module.tmpl23
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/interface_definition_for_module.tmpl211
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/module_definition.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom-lite.js.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom.m.js.tmpl66
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition_for_module.tmpl49
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/lite/union_definition_for_module.tmpl22
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py7
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py9
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py987
-rw-r--r--chromium/mojo/public/tools/bindings/mojom.gni150
-rw-r--r--chromium/mojo/public/tools/mojom/mojom/BUILD.gn1
-rw-r--r--chromium/mojo/public/tools/mojom/mojom/generate/constant_resolver.py93
-rw-r--r--chromium/mojo/public/tools/mojom/mojom/generate/module.py17
-rwxr-xr-xchromium/mojo/public/tools/mojom/mojom_parser.py29
104 files changed, 2291 insertions, 1103 deletions
diff --git a/chromium/mojo/BUILD.gn b/chromium/mojo/BUILD.gn
index ea1cc00ddc4..c1fe06e9f60 100644
--- a/chromium/mojo/BUILD.gn
+++ b/chromium/mojo/BUILD.gn
@@ -59,7 +59,6 @@ test("mojo_perftests") {
"//base",
"//base/test:test_support",
"//mojo/core:embedder_internal",
- "//mojo/core:test_utils",
"//mojo/core/embedder",
"//testing/gtest",
]
diff --git a/chromium/mojo/DIR_METADATA b/chromium/mojo/DIR_METADATA
new file mode 100644
index 00000000000..06992d0dc06
--- /dev/null
+++ b/chromium/mojo/DIR_METADATA
@@ -0,0 +1,11 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+monorail {
+ component: "Internals>Mojo"
+} \ No newline at end of file
diff --git a/chromium/mojo/OWNERS b/chromium/mojo/OWNERS
index 5d06c5f1b75..15bd89fcb36 100644
--- a/chromium/mojo/OWNERS
+++ b/chromium/mojo/OWNERS
@@ -5,5 +5,3 @@ sky@chromium.org
# For Fuchsia-specific changes:
per-file *_fuchsia*=file://build/fuchsia/OWNERS
-
-# COMPONENT: Internals>Mojo
diff --git a/chromium/mojo/core/BUILD.gn b/chromium/mojo/core/BUILD.gn
index db6af19ea9f..89add521c60 100644
--- a/chromium/mojo/core/BUILD.gn
+++ b/chromium/mojo/core/BUILD.gn
@@ -12,13 +12,6 @@ if (is_mac) {
import("//third_party/protobuf/proto_library.gni")
}
-# This file depends on the legacy global sources assignment filter. It should
-# be converted to check target platform before assigning source files to the
-# sources variable. Remove this import and set_sources_assignment_filter call
-# when the file has been converted. See https://crbug.com/1018739 for details.
-import("//build/config/deprecated_default_sources_assignment_filter.gni")
-set_sources_assignment_filter(deprecated_default_sources_assignment_filter)
-
component("embedder_internal") {
output_name = "mojo_core_embedder_internal"
public_deps = [ ":impl_for_embedder" ]
@@ -81,9 +74,7 @@ template("core_impl_source_set") {
sources = [
"atomic_flag.h",
"broker.h",
- "broker_win.cc",
"channel.cc",
- "channel_win.cc",
"configuration.cc",
"connection_params.cc",
"core.cc",
@@ -163,6 +154,10 @@ template("core_impl_source_set") {
}
if (is_win) {
+ sources += [
+ "broker_win.cc",
+ "channel_win.cc",
+ ]
cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()),
# which is uninteresting.
}
@@ -269,27 +264,6 @@ if (is_chromeos || is_linux || is_android || is_win) {
}
}
-source_set("test_utils") {
- testonly = true
-
- sources = [
- "test_utils.cc",
- "test_utils.h",
- ]
-
- public_deps = [
- "//mojo/public/c/system",
- "//mojo/public/cpp/system",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//mojo/core/test:test_support",
- "//testing/gtest:gtest",
- ]
-}
-
source_set("test_sources") {
testonly = true
sources = [
@@ -316,12 +290,12 @@ source_set("test_sources") {
"data_pipe_unittest.cc",
"invitation_unittest.cc",
"multiprocess_message_pipe_unittest.cc",
+ "node_controller_unittest.cc",
"platform_wrapper_unittest.cc",
]
}
deps = [
- ":test_utils",
"//base",
"//base/test:test_support",
"//mojo/core:embedder_internal",
diff --git a/chromium/mojo/core/channel.h b/chromium/mojo/core/channel.h
index 8d705c570bf..1a8ca65f613 100644
--- a/chromium/mojo/core/channel.h
+++ b/chromium/mojo/core/channel.h
@@ -278,6 +278,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
HandlePolicy handle_policy,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MAC)
+ // At this point only ChannelPosix needs InitFeatures.
+ static void set_posix_use_writev(bool use_writev);
+#endif
+
// Allows the caller to change the Channel's HandlePolicy after construction.
void set_handle_policy(HandlePolicy policy) { handle_policy_ = policy; }
diff --git a/chromium/mojo/core/channel_fuzzer.cc b/chromium/mojo/core/channel_fuzzer.cc
index cb41000d645..2fb651700c8 100644
--- a/chromium/mojo/core/channel_fuzzer.cc
+++ b/chromium/mojo/core/channel_fuzzer.cc
@@ -4,7 +4,7 @@
#include <stdint.h>
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/message_loop/message_pump_type.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
diff --git a/chromium/mojo/core/channel_posix.cc b/chromium/mojo/core/channel_posix.cc
index d7d9d6cfee1..141316d1c13 100644
--- a/chromium/mojo/core/channel_posix.cc
+++ b/chromium/mojo/core/channel_posix.cc
@@ -8,6 +8,7 @@
#include <sys/socket.h>
#include <algorithm>
+#include <atomic>
#include <limits>
#include <memory>
@@ -28,6 +29,7 @@
#include "mojo/public/cpp/platform/socket_utils_posix.h"
#if !defined(OS_NACL)
+#include <limits.h>
#include <sys/uio.h>
#endif
@@ -36,6 +38,10 @@ namespace core {
namespace {
+#if !defined(OS_NACL)
+std::atomic<bool> g_use_writev{false};
+#endif
+
const size_t kMaxBatchReadCapacity = 256 * 1024;
// A view over a Channel::Message object. The write queue uses these since
@@ -89,6 +95,10 @@ class MessageView {
num_handles_sent_ = num_handles_sent;
}
+ size_t num_handles_remaining() const {
+ return handles_.size() - num_handles_sent_;
+ }
+
private:
Channel::MessagePtr message_;
size_t offset_;
@@ -447,6 +457,11 @@ class ChannelPosix : public Channel,
}
bool FlushOutgoingMessagesNoLock() {
+#if !defined(OS_NACL)
+ if (g_use_writev)
+ return FlushOutgoingMessagesWritevNoLock();
+#endif
+
base::circular_deque<MessageView> messages;
std::swap(outgoing_messages_, messages);
@@ -478,6 +493,112 @@ class ChannelPosix : public Channel,
return true;
}
+#if !defined(OS_NACL)
+ bool WriteOutgoingMessagesWithWritev() {
+ if (outgoing_messages_.empty())
+ return true;
+
+ // If all goes well we can submit a writev(2) with a iovec of size
+ // outgoing_messages_.size() but never more than the kernel allows.
+ size_t num_messages_to_send =
+ std::min<size_t>(IOV_MAX, outgoing_messages_.size());
+ iovec iov[num_messages_to_send];
+ memset(&iov[0], 0, sizeof(iov));
+
+ // Populate the iov.
+ size_t num_iovs_set = 0;
+ for (auto it = outgoing_messages_.begin();
+ num_iovs_set < num_messages_to_send; ++it) {
+ if (it->num_handles_remaining() > 0) {
+ // We can't send handles with writev(2) so stop at this message.
+ break;
+ }
+
+ iov[num_iovs_set].iov_base = const_cast<void*>(it->data());
+ iov[num_iovs_set].iov_len = it->data_num_bytes();
+ num_iovs_set++;
+ }
+
+ UMA_HISTOGRAM_COUNTS_1000("Mojo.Channel.WritevBatchedMessages",
+ num_iovs_set);
+
+ size_t iov_offset = 0;
+ while (iov_offset < num_iovs_set) {
+ ssize_t bytes_written = SocketWritev(socket_.get(), &iov[iov_offset],
+ num_iovs_set - iov_offset);
+ if (bytes_written < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ WaitForWriteOnIOThreadNoLock();
+ return true;
+ }
+ return false;
+ }
+
+ // Let's walk our outgoing_messages_ popping off outgoing_messages_
+ // that were fully written.
+ size_t bytes_remaining = bytes_written;
+ while (bytes_remaining > 0) {
+ if (bytes_remaining >= outgoing_messages_.front().data_num_bytes()) {
+ // This message was fully written.
+ bytes_remaining -= outgoing_messages_.front().data_num_bytes();
+ outgoing_messages_.pop_front();
+ iov_offset++;
+ } else {
+ // This message was partially written, account for what was
+ // already written.
+ outgoing_messages_.front().advance_data_offset(bytes_remaining);
+ bytes_remaining = 0;
+
+ // Update the iov too as we will call writev again.
+ iov[iov_offset].iov_base =
+ const_cast<void*>(outgoing_messages_.front().data());
+ iov[iov_offset].iov_len = outgoing_messages_.front().data_num_bytes();
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // FlushOutgoingMessagesWritevNoLock is equivalent to
+ // FlushOutgoingMessagesNoLock except it looks for opportunities to make only
+ // a single write syscall by using writev(2) instead of write(2). In most
+ // situations this is very straight forward; however, when a handle needs to
+ // be transferred we cannot use writev(2) and instead will fall back to the
+ // standard write.
+ bool FlushOutgoingMessagesWritevNoLock() {
+ do {
+ // If the first message contains a handle we will flush it first using a
+ // standard write, we will also use the standard write if we only have a
+ // single message.
+ while (!outgoing_messages_.empty() &&
+ (outgoing_messages_.front().num_handles_remaining() > 0 ||
+ outgoing_messages_.size() == 1)) {
+ MessageView message = std::move(outgoing_messages_.front());
+
+ outgoing_messages_.pop_front();
+ size_t messages_before_write = outgoing_messages_.size();
+ if (!WriteNoLock(std::move(message)))
+ return false;
+
+ if (outgoing_messages_.size() > messages_before_write) {
+ // It was re-queued by WriteNoLock.
+ return true;
+ }
+ }
+
+ if (!WriteOutgoingMessagesWithWritev())
+ return false;
+
+ // At this point if we have more messages then it's either because we
+ // exceeded IOV_MAX OR it's because we ran into a FileHandle. Either way
+ // we just start the process all over again and it will flush any
+ // FileHandles before attempting writev(2) again.
+ } while (!outgoing_messages_.empty());
+ return true;
+ }
+#endif // !defined(OS_NACL)
+
#if defined(OS_IOS)
bool OnControlMessage(Message::MessageType message_type,
const void* payload,
@@ -601,6 +722,13 @@ class ChannelPosix : public Channel,
} // namespace
// static
+#if !defined(OS_NACL)
+void Channel::set_posix_use_writev(bool use_writev) {
+ g_use_writev = use_writev;
+}
+#endif
+
+// static
scoped_refptr<Channel> Channel::Create(
Delegate* delegate,
ConnectionParams connection_params,
diff --git a/chromium/mojo/core/channel_unittest.cc b/chromium/mojo/core/channel_unittest.cc
index 4fcb57b9651..58d6ee44ad6 100644
--- a/chromium/mojo/core/channel_unittest.cc
+++ b/chromium/mojo/core/channel_unittest.cc
@@ -14,7 +14,7 @@
#include "base/process/process_metrics.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
-#include "base/test/bind_test_util.h"
+#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/mojo/core/core.cc b/chromium/mojo/core/core.cc
index 9f344cfab31..61444a3dec1 100644
--- a/chromium/mojo/core/core.cc
+++ b/chromium/mojo/core/core.cc
@@ -137,7 +137,7 @@ void Core::SetIOTaskRunner(
NodeController* Core::GetNodeController() {
base::AutoLock lock(node_controller_lock_);
if (!node_controller_)
- node_controller_.reset(new NodeController(this));
+ node_controller_ = std::make_unique<NodeController>();
return node_controller_.get();
}
diff --git a/chromium/mojo/core/core_test_base.h b/chromium/mojo/core/core_test_base.h
index 5d37d252c2e..ebc5fe154e3 100644
--- a/chromium/mojo/core/core_test_base.h
+++ b/chromium/mojo/core/core_test_base.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "base/synchronization/lock.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/types.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/mojo/core/core_unittest.cc b/chromium/mojo/core/core_unittest.cc
index 8846051ad03..0d2024ccd9a 100644
--- a/chromium/mojo/core/core_unittest.cc
+++ b/chromium/mojo/core/core_unittest.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "build/build_config.h"
#include "mojo/core/core_test_base.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/cpp/system/wait.h"
#if defined(OS_WIN)
@@ -35,7 +34,7 @@ TEST_F(CoreTest, GetTimeTicksNow) {
const MojoTimeTicks start = core()->GetTimeTicksNow();
ASSERT_NE(static_cast<MojoTimeTicks>(0), start)
<< "GetTimeTicksNow should return nonzero value";
- test::Sleep(test::DeadlineFromMilliseconds(15));
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(15));
const MojoTimeTicks finish = core()->GetTimeTicksNow();
// Allow for some fuzz in sleep.
ASSERT_GE((finish - start), static_cast<MojoTimeTicks>(8000))
diff --git a/chromium/mojo/core/data_pipe_unittest.cc b/chromium/mojo/core/data_pipe_unittest.cc
index 9ff3e1668bf..395e8d8fdac 100644
--- a/chromium/mojo/core/data_pipe_unittest.cc
+++ b/chromium/mojo/core/data_pipe_unittest.cc
@@ -16,7 +16,6 @@
#include "build/build_config.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/test/mojo_test_base.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
@@ -45,6 +44,28 @@ const int kMultiprocessMaxIter = 5;
// Capacity that will cause data pipe creation to fail.
constexpr size_t kOversizedCapacity = std::numeric_limits<uint32_t>::max();
+// A timeout smaller than |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|.
+// Warning: This may lead to flakiness, but this is unavoidable if, e.g., you're
+// trying to ensure that functions with timeouts are reasonably accurate. We
+// want this to be as small as possible without causing too much flakiness.
+base::TimeDelta EpsilonDeadline() {
+ const int64_t tiny_timeout = TestTimeouts::tiny_timeout().InMicroseconds();
+// Originally, our epsilon timeout was 10 ms, which was mostly fine but flaky on
+// some Windows bots. I don't recall ever seeing flakes on other bots. At 30 ms
+// tests seem reliable on Windows bots, but not at 25 ms. We'd like this timeout
+// to be as small as possible (see the description in the .h file).
+//
+// Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN,
+// etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms
+// elsewhere.
+#if defined(OS_WIN) || defined(OS_ANDROID)
+ const int64_t deadline = (tiny_timeout * 3) / 10;
+#else
+ const int64_t deadline = (tiny_timeout * 2) / 10;
+#endif
+ return base::TimeDelta::FromMicroseconds(deadline);
+}
+
// TODO(rockot): There are many uses of ASSERT where EXPECT would be more
// appropriate. Fix this.
@@ -948,7 +969,7 @@ TEST_F(DataPipeTest, AllOrNone) {
if (num_bytes >= 10u * sizeof(int32_t))
break;
- test::Sleep(test::EpsilonDeadline());
+ base::PlatformThread::Sleep(EpsilonDeadline());
}
ASSERT_EQ(10u * sizeof(int32_t), num_bytes);
@@ -1154,7 +1175,7 @@ TEST_F(DataPipeTest, WriteCloseProducerRead) {
if (num_bytes >= 2u * kTestDataSize)
break;
- test::Sleep(test::EpsilonDeadline());
+ base::PlatformThread::Sleep(EpsilonDeadline());
}
ASSERT_EQ(2u * kTestDataSize, num_bytes);
@@ -1423,7 +1444,7 @@ TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) {
// Wait a bit, to make sure that if a signal were (incorrectly) sent, it'd
// have time to propagate.
- test::Sleep(test::EpsilonDeadline());
+ base::PlatformThread::Sleep(EpsilonDeadline());
// Still no data.
num_bytes = 1000u;
@@ -1441,7 +1462,7 @@ TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) {
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EndWriteData(0u));
// Wait a bit (as above).
- test::Sleep(test::EpsilonDeadline());
+ base::PlatformThread::Sleep(EpsilonDeadline());
// Still no data.
num_bytes = 1000u;
@@ -1460,7 +1481,7 @@ TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) {
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EndWriteData(0u));
// Wait a bit (as above).
- test::Sleep(test::EpsilonDeadline());
+ base::PlatformThread::Sleep(EpsilonDeadline());
// Still no data.
num_bytes = 1000u;
@@ -1705,7 +1726,7 @@ bool ReadAllData(MojoHandle consumer,
if (num_bytes == 0) {
if (expect_empty) {
// Expect no more data.
- test::Sleep(test::TinyDeadline());
+ base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
MojoReadDataOptions options;
options.struct_size = sizeof(options);
options.flags = MOJO_READ_DATA_FLAG_QUERY;
diff --git a/chromium/mojo/core/embedder/embedder.cc b/chromium/mojo/core/embedder/embedder.cc
index 3a4e3172938..29b6d058e91 100644
--- a/chromium/mojo/core/embedder/embedder.cc
+++ b/chromium/mojo/core/embedder/embedder.cc
@@ -5,10 +5,14 @@
#include "mojo/core/embedder/embedder.h"
#include <stdint.h>
+#include <atomic>
#include <utility>
+#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
+#include "build/build_config.h"
+#include "mojo/core/channel.h"
#include "mojo/core/configuration.h"
#include "mojo/core/core.h"
#include "mojo/core/entrypoints.h"
@@ -18,6 +22,21 @@
namespace mojo {
namespace core {
+namespace {
+#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MAC)
+const base::Feature kMojoPosixUseWritev{"MojoPosixUseWritev",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+} // namespace
+
+// InitFeatures will be called as soon as the base::FeatureList is initialized.
+void InitFeatures() {
+#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MAC)
+ Channel::set_posix_use_writev(
+ base::FeatureList::IsEnabled(kMojoPosixUseWritev));
+#endif
+}
+
void Init(const Configuration& configuration) {
internal::g_configuration = configuration;
InitializeCore();
diff --git a/chromium/mojo/core/embedder/embedder.h b/chromium/mojo/core/embedder/embedder.h
index 575b301468d..56b8bb6c9d5 100644
--- a/chromium/mojo/core/embedder/embedder.h
+++ b/chromium/mojo/core/embedder/embedder.h
@@ -38,6 +38,14 @@ COMPONENT_EXPORT(MOJO_CORE_EMBEDDER) void Init();
COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner();
+// InitFeatures will be called as soon as the base::FeatureList is initialized.
+// NOTE: This is temporarily necessary because of how Mojo is started with
+// respect to base::FeatureList.
+//
+// TODO(rockot): Remove once a long term solution is in place for using
+// base::Features inside of Mojo.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER) void InitFeatures();
+
} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/core/embedder/scoped_ipc_support.cc b/chromium/mojo/core/embedder/scoped_ipc_support.cc
index 4bfbc9e0775..0fbf446eca9 100644
--- a/chromium/mojo/core/embedder/scoped_ipc_support.cc
+++ b/chromium/mojo/core/embedder/scoped_ipc_support.cc
@@ -5,7 +5,7 @@
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "mojo/core/core.h"
diff --git a/chromium/mojo/core/embedder_unittest.cc b/chromium/mojo/core/embedder_unittest.cc
index 5d85b367e2c..7f24ea6b159 100644
--- a/chromium/mojo/core/embedder_unittest.cc
+++ b/chromium/mojo/core/embedder_unittest.cc
@@ -30,7 +30,6 @@
#include "mojo/core/core.h"
#include "mojo/core/shared_buffer_dispatcher.h"
#include "mojo/core/test/mojo_test_base.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -47,7 +46,7 @@ MojoResult CreateSharedBufferFromRegion(T&& region, MojoHandle* handle) {
scoped_refptr<SharedBufferDispatcher> buffer;
MojoResult result =
SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
- T::TakeHandleForSerialization(std::move(region)), &buffer);
+ T::TakeHandleForSerialization(std::forward<T>(region)), &buffer);
if (result != MOJO_RESULT_OK)
return result;
diff --git a/chromium/mojo/core/invitation_unittest.cc b/chromium/mojo/core/invitation_unittest.cc
index 684bbfe2a41..c88c20bf83a 100644
--- a/chromium/mojo/core/invitation_unittest.cc
+++ b/chromium/mojo/core/invitation_unittest.cc
@@ -18,7 +18,7 @@
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
-#include "base/test/bind_test_util.h"
+#include "base/test/bind.h"
#include "base/test/multiprocess_test.h"
#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
diff --git a/chromium/mojo/core/message_pipe_dispatcher.cc b/chromium/mojo/core/message_pipe_dispatcher.cc
index e17fdabc2d3..980d01ceccc 100644
--- a/chromium/mojo/core/message_pipe_dispatcher.cc
+++ b/chromium/mojo/core/message_pipe_dispatcher.cc
@@ -199,42 +199,51 @@ MojoResult MessagePipeDispatcher::ReadMessage(
}
MojoResult MessagePipeDispatcher::SetQuota(MojoQuotaType type, uint64_t limit) {
- base::AutoLock lock(signal_lock_);
-
- switch (type) {
- case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH:
- if (limit == MOJO_QUOTA_LIMIT_NONE)
- receive_queue_length_limit_.reset();
- else
- receive_queue_length_limit_ = limit;
- break;
-
- case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE:
- if (limit == MOJO_QUOTA_LIMIT_NONE)
- receive_queue_memory_size_limit_.reset();
- else
- receive_queue_memory_size_limit_ = limit;
- break;
-
- case MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT:
- if (limit == MOJO_QUOTA_LIMIT_NONE) {
- unread_message_count_limit_.reset();
- node_controller_->node()->SetAcknowledgeRequestInterval(port_, 0);
- } else {
- unread_message_count_limit_ = limit;
- // Setting the acknowledge request interval for the port to half the
- // unread quota limit, means the ack roundtrip has half the window to
- // catch up with sent messages. In other words, if the producer is
- // producing messages at a steady rate of limit/2 packets per message
- // round trip or lower, the quota limit won't be exceeded. This is
- // assuming the consumer is consuming messages at the same rate.
- node_controller_->node()->SetAcknowledgeRequestInterval(
- port_, (limit + 1) / 2);
- }
- break;
+ base::Optional<uint64_t> new_ack_request_interval;
+ {
+ base::AutoLock lock(signal_lock_);
+ switch (type) {
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH:
+ if (limit == MOJO_QUOTA_LIMIT_NONE)
+ receive_queue_length_limit_.reset();
+ else
+ receive_queue_length_limit_ = limit;
+ break;
+
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE:
+ if (limit == MOJO_QUOTA_LIMIT_NONE)
+ receive_queue_memory_size_limit_.reset();
+ else
+ receive_queue_memory_size_limit_ = limit;
+ break;
+
+ case MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT:
+ if (limit == MOJO_QUOTA_LIMIT_NONE) {
+ unread_message_count_limit_.reset();
+ new_ack_request_interval = 0;
+ } else {
+ unread_message_count_limit_ = limit;
+ // Setting the acknowledge request interval for the port to half the
+ // unread quota limit, means the ack roundtrip has half the window to
+ // catch up with sent messages. In other words, if the producer is
+ // producing messages at a steady rate of limit/2 packets per message
+ // round trip or lower, the quota limit won't be exceeded. This is
+ // assuming the consumer is consuming messages at the same rate.
+ new_ack_request_interval = (limit + 1) / 2;
+ }
+ break;
+
+ default:
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+ }
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
+ if (new_ack_request_interval.has_value()) {
+ // NOTE: It is not safe to call into SetAcknowledgeRequestInterval while
+ // holding a `signal_lock_`, as it may re-enter this object when the peer is
+ // in the same process.
+ node_controller_->node()->SetAcknowledgeRequestInterval(
+ port_, *new_ack_request_interval);
}
return MOJO_RESULT_OK;
diff --git a/chromium/mojo/core/message_pipe_perftest.cc b/chromium/mojo/core/message_pipe_perftest.cc
index af832586393..f7ae32e345c 100644
--- a/chromium/mojo/core/message_pipe_perftest.cc
+++ b/chromium/mojo/core/message_pipe_perftest.cc
@@ -9,7 +9,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
@@ -19,7 +19,6 @@
#include "mojo/core/handle_signals_state.h"
#include "mojo/core/test/mojo_test_base.h"
#include "mojo/core/test/test_utils.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/mojo/core/message_pipe_unittest.cc b/chromium/mojo/core/message_pipe_unittest.cc
index 20c71ff4549..9aa13f69f2f 100644
--- a/chromium/mojo/core/message_pipe_unittest.cc
+++ b/chromium/mojo/core/message_pipe_unittest.cc
@@ -14,7 +14,6 @@
#include "base/memory/ref_counted.h"
#include "build/build_config.h"
#include "mojo/core/test/mojo_test_base.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/message_pipe.h"
diff --git a/chromium/mojo/core/multiprocess_message_pipe_unittest.cc b/chromium/mojo/core/multiprocess_message_pipe_unittest.cc
index bdce6c7fd8a..26e2c80b0d2 100644
--- a/chromium/mojo/core/multiprocess_message_pipe_unittest.cc
+++ b/chromium/mojo/core/multiprocess_message_pipe_unittest.cc
@@ -26,7 +26,6 @@
#include "mojo/core/handle_signals_state.h"
#include "mojo/core/test/mojo_test_base.h"
#include "mojo/core/test/test_utils.h"
-#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/types.h"
diff --git a/chromium/mojo/core/node_channel.cc b/chromium/mojo/core/node_channel.cc
index 5db339ec802..e9cc9f23c2f 100644
--- a/chromium/mojo/core/node_channel.cc
+++ b/chromium/mojo/core/node_channel.cc
@@ -45,6 +45,8 @@ enum class MessageType : uint32_t {
BIND_BROKER_HOST,
};
+#pragma pack(push, 1)
+
struct Header {
MessageType type;
uint32_t padding;
@@ -130,6 +132,8 @@ struct EventMessageFromRelayData {
};
#endif
+#pragma pack(pop)
+
template <typename DataType>
Channel::MessagePtr CreateMessage(MessageType type,
size_t payload_size,
diff --git a/chromium/mojo/core/node_channel_fuzzer.cc b/chromium/mojo/core/node_channel_fuzzer.cc
index 54fe757e0de..33188323f05 100644
--- a/chromium/mojo/core/node_channel_fuzzer.cc
+++ b/chromium/mojo/core/node_channel_fuzzer.cc
@@ -4,7 +4,7 @@
#include <stdint.h>
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/message_loop/message_pump_type.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
diff --git a/chromium/mojo/core/node_channel_unittest.cc b/chromium/mojo/core/node_channel_unittest.cc
index 13c46f13fea..e89f5a13bb0 100644
--- a/chromium/mojo/core/node_channel_unittest.cc
+++ b/chromium/mojo/core/node_channel_unittest.cc
@@ -4,7 +4,7 @@
#include "mojo/core/node_channel.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/test/task_environment.h"
diff --git a/chromium/mojo/core/node_controller.cc b/chromium/mojo/core/node_controller.cc
index 029bd350b08..823a4619efa 100644
--- a/chromium/mojo/core/node_controller.cc
+++ b/chromium/mojo/core/node_controller.cc
@@ -21,7 +21,6 @@
#include "mojo/core/broker.h"
#include "mojo/core/broker_host.h"
#include "mojo/core/configuration.h"
-#include "mojo/core/core.h"
#include "mojo/core/request_context.h"
#include "mojo/core/user_message_impl.h"
#include "mojo/public/cpp/platform/named_platform_channel.h"
@@ -146,10 +145,8 @@ class ThreadDestructionObserver
NodeController::~NodeController() = default;
-NodeController::NodeController(Core* core)
- : core_(core),
- name_(GetRandomNodeName()),
- node_(new ports::Node(name_, this)) {
+NodeController::NodeController()
+ : name_(GetRandomNodeName()), node_(new ports::Node(name_, this)) {
DVLOG(1) << "Initializing node " << name_;
}
@@ -588,10 +585,17 @@ void NodeController::AddPeer(const ports::NodeName& name,
}
}
-void NodeController::DropPeer(const ports::NodeName& name,
+void NodeController::DropPeer(const ports::NodeName& node_name,
NodeChannel* channel) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ // NOTE: Either the `peers_` erasure or the `pending_invitations_` erasure
+ // below, if executed, may drop the last reference to the named NodeChannel
+ // and thus result in its deletion. The passed `node_name` argument may be
+ // owned by that same NodeChannel, so we make a copy of it here to avoid
+ // potentially unsafe references further below.
+ ports::NodeName name = node_name;
+
{
base::AutoLock lock(peers_lock_);
auto it = peers_.find(name);
diff --git a/chromium/mojo/core/node_controller.h b/chromium/mojo/core/node_controller.h
index f35237f4eb5..b0ddd290973 100644
--- a/chromium/mojo/core/node_controller.h
+++ b/chromium/mojo/core/node_controller.h
@@ -52,11 +52,10 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
};
// |core| owns and out-lives us.
- explicit NodeController(Core* core);
+ NodeController();
~NodeController() override;
const ports::NodeName& name() const { return name_; }
- Core* core() const { return core_; }
ports::Node* node() const { return node_.get(); }
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
return io_task_runner_;
@@ -135,6 +134,8 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
base::span<const unsigned char> data);
static void DeserializeMessageAsEventForFuzzer(Channel::MessagePtr message);
+ scoped_refptr<NodeChannel> GetBrokerChannel();
+
private:
friend Core;
@@ -176,7 +177,6 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
scoped_refptr<NodeChannel> GetPeerChannel(const ports::NodeName& name);
scoped_refptr<NodeChannel> GetInviterChannel();
- scoped_refptr<NodeChannel> GetBrokerChannel();
void AddPeer(const ports::NodeName& name,
scoped_refptr<NodeChannel> channel,
@@ -254,7 +254,6 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
void ForceDisconnectProcessForTestingOnIOThread(base::ProcessId process_id);
// These are safe to access from any thread as long as the Node is alive.
- Core* const core_;
const ports::NodeName name_;
const std::unique_ptr<ports::Node> node_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
@@ -319,7 +318,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
AtomicFlag shutdown_callback_flag_;
// All other fields below must only be accessed on the I/O thread, i.e., the
- // thread on which core_->io_task_runner() runs tasks.
+ // thread on which `io_task_runner_` runs tasks.
// Channels to invitees during handshake.
NodeMap pending_invitations_;
diff --git a/chromium/mojo/core/node_controller_unittest.cc b/chromium/mojo/core/node_controller_unittest.cc
new file mode 100644
index 00000000000..316e1623763
--- /dev/null
+++ b/chromium/mojo/core/node_controller_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "mojo/core/core.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/public/c/system/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace core {
+namespace {
+
+using NodeControllerTest = test::MojoTestBase;
+
+TEST_F(NodeControllerTest, AcceptInvitationFailure) {
+ // Spawn a child process that will send an invalid AcceptInvitation
+ // NodeChannel message. This is a regression test for
+ // https://crbug.com/1162198.
+ RunTestClient("SendInvalidAcceptInvitation",
+ [&](MojoHandle h) { WriteMessage(h, "hi"); });
+}
+
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendInvalidAcceptInvitation,
+ NodeControllerTest,
+ h) {
+ // A little communication to synchronize against Mojo bringup. By the time
+ // this read completes, we must have an internal NodeController with the
+ // parent test process connected as its broker.
+ EXPECT_EQ("hi", ReadMessage(h));
+
+ // Send an unexpected AcceptInvitation message to the parent process. This
+ // exercises the regression code path in the parent process.
+ NodeController* controller = Core::Get()->GetNodeController();
+ scoped_refptr<NodeChannel> channel = controller->GetBrokerChannel();
+ channel->AcceptInvitation(ports::NodeName{0, 0}, ports::NodeName{0, 0});
+}
+
+} // namespace
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/core/ports/node.cc b/chromium/mojo/core/ports/node.cc
index 5b2558a0465..7907b38d4e6 100644
--- a/chromium/mojo/core/ports/node.cc
+++ b/chromium/mojo/core/ports/node.cc
@@ -920,7 +920,8 @@ int Node::OnUserMessageReadAckRequest(
}
}
- delegate_->ForwardEvent(peer_node_name, std::move(event_to_send));
+ if (event_to_send)
+ delegate_->ForwardEvent(peer_node_name, std::move(event_to_send));
return OK;
}
diff --git a/chromium/mojo/core/test/BUILD.gn b/chromium/mojo/core/test/BUILD.gn
index 9d0d150771d..d3025e4c1c2 100644
--- a/chromium/mojo/core/test/BUILD.gn
+++ b/chromium/mojo/core/test/BUILD.gn
@@ -4,13 +4,6 @@
import("//third_party/protobuf/proto_library.gni")
-# This file depends on the legacy global sources assignment filter. It should
-# be converted to check target platform before assigning source files to the
-# sources variable. Remove this import and set_sources_assignment_filter call
-# when the file has been converted. See https://crbug.com/1018739 for details.
-import("//build/config/deprecated_default_sources_assignment_filter.gni")
-set_sources_assignment_filter(deprecated_default_sources_assignment_filter)
-
static_library("test_support") {
testonly = true
sources = [
@@ -19,7 +12,6 @@ static_library("test_support") {
"mojo_test_base.cc",
"mojo_test_base.h",
"test_utils.h",
- "test_utils_win.cc",
]
if (!is_ios) {
@@ -29,6 +21,10 @@ static_library("test_support") {
]
}
+ if (is_win) {
+ sources += [ "test_utils_win.cc" ]
+ }
+
if (is_fuchsia || is_posix) {
sources += [ "test_utils.cc" ]
}
diff --git a/chromium/mojo/core/test_utils.cc b/chromium/mojo/core/test_utils.cc
deleted file mode 100644
index acbfca018af..00000000000
--- a/chromium/mojo/core/test_utils.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/core/test_utils.h"
-
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/check_op.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "build/build_config.h"
-
-namespace mojo {
-namespace core {
-namespace test {
-
-MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds) {
- return static_cast<MojoDeadline>(milliseconds) * 1000;
-}
-
-MojoDeadline EpsilonDeadline() {
-// Originally, our epsilon timeout was 10 ms, which was mostly fine but flaky on
-// some Windows bots. I don't recall ever seeing flakes on other bots. At 30 ms
-// tests seem reliable on Windows bots, but not at 25 ms. We'd like this timeout
-// to be as small as possible (see the description in the .h file).
-//
-// Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN,
-// etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms
-// elsewhere.
-#if defined(OS_WIN) || defined(OS_ANDROID)
- return (TinyDeadline() * 3) / 10;
-#else
- return (TinyDeadline() * 2) / 10;
-#endif
-}
-
-MojoDeadline TinyDeadline() {
- return static_cast<MojoDeadline>(
- TestTimeouts::tiny_timeout().InMicroseconds());
-}
-
-MojoDeadline ActionDeadline() {
- return static_cast<MojoDeadline>(
- TestTimeouts::action_timeout().InMicroseconds());
-}
-
-void Sleep(MojoDeadline deadline) {
- CHECK_LE(deadline,
- static_cast<MojoDeadline>(std::numeric_limits<int64_t>::max()));
- base::PlatformThread::Sleep(
- base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline)));
-}
-
-Stopwatch::Stopwatch() = default;
-
-Stopwatch::~Stopwatch() = default;
-
-void Stopwatch::Start() {
- start_time_ = base::TimeTicks::Now();
-}
-
-MojoDeadline Stopwatch::Elapsed() {
- int64_t result = (base::TimeTicks::Now() - start_time_).InMicroseconds();
- // |DCHECK_GE|, not |CHECK_GE|, since this may be performance-important.
- DCHECK_GE(result, 0);
- return static_cast<MojoDeadline>(result);
-}
-
-} // namespace test
-} // namespace core
-} // namespace mojo
diff --git a/chromium/mojo/core/test_utils.h b/chromium/mojo/core/test_utils.h
deleted file mode 100644
index 98ac51e182d..00000000000
--- a/chromium/mojo/core/test_utils.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_CORE_TEST_UTILS_H_
-#define MOJO_CORE_TEST_UTILS_H_
-
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "mojo/public/c/system/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace core {
-namespace test {
-
-MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds);
-
-// A timeout smaller than |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|.
-// Warning: This may lead to flakiness, but this is unavoidable if, e.g., you're
-// trying to ensure that functions with timeouts are reasonably accurate. We
-// want this to be as small as possible without causing too much flakiness.
-MojoDeadline EpsilonDeadline();
-
-// |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|. (Expect this to be on
-// the order of 100 ms.)
-MojoDeadline TinyDeadline();
-
-// |TestTimeouts::action_timeout()|, as a |MojoDeadline|. (Expect this to be on
-// the order of 10 s.)
-MojoDeadline ActionDeadline();
-
-// Sleeps for at least the specified duration.
-void Sleep(MojoDeadline deadline);
-
-// Stopwatch -------------------------------------------------------------------
-
-// A simple "stopwatch" for measuring time elapsed from a given starting point.
-class Stopwatch {
- public:
- Stopwatch();
- ~Stopwatch();
-
- void Start();
- // Returns the amount of time elapsed since the last call to |Start()| (in
- // microseconds).
- MojoDeadline Elapsed();
-
- private:
- base::TimeTicks start_time_;
-
- DISALLOW_COPY_AND_ASSIGN(Stopwatch);
-};
-
-} // namespace test
-} // namespace core
-} // namespace mojo
-
-#endif // MOJO_CORE_TEST_UTILS_H_
diff --git a/chromium/mojo/core/trap_unittest.cc b/chromium/mojo/core/trap_unittest.cc
index 8ff1f74a6ad..65595510930 100644
--- a/chromium/mojo/core/trap_unittest.cc
+++ b/chromium/mojo/core/trap_unittest.cc
@@ -14,7 +14,7 @@
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/bind_test_util.h"
+#include "base/test/bind.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "base/time/time.h"
diff --git a/chromium/mojo/public/DEPS b/chromium/mojo/public/DEPS
index 185539038b8..8bed1ad0e7c 100644
--- a/chromium/mojo/public/DEPS
+++ b/chromium/mojo/public/DEPS
@@ -9,4 +9,5 @@ include_rules = [
# Temporary until mojom [Native] is gone.
"+ipc/ipc_param_traits.h",
+ "+third_party/perfetto/protos/perfetto/trace/track_event",
]
diff --git a/chromium/mojo/public/c/system/types.h b/chromium/mojo/public/c/system/types.h
index bb6504343a7..56ffd789916 100644
--- a/chromium/mojo/public/c/system/types.h
+++ b/chromium/mojo/public/c/system/types.h
@@ -124,18 +124,6 @@ const MojoResult MOJO_RESULT_SHOULD_WAIT = 17;
#define MOJO_RESULT_SHOULD_WAIT ((MojoResult)17)
#endif
-// |MojoDeadline|: Used to specify deadlines (timeouts), in microseconds (except
-// for |MOJO_DEADLINE_INDEFINITE|).
-// |MOJO_DEADLINE_INDEFINITE| - Used to indicate "forever".
-
-typedef uint64_t MojoDeadline;
-
-#ifdef __cplusplus
-const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1);
-#else
-#define MOJO_DEADLINE_INDEFINITE ((MojoDeadline)-1)
-#endif
-
// Flags passed to |MojoInitialize()| via |MojoInitializeOptions|.
typedef uint32_t MojoInitializeFlags;
diff --git a/chromium/mojo/public/cpp/base/BUILD.gn b/chromium/mojo/public/cpp/base/BUILD.gn
index 9aaf1e0d796..ee0eb158939 100644
--- a/chromium/mojo/public/cpp/base/BUILD.gn
+++ b/chromium/mojo/public/cpp/base/BUILD.gn
@@ -90,6 +90,8 @@ component("shared_typemap_traits") {
"generic_pending_receiver_mojom_traits.h",
"read_only_buffer_mojom_traits.cc",
"read_only_buffer_mojom_traits.h",
+ "read_only_file_mojom_traits.cc",
+ "read_only_file_mojom_traits.h",
"shared_memory_mojom_traits.cc",
"shared_memory_mojom_traits.h",
"time_mojom_traits.cc",
diff --git a/chromium/mojo/public/cpp/base/big_buffer.h b/chromium/mojo/public/cpp/base/big_buffer.h
index ef13e1e39b0..81d0b994d41 100644
--- a/chromium/mojo/public/cpp/base/big_buffer.h
+++ b/chromium/mojo/public/cpp/base/big_buffer.h
@@ -176,7 +176,7 @@ class COMPONENT_EXPORT(MOJO_BASE) BigBufferView {
static BigBufferView CreateInvalidForTest();
private:
- BigBuffer::StorageType storage_type_;
+ BigBuffer::StorageType storage_type_ = BigBuffer::StorageType::kBytes;
base::span<const uint8_t> bytes_;
base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
diff --git a/chromium/mojo/public/cpp/base/file_unittest.cc b/chromium/mojo/public/cpp/base/file_unittest.cc
index e1db729c752..90d08eb97b2 100644
--- a/chromium/mojo/public/cpp/base/file_unittest.cc
+++ b/chromium/mojo/public/cpp/base/file_unittest.cc
@@ -3,9 +3,13 @@
// found in the LICENSE file.
#include "base/files/scoped_temp_dir.h"
+#include "base/sync_socket.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/base/file_mojom_traits.h"
+#include "mojo/public/cpp/base/read_only_file_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "mojo/public/mojom/base/file.mojom.h"
+#include "mojo/public/mojom/base/read_only_file.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo_base {
@@ -69,5 +73,97 @@ TEST(FileTest, InvalidFile) {
EXPECT_FALSE(file_out.IsValid());
}
+TEST(FileTest, ReadOnlyFile) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ base::File file(
+ temp_dir.GetPath().AppendASCII("test_file.txt"),
+ base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ);
+ const base::StringPiece test_content =
+ "A test string to be stored in a test file";
+ file.WriteAtCurrentPos(test_content.data(),
+ base::checked_cast<int>(test_content.size()));
+ file.Close();
+
+ base::File readonly(temp_dir.GetPath().AppendASCII("test_file.txt"),
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ base::File file_out;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::ReadOnlyFile>(
+ &readonly, &file_out));
+ std::vector<char> content(test_content.size());
+ ASSERT_TRUE(file_out.IsValid());
+ ASSERT_FALSE(file_out.async());
+ ASSERT_EQ(static_cast<int>(test_content.size()),
+ file_out.Read(0, content.data(),
+ base::checked_cast<int>(test_content.size())));
+ EXPECT_EQ(test_content,
+ base::StringPiece(content.data(), test_content.size()));
+}
+
+// This dies only if we can interrogate the underlying platform handle.
+#if defined(OS_WIN) || defined(OS_POSIX) || defined(OS_FUCHSIA)
+#if !defined(OS_NACL) && !defined(OS_AIX)
+TEST(FileTest, ReadOnlyFileDeath) {
+#if defined(OFFICIAL_BUILD)
+ const char kReadOnlyFileCheckFailedRegex[] = "";
+#else
+ const char kReadOnlyFileCheckFailedRegex[] = "Check failed: IsReadOnlyFile";
+#endif
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ base::File file(
+ temp_dir.GetPath().AppendASCII("test_file.txt"),
+ base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ);
+ const base::StringPiece test_content =
+ "A test string to be stored in a test file";
+ file.WriteAtCurrentPos(test_content.data(),
+ base::checked_cast<int>(test_content.size()));
+ file.Close();
+
+ base::File writable(
+ temp_dir.GetPath().AppendASCII("test_file.txt"),
+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
+
+ base::File file_out;
+ EXPECT_DEATH_IF_SUPPORTED(
+ mojo::test::SerializeAndDeserialize<mojom::ReadOnlyFile>(&writable,
+ &file_out),
+ kReadOnlyFileCheckFailedRegex);
+}
+#endif // !defined(OS_NACL) && !defined(OS_AIX)
+#endif // defined(OS_WIN) || defined(OS_POSIX) || defined(OS_FUCHSIA)
+
+// This should work on all platforms. This check might be relaxed in which case
+// this test can be removed.
+#if DCHECK_IS_ON()
+TEST(FileTest, NonPhysicalFileDeath) {
+#if defined(OFFICIAL_BUILD)
+ const char kPhysicalFileCheckFailedRegex[] = "";
+#else
+ const char kPhysicalFileCheckFailedRegex[] = "Check failed: IsPhysicalFile";
+#endif
+
+ base::SyncSocket sync_a;
+ base::SyncSocket sync_b;
+ ASSERT_TRUE(base::SyncSocket::CreatePair(&sync_a, &sync_b));
+ base::File file_pipe_a(sync_a.Take());
+ base::File file_pipe_b(sync_b.Take());
+
+ base::File file_out;
+ EXPECT_DEATH_IF_SUPPORTED(
+ mojo::test::SerializeAndDeserialize<mojom::ReadOnlyFile>(&file_pipe_a,
+ &file_out),
+ kPhysicalFileCheckFailedRegex);
+ EXPECT_DEATH_IF_SUPPORTED(
+ mojo::test::SerializeAndDeserialize<mojom::ReadOnlyFile>(&file_pipe_b,
+ &file_out),
+ kPhysicalFileCheckFailedRegex);
+}
+#endif // DCHECK_IS_ON()
+
} // namespace file_unittest
} // namespace mojo_base
diff --git a/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.cc b/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.cc
new file mode 100644
index 00000000000..190e659d16e
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.cc
@@ -0,0 +1,101 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/base/read_only_file_mojom_traits.h"
+
+#include "base/files/file.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+#if defined(OS_WIN)
+#include <windows.h>
+#include <winternl.h>
+#endif
+
+namespace mojo {
+namespace {
+#if defined(OS_WIN)
+bool GetGrantedAccess(HANDLE handle, DWORD* flags) {
+ static const auto nt_query_object =
+ reinterpret_cast<decltype(&NtQueryObject)>(
+ GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryObject"));
+ PUBLIC_OBJECT_BASIC_INFORMATION info;
+ ULONG len = sizeof(info);
+ ULONG consumed = 0;
+ auto ret =
+ nt_query_object(handle, ObjectBasicInformation, &info, len, &consumed);
+ if (ret)
+ return false;
+ *flags = info.GrantedAccess;
+ return true;
+}
+#endif // defined(OS_WIN)
+
+// True if the underlying handle is only readable. Where possible this excludes
+// deletion, writing, truncation, append and other operations that might modify
+// the underlying file. False if we can tell that the file could be modified.
+// On platforms where we cannot test the handle, always returns true.
+bool IsReadOnlyFile(base::File& file) {
+ bool is_readonly = true;
+#if defined(OS_WIN)
+ DWORD flags = 0;
+ if (!GetGrantedAccess(file.GetPlatformFile(), &flags))
+ return false;
+
+ // Cannot use GENERIC_WRITE as that includes SYNCHRONIZE.
+ // This is ~(all the writable permissions).
+ is_readonly =
+ !(flags & (FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA |
+ FILE_WRITE_EA | WRITE_DAC | WRITE_OWNER | DELETE));
+#elif defined(OS_FUCHSIA) || \
+ (defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_AIX))
+ is_readonly =
+ (fcntl(file.GetPlatformFile(), F_GETFL) & O_ACCMODE) == O_RDONLY;
+#endif
+ return is_readonly;
+}
+
+bool IsPhysicalFile(base::File& file) {
+#if defined(OS_WIN)
+ // Verify if this is a real file (not a socket/pipe etc.).
+ DWORD type = GetFileType(file.GetPlatformFile());
+ return type == FILE_TYPE_DISK;
+#else
+ // This may block but in practice this is unlikely for already opened
+ // physical files.
+ struct stat st;
+ if (fstat(file.GetPlatformFile(), &st) != 0)
+ return false;
+ return S_ISREG(st.st_mode);
+#endif
+}
+
+} // namespace
+
+mojo::PlatformHandle StructTraits<mojo_base::mojom::ReadOnlyFileDataView,
+ base::File>::fd(base::File& file) {
+ DCHECK(file.IsValid());
+ // For now we require real files as on some platforms it is too difficult to
+ // be sure that more general handles cannot be written or made writable. This
+ // could be relaxed if an interface needs readonly pipes. This check may block
+ // so cannot be enabled in release builds.
+ DCHECK(IsPhysicalFile(file));
+ CHECK(IsReadOnlyFile(file));
+
+ return mojo::PlatformHandle(
+ base::ScopedPlatformFile(file.TakePlatformFile()));
+}
+
+bool StructTraits<mojo_base::mojom::ReadOnlyFileDataView, base::File>::Read(
+ mojo_base::mojom::ReadOnlyFileDataView data,
+ base::File* file) {
+ *file = base::File(data.TakeFd().TakePlatformFile(), data.async());
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.h b/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.h
new file mode 100644
index 00000000000..025ee7f2374
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/read_only_file_mojom_traits.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BASE_READ_ONLY_FILE_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_READ_ONLY_FILE_MOJOM_TRAITS_H_
+
+#include "base/component_export.h"
+#include "base/files/file.h"
+#include "mojo/public/mojom/base/read_only_file.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
+ StructTraits<mojo_base::mojom::ReadOnlyFileDataView, base::File> {
+ static bool IsNull(const base::File& file) { return !file.IsValid(); }
+
+ static void SetToNull(base::File* file) { *file = base::File(); }
+
+ static mojo::PlatformHandle fd(base::File& file);
+ static bool async(base::File& file) { return file.async(); }
+ static bool Read(mojo_base::mojom::ReadOnlyFileDataView data,
+ base::File* file);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BASE_READ_ONLY_FILE_MOJOM_TRAITS_H_
diff --git a/chromium/mojo/public/cpp/base/values_mojom_traits.cc b/chromium/mojo/public/cpp/base/values_mojom_traits.cc
index 9a1d84c604a..69bd8167377 100644
--- a/chromium/mojo/public/cpp/base/values_mojom_traits.cc
+++ b/chromium/mojo/public/cpp/base/values_mojom_traits.cc
@@ -20,8 +20,8 @@ bool StructTraits<mojo_base::mojom::DictionaryValueDataView, base::Value>::Read(
dict_storage.reserve(view.size());
for (size_t i = 0; i < view.size(); ++i) {
base::StringPiece key;
- auto value = std::make_unique<base::Value>();
- if (!view.keys().Read(i, &key) || !view.values().Read(i, value.get()))
+ base::Value value;
+ if (!view.keys().Read(i, &key) || !view.values().Read(i, &value))
return false;
dict_storage.emplace_back(key.as_string(), std::move(value));
}
diff --git a/chromium/mojo/public/cpp/base/values_unittest.cc b/chromium/mojo/public/cpp/base/values_unittest.cc
index 75d975470bc..5624238916a 100644
--- a/chromium/mojo/public/cpp/base/values_unittest.cc
+++ b/chromium/mojo/public/cpp/base/values_unittest.cc
@@ -85,17 +85,14 @@ TEST(ValuesStructTraitsTest, DictionaryValue) {
// move-only types and initializer lists don't mix. Initializer lists can't be
// modified: thus it's not possible to move.
std::vector<base::Value::DictStorage::value_type> storage;
- storage.emplace_back("null", std::make_unique<base::Value>());
- storage.emplace_back("bool", std::make_unique<base::Value>(false));
- storage.emplace_back("int", std::make_unique<base::Value>(0));
- storage.emplace_back("double", std::make_unique<base::Value>(0.0));
- storage.emplace_back("string", std::make_unique<base::Value>("0"));
- storage.emplace_back(
- "binary", std::make_unique<base::Value>(base::Value::BlobStorage({0})));
- storage.emplace_back(
- "dictionary", std::make_unique<base::Value>(base::Value::DictStorage()));
- storage.emplace_back(
- "list", std::make_unique<base::Value>(base::Value::ListStorage()));
+ storage.emplace_back("null", base::Value());
+ storage.emplace_back("bool", false);
+ storage.emplace_back("int", 0);
+ storage.emplace_back("double", 0.0);
+ storage.emplace_back("string", "0");
+ storage.emplace_back("binary", base::Value::BlobStorage({0}));
+ storage.emplace_back("dictionary", base::Value::DictStorage());
+ storage.emplace_back("list", base::Value::ListStorage());
base::Value in(base::Value::DictStorage(std::move(storage)));
base::Value out;
diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn
index fb725f77058..77efb306eaf 100644
--- a/chromium/mojo/public/cpp/bindings/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/BUILD.gn
@@ -2,13 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//base/trace_event/tracing.gni")
import("//build/buildflag_header.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/nacl/config.gni")
import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
declare_args() {
- enable_mojo_tracing = false
+ enable_mojo_tracing = extended_tracing_enabled
# enable_random_mojo_delays starts a task runner that periodically pauses
# random Mojo bindings and later resumes them, in order to test whether parts
@@ -79,7 +80,6 @@ component("bindings_base") {
"lib/serialization_util.h",
"lib/string_serialization.h",
"lib/template_util.h",
- "lib/tracing_helper.h",
"lib/unserialized_message_context.cc",
"lib/unserialized_message_context.h",
"lib/validate_params.h",
diff --git a/chromium/mojo/public/cpp/bindings/README.md b/chromium/mojo/public/cpp/bindings/README.md
index a15cf13632f..9eff612fb6e 100644
--- a/chromium/mojo/public/cpp/bindings/README.md
+++ b/chromium/mojo/public/cpp/bindings/README.md
@@ -168,7 +168,7 @@ defines a `BindNewPipeAndPassReceiver` method:
``` cpp
mojo::Remote<sample::mojom::Logger> logger;
-auto receiver = logger.BindNewPipeAndPassReceiver());
+auto receiver = logger.BindNewPipeAndPassReceiver();
```
This second snippet is equivalent to the first one.
diff --git a/chromium/mojo/public/cpp/bindings/associated_binding.h b/chromium/mojo/public/cpp/bindings/associated_binding.h
index a0b6eeadc21..62f12b16564 100644
--- a/chromium/mojo/public/cpp/bindings/associated_binding.h
+++ b/chromium/mojo/public/cpp/bindings/associated_binding.h
@@ -149,9 +149,29 @@ class AssociatedBinding : public AssociatedBindingBase {
return old_impl;
}
+ // Acquires a callback which may be run to report the currently dispatching
+ // message as bad and close this binding. Note that this is only legal to
+ // call from directly within stack frame of a message dispatch, but the
+ // returned callback may be called exactly once any time thereafter to report
+ // the message as bad. |GetBadMessageCallback()| may only be called once per
+ // message, and the returned callback must be run on the same sequence to
+ // which this binding is bound.
+ ReportBadMessageCallback GetBadMessageCallback() {
+ return base::BindOnce(
+ [](ReportBadMessageCallback inner_callback,
+ base::WeakPtr<AssociatedBinding> binding, const std::string& error) {
+ std::move(inner_callback).Run(error);
+ if (binding)
+ binding->Close();
+ },
+ mojo::GetBadMessageCallback(), weak_ptr_factory_.GetWeakPtr());
+ }
+
private:
typename Interface::template Stub_<ImplRefTraits> stub_;
+ base::WeakPtrFactory<AssociatedBinding> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(AssociatedBinding);
};
diff --git a/chromium/mojo/public/cpp/bindings/associated_receiver.h b/chromium/mojo/public/cpp/bindings/associated_receiver.h
index f03b37dd27a..2d9ed6a09d5 100644
--- a/chromium/mojo/public/cpp/bindings/associated_receiver.h
+++ b/chromium/mojo/public/cpp/bindings/associated_receiver.h
@@ -241,6 +241,26 @@ class AssociatedReceiver {
return binding_.SwapImplForTesting(new_impl);
}
+ // Reports the currently dispatching message as bad and resets this receiver.
+ // Note that this is only legal to call from within the stack frame of a
+ // message dispatch. If you need to do asynchronous work before determining
+ // the legitimacy of a message, use GetBadMessageCallback() and retain its
+ // result until ready to invoke or discard it.
+ void ReportBadMessage(const std::string& error) {
+ GetBadMessageCallback().Run(error);
+ }
+
+ // Acquires a callback which may be run to report the currently dispatching
+ // message as bad and reset this receiver. Note that this is only legal to
+ // call from directly within stack frame of a message dispatch, but the
+ // returned callback may be called exactly once any time thereafter to report
+ // the message as bad. |GetBadMessageCallback()| may only be called once per
+ // message, and the returned callback must be run on the same sequence to
+ // which this Receiver is bound.
+ ReportBadMessageCallback GetBadMessageCallback() {
+ return binding_.GetBadMessageCallback();
+ }
+
private:
// TODO(https://crbug.com/875030): Move AssociatedBinding details into this
// class.
diff --git a/chromium/mojo/public/cpp/bindings/connector.h b/chromium/mojo/public/cpp/bindings/connector.h
index 1616f1bf023..905829cdfb1 100644
--- a/chromium/mojo/public/cpp/bindings/connector.h
+++ b/chromium/mojo/public/cpp/bindings/connector.h
@@ -85,7 +85,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver {
Connector(ScopedMessagePipeHandle message_pipe,
ConnectorConfig config,
scoped_refptr<base::SequencedTaskRunner> runner,
- const char* heap_profiler_tag = "unknown interface");
+ const char* interface_name = "unknown interface");
~Connector() override;
// Sets outgoing serialization mode.
@@ -306,7 +306,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver {
// The tag used to track heap allocations that originated from a Watcher
// notification.
- const char* heap_profiler_tag_ = "unknown interface";
+ const char* interface_name_ = "unknown interface";
// A cached pointer to the RunLoopNestingObserver for the thread on which this
// Connector was created.
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc
index 93ea25007ec..2766f8d65c3 100644
--- a/chromium/mojo/public/cpp/bindings/lib/connector.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc
@@ -21,14 +21,15 @@
#include "base/task/current_thread.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/trace_event/trace_event.h"
+#include "base/trace_event/typed_macros.h"
#include "mojo/public/c/system/quota.h"
#include "mojo/public/cpp/bindings/features.h"
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
#include "mojo/public/cpp/bindings/lib/message_quota_checker.h"
-#include "mojo/public/cpp/bindings/lib/tracing_helper.h"
#include "mojo/public/cpp/bindings/mojo_buildflags.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
#include "mojo/public/cpp/system/wait.h"
+#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h"
#if defined(ENABLE_IPC_FUZZER)
#include "mojo/public/cpp/bindings/message_dumper.h"
@@ -145,14 +146,14 @@ void Connector::ActiveDispatchTracker::NotifyBeginNesting() {
Connector::Connector(ScopedMessagePipeHandle message_pipe,
ConnectorConfig config,
scoped_refptr<base::SequencedTaskRunner> runner,
- const char* heap_profiler_tag)
+ const char* interface_name)
: message_pipe_(std::move(message_pipe)),
task_runner_(std::move(runner)),
error_(false),
force_immediate_dispatch_(!EnableTaskPerMessage()),
outgoing_serialization_mode_(g_default_outgoing_serialization_mode),
incoming_serialization_mode_(g_default_incoming_serialization_mode),
- heap_profiler_tag_(heap_profiler_tag),
+ interface_name_(interface_name),
nesting_observer_(RunLoopNestingObserver::GetForThread()) {
if (config == MULTI_THREADED_SEND)
lock_.emplace();
@@ -410,7 +411,7 @@ void Connector::WaitToReadMore() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
handle_watcher_ = std::make_unique<SimpleWatcher>(
FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL, task_runner_,
- heap_profiler_tag_);
+ interface_name_);
MojoResult rv = handle_watcher_->Watch(
message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE,
base::BindRepeating(&Connector::OnWatcherHandleReady,
@@ -459,11 +460,11 @@ MojoResult Connector::ReadMessage(Message* message) {
// was a problem extracting handles from it. We treat this essentially as
// a bad IPC because we don't really have a better option.
//
- // We include |heap_profiler_tag_| in the error message since it usually
+ // We include |interface_name_| in the error message since it usually
// (via this Connector's owner) provides useful information about which
// binding interface is using this Connector.
NotifyBadMessage(handle.get(),
- std::string(heap_profiler_tag_) +
+ std::string(interface_name_) +
"One or more handle attachments were invalid.");
return MOJO_RESULT_ABORTED;
}
@@ -490,11 +491,15 @@ bool Connector::DispatchMessage(Message message) {
}
TRACE_EVENT_WITH_FLOW0("toplevel.flow", "mojo::Message Receive",
- MANGLE_MESSAGE_ID(message.header()->trace_id),
- TRACE_EVENT_FLAG_FLOW_IN);
+ message.header()->trace_id, TRACE_EVENT_FLAG_FLOW_IN);
#if !BUILDFLAG(MOJO_TRACE_ENABLED)
// This emits just full class name, and is inferior to mojo tracing.
- TRACE_EVENT0("mojom", heap_profiler_tag_);
+ TRACE_EVENT("toplevel", "Connector::DispatchMessage",
+ [this](perfetto::EventContext ctx) {
+ ctx.event()
+ ->set_chrome_mojo_event_info()
+ ->set_watcher_notify_interface_tag(interface_name_);
+ });
#endif
if (connection_group_)
diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc
index 8c489947606..d5403f933ce 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message.cc
@@ -20,9 +20,9 @@
#include "base/strings/stringprintf.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_id_helper.h"
#include "mojo/public/cpp/bindings/associated_group_controller.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
-#include "mojo/public/cpp/bindings/lib/tracing_helper.h"
#include "mojo/public/cpp/bindings/lib/unserialized_message_context.h"
namespace mojo {
@@ -47,19 +47,6 @@ void AllocateHeaderFromBuffer(internal::Buffer* buffer, HeaderType** header) {
(*header)->num_bytes = sizeof(HeaderType);
}
-uint32_t GetTraceId(void* object) {
- // |object| is a pointer to some object, which we are going to use as
- // a hopefully unique id for this message.
- // Additionally xor it with a counter to protect against the situations when
- // a new object is allocated with the same address.
- // The counter alone is not sufficient because we also have to deal with
- // different processes, and the counter is only process-unique.
- static std::atomic<int> counter{0};
- uint64_t value = reinterpret_cast<intptr_t>(object);
- return static_cast<uint32_t>(counter.fetch_add(1, std::memory_order_relaxed) ^
- (value >> 32) ^ ((value << 32) >> 32));
-}
-
void WriteMessageHeader(uint32_t name,
uint32_t flags,
uint32_t trace_id,
@@ -96,15 +83,15 @@ void WriteMessageHeader(uint32_t name,
void CreateSerializedMessageObject(uint32_t name,
uint32_t flags,
- uint32_t trace_id,
size_t payload_size,
size_t payload_interface_id_count,
MojoCreateMessageFlags create_message_flags,
std::vector<ScopedHandle>* handles,
ScopedMessageHandle* out_handle,
internal::Buffer* out_buffer) {
- TRACE_EVENT_WITH_FLOW0("toplevel.flow", "mojo::Message Send",
- MANGLE_MESSAGE_ID(trace_id),
+ uint32_t trace_id =
+ static_cast<uint32_t>(base::trace_event::GetNextGlobalTraceId());
+ TRACE_EVENT_WITH_FLOW0("toplevel.flow", "mojo::Message Send", trace_id,
TRACE_EVENT_FLAG_FLOW_OUT);
ScopedMessageHandle handle;
@@ -147,10 +134,10 @@ void SerializeUnserializedContext(MojoMessageHandle message,
uintptr_t context_value) {
auto* context =
reinterpret_cast<internal::UnserializedMessageContext*>(context_value);
- uint32_t trace_id = GetTraceId(context);
+ uint32_t trace_id =
+ static_cast<uint32_t>(base::trace_event::GetNextGlobalTraceId());
- TRACE_EVENT_WITH_FLOW0("toplevel.flow", "mojo::Message Send",
- MANGLE_MESSAGE_ID(trace_id),
+ TRACE_EVENT_WITH_FLOW0("toplevel.flow", "mojo::Message Send", trace_id,
TRACE_EVENT_FLAG_FLOW_OUT);
void* buffer;
@@ -244,7 +231,7 @@ Message::Message(uint32_t name,
MojoCreateMessageFlags create_message_flags,
std::vector<ScopedHandle>* handles) {
CreateSerializedMessageObject(
- name, flags, GetTraceId(this), payload_size, payload_interface_id_count,
+ name, flags, payload_size, payload_interface_id_count,
create_message_flags, handles, &handle_, &payload_buffer_);
transferable_ = true;
serialized_ = true;
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization.h b/chromium/mojo/public/cpp/bindings/lib/serialization.h
index 1f5d7de89b5..7927d1d4092 100644
--- a/chromium/mojo/public/cpp/bindings/lib/serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/serialization.h
@@ -63,7 +63,11 @@ struct MojomSerializationImplTraits<
template <typename MojomType, typename UserType>
mojo::Message SerializeAsMessageImpl(UserType* input) {
SerializationContext context;
- mojo::Message message(0, 0, 0, 0, nullptr);
+ // Note that this is only called by application code serializing a structure
+ // manually (e.g. for storage). As such we don't want Mojo's soft message size
+ // limits to be applied.
+ mojo::Message message(0, 0, 0, 0, MOJO_CREATE_MESSAGE_FLAG_UNLIMITED_SIZE,
+ nullptr);
typename MojomTypeTraits<MojomType>::Data::BufferWriter writer;
MojomSerializationImplTraits<MojomType>::Serialize(
*input, message.payload_buffer(), &writer, &context);
diff --git a/chromium/mojo/public/cpp/bindings/lib/tracing_helper.h b/chromium/mojo/public/cpp/bindings/lib/tracing_helper.h
deleted file mode 100644
index ebc5cc27e85..00000000000
--- a/chromium/mojo/public/cpp/bindings/lib/tracing_helper.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_TRACING_HELPER_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TRACING_HELPER_H_
-
-#define MANGLE_MESSAGE_ID(id) (id ^ ::mojo::internal::kMojoMessageMangleMask)
-
-namespace mojo {
-namespace internal {
-
-// Mojo message id is 32-bit, but for tracing we ensure that mojo messages
-// don't collide with other trace events.
-constexpr uint64_t kMojoMessageMangleMask = 0x655b2a8e8efdf27f;
-
-} // namespace internal
-} // namespace mojo
-
-#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_TRACING_HELPER_H_
diff --git a/chromium/mojo/public/cpp/bindings/pending_receiver.h b/chromium/mojo/public/cpp/bindings/pending_receiver.h
index 07d300f424e..1df56ce9278 100644
--- a/chromium/mojo/public/cpp/bindings/pending_receiver.h
+++ b/chromium/mojo/public/cpp/bindings/pending_receiver.h
@@ -74,7 +74,7 @@ class PendingReceiver {
Interface>)(T&&)>>::value>* = nullptr>
PendingReceiver(T&& other)
: PendingReceiver(PendingReceiverConverter<T>::template To<Interface>(
- std::move(other))) {}
+ std::forward<T>(other))) {}
#endif // !defined(OS_NACL)
~PendingReceiver() = default;
diff --git a/chromium/mojo/public/cpp/bindings/receiver.h b/chromium/mojo/public/cpp/bindings/receiver.h
index 6f8b9976581..e1357f64fa2 100644
--- a/chromium/mojo/public/cpp/bindings/receiver.h
+++ b/chromium/mojo/public/cpp/bindings/receiver.h
@@ -185,9 +185,9 @@ class Receiver {
}
// Sets the message filter to be notified of each incoming message before
- // dispatch. If a filter returns |false| from Accept(), the message is not
- // dispatched and the pipe is closed. Filters cannot be removed once added
- // and only one can be set.
+ // dispatch. If a filter returns |false| from WillDispatch(), the message is
+ // not dispatched and the pipe is closed. Filters cannot be removed once
+ // added and only one can be set.
void SetFilter(std::unique_ptr<MessageFilter> filter) {
DCHECK(is_bound());
internal_state_.SetFilter(std::move(filter));
diff --git a/chromium/mojo/public/cpp/bindings/service_factory.cc b/chromium/mojo/public/cpp/bindings/service_factory.cc
index 18f12eb3490..b083ac15839 100644
--- a/chromium/mojo/public/cpp/bindings/service_factory.cc
+++ b/chromium/mojo/public/cpp/bindings/service_factory.cc
@@ -5,33 +5,44 @@
#include "mojo/public/cpp/bindings/service_factory.h"
#include "base/bind.h"
+#include "base/stl_util.h"
namespace mojo {
+ServiceFactory::ServiceFactory() = default;
+
ServiceFactory::~ServiceFactory() = default;
-bool ServiceFactory::MaybeRunService(mojo::GenericPendingReceiver* receiver) {
- DCHECK(receiver->is_valid());
+bool ServiceFactory::CanRunService(
+ const GenericPendingReceiver& receiver) const {
+ DCHECK(receiver.is_valid());
+ return base::Contains(constructors_, *receiver.interface_name());
+}
+
+bool ServiceFactory::RunService(GenericPendingReceiver receiver,
+ base::OnceClosure termination_callback) {
+ DCHECK(receiver.is_valid());
// We grab a weak handle to the receiver's message pipe first. If any function
// accepts the receiver, we will tie its returned object's lifetime to the
// connection state of that pipe.
- MessagePipeHandle pipe = receiver->pipe();
-
- for (const auto& callback : callbacks_) {
- if (auto instance = callback.Run(receiver)) {
- DCHECK(!receiver->is_valid());
- instance->WatchPipe(
- pipe, base::BindOnce(&ServiceFactory::OnInstanceDisconnected,
- weak_ptr_factory_.GetWeakPtr(), instance.get()));
- instances_.insert(std::move(instance));
- return true;
- }
-
- DCHECK(receiver->is_valid());
- }
+ MessagePipeHandle pipe = receiver.pipe();
- return false;
+ auto it = constructors_.find(*receiver.interface_name());
+ if (it == constructors_.end())
+ return false;
+
+ auto instance = it->second.Run(std::move(receiver));
+ auto disconnect_callback =
+ base::BindOnce(&ServiceFactory::OnInstanceDisconnected,
+ weak_ptr_factory_.GetWeakPtr(), instance.get());
+ if (termination_callback) {
+ disconnect_callback =
+ std::move(disconnect_callback).Then(std::move(termination_callback));
+ }
+ instance->WatchPipe(pipe, std::move(disconnect_callback));
+ instances_.insert(std::move(instance));
+ return true;
}
void ServiceFactory::OnInstanceDisconnected(InstanceHolderBase* instance) {
@@ -48,21 +59,26 @@ void ServiceFactory::InstanceHolderBase::WatchPipe(
base::OnceClosure disconnect_callback) {
DCHECK(!disconnect_callback_);
disconnect_callback_ = std::move(disconnect_callback);
- watcher_.Watch(pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ watcher_.Watch(pipe, MOJO_HANDLE_SIGNAL_READABLE,
MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
- base::BindRepeating(&InstanceHolderBase::OnDisconnect,
+ base::BindRepeating(&InstanceHolderBase::OnPipeSignaled,
base::Unretained(this)));
}
-void ServiceFactory::InstanceHolderBase::OnDisconnect(
+void ServiceFactory::InstanceHolderBase::OnPipeSignaled(
MojoResult result,
const HandleSignalsState& state) {
- // It doesn't matter what the parameters are, since the only way the watcher
- // can signal is if the peer was closed or the local pipe handle was closed.
- // The callback always destroys |this| when run, so there's also no chance of
- // this method running more than once.
- DCHECK(disconnect_callback_);
- std::move(disconnect_callback_).Run();
+ // We only care about the two conditions below. FAILED_PRECONDITION implies
+ // that the peer was closed and all its sent messages have been read (and
+ // dispatched) locally, while CANCELLED implies that the service pipe was
+ // closed locally. In both cases, we run the callback which will delete
+ // `this` and, ultimately, the service instance itself.
+ if (result == MOJO_RESULT_FAILED_PRECONDITION ||
+ result == MOJO_RESULT_CANCELLED) {
+ watcher_.Cancel();
+ DCHECK(disconnect_callback_);
+ std::move(disconnect_callback_).Run();
+ }
}
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/service_factory.h b/chromium/mojo/public/cpp/bindings/service_factory.h
index e31441389cd..baaf683056b 100644
--- a/chromium/mojo/public/cpp/bindings/service_factory.h
+++ b/chromium/mojo/public/cpp/bindings/service_factory.h
@@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_
#define MOJO_PUBLIC_CPP_BINDINGS_SERVICE_FACTORY_H_
+#include <map>
#include <memory>
#include "base/bind.h"
@@ -35,11 +36,11 @@ struct ServiceFactoryTraits;
// where |T| is any type (generally an implementation of |Interface|), and
// |Interface| is a mojom interface.
//
-// Any time |MaybeRunService()| is called on the ServiceFactory, it will match
-// the GenericPendingReceiver argument's interface type against the list of
-// factories it has available, and if it finds a match it will run that function
-// and retain ownership of the returned object until the corresponding receiver
-// is disconnected.
+// Any time |RunService()| is called on the ServiceFactory, it will match the
+// GenericPendingReceiver argument's interface type against the list of
+// factories it has available and run the corresponding function, retaining
+// ownership of the returned object until the corresponding receiver is
+// disconnected.
//
// Typical usage might look something like:
//
@@ -51,31 +52,54 @@ struct ServiceFactoryTraits;
// return std::make_unique<bar::BarImpl>(std::move(receiver));
// }
//
-// void HandleServiceRequest(mojo::GenericPendingReceiver receiver) {
-// static base::NoDestructor<mojo::ServiceFactory> factory{
-// RunFooService,
-// RunBarService,
-// };
+// void RegisterServices(mojo::ServiceFactory& services) {
+// services.Add(RunFooService);
+// services.Add(RunBarService);
+// }
//
-// if (!factory->MaybeRunService(&receiver)) {
-// // The receiver was for neither the Foo nor Bar service. Sad!
-// LOG(ERROR) << "Unknown service: " << *receiver.interface_name();
+// void HandleServiceRequest(const mojo::ServiceFactory& factory,
+// mojo::GenericPendingReceiver receiver) {
+// if (factory.CanRunService(receiver)) {
+// factory.RunService(std::move(receiver), base::NullCallback());
+// return;
// }
+//
+// // The receiver was for neither the Foo nor Bar service. Sad!
+// LOG(ERROR) << "Unknown service: " << *receiver.interface_name();
// }
//
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) ServiceFactory {
public:
- template <typename... Funcs>
- explicit ServiceFactory(Funcs... fns)
- : callbacks_({base::BindRepeating(&RunFunction<Funcs>, fns)...}) {}
+ ServiceFactory();
~ServiceFactory();
- // Attempts to run a service supported by this factory.
+ // Adds a new service to the factory. The argument may be any function that
+ // accepts a single PendingReceiver<T> and returns a unique_ptr<T>, where T is
+ // a service interface (that is, a generated mojom interface class
+ // corresponding to some service's main interface.)
+ template <typename Func>
+ void Add(Func func) {
+ using Interface = typename internal::ServiceFactoryTraits<Func>::Interface;
+ constructors_[Interface::Name_] =
+ base::BindRepeating(&RunConstructor<Func>, func);
+ }
+
+ // If `receiver` is references an interface matching a service known to this
+ // factory, this returns true. Otherwise it returns false. `receiver` MUST be
+ // valid.
+ bool CanRunService(const GenericPendingReceiver& receiver) const;
+
+ // Consumes `receiver` and binds it to a new instance of the corresponding
+ // service, constructed using the service's registered function within this
+ // factory.
+ //
+ // `termination_callback`, if not null, will be invoked on the calling
+ // TaskRunner whenever the new service instance is eventually destroyed.
//
- // Returns |true| and consumes |*receiver| if it is a suitable match for some
- // function known by the factory; otherwise returns |false| and leaves
- // |*receiver| intact.
- bool MaybeRunService(GenericPendingReceiver* receiver);
+ // If the service represented by `receiver` is not known to this factory, it
+ // is discarded and `termination_callback` is never run.
+ bool RunService(GenericPendingReceiver receiver,
+ base::OnceClosure termination_callback);
private:
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InstanceHolderBase {
@@ -87,7 +111,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) ServiceFactory {
base::OnceClosure disconnect_callback);
private:
- void OnDisconnect(MojoResult result, const HandleSignalsState& state);
+ void OnPipeSignaled(MojoResult result, const HandleSignalsState& state);
SimpleWatcher watcher_;
base::OnceClosure disconnect_callback_;
@@ -109,23 +133,20 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) ServiceFactory {
};
template <typename Func>
- static std::unique_ptr<InstanceHolderBase> RunFunction(
+ static std::unique_ptr<InstanceHolderBase> RunConstructor(
Func fn,
- GenericPendingReceiver* receiver) {
+ GenericPendingReceiver receiver) {
using Interface = typename internal::ServiceFactoryTraits<Func>::Interface;
- if (auto typed_receiver = receiver->As<Interface>()) {
- return std::make_unique<InstanceHolder<Interface>>(
- fn(std::move(typed_receiver)));
- }
- return nullptr;
+ return std::make_unique<InstanceHolder<Interface>>(
+ fn(receiver.As<Interface>()));
}
void OnInstanceDisconnected(InstanceHolderBase* instance);
- using GenericCallback =
+ using Constructor =
base::RepeatingCallback<std::unique_ptr<InstanceHolderBase>(
- GenericPendingReceiver*)>;
- const std::vector<GenericCallback> callbacks_;
+ GenericPendingReceiver)>;
+ std::map<std::string, Constructor> constructors_;
base::flat_set<std::unique_ptr<InstanceHolderBase>, base::UniquePtrComparator>
instances_;
diff --git a/chromium/mojo/public/cpp/bindings/struct_ptr.h b/chromium/mojo/public/cpp/bindings/struct_ptr.h
index e76c34188dd..af192d33831 100644
--- a/chromium/mojo/public/cpp/bindings/struct_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/struct_ptr.h
@@ -171,7 +171,11 @@ class InlinedStructPtr {
DCHECK(state_ == VALID);
return &value_;
}
- Struct* get() const { return &value_; }
+ Struct* get() const {
+ if (state_ == NIL)
+ return nullptr;
+ return &value_;
+ }
void Swap(InlinedStructPtr* other) {
std::swap(value_, other->value_);
diff --git a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
index fec6e6b0441..459a4dc4f79 100644
--- a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -28,6 +28,7 @@ source_set("tests") {
"handle_passing_unittest.cc",
"hash_unittest.cc",
"idle_tracking_unittest.cc",
+ "interface_unittest.cc",
"lazy_serialization_unittest.cc",
"map_unittest.cc",
"message_queue.cc",
@@ -154,6 +155,7 @@ mojom("test_mojom") {
"enum_headers_unittest.test-mojom",
"flush_async_unittest.test-mojom",
"idle_tracking_unittest.test-mojom",
+ "interface_unittest.test-mojom",
"receiver_unittest.test-mojom",
"remote_unittest.test-mojom",
"service_factory_unittest.test-mojom",
diff --git a/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
index 592e83c0e2b..2fe3211b64a 100644
--- a/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
@@ -9,7 +9,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
diff --git a/chromium/mojo/public/cpp/platform/BUILD.gn b/chromium/mojo/public/cpp/platform/BUILD.gn
index 9f17405f4bf..6cd7355222f 100644
--- a/chromium/mojo/public/cpp/platform/BUILD.gn
+++ b/chromium/mojo/public/cpp/platform/BUILD.gn
@@ -4,13 +4,6 @@
import("//build/config/nacl/config.gni")
-# This file depends on the legacy global sources assignment filter. It should
-# be converted to check target platform before assigning source files to the
-# sources variable. Remove this import and set_sources_assignment_filter call
-# when the file has been converted. See https://crbug.com/1018739 for details.
-import("//build/config/deprecated_default_sources_assignment_filter.gni")
-set_sources_assignment_filter(deprecated_default_sources_assignment_filter)
-
component("platform") {
output_name = "mojo_cpp_platform"
@@ -22,7 +15,6 @@ component("platform") {
]
sources = [
- "named_platform_channel_win.cc",
"platform_channel.cc",
"platform_channel_endpoint.cc",
"platform_channel_server_endpoint.cc",
@@ -47,14 +39,16 @@ component("platform") {
sources += [ "named_platform_channel_mac.cc" ]
}
+ if (is_win) {
+ sources += [ "named_platform_channel_win.cc" ]
+ }
+
if (is_fuchsia) {
public_deps += [
"//third_party/fuchsia-sdk/sdk/pkg/fdio",
"//third_party/fuchsia-sdk/sdk/pkg/zx",
]
- }
-
- if (!is_fuchsia) {
+ } else {
sources += [ "named_platform_channel.cc" ]
public += [ "named_platform_channel.h" ]
}
diff --git a/chromium/mojo/public/cpp/system/platform_handle.cc b/chromium/mojo/public/cpp/system/platform_handle.cc
index 64c50bb2cb8..3b04fd7a28c 100644
--- a/chromium/mojo/public/cpp/system/platform_handle.cc
+++ b/chromium/mojo/public/cpp/system/platform_handle.cc
@@ -14,19 +14,20 @@ namespace mojo {
namespace {
-uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) {
+uint64_t ReleasePlatformHandleValueFromPlatformFile(
+ base::ScopedPlatformFile file) {
#if defined(OS_WIN)
- return reinterpret_cast<uint64_t>(file);
+ return reinterpret_cast<uint64_t>(file.Take());
#else
- return static_cast<uint64_t>(file);
+ return static_cast<uint64_t>(file.release());
#endif
}
-base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
+base::ScopedPlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
#if defined(OS_WIN)
- return reinterpret_cast<base::PlatformFile>(value);
+ return base::ScopedPlatformFile(reinterpret_cast<base::PlatformFile>(value));
#else
- return static_cast<base::PlatformFile>(value);
+ return base::ScopedPlatformFile(static_cast<base::PlatformFile>(value));
#endif
}
@@ -198,12 +199,12 @@ PlatformHandle UnwrapPlatformHandle(ScopedHandle handle) {
return PlatformHandle::FromMojoPlatformHandle(&platform_handle);
}
-// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object.
-ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) {
+ScopedHandle WrapPlatformFile(base::ScopedPlatformFile platform_file) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
platform_handle.type = kPlatformFileHandleType;
- platform_handle.value = PlatformHandleValueFromPlatformFile(platform_file);
+ platform_handle.value =
+ ReleasePlatformHandleValueFromPlatformFile(std::move(platform_file));
MojoHandle mojo_handle;
MojoResult result =
@@ -213,7 +214,8 @@ ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) {
return ScopedHandle(Handle(mojo_handle));
}
-MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file) {
+MojoResult UnwrapPlatformFile(ScopedHandle handle,
+ base::ScopedPlatformFile* file) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
MojoResult result = MojoUnwrapPlatformHandle(handle.release().value(),
@@ -222,7 +224,7 @@ MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file) {
return result;
if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
- *file = base::kInvalidPlatformFile;
+ *file = base::ScopedPlatformFile();
} else {
CHECK_EQ(platform_handle.type, kPlatformFileHandleType);
*file = PlatformFileFromPlatformHandleValue(platform_handle.value);
diff --git a/chromium/mojo/public/cpp/system/platform_handle.h b/chromium/mojo/public/cpp/system/platform_handle.h
index 106a8527254..676906ce5fa 100644
--- a/chromium/mojo/public/cpp/system/platform_handle.h
+++ b/chromium/mojo/public/cpp/system/platform_handle.h
@@ -13,7 +13,6 @@
#include <stdint.h>
-#include "base/compiler_specific.h"
#include "base/files/platform_file.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
@@ -27,53 +26,16 @@
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/system_export.h"
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
namespace mojo {
#if defined(OS_WIN)
const MojoPlatformHandleType kPlatformFileHandleType =
MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
-
-const MojoPlatformHandleType kPlatformSharedBufferHandleType =
- MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
-
-#elif defined(OS_FUCHSIA)
-const MojoPlatformHandleType kPlatformFileHandleType =
- MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
-const MojoPlatformHandleType kPlatformSharedBufferHandleType =
- MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
-
-#elif defined(OS_POSIX)
-const MojoPlatformHandleType kPlatformFileHandleType =
- MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
-
-#if defined(OS_MAC)
-const MojoPlatformHandleType kPlatformSharedBufferHandleType =
- MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
#else
-const MojoPlatformHandleType kPlatformSharedBufferHandleType =
+const MojoPlatformHandleType kPlatformFileHandleType =
MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
-#endif // defined(OS_MAC)
-
#endif // defined(OS_WIN)
-// Used to specify the protection status of a base::SharedMemoryHandle memory
-// handle wrapped or unwrapped by mojo::WrapSharedMemoryHandle or
-// mojo::UnwrapSharedMemoryHandle below. See those functions for additional
-// details.
-enum class UnwrappedSharedMemoryHandleProtection {
- // Indicates that the base::SharedMemoryHandle supports being mapped to
- // writable memory regions.
- kReadWrite,
-
- // Indicates that the base::SharedMemoryHandle supports being mapped only to
- // read-only memory regions.
- kReadOnly,
-};
-
// Wraps and unwraps base::subtle::PlatformSharedMemoryRegions. This should be
// used only while transitioning from the legacy shared memory API. In new code
// only base::*SharedMemoryRegion should be used instead.
@@ -90,14 +52,15 @@ MOJO_CPP_SYSTEM_EXPORT ScopedHandle WrapPlatformHandle(PlatformHandle handle);
// support library.
MOJO_CPP_SYSTEM_EXPORT PlatformHandle UnwrapPlatformHandle(ScopedHandle handle);
-// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object.
-// If |platform_file| is valid, this will return a valid handle.
+// Wraps a ScopedPlatformFile as a Mojo handle. Takes ownership of the file
+// object. If |platform_file| is valid, this will return a valid handle.
MOJO_CPP_SYSTEM_EXPORT
-ScopedHandle WrapPlatformFile(base::PlatformFile platform_file);
+ScopedHandle WrapPlatformFile(base::ScopedPlatformFile platform_file);
// Unwraps a PlatformFile from a Mojo handle.
MOJO_CPP_SYSTEM_EXPORT
-MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file);
+MojoResult UnwrapPlatformFile(ScopedHandle handle,
+ base::ScopedPlatformFile* file);
// Helpers for wrapping and unwrapping new base shared memory API primitives.
// If the input |region| is valid for the Wrap* functions, they will always
diff --git a/chromium/mojo/public/cpp/system/simple_watcher.cc b/chromium/mojo/public/cpp/system/simple_watcher.cc
index f34b90e05fb..700fda474bf 100644
--- a/chromium/mojo/public/cpp/system/simple_watcher.cc
+++ b/chromium/mojo/public/cpp/system/simple_watcher.cc
@@ -13,7 +13,9 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/heap_profiler.h"
#include "base/trace_event/trace_event.h"
+#include "base/trace_event/typed_macros.h"
#include "mojo/public/c/system/trap.h"
+#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h"
namespace mojo {
@@ -32,9 +34,9 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
MojoTriggerCondition condition,
int watch_id,
MojoResult* result,
- const char* heap_profiler_tag) {
+ const char* handler_tag) {
scoped_refptr<Context> context =
- new Context(watcher, task_runner, watch_id, heap_profiler_tag);
+ new Context(watcher, task_runner, watch_id, handler_tag);
// If MojoAddTrigger succeeds, it effectively assumes ownership of a
// reference to |context|. In that case, this reference is balanced in
@@ -70,11 +72,11 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
Context(base::WeakPtr<SimpleWatcher> weak_watcher,
scoped_refptr<base::SequencedTaskRunner> task_runner,
int watch_id,
- const char* heap_profiler_tag)
+ const char* handler_tag)
: weak_watcher_(weak_watcher),
task_runner_(task_runner),
watch_id_(watch_id),
- heap_profiler_tag_(heap_profiler_tag) {}
+ handler_tag_(handler_tag) {}
~Context() = default;
@@ -92,10 +94,8 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
weak_watcher_->OnHandleReady(watch_id_, result, state);
} else {
{
- // Annotate the posted task with |heap_profiler_tag_| as the IPC
- // interface.
- base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(
- heap_profiler_tag_);
+ // Annotate the posted task with |handler_tag_| as the IPC interface.
+ base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(handler_tag_);
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&SimpleWatcher::OnHandleReady,
weak_watcher_, watch_id_, result, state));
@@ -106,7 +106,7 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
const base::WeakPtr<SimpleWatcher> weak_watcher_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
const int watch_id_;
- const char* heap_profiler_tag_ = nullptr;
+ const char* handler_tag_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(Context);
};
@@ -114,14 +114,13 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
SimpleWatcher::SimpleWatcher(const base::Location& from_here,
ArmingPolicy arming_policy,
scoped_refptr<base::SequencedTaskRunner> runner,
- const char* heap_profiler_tag)
+ const char* handler_tag)
: arming_policy_(arming_policy),
task_runner_(std::move(runner)),
is_default_task_runner_(base::ThreadTaskRunnerHandle::IsSet() &&
task_runner_ ==
base::ThreadTaskRunnerHandle::Get()),
- heap_profiler_tag_(heap_profiler_tag ? heap_profiler_tag
- : from_here.file_name()) {
+ handler_tag_(handler_tag ? handler_tag : from_here.file_name()) {
MojoResult rv = CreateTrap(&Context::CallNotify, &trap_handle_);
DCHECK_EQ(MOJO_RESULT_OK, rv);
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -152,7 +151,7 @@ MojoResult SimpleWatcher::Watch(Handle handle,
MojoResult result = MOJO_RESULT_UNKNOWN;
context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_,
trap_handle_.get(), handle_, signals, condition,
- watch_id_, &result, heap_profiler_tag_);
+ watch_id_, &result, handler_tag_);
if (!context_) {
handle_.set_value(kInvalidHandleValue);
callback_.Reset();
@@ -225,14 +224,17 @@ void SimpleWatcher::ArmOrNotify() {
MojoResult ready_result;
HandleSignalsState ready_state;
MojoResult rv = Arm(&ready_result, &ready_state);
- if (rv == MOJO_RESULT_OK)
+
+ // NOTE: If the watched handle has been closed, the above call will result in
+ // MOJO_RESULT_NOT_FOUND. A MOJO_RESULT_CANCELLED notification will already
+ // have been posted to this object as a result, so there's nothing else to do.
+ if (rv == MOJO_RESULT_OK || rv == MOJO_RESULT_NOT_FOUND)
return;
DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
{
- // Annotate the posted task with |heap_profiler_tag_| as the IPC interface.
- base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(
- heap_profiler_tag_);
+ // Annotate the posted task with |handler_tag_| as the IPC interface.
+ base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(handler_tag_);
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&SimpleWatcher::OnHandleReady,
weak_factory_.GetWeakPtr(), watch_id_,
@@ -261,12 +263,16 @@ void SimpleWatcher::OnHandleReady(int watch_id,
// NOTE: It's legal for |callback| to delete |this|.
if (!callback.is_null()) {
- TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event(heap_profiler_tag_);
+ TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event(handler_tag_);
// Lot of janks caused are grouped to OnHandleReady tasks. This trace event
- // helps identify the cause of janks. It is ok to pass |heap_profiler_tag_|
+ // helps identify the cause of janks. It is ok to pass |handler_tag_|
// here since it is a string literal.
- // TODO(927206): Consider renaming |heap_profiler_tag_|.
- TRACE_EVENT0("toplevel", heap_profiler_tag_);
+ TRACE_EVENT("toplevel", "SimpleWatcher::OnHandleReady",
+ [this](perfetto::EventContext ctx) {
+ ctx.event()
+ ->set_chrome_mojo_event_info()
+ ->set_watcher_notify_interface_tag(handler_tag_);
+ });
base::WeakPtr<SimpleWatcher> weak_self = weak_factory_.GetWeakPtr();
callback.Run(result, state);
diff --git a/chromium/mojo/public/cpp/system/simple_watcher.h b/chromium/mojo/public/cpp/system/simple_watcher.h
index 24123bcb905..3ccec253e88 100644
--- a/chromium/mojo/public/cpp/system/simple_watcher.h
+++ b/chromium/mojo/public/cpp/system/simple_watcher.h
@@ -90,7 +90,7 @@ class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher {
ArmingPolicy arming_policy,
scoped_refptr<base::SequencedTaskRunner> runner =
base::SequencedTaskRunnerHandle::Get(),
- const char* heap_profiler_tag = nullptr);
+ const char* handler_tag = nullptr);
~SimpleWatcher();
// Indicates if the SimpleWatcher is currently watching a handle.
@@ -226,7 +226,7 @@ class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher {
// Tag used to ID memory allocations that originated from notifications in
// this watcher.
- const char* heap_profiler_tag_ = nullptr;
+ const char* handler_tag_ = nullptr;
base::WeakPtrFactory<SimpleWatcher> weak_factory_{this};
diff --git a/chromium/mojo/public/cpp/test_support/lib/test_utils.cc b/chromium/mojo/public/cpp/test_support/lib/test_utils.cc
index 062106db864..6fa00a537ba 100644
--- a/chromium/mojo/public/cpp/test_support/lib/test_utils.cc
+++ b/chromium/mojo/public/cpp/test_support/lib/test_utils.cc
@@ -10,7 +10,7 @@
#include <vector>
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/cpp/system/wait.h"
#include "mojo/public/cpp/test_support/test_support.h"
diff --git a/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn b/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
index 404d9cf94f4..6eda7da6d8a 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/python.gni")
import("../../../tools/bindings/mojom.gni")
group("test_data_deps") {
@@ -254,7 +255,8 @@ copy("validation_test_data") {
outputs = [ "$root_gen_dir/layout_test_data/{{source_root_relative_dir}}/{{source_file_part}}" ]
}
-action_foreach("validation_test_data_list") {
+# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+python2_action_foreach("validation_test_data_list") {
testonly = true
script = "//mojo/public/tools/bindings/gen_data_files_list.py"
inputs = mojom_generator_sources
diff --git a/chromium/mojo/public/js/BUILD.gn b/chromium/mojo/public/js/BUILD.gn
index 47ee8536397..e3febd86e77 100644
--- a/chromium/mojo/public/js/BUILD.gn
+++ b/chromium/mojo/public/js/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/python.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//third_party/closure_compiler/closure_args.gni")
import("//third_party/closure_compiler/compile_js.gni")
@@ -9,7 +10,8 @@ import("//tools/grit/grit_rule.gni")
interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings"
-action("bindings") {
+# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+python2_action("bindings") {
bindings_js_files = [
# This must be the first file in the list, because it initializes global
# variable |mojo| that the others need to refer to.
@@ -49,26 +51,71 @@ action("bindings") {
deps = [ "//mojo/public/interfaces/bindings:bindings_js__generator" ]
}
-bindings_lite_sources = [
- "bindings_lite.js",
- "interface_support.js",
-]
+template("concatenate_files") {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(target_name) {
+ script = "//mojo/public/tools/bindings/concatenate-files.py"
+ inputs = invoker.inputs
+ output = "$target_gen_dir/${invoker.output}"
+ outputs = [ output ]
+ args = rebase_path(inputs, root_build_dir) +
+ [ rebase_path(output, root_build_dir) ]
+ if (defined(invoker.deps)) {
+ deps = invoker.deps
+ }
+ }
+}
-bindings_lite_compiled_file = "$target_gen_dir/mojo_bindings_lite.js"
+concatenate_files("generate_mojo_internal_js") {
+ inputs = [
+ "mojo_internal_preamble.js.part",
+ "bindings_lite.js",
+ ]
+ output = "mojo_internal.js"
+}
+
+concatenate_files("generate_interface_support_js") {
+ inputs = [
+ "interface_support_preamble.js.part",
+ "interface_support.js",
+ ]
+ output = "interface_support.js"
+}
js_library("bindings_lite_sources") {
- sources = [ "compile_preamble.js" ] + bindings_lite_sources
+ sources = [
+ "$target_gen_dir/interface_support.js",
+ "$target_gen_dir/mojo_internal.js",
+ "compile_preamble.js",
+ ]
deps = [ "//mojo/public/interfaces/bindings:bindings_js_library_for_compile" ]
+ extra_deps = [
+ ":generate_interface_support_js",
+ ":generate_mojo_internal_js",
+ ]
+}
+
+# All generated mojom JS modules consume the API defined by this module. The
+# uncompiled source is simply a concatenation of the various pieces listed
+# below.
+concatenate_files("bindings_uncompiled_module") {
+ inputs = [
+ "bindings_module_preamble.js.part",
+ "bindings_lite.js",
+ "$root_gen_dir/mojo/public/interfaces/bindings/interface_control_messages.mojom-lite.js",
+ "interface_support.js",
+ "bindings_uncompiled_module_export.js.part",
+ ]
+ output = "bindings_uncompiled.js"
+ deps = [ "//mojo/public/interfaces/bindings:bindings_js_library" ]
}
if (enable_mojom_closure_compile || enable_js_type_check) {
js_binary("bindings_lite") {
- outputs = [ bindings_lite_compiled_file ]
+ outputs = [ "$target_gen_dir/mojo_bindings_lite.js" ]
+ sources = []
deps = [ ":bindings_lite_sources" ]
- externs_list = [
- "$externs_path/mojo_core.js",
- "$externs_path/pending.js",
- ]
+ externs_list = [ "$externs_path/mojo_core.js" ]
closure_flags = strict_error_checking_closure_args + [
"compilation_level=ADVANCED_OPTIMIZATIONS",
"language_in=ECMASCRIPT_2017",
@@ -78,19 +125,61 @@ if (enable_mojom_closure_compile || enable_js_type_check) {
"isolation_mode=IIFE",
]
}
+
+ concatenate_files("bindings_compiled_module") {
+ inputs = [
+ "$target_gen_dir/mojo_bindings_lite.js",
+ "bindings_module_export.js.part",
+ ]
+ output = "bindings_compiled.js"
+ deps = [ ":bindings_lite" ]
+ }
+
+ copy("bindings_module") {
+ sources = [ "$target_gen_dir/bindings_compiled.js" ]
+ outputs = [ "$target_gen_dir/bindings.js" ]
+ deps = [ ":bindings_compiled_module" ]
+ }
} else {
action("bindings_lite") {
- all_sources = bindings_lite_sources + [ "$root_gen_dir/mojo/public/interfaces/bindings/interface_control_messages.mojom-lite.js" ]
+ inputs = [
+ "$target_gen_dir/mojo_internal.js",
+ "$root_gen_dir/mojo/public/interfaces/bindings/interface_control_messages.mojom-lite-for-compile.js",
+ "$target_gen_dir/interface_support.js",
+ ]
script = "//mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py"
- sources = all_sources
- outputs = [ bindings_lite_compiled_file ]
- args = rebase_path(all_sources, root_build_dir) +
- [ rebase_path(bindings_lite_compiled_file, root_build_dir) ]
- deps = [ "//mojo/public/interfaces/bindings:bindings_js__generator" ]
+ sources = inputs
+ outputs = [ "$target_gen_dir/mojo_bindings_lite.js" ]
+ args =
+ rebase_path(inputs, root_build_dir) +
+ [ rebase_path("$target_gen_dir/mojo_bindings_lite.js", root_build_dir) ]
+ deps = [
+ ":generate_interface_support_js",
+ ":generate_mojo_internal_js",
+ "//mojo/public/interfaces/bindings:bindings_js__generator",
+ ]
}
+
+ copy("bindings_module") {
+ sources = [ "$target_gen_dir/bindings_uncompiled.js" ]
+ outputs = [ "$target_gen_dir/bindings.js" ]
+ deps = [ ":bindings_uncompiled_module" ]
+ }
+}
+
+# This is the library target used in the dependency tree of any JS libraries
+# or binaries compiling against mojom JS bindings. This library is functionally
+# equivalent to the bindings.js generated by the ":bindings_module" target and
+# used at runtime by all consumers, except that this module includes all type
+# annotations and is suitable for Closure compilation and type checking.
+js_library("bindings_uncompiled") {
+ sources = [ "$target_gen_dir/bindings_uncompiled.js" ]
+ extra_deps = [ ":bindings_uncompiled_module" ]
}
grit("resources") {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ run_under_python2 = true
source = "mojo_bindings_resources.grd"
outputs = [
@@ -100,14 +189,10 @@ grit("resources") {
"mojo_bindings_resources.pak",
]
- grit_flags = [
- "-E",
- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
- ]
-
deps = [
":bindings",
":bindings_lite",
+ ":bindings_module",
"//mojo/public/mojom/base:base_js",
]
}
diff --git a/chromium/mojo/public/js/bindings_lite.js b/chromium/mojo/public/js/bindings_lite.js
index d2521fc30b2..1821540fda8 100644
--- a/chromium/mojo/public/js/bindings_lite.js
+++ b/chromium/mojo/public/js/bindings_lite.js
@@ -1,33 +1,6 @@
// Copyright 2018 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.
-'use strict';
-
-goog.provide('mojo.internal');
-
-// "self" is always defined as opposed to "this", which isn't defined in
-// modules, or "window", which isn't defined in workers.
-/** @const {!Object} */
-mojo.internal.globalScope = self;
-
-/**
- * This is effectively the same as goog.provide, but it's made available under
- * the mojo.internal namespace to avoid potential collisions in certain
- * compilation environments.
- *
- * @param {string} namespace
- * @export
- */
-mojo.internal.exportModule = function(namespace) {
- let current = mojo.internal.globalScope;
- const parts = namespace.split('.');
-
- for (let part; parts.length && (part = parts.shift());) {
- if (!current[part])
- current[part] = {};
- current = current[part];
- }
-};
/** @const {number} */
mojo.internal.kArrayHeaderSize = 8;
@@ -85,7 +58,7 @@ mojo.internal.align = function(size, alignment) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
- * @param {number} value
+ * @param {number|bigint} value
*/
mojo.internal.setInt64 = function(dataView, byteOffset, value) {
if (mojo.internal.kHostLittleEndian) {
@@ -93,11 +66,12 @@ mojo.internal.setInt64 = function(dataView, byteOffset, value) {
byteOffset, Number(BigInt(value) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setInt32(
- byteOffset + 4, Number(BigInt(value) >> BigInt(32)),
+ byteOffset + 4,
+ Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
} else {
dataView.setInt32(
- byteOffset, Number(BigInt(value) >> BigInt(32)),
+ byteOffset, Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
byteOffset + 4, Number(BigInt(value) & BigInt(0xffffffff)),
@@ -108,7 +82,7 @@ mojo.internal.setInt64 = function(dataView, byteOffset, value) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
- * @param {number} value
+ * @param {number|bigint} value
*/
mojo.internal.setUint64 = function(dataView, byteOffset, value) {
if (mojo.internal.kHostLittleEndian) {
@@ -116,11 +90,12 @@ mojo.internal.setUint64 = function(dataView, byteOffset, value) {
byteOffset, Number(BigInt(value) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
- byteOffset + 4, Number(BigInt(value) >> BigInt(32)),
+ byteOffset + 4,
+ Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
} else {
dataView.setUint32(
- byteOffset, Number(BigInt(value) >> BigInt(32)),
+ byteOffset, Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
byteOffset + 4, Number(BigInt(value) & BigInt(0xffffffff)),
@@ -131,7 +106,7 @@ mojo.internal.setUint64 = function(dataView, byteOffset, value) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
- * @return {number}
+ * @return {bigint}
*/
mojo.internal.getInt64 = function(dataView, byteOffset) {
let low, high;
@@ -142,12 +117,24 @@ mojo.internal.getInt64 = function(dataView, byteOffset) {
low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
high = dataView.getInt32(byteOffset, mojo.internal.kHostLittleEndian);
}
- const value = (BigInt(high) << BigInt(32)) | BigInt(low);
- if (value <= BigInt(Number.MAX_SAFE_INTEGER) &&
- value >= BigInt(Number.MIN_SAFE_INTEGER)) {
- return Number(value);
+ return (BigInt(high) << BigInt(32)) | BigInt(low);
+};
+
+/**
+ * @param {!DataView} dataView
+ * @param {number} byteOffset
+ * @return {bigint}
+ */
+mojo.internal.getUint64 = function(dataView, byteOffset) {
+ let low, high;
+ if (mojo.internal.kHostLittleEndian) {
+ low = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
+ high = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
+ } else {
+ low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
+ high = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
}
- return value;
+ return (BigInt(high) << BigInt(32)) | BigInt(low);
};
/**
@@ -249,26 +236,6 @@ mojo.internal.computeTotalArraySize = function(arraySpec, value) {
return totalSize;
};
-/**
- * @param {!DataView} dataView
- * @param {number} byteOffset
- * @return {number}
- */
-mojo.internal.getUint64 = function(dataView, byteOffset) {
- let low, high;
- if (mojo.internal.kHostLittleEndian) {
- low = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
- high = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
- } else {
- low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
- high = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
- }
- const value = (BigInt(high) << BigInt(32)) | BigInt(low);
- if (value <= BigInt(Number.MAX_SAFE_INTEGER))
- return Number(value);
- return value;
-};
-
/** Owns an outgoing message buffer and facilitates serialization. */
mojo.internal.Message = class {
/**
@@ -683,7 +650,9 @@ mojo.internal.Decoder = class {
const relativeOffset = this.decodeUint64(offset);
if (relativeOffset == 0)
return 0;
- return this.data_.byteOffset + offset + relativeOffset;
+ if (relativeOffset > BigInt(Number.MAX_SAFE_INTEGER))
+ throw new Error('Mesage offset too large');
+ return this.data_.byteOffset + offset + Number(relativeOffset);
}
/**
diff --git a/chromium/mojo/public/js/bindings_module_export.js.part b/chromium/mojo/public/js/bindings_module_export.js.part
new file mode 100644
index 00000000000..455896d4ab1
--- /dev/null
+++ b/chromium/mojo/public/js/bindings_module_export.js.part
@@ -0,0 +1,3 @@
+const mojoTmp = self['mojo'];
+delete self['mojo'];
+export const mojo = mojoTmp;
diff --git a/chromium/mojo/public/js/bindings_module_preamble.js.part b/chromium/mojo/public/js/bindings_module_preamble.js.part
new file mode 100644
index 00000000000..1d00fd82e02
--- /dev/null
+++ b/chromium/mojo/public/js/bindings_module_preamble.js.part
@@ -0,0 +1,4 @@
+const mojo = {
+ internal: { interfaceSupport: {} },
+ interfaceControl: {}
+};
diff --git a/chromium/mojo/public/js/bindings_uncompiled_module_export.js.part b/chromium/mojo/public/js/bindings_uncompiled_module_export.js.part
new file mode 100644
index 00000000000..712a9e34ea4
--- /dev/null
+++ b/chromium/mojo/public/js/bindings_uncompiled_module_export.js.part
@@ -0,0 +1 @@
+export {mojo};
diff --git a/chromium/mojo/public/js/interface_support.js b/chromium/mojo/public/js/interface_support.js
index 6d95bb8ce7a..1810c790e0c 100644
--- a/chromium/mojo/public/js/interface_support.js
+++ b/chromium/mojo/public/js/interface_support.js
@@ -1,14 +1,6 @@
// Copyright 2018 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.
-'use strict';
-
-goog.require('mojo.interfaceControl.RUN_MESSAGE_ID');
-goog.require('mojo.interfaceControl.RunResponseMessageParamsSpec');
-goog.require('mojo.internal');
-
-goog.provide('mojo.internal.interfaceSupport');
-
/**
* Handles incoming interface control messages on a remote or router endpoint.
diff --git a/chromium/mojo/public/js/interface_support_preamble.js.part b/chromium/mojo/public/js/interface_support_preamble.js.part
new file mode 100644
index 00000000000..bb98866e4c5
--- /dev/null
+++ b/chromium/mojo/public/js/interface_support_preamble.js.part
@@ -0,0 +1,8 @@
+'use strict';
+
+goog.require('mojo.interfaceControl.RUN_MESSAGE_ID');
+goog.require('mojo.interfaceControl.RunResponseMessageParamsSpec');
+goog.require('mojo.internal');
+
+goog.provide('mojo.internal.interfaceSupport');
+
diff --git a/chromium/mojo/public/js/lib/interface_endpoint_client.js b/chromium/mojo/public/js/lib/interface_endpoint_client.js
index 9b45b69b05e..392cb59d297 100644
--- a/chromium/mojo/public/js/lib/interface_endpoint_client.js
+++ b/chromium/mojo/public/js/lib/interface_endpoint_client.js
@@ -33,12 +33,17 @@
}
InterfaceEndpointClient.prototype.initControllerIfNecessary_ = function() {
+ if (!this.handle_) {
+ return false;
+ }
+
if (this.controller_ || this.handle_.pendingAssociation()) {
- return;
+ return true;
}
this.controller_ = this.handle_.groupController().attachEndpointClient(
this.handle_, this);
+ return true;
};
InterfaceEndpointClient.prototype.onAssociationEvent = function(
@@ -84,7 +89,9 @@
return false;
}
- this.initControllerIfNecessary_();
+ if (!this.initControllerIfNecessary_()) {
+ return false;
+ }
return this.controller_.sendMessage(message);
};
@@ -99,7 +106,9 @@
return Promise.reject();
}
- this.initControllerIfNecessary_();
+ if (!this.initControllerIfNecessary_()) {
+ return Promise.reject(Error('Endpoint has been closed'));
+ }
// Reserve 0 in case we want it to convey special meaning in the future.
var requestID = this.nextRequestID_++;
diff --git a/chromium/mojo/public/js/mojo_bindings_resources.grd b/chromium/mojo/public/js/mojo_bindings_resources.grd
index e86d260df3c..999a411ea9b 100644
--- a/chromium/mojo/public/js/mojo_bindings_resources.grd
+++ b/chromium/mojo/public/js/mojo_bindings_resources.grd
@@ -7,7 +7,7 @@
<output filename="grit/mojo_bindings_resources_map.h"
type="resource_map_header" />
<output filename="grit/mojo_bindings_resources_map.cc"
- type="resource_map_source" />
+ type="resource_file_map_source" />
<output filename="mojo_bindings_resources.pak" type="data_package" />
</outputs>
<translations />
@@ -18,58 +18,89 @@
<include name="IDR_MOJO_MOJO_BINDINGS_JS"
file="${root_gen_dir}/mojo/public/js/mojo_bindings.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/js/mojo_bindings.js"
type="BINDATA" />
</if>
+ <include name="IDR_MOJO_BINDINGS_JS"
+ file="${root_gen_dir}/mojo/public/js/bindings.js"
+ use_base_dir="false"
+ resource_path="mojo/mojo/public/js/bindings.js"
+ type="BINDATA" />
<include name="IDR_MOJO_MOJO_BINDINGS_LITE_HTML"
file="mojo_bindings_lite.html"
+ resource_path="mojo/mojo/public/js/mojo_bindings_lite.html"
type="BINDATA" />
<include name="IDR_MOJO_MOJO_BINDINGS_LITE_JS"
file="${root_gen_dir}/mojo/public/js/mojo_bindings_lite.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/js/mojo_bindings_lite.js"
type="BINDATA" />
<include name="IDR_MOJO_BIG_BUFFER_MOJOM_HTML"
file="${root_gen_dir}/mojo/public/mojom/base/big_buffer.mojom.html"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/big_buffer.mojom.html"
type="BINDATA" />
<include name="IDR_MOJO_BIG_BUFFER_MOJOM_LITE_JS"
file="${root_gen_dir}/mojo/public/mojom/base/big_buffer.mojom-lite.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"
type="BINDATA" />
- <include name="IDR_MOJO_FILE_MOJOM_HTML"
- file="${root_gen_dir}/mojo/public/mojom/base/file.mojom.html"
+ <include name="IDR_MOJO_BIG_BUFFER_MOJOM_WEBUI_JS"
+ file="${root_gen_dir}/mojom-webui/mojo/public/mojom/base/big_buffer.mojom-webui.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/big_buffer.mojom-webui.js"
type="BINDATA" />
- <include name="IDR_MOJO_FILE_MOJOM_LITE_JS"
- file="${root_gen_dir}/mojo/public/mojom/base/file.mojom-lite.js"
+ <include name="IDR_MOJO_FILE_MOJOM_WEBUI_JS"
+ file="${root_gen_dir}/mojom-webui/mojo/public/mojom/base/file.mojom-webui.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/file.mojom-webui.js"
type="BINDATA" />
<include name="IDR_MOJO_STRING16_MOJOM_HTML"
file="${root_gen_dir}/mojo/public/mojom/base/string16.mojom.html"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/string16.mojom.html"
type="BINDATA" />
<include name="IDR_MOJO_STRING16_MOJOM_LITE_JS"
file="${root_gen_dir}/mojo/public/mojom/base/string16.mojom-lite.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/string16.mojom-lite.js"
+ type="BINDATA" />
+ <include name="IDR_MOJO_STRING16_MOJOM_WEBUI_JS"
+ file="${root_gen_dir}/mojom-webui/mojo/public/mojom/base/string16.mojom-webui.js"
+ use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/string16.mojom-webui.js"
type="BINDATA" />
<include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_HTML"
file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom.html"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/text_direction.mojom.html"
type="BINDATA" />
<include name="IDR_MOJO_TEXT_DIRECTION_MOJOM_LITE_JS"
file="${root_gen_dir}/mojo/public/mojom/base/text_direction.mojom-lite.js"
use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/text_direction.mojom-lite.js"
type="BINDATA" />
<if expr="is_win or is_macosx or is_linux or is_android">
+ <include name="IDR_MOJO_PROCESS_ID_MOJOM_WEBUI_JS"
+ file="${root_gen_dir}/mojom-webui/mojo/public/mojom/base/process_id.mojom-webui.js"
+ use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/process_id.mojom-webui.js"
+ type="BINDATA" />
<include name="IDR_MOJO_TIME_MOJOM_HTML"
file="${root_gen_dir}/mojo/public/mojom/base/time.mojom.html"
use_base_dir="false"
- type="BINDATA"
- compress="gzip" />
+ resource_path="mojo/mojo/public/mojom/base/time.mojom.html"
+ type="BINDATA" />
<include name="IDR_MOJO_TIME_MOJOM_LITE_JS"
file="${root_gen_dir}/mojo/public/mojom/base/time.mojom-lite.js"
+ resource_path="mojo/mojo/public/mojom/base/time.mojom-lite.js"
use_base_dir="false"
- type="BINDATA"
- compress="gzip" />
+ type="BINDATA" />
+ <include name="IDR_MOJO_TIME_MOJOM_WEBUI_JS"
+ file="${root_gen_dir}/mojom-webui/mojo/public/mojom/base/time.mojom-webui.js"
+ use_base_dir="false"
+ resource_path="mojo/mojo/public/mojom/base/time.mojom-webui.js"
+ type="BINDATA" />
</if>
</includes>
</release>
diff --git a/chromium/mojo/public/js/mojo_internal_preamble.js.part b/chromium/mojo/public/js/mojo_internal_preamble.js.part
new file mode 100644
index 00000000000..28a18b25150
--- /dev/null
+++ b/chromium/mojo/public/js/mojo_internal_preamble.js.part
@@ -0,0 +1,27 @@
+'use strict';
+
+goog.provide('mojo.internal');
+
+// "self" is always defined as opposed to "this", which isn't defined in
+// modules, or "window", which isn't defined in workers.
+/** @const {!Object} */
+mojo.internal.globalScope = self;
+
+/**
+ * This is effectively the same as goog.provide, but it's made available under
+ * the mojo.internal namespace to avoid potential collisions in certain
+ * compilation environments.
+ *
+ * @param {string} namespace
+ * @export
+ */
+mojo.internal.exportModule = function(namespace) {
+ let current = mojo.internal.globalScope;
+ const parts = namespace.split('.');
+
+ for (let part; parts.length && (part = parts.shift());) {
+ if (!current[part])
+ current[part] = {};
+ current = current[part];
+ }
+};
diff --git a/chromium/mojo/public/mojom/base/BUILD.gn b/chromium/mojo/public/mojom/base/BUILD.gn
index 61bb72a6183..53acc61d85d 100644
--- a/chromium/mojo/public/mojom/base/BUILD.gn
+++ b/chromium/mojo/public/mojom/base/BUILD.gn
@@ -21,6 +21,7 @@ mojom_component("base") {
"message_pump_type.mojom",
"process_id.mojom",
"read_only_buffer.mojom",
+ "read_only_file.mojom",
"ref_counted_memory.mojom",
"shared_memory.mojom",
"string16.mojom",
@@ -42,6 +43,8 @@ mojom_component("base") {
enabled_features += [ "file_path_is_string" ]
}
+ webui_module_path = "chrome://resources/mojo/mojo/public/mojom/base"
+
output_prefix = "mojo_base_mojom"
macro_prefix = "MOJO_BASE_MOJOM"
@@ -121,6 +124,24 @@ mojom_component("base") {
{
types = [
{
+ mojom = "mojo_base.mojom.ReadOnlyFile"
+ cpp = "::base::File"
+ move_only = true
+ nullable_is_same_type = true
+ force_serialize = true
+ },
+ ]
+ traits_headers =
+ [ "//mojo/public/cpp/base/read_only_file_mojom_traits.h" ]
+ traits_public_deps = [
+ "//base",
+ "//mojo/public/cpp/base",
+ "//mojo/public/cpp/base:shared_typemap_traits",
+ ]
+ },
+ {
+ types = [
+ {
mojom = "mojo_base.mojom.GenericPendingReceiver"
cpp = "::mojo::GenericPendingReceiver"
move_only = true
diff --git a/chromium/mojo/public/mojom/base/big_string.mojom b/chromium/mojo/public/mojom/base/big_string.mojom
index c971caf5674..fd0a5c00690 100644
--- a/chromium/mojo/public/mojom/base/big_string.mojom
+++ b/chromium/mojo/public/mojom/base/big_string.mojom
@@ -14,6 +14,7 @@ import "mojo/public/mojom/base/big_buffer.mojom";
// an arbitrarily large amount of data (available memory permitting) without
// negatively impacting IPC performance or hitting hard message size
// boundaries.
+[Stable]
struct BigString {
mojo_base.mojom.BigBuffer data;
};
diff --git a/chromium/mojo/public/mojom/base/file.mojom b/chromium/mojo/public/mojom/base/file.mojom
index 199af80a262..6c7f5043be0 100644
--- a/chromium/mojo/public/mojom/base/file.mojom
+++ b/chromium/mojo/public/mojom/base/file.mojom
@@ -5,6 +5,7 @@
module mojo_base.mojom;
// Corresponds to |base::File| in base/files/file.h
+[Stable]
struct File {
handle<platform> fd;
bool async;
diff --git a/chromium/mojo/public/mojom/base/process_id.mojom b/chromium/mojo/public/mojom/base/process_id.mojom
index f3b17780a51..3a6e09f4242 100644
--- a/chromium/mojo/public/mojom/base/process_id.mojom
+++ b/chromium/mojo/public/mojom/base/process_id.mojom
@@ -4,6 +4,7 @@
module mojo_base.mojom;
+[Stable]
struct ProcessId {
// This is the storage for the pid, on windows the pid is a DWORD and the
// value can be DWORD_MAX which maps gracefully to uint32 while on linux
diff --git a/chromium/mojo/public/mojom/base/read_only_file.mojom b/chromium/mojo/public/mojom/base/read_only_file.mojom
new file mode 100644
index 00000000000..6f361ffe7f2
--- /dev/null
+++ b/chromium/mojo/public/mojom/base/read_only_file.mojom
@@ -0,0 +1,20 @@
+// Copyright 2020 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.
+
+module mojo_base.mojom;
+
+// Corresponds to |base::File| in base/files/file.h but, on most
+// platforms, will not serialise handles which are writable. At
+// present this only supports physically backed files, but this may be
+// relaxed in future.
+//
+// SECURITY_NOTE: This type is an indication that a readonly handle can
+// be provided. A sandboxed process should ensure that the handle cannot
+// be made writable. This may not be possible on all platforms.
+//
+// See |file_mojom_traits.cc| for details.
+struct ReadOnlyFile {
+ handle<platform> fd;
+ bool async;
+};
diff --git a/chromium/mojo/public/mojom/base/time.mojom b/chromium/mojo/public/mojom/base/time.mojom
index 64777e56754..5eb3fa5cee2 100644
--- a/chromium/mojo/public/mojom/base/time.mojom
+++ b/chromium/mojo/public/mojom/base/time.mojom
@@ -11,10 +11,12 @@ struct Time {
int64 internal_value;
};
+[Stable]
struct TimeDelta {
int64 microseconds;
};
+[Stable]
struct TimeTicks {
// The internal value is expressed in terms of microseconds since a fixed but
// intentionally unspecified epoch.
diff --git a/chromium/mojo/public/mojom/base/token.mojom b/chromium/mojo/public/mojom/base/token.mojom
index ac5f32c37b9..62f85b3f0c9 100644
--- a/chromium/mojo/public/mojom/base/token.mojom
+++ b/chromium/mojo/public/mojom/base/token.mojom
@@ -5,6 +5,7 @@
module mojo_base.mojom;
// Corresponds to |base::Token| defined in base/token.h
+[Stable]
struct Token {
uint64 high;
uint64 low;
diff --git a/chromium/mojo/public/mojom/base/values.mojom b/chromium/mojo/public/mojom/base/values.mojom
index ea7c1fa590f..5ffe845af53 100644
--- a/chromium/mojo/public/mojom/base/values.mojom
+++ b/chromium/mojo/public/mojom/base/values.mojom
@@ -8,6 +8,7 @@ module mojo_base.mojom;
//
// One notable caveat is that Value supports arbitrary binary data, which JSON
// does not support natively.
+[Stable]
union Value {
// Null type placeholder. This field is never used.
uint8 null_value;
@@ -29,10 +30,12 @@ union Value {
// declaration. Though both of these types are mapped to base::Value in C++,
// the generated deserialization will guarantee that the method is only invoked
// with a base::Value of the correct subtype.
+[Stable]
struct DictionaryValue {
map<string, Value> storage;
};
+[Stable]
struct ListValue {
array<Value> storage;
};
diff --git a/chromium/mojo/public/tools/bindings/BUILD.gn b/chromium/mojo/public/tools/bindings/BUILD.gn
index 8ba6e922a4b..f25c4afa8b0 100644
--- a/chromium/mojo/public/tools/bindings/BUILD.gn
+++ b/chromium/mojo/public/tools/bindings/BUILD.gn
@@ -2,10 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/python.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//third_party/jinja2/jinja2.gni")
-action("precompile_templates") {
+# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+python2_action("precompile_templates") {
sources = mojom_generator_sources
sources += [
"$mojom_generator_root/generators/cpp_templates/enum_macros.tmpl",
@@ -69,11 +71,16 @@ action("precompile_templates") {
"$mojom_generator_root/generators/js_templates/fuzzing.tmpl",
"$mojom_generator_root/generators/js_templates/interface_definition.tmpl",
"$mojom_generator_root/generators/js_templates/lite/enum_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/lite/enum_definition_for_module.tmpl",
"$mojom_generator_root/generators/js_templates/lite/interface_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/lite/interface_definition_for_module.tmpl",
"$mojom_generator_root/generators/js_templates/lite/module_definition.tmpl",
"$mojom_generator_root/generators/js_templates/lite/mojom-lite.js.tmpl",
+ "$mojom_generator_root/generators/js_templates/lite/mojom.m.js.tmpl",
"$mojom_generator_root/generators/js_templates/lite/struct_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/lite/struct_definition_for_module.tmpl",
"$mojom_generator_root/generators/js_templates/lite/union_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/lite/union_definition_for_module.tmpl",
"$mojom_generator_root/generators/js_templates/module.amd.tmpl",
"$mojom_generator_root/generators/js_templates/module_definition.tmpl",
"$mojom_generator_root/generators/js_templates/struct_definition.tmpl",
diff --git a/chromium/mojo/public/tools/bindings/README.md b/chromium/mojo/public/tools/bindings/README.md
index 228a2d3355b..7ddbb79a6ff 100644
--- a/chromium/mojo/public/tools/bindings/README.md
+++ b/chromium/mojo/public/tools/bindings/README.md
@@ -418,6 +418,13 @@ interesting attributes supported today.
strict presubmit check. See [Versioning](#Versioning) for more details on
backward-compatibility constraints.
+**`[Uuid=<UUID>]`**
+: Specifies a UUID to be associated with a given interface. The UUID is
+ intended to remain stable across all changes to the interface definition,
+ including name changes. The value given for this attribute should be a
+ standard UUID string representation as specified by RFC 4122. New UUIDs can
+ be generated with common tools such as `uuidgen`.
+
**`[EnableIf=value]`**
: The `EnableIf` attribute is used to conditionally enable definitions when
the mojom is parsed. If the `mojom` target in the GN file does not include
@@ -712,6 +719,24 @@ values and will need to deal with them gracefully. See
[C++ Versioning Considerations](/mojo/public/cpp/bindings/README.md#Versioning-Considerations)
for details.
+### Renaming versioned structs
+It's possible to rename versioned structs by using the `[RenamedFrom]` attribute.
+RenamedFrom
+
+``` cpp
+module asdf.mojom;
+
+// Old version:
+[Stable]
+struct OldStruct {
+};
+
+// New version:
+[Stable, RenamedFrom="asdf.mojom.OldStruct"]
+struct NewStruct {
+};
+```
+
## Grammar Reference
Below is the (BNF-ish) context-free grammar of the Mojom language:
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
index f8b28e79c3b..a1a87fb125d 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -16,6 +16,10 @@ class {{export_attribute}} {{interface.name}}
: public {{interface.name}}InterfaceBase {
public:
static const char Name_[];
+{%- if interface.uuid %}
+ static constexpr base::Token Uuid_{ {{interface.uuid[0]}}ULL,
+ {{interface.uuid[1]}}ULL };
+{%- endif %}
static constexpr uint32_t Version_ = {{interface.version}};
static constexpr bool PassesAssociatedKinds_ = {% if interface|passes_associated_kinds %}true{% else %}false{% endif %};
static constexpr bool HasSyncMethods_ = {% if interface|has_sync_methods %}true{% else %}false{% endif %};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index d8d10b3c672..c3ca8506c11 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -32,6 +32,9 @@ std::move(p_{{param.name}})
{#--- Begin #}
const char {{class_name}}::Name_[] = "{{module_namespace}}.{{class_name}}";
+{%- if interface.uuid %}
+constexpr base::Token {{class_name}}::Uuid_;
+{%- endif %}
{#--- Constants #}
{%- for constant in interface.constants %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
index eb7fd89a4e7..e934b41c728 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -59,6 +59,9 @@ class {{export_attribute}} {{struct.name}} {
template <typename T, {{struct.name}}::EnableIfSame<T>* = nullptr>
bool Equals(const T& other) const;
+ template <typename T, {{struct.name}}::EnableIfSame<T>* = nullptr>
+ bool operator==(const T& rhs) const { return Equals(rhs); }
+
{%- if struct|is_hashable %}
size_t Hash(size_t seed) const;
{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
index 40603a7fe53..05686c9ddf7 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -49,6 +49,11 @@ class {{export_attribute}} {{union.name}} {
T, {{union.name}}>::value>::type* = nullptr>
bool Equals(const T& other) const;
+ template <typename T,
+ typename std::enable_if<std::is_same<
+ T, {{union.name}}>::value>::type* = nullptr>
+ bool operator==(const T& rhs) const { return Equals(rhs); }
+
{%- if union|is_hashable %}
size_t Hash(size_t seed) const;
{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/enum_definition_for_module.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/enum_definition_for_module.tmpl
new file mode 100644
index 00000000000..27c4817c9d9
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/enum_definition_for_module.tmpl
@@ -0,0 +1,23 @@
+{%- macro enum_def(enum) -%}
+/**
+ * @const { {$: !mojo.internal.MojomType} }
+ */
+export const {{enum|type_in_js_module}}Spec = { $: mojo.internal.Enum() };
+
+/**
+ * @enum {number}
+ */
+export const {{enum|type_in_js_module}} = {
+ {# Set up the enum here, but fill out the values later. #}
+{%- for field in enum.fields %}
+ {{field.name}}: {{field.numeric_value}},
+{%- endfor %}
+{%- if enum.min_value is not none %}
+ MIN_VALUE: {{enum.min_value}},
+{%- endif %}
+{%- if enum.max_value is not none %}
+ MAX_VALUE: {{enum.max_value}},
+{%- endif %}
+};
+
+{%- endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/interface_definition_for_module.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/interface_definition_for_module.tmpl
new file mode 100644
index 00000000000..bc000ba3d82
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/interface_definition_for_module.tmpl
@@ -0,0 +1,211 @@
+{% macro generateMethodAnnotation(method) %}
+ /**
+{%- for param in method.parameters %}
+ * @param { {{param.kind|param_type_in_js_module}} } {{param.name|sanitize_identifier}}
+{%- endfor -%}
+{%- if method.response_parameters != None %}
+{%- if method.response_parameters|length == 0 %}
+ * @return {!Promise}
+{%- else %}
+ * @return {!Promise<{
+{%- for response_parameter in method.response_parameters %}
+ {{response_parameter.name}}: {{response_parameter.kind|param_type_in_js_module}},
+{%- endfor %}
+ * }>}
+{%- endif %}
+{%- endif %}
+ */
+{% endmacro %}
+
+/**
+ * @implements {mojo.internal.interfaceSupport.PendingReceiver}
+ */
+export const {{interface.name}}PendingReceiver = class {
+ /** @param {!MojoHandle} handle */
+ constructor(handle) {
+ /** @public {!MojoHandle} */
+ this.handle = handle;
+ }
+};
+
+/** @interface */
+export const {{interface.name}}Interface = class {
+{%- for method in interface.methods %}
+ {{generateMethodAnnotation(method)}}
+ {{method.name}}(
+{%- for param in method.parameters -%}
+{{param.name|sanitize_identifier}}{% if not loop.last %}, {% endif %}
+{%- endfor -%}
+) {}
+{%- endfor %}
+};
+
+/**
+ * @implements { {{interface.name}}Interface }
+ */
+export const {{interface.name}}Remote = class {
+ /** @param {MojoHandle=} opt_handle */
+ constructor(opt_handle) {
+ /**
+ * @private {!mojo.internal.interfaceSupport.InterfaceRemoteBase<!{{interface.name}}PendingReceiver>}
+ */
+ this.proxy =
+ new mojo.internal.interfaceSupport.InterfaceRemoteBase(
+ {{interface.name}}PendingReceiver,
+ opt_handle);
+
+ /**
+ * @public {!mojo.internal.interfaceSupport.InterfaceRemoteBaseWrapper<!{{interface.name}}PendingReceiver>}
+ */
+ this.$ = new mojo.internal.interfaceSupport.InterfaceRemoteBaseWrapper(this.proxy);
+
+ /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
+ this.onConnectionError = this.proxy.getConnectionErrorEventRouter();
+ }
+
+{%- for method in interface.methods -%}
+{%- set interface_message_id =
+ interface.mojom_name ~ "_" ~ method.mojom_name %}
+
+ {{generateMethodAnnotation(method)}}
+ {{method.name}}(
+{%- for param in method.parameters %}
+ {{param.name}}{%- if not loop.last %},{% endif %}
+{%- endfor -%}) {
+{%- if method.response_parameters != None %}
+ return this.proxy.sendMessage(
+{%- else %}
+ this.proxy.sendMessage(
+{%- endif %}
+ {{method.ordinal}},
+ {{interface_message_id}}_ParamsSpec.$,
+{%- if method.response_parameters != None %}
+ {{interface_message_id}}_ResponseParamsSpec.$,
+{%- else %}
+ null,
+{%- endif %}
+ [
+{%- for param in method.parameters %}
+ {{param.name}}{%- if not loop.last %},{% endif %}
+{%- endfor %}
+ ]);
+ }
+{%- endfor %}
+};
+
+/**
+ * An object which receives request messages for the {{interface.name}}
+ * mojom interface. Must be constructed over an object which implements that
+ * interface.
+ */
+export const {{interface.name}}Receiver = class {
+ /**
+ * @param {!{{interface.name}}Interface } impl
+ */
+ constructor(impl) {
+ /** @private {!mojo.internal.interfaceSupport.InterfaceReceiverHelperInternal<!{{interface.name}}Remote>} */
+ this.helper_internal_ = new mojo.internal.interfaceSupport.InterfaceReceiverHelperInternal(
+ {{interface.name}}Remote);
+
+ /**
+ * @public {!mojo.internal.interfaceSupport.InterfaceReceiverHelper<!{{interface.name}}Remote>}
+ */
+ this.$ = new mojo.internal.interfaceSupport.InterfaceReceiverHelper(this.helper_internal_);
+
+{% for method in interface.methods %}
+{%- set interface_message_id =
+ interface.mojom_name ~ "_" ~ method.mojom_name %}
+ this.helper_internal_.registerHandler(
+ {{method.ordinal}},
+ {{interface_message_id}}_ParamsSpec.$,
+{%- if method.response_parameters != None %}
+ {{interface_message_id}}_ResponseParamsSpec.$,
+{%- else %}
+ null,
+{%- endif %}
+ impl.{{method.name}}.bind(impl));
+{%- endfor %}
+ /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
+ this.onConnectionError = this.helper_internal_.getConnectionErrorEventRouter();
+ }
+};
+
+export const {{interface.name}} = class {
+ /**
+ * @return {!string}
+ */
+ static get $interfaceName() {
+ return "{{mojom_namespace}}.{{interface.name}}";
+ }
+
+ /**
+ * Returns a remote for this interface which sends messages to the browser.
+ * The browser must have an interface request binder registered for this
+ * interface and accessible to the calling document's frame.
+ *
+ * @return {!{{interface.name}}Remote}
+ */
+ static getRemote() {
+ let remote = new {{interface.name}}Remote;
+ Mojo.bindInterface("{{mojom_namespace}}.{{interface.name}}",
+ remote.$.bindNewPipeAndPassReceiver().handle);
+ return remote;
+ }
+};
+
+{#--- Enums #}
+{% from "lite/enum_definition_for_module.tmpl" import enum_def with context %}
+{%- for enum in interface.enums %}
+{{enum_def(enum)}}
+{%- endfor %}
+
+/**
+ * An object which receives request messages for the {{interface.name}}
+ * mojom interface and dispatches them as callbacks. One callback receiver exists
+ * on this object for each message defined in the mojom interface, and each
+ * receiver can have any number of listeners added to it.
+ */
+export const {{interface.name}}CallbackRouter = class {
+ constructor() {
+ this.helper_internal_ = new mojo.internal.interfaceSupport.InterfaceReceiverHelperInternal(
+ {{interface.name}}Remote);
+
+ /**
+ * @public {!mojo.internal.interfaceSupport.InterfaceReceiverHelper<!{{interface.name}}Remote>}
+ */
+ this.$ = new mojo.internal.interfaceSupport.InterfaceReceiverHelper(this.helper_internal_);
+
+ this.router_ = new mojo.internal.interfaceSupport.CallbackRouter;
+{% for method in interface.methods %}
+{%- set interface_message_id =
+ interface.mojom_name ~ "_" ~ method.mojom_name %}
+ /**
+ * @public {!mojo.internal.interfaceSupport.InterfaceCallbackReceiver}
+ */
+ this.{{method.name}} =
+ new mojo.internal.interfaceSupport.InterfaceCallbackReceiver(
+ this.router_);
+
+ this.helper_internal_.registerHandler(
+ {{method.ordinal}},
+ {{interface_message_id}}_ParamsSpec.$,
+{%- if method.response_parameters != None %}
+ {{interface_message_id}}_ResponseParamsSpec.$,
+ this.{{method.name}}.createReceiverHandler(true /* expectsResponse */));
+{%- else %}
+ null,
+ this.{{method.name}}.createReceiverHandler(false /* expectsResponse */));
+{%- endif %}
+{%- endfor %}
+ /** @public {!mojo.internal.interfaceSupport.ConnectionErrorEventRouter} */
+ this.onConnectionError = this.helper_internal_.getConnectionErrorEventRouter();
+ }
+
+ /**
+ * @param {number} id An ID returned by a prior call to addListener.
+ * @return {boolean} True iff the identified listener was found and removed.
+ */
+ removeListener(id) {
+ return this.router_.removeListener(id);
+ }
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/module_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/module_definition.tmpl
index e8124d4a865..99422f42f30 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/module_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/module_definition.tmpl
@@ -8,8 +8,7 @@ goog.provide('{{module.namespace}}.{{constant.name}}');
* @const { {{constant.kind|lite_closure_type_with_nullability}} }
* @export
*/
-{{module.namespace}}.{{constant.name}} =
- {{constant.value|expression_to_text_lite}};
+{{module.namespace}}.{{constant.name}} = {{constant|constant_value}};
{%- endfor %}
{#--- Enums #}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom-lite.js.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom-lite.js.tmpl
index a02c7a32077..e057457d615 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom-lite.js.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom-lite.js.tmpl
@@ -1,7 +1,11 @@
+{# For bindings internals, generated code is concatenated into a larger module
+ # at build time, so we avoid a superfluous file header here. #}
+{%- if not for_bindings_internals -%}
// Copyright 2018 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.
'use strict';
+{%- endif %}
{% if generate_closure_exports -%}
goog.require('mojo.internal');
@@ -11,7 +15,7 @@ goog.require('mojo.internal.interfaceSupport');
{% for kind in module.imported_kinds.values() %}
goog.require('{{kind|lite_js_import_name}}');
{%- endfor %}
-{% else %}
+{% elif not for_bindings_internals %}
mojo.internal.exportModule('{{module.namespace}}');
{% endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom.m.js.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom.m.js.tmpl
new file mode 100644
index 00000000000..659d6480c9e
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/mojom.m.js.tmpl
@@ -0,0 +1,66 @@
+// Copyright 2020 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.
+
+{% if not for_bindings_internals -%}
+import {mojo} from '{{bindings_library_path}}';
+{%- endif %}
+
+{% for path, kinds in js_module_imports.items() -%}
+import {
+{%- for kind in kinds %}
+{%- for item in kind|imports_for_kind %}
+ {{item.name}} as {{item.alias}}
+{%- if not loop.last -%},{% endif -%}
+{%- endfor %}
+{%- if not loop.last -%},{% endif -%}
+{%- endfor %}
+} from '{{path}}';
+
+{% endfor -%}
+
+{#--- Constants #}
+{%- for constant in module.constants %}
+/**
+ * @const { {{constant.kind|type_in_js_module_with_nullability}} }
+ */
+export const {{constant.name}} = {{constant|constant_value_in_js_module}};
+
+{% endfor -%}
+
+{#--- Enums #}
+{%- from "lite/enum_definition_for_module.tmpl" import enum_def with context %}
+{%- for enum in enums %}
+{{enum_def(enum)}}
+{% endfor -%}
+
+{#--- Interfaces #}
+{%- for interface in interfaces %}
+{% include "lite/interface_definition_for_module.tmpl" %}
+{%- endfor %}
+
+{#--- Struct and Union forward declarations #}
+{% for struct in structs %}
+/**
+ * @const { {$:!mojo.internal.MojomType}}
+ */
+export const {{struct.name}}Spec =
+ { $: /** @type {!mojo.internal.MojomType} */ ({}) };
+{% endfor %}
+{%- for union in unions %}
+/**
+ * @const { {$:!mojo.internal.MojomType} }
+ */
+export const {{union.name}}Spec =
+ { $: /** @type {!mojo.internal.MojomType} */ ({}) };
+{% endfor %}
+
+{#--- Struct definitions #}
+{% for struct in structs %}
+{%- include "lite/struct_definition_for_module.tmpl" %}
+{% endfor -%}
+
+{#--- Union definitions #}
+{% for union in unions %}
+{%- include "lite/union_definition_for_module.tmpl" %}
+{% endfor %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition.tmpl
index 1d6acbcb5d7..2e4eb953412 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition.tmpl
@@ -4,7 +4,7 @@
* @export
*/
{{module.namespace}}.{{struct.name}}_{{constant.name}} =
- {{constant.value|expression_to_text_lite}};
+ {{constant|constant_value}};
{% endfor %}
{%- from "lite/enum_definition.tmpl" import enum_def with context %}
@@ -40,6 +40,7 @@ mojo.internal.Struct(
{% if generate_closure_exports -%}
goog.provide('{{module.namespace}}.{{struct.name}}');
+{%- endif %}
/** @record */
{{module.namespace}}.{{struct.name}} = class {
@@ -51,4 +52,3 @@ goog.provide('{{module.namespace}}.{{struct.name}}');
}
};
-{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition_for_module.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition_for_module.tmpl
new file mode 100644
index 00000000000..b6ef3829b6f
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/struct_definition_for_module.tmpl
@@ -0,0 +1,49 @@
+{% for constant in struct.constants %}
+/**
+ * @const { {{constant.kind|type_in_js_module_with_nullability}} }
+ */
+export const {{struct.name}}_{{constant.name}} =
+ {{constant|constant_value_in_js_module}};
+{% endfor %}
+
+{%- from "lite/enum_definition_for_module.tmpl" import enum_def with context %}
+{% for enum in struct.enums %}
+{{enum_def(enum)}}
+{% endfor %}
+
+mojo.internal.Struct(
+ {{struct.name}}Spec.$,
+ '{{struct.name}}',
+ {{struct.packed|payload_size}},
+ [
+{%- for packed_field in struct.packed.packed_fields_in_ordinal_order %}
+ mojo.internal.StructField(
+ '{{packed_field.field.name}}', {{packed_field.offset}},
+ {% if packed_field.field.kind|is_bool_kind %}{{packed_field.bit}}
+ {%- else %}0{% endif %},
+ {{packed_field.field.kind|spec_type_in_js_module}},
+ {{packed_field.field|default_value_in_js_module}},
+{%- if packed_field.field.kind.is_nullable %}
+ true /* nullable */),
+{%- else %}
+ false /* nullable */),
+{%- endif %}
+{%- endfor %}
+ ]);
+
+{% if generate_struct_deserializers %}
+export const {{struct.name}}_Deserialize =
+ mojo.internal.createStructDeserializer({{struct.name}}Spec.$);
+{% endif %}
+
+/**
+ * @record
+ */
+export const {{struct.name}} = class {
+ constructor() {
+{%- for packed_field in struct.packed.packed_fields %}
+ /** @type { {{packed_field.field.kind|field_type_in_js_module}} } */
+ this.{{packed_field.field.name}};
+{%- endfor %}
+ }
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/lite/union_definition_for_module.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/union_definition_for_module.tmpl
new file mode 100644
index 00000000000..68be8b22b56
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/lite/union_definition_for_module.tmpl
@@ -0,0 +1,22 @@
+mojo.internal.Union(
+ {{union.name}}Spec.$, '{{union.name}}',
+ {
+{%- for field in union.fields %}
+ '{{field.name}}': {
+ 'ordinal': {{field.ordinal}},
+ 'type': {{field.kind|spec_type_in_js_module}},
+{%- if field.kind.is_nullable %}
+ 'nullable': true,
+{%- endif %}
+ },
+{%- endfor %}
+ });
+
+/**
+ * @typedef { {
+{%- for field in union.fields %}
+ * {{field.name}}: ({{field.kind|type_in_js_module_with_nullability}}|undefined),
+{%- endfor %}
+ * } }
+ */
+export const {{union.name}} = {};
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index d73b3f48354..fc7728a1f59 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -35,8 +35,6 @@ _kind_to_cpp_literal_suffix = {
}
-
-
class _NameFormatter(object):
"""A formatter for the names of kinds or values."""
@@ -268,16 +266,19 @@ class Generator(generator.Generator):
return used_typemaps
def _GetExtraPublicHeaders(self):
+ headers = set()
+
all_enums = list(self.module.enums)
for struct in self.module.structs:
all_enums.extend(struct.enums)
for interface in self.module.interfaces:
all_enums.extend(interface.enums)
+ if interface.uuid:
+ headers.add('base/token.h')
types = set(self._GetFullMojomNameForKind(typename)
for typename in
self.module.structs + all_enums + self.module.unions)
- headers = set()
for typename, typemap in self.typemap.items():
if typename in types:
headers.update(typemap.get("public_headers", []))
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 96b2fdfae0c..c51824a444b 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -20,9 +20,12 @@ import mojom.generate.generator as generator
import mojom.generate.module as mojom
from mojom.generate.template_expander import UseJinja
-sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir,
- os.pardir, os.pardir, os.pardir, os.pardir,
- 'build', 'android', 'gyp'))
+# Item 0 of sys.path is the directory of the main file; item 1 is PYTHONPATH
+# (if set); item 2 is system libraries.
+sys.path.insert(
+ 1,
+ os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
+ os.pardir, os.pardir, 'build', 'android', 'gyp'))
from util import build_utils
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
index d8e275d83d2..c7068f5d008 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -1,7 +1,6 @@
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Generates JavaScript source files from a mojom.Module."""
import mojom.generate.generator as generator
@@ -17,115 +16,115 @@ else:
import urllib.request as urllib_request
_kind_to_javascript_default_value = {
- mojom.BOOL: "false",
- mojom.INT8: "0",
- mojom.UINT8: "0",
- mojom.INT16: "0",
- mojom.UINT16: "0",
- mojom.INT32: "0",
- mojom.UINT32: "0",
- mojom.FLOAT: "0",
- mojom.HANDLE: "null",
- mojom.DCPIPE: "null",
- mojom.DPPIPE: "null",
- mojom.MSGPIPE: "null",
- mojom.SHAREDBUFFER: "null",
- mojom.PLATFORMHANDLE: "null",
- mojom.NULLABLE_HANDLE: "null",
- mojom.NULLABLE_DCPIPE: "null",
- mojom.NULLABLE_DPPIPE: "null",
- mojom.NULLABLE_MSGPIPE: "null",
- mojom.NULLABLE_SHAREDBUFFER: "null",
- mojom.NULLABLE_PLATFORMHANDLE: "null",
- mojom.INT64: "0",
- mojom.UINT64: "0",
- mojom.DOUBLE: "0",
- mojom.STRING: "null",
- mojom.NULLABLE_STRING: "null"
+ mojom.BOOL: "false",
+ mojom.INT8: "0",
+ mojom.UINT8: "0",
+ mojom.INT16: "0",
+ mojom.UINT16: "0",
+ mojom.INT32: "0",
+ mojom.UINT32: "0",
+ mojom.FLOAT: "0",
+ mojom.HANDLE: "null",
+ mojom.DCPIPE: "null",
+ mojom.DPPIPE: "null",
+ mojom.MSGPIPE: "null",
+ mojom.SHAREDBUFFER: "null",
+ mojom.PLATFORMHANDLE: "null",
+ mojom.NULLABLE_HANDLE: "null",
+ mojom.NULLABLE_DCPIPE: "null",
+ mojom.NULLABLE_DPPIPE: "null",
+ mojom.NULLABLE_MSGPIPE: "null",
+ mojom.NULLABLE_SHAREDBUFFER: "null",
+ mojom.NULLABLE_PLATFORMHANDLE: "null",
+ mojom.INT64: "0",
+ mojom.UINT64: "0",
+ mojom.DOUBLE: "0",
+ mojom.STRING: "null",
+ mojom.NULLABLE_STRING: "null"
}
_kind_to_codec_type = {
- mojom.BOOL: "codec.Uint8",
- mojom.INT8: "codec.Int8",
- mojom.UINT8: "codec.Uint8",
- mojom.INT16: "codec.Int16",
- mojom.UINT16: "codec.Uint16",
- mojom.INT32: "codec.Int32",
- mojom.UINT32: "codec.Uint32",
- mojom.FLOAT: "codec.Float",
- mojom.HANDLE: "codec.Handle",
- mojom.DCPIPE: "codec.Handle",
- mojom.DPPIPE: "codec.Handle",
- mojom.MSGPIPE: "codec.Handle",
- mojom.SHAREDBUFFER: "codec.Handle",
- mojom.PLATFORMHANDLE: "codec.Handle",
- mojom.NULLABLE_HANDLE: "codec.NullableHandle",
- mojom.NULLABLE_DCPIPE: "codec.NullableHandle",
- mojom.NULLABLE_DPPIPE: "codec.NullableHandle",
- mojom.NULLABLE_MSGPIPE: "codec.NullableHandle",
- mojom.NULLABLE_SHAREDBUFFER: "codec.NullableHandle",
- mojom.NULLABLE_PLATFORMHANDLE: "codec.NullableHandle",
- mojom.INT64: "codec.Int64",
- mojom.UINT64: "codec.Uint64",
- mojom.DOUBLE: "codec.Double",
- mojom.STRING: "codec.String",
- mojom.NULLABLE_STRING: "codec.NullableString",
+ mojom.BOOL: "codec.Uint8",
+ mojom.INT8: "codec.Int8",
+ mojom.UINT8: "codec.Uint8",
+ mojom.INT16: "codec.Int16",
+ mojom.UINT16: "codec.Uint16",
+ mojom.INT32: "codec.Int32",
+ mojom.UINT32: "codec.Uint32",
+ mojom.FLOAT: "codec.Float",
+ mojom.HANDLE: "codec.Handle",
+ mojom.DCPIPE: "codec.Handle",
+ mojom.DPPIPE: "codec.Handle",
+ mojom.MSGPIPE: "codec.Handle",
+ mojom.SHAREDBUFFER: "codec.Handle",
+ mojom.PLATFORMHANDLE: "codec.Handle",
+ mojom.NULLABLE_HANDLE: "codec.NullableHandle",
+ mojom.NULLABLE_DCPIPE: "codec.NullableHandle",
+ mojom.NULLABLE_DPPIPE: "codec.NullableHandle",
+ mojom.NULLABLE_MSGPIPE: "codec.NullableHandle",
+ mojom.NULLABLE_SHAREDBUFFER: "codec.NullableHandle",
+ mojom.NULLABLE_PLATFORMHANDLE: "codec.NullableHandle",
+ mojom.INT64: "codec.Int64",
+ mojom.UINT64: "codec.Uint64",
+ mojom.DOUBLE: "codec.Double",
+ mojom.STRING: "codec.String",
+ mojom.NULLABLE_STRING: "codec.NullableString",
}
_kind_to_closure_type = {
- mojom.BOOL: "boolean",
- mojom.INT8: "number",
- mojom.UINT8: "number",
- mojom.INT16: "number",
- mojom.UINT16: "number",
- mojom.INT32: "number",
- mojom.UINT32: "number",
- mojom.FLOAT: "number",
- mojom.INT64: "number",
- mojom.UINT64: "number",
- mojom.DOUBLE: "number",
- mojom.STRING: "string",
- mojom.NULLABLE_STRING: "string",
- mojom.HANDLE: "MojoHandle",
- mojom.DCPIPE: "MojoHandle",
- mojom.DPPIPE: "MojoHandle",
- mojom.MSGPIPE: "MojoHandle",
- mojom.SHAREDBUFFER: "MojoHandle",
- mojom.PLATFORMHANDLE: "MojoHandle",
- mojom.NULLABLE_HANDLE: "MojoHandle",
- mojom.NULLABLE_DCPIPE: "MojoHandle",
- mojom.NULLABLE_DPPIPE: "MojoHandle",
- mojom.NULLABLE_MSGPIPE: "MojoHandle",
- mojom.NULLABLE_SHAREDBUFFER: "MojoHandle",
- mojom.NULLABLE_PLATFORMHANDLE: "MojoHandle",
+ mojom.BOOL: "boolean",
+ mojom.INT8: "number",
+ mojom.UINT8: "number",
+ mojom.INT16: "number",
+ mojom.UINT16: "number",
+ mojom.INT32: "number",
+ mojom.UINT32: "number",
+ mojom.FLOAT: "number",
+ mojom.INT64: "number",
+ mojom.UINT64: "number",
+ mojom.DOUBLE: "number",
+ mojom.STRING: "string",
+ mojom.NULLABLE_STRING: "string",
+ mojom.HANDLE: "MojoHandle",
+ mojom.DCPIPE: "MojoHandle",
+ mojom.DPPIPE: "MojoHandle",
+ mojom.MSGPIPE: "MojoHandle",
+ mojom.SHAREDBUFFER: "MojoHandle",
+ mojom.PLATFORMHANDLE: "MojoHandle",
+ mojom.NULLABLE_HANDLE: "MojoHandle",
+ mojom.NULLABLE_DCPIPE: "MojoHandle",
+ mojom.NULLABLE_DPPIPE: "MojoHandle",
+ mojom.NULLABLE_MSGPIPE: "MojoHandle",
+ mojom.NULLABLE_SHAREDBUFFER: "MojoHandle",
+ mojom.NULLABLE_PLATFORMHANDLE: "MojoHandle",
}
_kind_to_lite_js_type = {
- mojom.BOOL: "mojo.internal.Bool",
- mojom.INT8: "mojo.internal.Int8",
- mojom.UINT8: "mojo.internal.Uint8",
- mojom.INT16: "mojo.internal.Int16",
- mojom.UINT16: "mojo.internal.Uint16",
- mojom.INT32: "mojo.internal.Int32",
- mojom.UINT32: "mojo.internal.Uint32",
- mojom.FLOAT: "mojo.internal.Float",
- mojom.HANDLE: "mojo.internal.Handle",
- mojom.DCPIPE: "mojo.internal.Handle",
- mojom.DPPIPE: "mojo.internal.Handle",
- mojom.MSGPIPE: "mojo.internal.Handle",
- mojom.SHAREDBUFFER: "mojo.internal.Handle",
- mojom.PLATFORMHANDLE: "mojo.internal.Handle",
- mojom.NULLABLE_HANDLE: "mojo.internal.Handle",
- mojom.NULLABLE_DCPIPE: "mojo.internal.Handle",
- mojom.NULLABLE_DPPIPE: "mojo.internal.Handle",
- mojom.NULLABLE_MSGPIPE: "mojo.internal.Handle",
- mojom.NULLABLE_SHAREDBUFFER: "mojo.internal.Handle",
- mojom.NULLABLE_PLATFORMHANDLE: "mojo.internal.Handle",
- mojom.INT64: "mojo.internal.Int64",
- mojom.UINT64: "mojo.internal.Uint64",
- mojom.DOUBLE: "mojo.internal.Double",
- mojom.STRING: "mojo.internal.String",
- mojom.NULLABLE_STRING: "mojo.internal.String",
+ mojom.BOOL: "mojo.internal.Bool",
+ mojom.INT8: "mojo.internal.Int8",
+ mojom.UINT8: "mojo.internal.Uint8",
+ mojom.INT16: "mojo.internal.Int16",
+ mojom.UINT16: "mojo.internal.Uint16",
+ mojom.INT32: "mojo.internal.Int32",
+ mojom.UINT32: "mojo.internal.Uint32",
+ mojom.FLOAT: "mojo.internal.Float",
+ mojom.HANDLE: "mojo.internal.Handle",
+ mojom.DCPIPE: "mojo.internal.Handle",
+ mojom.DPPIPE: "mojo.internal.Handle",
+ mojom.MSGPIPE: "mojo.internal.Handle",
+ mojom.SHAREDBUFFER: "mojo.internal.Handle",
+ mojom.PLATFORMHANDLE: "mojo.internal.Handle",
+ mojom.NULLABLE_HANDLE: "mojo.internal.Handle",
+ mojom.NULLABLE_DCPIPE: "mojo.internal.Handle",
+ mojom.NULLABLE_DPPIPE: "mojo.internal.Handle",
+ mojom.NULLABLE_MSGPIPE: "mojo.internal.Handle",
+ mojom.NULLABLE_SHAREDBUFFER: "mojo.internal.Handle",
+ mojom.NULLABLE_PLATFORMHANDLE: "mojo.internal.Handle",
+ mojom.INT64: "mojo.internal.Int64",
+ mojom.UINT64: "mojo.internal.Uint64",
+ mojom.DOUBLE: "mojo.internal.Double",
+ mojom.STRING: "mojo.internal.String",
+ mojom.NULLABLE_STRING: "mojo.internal.String",
}
_js_reserved_keywords = [
@@ -176,34 +175,51 @@ _js_reserved_keywords = [
]
_primitive_kind_to_fuzz_type = {
- mojom.BOOL: "Bool",
- mojom.INT8: "Int8",
- mojom.UINT8: "Uint8",
- mojom.INT16: "Int16",
- mojom.UINT16: "Uint16",
- mojom.INT32: "Int32",
- mojom.UINT32: "Uint32",
- mojom.FLOAT: "Float",
- mojom.INT64: "Int64",
- mojom.UINT64: "Uint64",
- mojom.DOUBLE: "Double",
- mojom.STRING: "String",
- mojom.NULLABLE_STRING: "String",
- mojom.HANDLE: "Handle",
- mojom.DCPIPE: "DataPipeConsumer",
- mojom.DPPIPE: "DataPipeProducer",
- mojom.MSGPIPE: "MessagePipe",
- mojom.SHAREDBUFFER: "SharedBuffer",
- mojom.PLATFORMHANDLE: "PlatformHandle",
- mojom.NULLABLE_HANDLE: "Handle",
- mojom.NULLABLE_DCPIPE: "DataPipeConsumer",
- mojom.NULLABLE_DPPIPE: "DataPipeProducer",
- mojom.NULLABLE_MSGPIPE: "MessagePipe",
- mojom.NULLABLE_SHAREDBUFFER: "SharedBuffer",
- mojom.NULLABLE_PLATFORMHANDLE: "PlatformHandle",
+ mojom.BOOL: "Bool",
+ mojom.INT8: "Int8",
+ mojom.UINT8: "Uint8",
+ mojom.INT16: "Int16",
+ mojom.UINT16: "Uint16",
+ mojom.INT32: "Int32",
+ mojom.UINT32: "Uint32",
+ mojom.FLOAT: "Float",
+ mojom.INT64: "Int64",
+ mojom.UINT64: "Uint64",
+ mojom.DOUBLE: "Double",
+ mojom.STRING: "String",
+ mojom.NULLABLE_STRING: "String",
+ mojom.HANDLE: "Handle",
+ mojom.DCPIPE: "DataPipeConsumer",
+ mojom.DPPIPE: "DataPipeProducer",
+ mojom.MSGPIPE: "MessagePipe",
+ mojom.SHAREDBUFFER: "SharedBuffer",
+ mojom.PLATFORMHANDLE: "PlatformHandle",
+ mojom.NULLABLE_HANDLE: "Handle",
+ mojom.NULLABLE_DCPIPE: "DataPipeConsumer",
+ mojom.NULLABLE_DPPIPE: "DataPipeProducer",
+ mojom.NULLABLE_MSGPIPE: "MessagePipe",
+ mojom.NULLABLE_SHAREDBUFFER: "SharedBuffer",
+ mojom.NULLABLE_PLATFORMHANDLE: "PlatformHandle",
}
+_SHARED_MODULE_PREFIX = 'chrome://resources/mojo'
+
+
+def _GetWebUiModulePath(module):
+ """Returns the path to a WebUI module, from the perspective of a WebUI page
+ that makes it available. This is based on the corresponding mojom target's
+ webui_module_path value. Returns None if the target specifies no module
+ path. Otherwise, returned paths always end in a '/' and begin with either
+ `_SHARED_MODULE_PREFIX` or a '/'."""
+ path = module.metadata.get('webui_module_path')
+ if path is None or path == '/':
+ return path
+ if path.startswith(_SHARED_MODULE_PREFIX):
+ return path.rstrip('/') + '/'
+ return '/{}/'.format(path.strip('/'))
+
+
def JavaScriptPayloadSize(packed):
packed_fields = packed.packed_fields
if not packed_fields:
@@ -260,26 +276,46 @@ class JavaScriptStylizer(generator.Stylizer):
return mojom_name
def StylizeModule(self, mojom_namespace):
- return '.'.join(generator.ToCamel(word, lower_initial=True)
- for word in mojom_namespace.split('.'))
+ return '.'.join(
+ generator.ToCamel(word, lower_initial=True)
+ for word in mojom_namespace.split('.'))
class Generator(generator.Generator):
- def _GetParameters(self, for_compile=False):
+ def _GetParameters(self, for_compile=False, for_webui_module=False):
return {
- "enums": self.module.enums,
- "html_imports": self._GenerateHtmlImports(),
- "imports": self.module.imports,
- "interfaces": self.module.interfaces,
- "kinds": self.module.kinds,
- "module": self.module,
- "mojom_filename": os.path.basename(self.module.path),
- "mojom_namespace": self.module.mojom_namespace,
- "structs": self.module.structs + self._GetStructsFromMethods(),
- "unions": self.module.unions,
- "generate_fuzzing": self.generate_fuzzing,
- "generate_closure_exports": for_compile,
- "generate_struct_deserializers": self.js_generate_struct_deserializers,
+ "bindings_library_path":
+ self._GetBindingsLibraryPath(for_webui_module=for_webui_module),
+ "enums":
+ self.module.enums,
+ "for_bindings_internals":
+ self.disallow_native_types,
+ "html_imports":
+ self._GenerateHtmlImports(),
+ "imports":
+ self.module.imports,
+ "interfaces":
+ self.module.interfaces,
+ "js_module_imports":
+ self._GetJsModuleImports(for_webui_module=for_webui_module),
+ "kinds":
+ self.module.kinds,
+ "module":
+ self.module,
+ "mojom_filename":
+ os.path.basename(self.module.path),
+ "mojom_namespace":
+ self.module.mojom_namespace,
+ "structs":
+ self.module.structs + self._GetStructsFromMethods(),
+ "unions":
+ self.module.unions,
+ "generate_fuzzing":
+ self.generate_fuzzing,
+ "generate_closure_exports":
+ for_compile,
+ "generate_struct_deserializers":
+ self.js_generate_struct_deserializers,
}
@staticmethod
@@ -288,65 +324,75 @@ class Generator(generator.Generator):
def GetFilters(self):
js_filters = {
- "closure_type": self._ClosureType,
- "decode_snippet": self._JavaScriptDecodeSnippet,
- "default_value": self._JavaScriptDefaultValue,
- "encode_snippet": self._JavaScriptEncodeSnippet,
- "expression_to_text": self._ExpressionToText,
- "expression_to_text_lite": self._ExpressionToTextLite,
- "field_offset": JavaScriptFieldOffset,
- "get_relative_url": GetRelativeUrl,
- "has_callbacks": mojom.HasCallbacks,
- "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind,
- "is_array_kind": mojom.IsArrayKind,
- "is_associated_interface_kind": mojom.IsAssociatedInterfaceKind,
- "is_pending_associated_remote_kind": mojom.IsPendingAssociatedRemoteKind,
- "is_associated_interface_request_kind":
- mojom.IsAssociatedInterfaceRequestKind,
- "is_pending_associated_receiver_kind":
- mojom.IsPendingAssociatedReceiverKind,
- "is_bool_kind": mojom.IsBoolKind,
- "is_enum_kind": mojom.IsEnumKind,
- "is_any_handle_kind": mojom.IsAnyHandleKind,
- "is_any_interface_kind": mojom.IsAnyInterfaceKind,
- "is_interface_kind": mojom.IsInterfaceKind,
- "is_pending_remote_kind": mojom.IsPendingRemoteKind,
- "is_interface_request_kind": mojom.IsInterfaceRequestKind,
- "is_pending_receiver_kind": mojom.IsPendingReceiverKind,
- "is_map_kind": mojom.IsMapKind,
- "is_object_kind": mojom.IsObjectKind,
- "is_reference_kind": mojom.IsReferenceKind,
- "is_string_kind": mojom.IsStringKind,
- "is_struct_kind": mojom.IsStructKind,
- "is_union_kind": mojom.IsUnionKind,
- "js_type": self._JavaScriptType,
- "lite_default_value": self._LiteJavaScriptDefaultValue,
- "lite_js_type": self._LiteJavaScriptType,
- "lite_js_import_name": self._LiteJavaScriptImportName,
- "method_passes_associated_kinds": mojom.MethodPassesAssociatedKinds,
- "namespace_declarations": self._NamespaceDeclarations,
- "closure_type_with_nullability": self._ClosureTypeWithNullability,
- "lite_closure_param_type": self._LiteClosureParamType,
- "lite_closure_type": self._LiteClosureType,
- "lite_closure_type_with_nullability":
- self._LiteClosureTypeWithNullability,
- "lite_closure_field_type": self._LiteClosureFieldType,
- "payload_size": JavaScriptPayloadSize,
- "to_camel": generator.ToCamel,
- "union_decode_snippet": self._JavaScriptUnionDecodeSnippet,
- "union_encode_snippet": self._JavaScriptUnionEncodeSnippet,
- "validate_array_params": self._JavaScriptValidateArrayParams,
- "validate_enum_params": self._JavaScriptValidateEnumParams,
- "validate_map_params": self._JavaScriptValidateMapParams,
- "validate_nullable_params": self._JavaScriptNullableParam,
- "validate_struct_params": self._JavaScriptValidateStructParams,
- "validate_union_params": self._JavaScriptValidateUnionParams,
- "sanitize_identifier": self._JavaScriptSanitizeIdentifier,
- "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces,
- "fuzz_handle_name": self._FuzzHandleName,
- "is_primitive_kind": self._IsPrimitiveKind,
- "primitive_to_fuzz_type": self._PrimitiveToFuzzType,
- "to_js_boolean": self._ToJsBoolean,
+ "closure_type": self._ClosureType,
+ "constant_value": self._GetConstantValue,
+ "constant_value_in_js_module": self._GetConstantValueInJsModule,
+ "decode_snippet": self._JavaScriptDecodeSnippet,
+ "default_value": self._JavaScriptDefaultValue,
+ "default_value_in_js_module": self._DefaultValueInJsModule,
+ "encode_snippet": self._JavaScriptEncodeSnippet,
+ "expression_to_text": self._ExpressionToText,
+ "field_offset": JavaScriptFieldOffset,
+ "field_type_in_js_module": self._GetFieldTypeInJsModule,
+ "get_relative_url": GetRelativeUrl,
+ "has_callbacks": mojom.HasCallbacks,
+ "imports_for_kind": self._GetImportsForKind,
+ "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind,
+ "is_array_kind": mojom.IsArrayKind,
+ "is_associated_interface_kind": mojom.IsAssociatedInterfaceKind,
+ "is_pending_associated_remote_kind":
+ mojom.IsPendingAssociatedRemoteKind,
+ "is_associated_interface_request_kind":
+ mojom.IsAssociatedInterfaceRequestKind,
+ "is_pending_associated_receiver_kind":
+ mojom.IsPendingAssociatedReceiverKind,
+ "is_bool_kind": mojom.IsBoolKind,
+ "is_enum_kind": mojom.IsEnumKind,
+ "is_any_handle_kind": mojom.IsAnyHandleKind,
+ "is_any_interface_kind": mojom.IsAnyInterfaceKind,
+ "is_interface_kind": mojom.IsInterfaceKind,
+ "is_pending_remote_kind": mojom.IsPendingRemoteKind,
+ "is_interface_request_kind": mojom.IsInterfaceRequestKind,
+ "is_pending_receiver_kind": mojom.IsPendingReceiverKind,
+ "is_map_kind": mojom.IsMapKind,
+ "is_object_kind": mojom.IsObjectKind,
+ "is_reference_kind": mojom.IsReferenceKind,
+ "is_string_kind": mojom.IsStringKind,
+ "is_struct_kind": mojom.IsStructKind,
+ "is_union_kind": mojom.IsUnionKind,
+ "js_type": self._JavaScriptType,
+ "lite_default_value": self._LiteJavaScriptDefaultValue,
+ "lite_js_type": self._LiteJavaScriptType,
+ "lite_js_import_name": self._LiteJavaScriptImportName,
+ "method_passes_associated_kinds": mojom.MethodPassesAssociatedKinds,
+ "namespace_declarations": self._NamespaceDeclarations,
+ "closure_type_with_nullability": self._ClosureTypeWithNullability,
+ "lite_closure_param_type": self._LiteClosureParamType,
+ "lite_closure_type": self._LiteClosureType,
+ "lite_closure_type_with_nullability":
+ self._LiteClosureTypeWithNullability,
+ "lite_closure_field_type": self._LiteClosureFieldType,
+ "param_type_in_js_module": self._GetParamTypeInJsModule,
+ "payload_size": JavaScriptPayloadSize,
+ "spec_type_in_js_module": self._GetSpecTypeInJsModule,
+ "to_camel": generator.ToCamel,
+ "type_in_js_module": self._GetTypeInJsModule,
+ "type_in_js_module_with_nullability":
+ self._GetTypeInJsModuleWithNullability,
+ "union_decode_snippet": self._JavaScriptUnionDecodeSnippet,
+ "union_encode_snippet": self._JavaScriptUnionEncodeSnippet,
+ "validate_array_params": self._JavaScriptValidateArrayParams,
+ "validate_enum_params": self._JavaScriptValidateEnumParams,
+ "validate_map_params": self._JavaScriptValidateMapParams,
+ "validate_nullable_params": self._JavaScriptNullableParam,
+ "validate_struct_params": self._JavaScriptValidateStructParams,
+ "validate_union_params": self._JavaScriptValidateUnionParams,
+ "sanitize_identifier": self._JavaScriptSanitizeIdentifier,
+ "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces,
+ "fuzz_handle_name": self._FuzzHandleName,
+ "is_primitive_kind": self._IsPrimitiveKind,
+ "primitive_to_fuzz_type": self._PrimitiveToFuzzType,
+ "to_js_boolean": self._ToJsBoolean,
}
return js_filters
@@ -370,6 +416,14 @@ class Generator(generator.Generator):
def _GenerateLiteBindingsForCompile(self):
return self._GetParameters(for_compile=True)
+ @UseJinja("lite/mojom.m.js.tmpl")
+ def _GenerateJsModule(self):
+ return self._GetParameters()
+
+ @UseJinja("lite/mojom.m.js.tmpl")
+ def _GenerateWebUiModule(self):
+ return self._GetParameters(for_webui_module=True)
+
def GenerateFiles(self, args):
if self.variant:
raise Exception("Variants not supported in JavaScript bindings.")
@@ -391,6 +445,23 @@ class Generator(generator.Generator):
"%s-lite.js" % self.module.path)
self.WriteWithComment(self._GenerateLiteBindingsForCompile(),
"%s-lite-for-compile.js" % self.module.path)
+ self.WriteWithComment(self._GenerateJsModule(),
+ "%s.m.js" % self.module.path)
+ if _GetWebUiModulePath(self.module) is not None:
+ self.WriteWithComment(self._GenerateWebUiModule(),
+ "mojom-webui/%s-webui.js" % self.module.path)
+
+ def _GetRelativePath(self, path):
+ relpath = urllib_request.pathname2url(
+ os.path.relpath(path, os.path.dirname(self.module.path)))
+ if relpath.startswith('.') or relpath.startswith('/'):
+ return relpath
+ return './' + relpath
+
+ def _GetBindingsLibraryPath(self, for_webui_module=False):
+ if for_webui_module:
+ return "chrome://resources/mojo/mojo/public/js/bindings.js"
+ return self._GetRelativePath('mojo/public/js/bindings.js')
def _SetUniqueNameForImports(self):
used_names = set()
@@ -416,8 +487,7 @@ class Generator(generator.Generator):
return kind.module.namespace + "." + kind.name + "Ptr"
if mojom.IsPendingRemoteKind(kind):
return kind.kind.module.namespace + "." + kind.kind.name + "Ptr"
- if (mojom.IsStructKind(kind) or
- mojom.IsEnumKind(kind)):
+ if (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)):
return kind.module.namespace + "." + kind.name
# TODO(calamity): Support unions properly.
if mojom.IsUnionKind(kind):
@@ -425,17 +495,17 @@ class Generator(generator.Generator):
if mojom.IsArrayKind(kind):
return "Array<%s>" % self._ClosureType(kind.kind)
if mojom.IsMapKind(kind):
- return "Map<%s, %s>" % (
- self._ClosureType(kind.key_kind), self._ClosureType(kind.value_kind))
+ return "Map<%s, %s>" % (self._ClosureType(
+ kind.key_kind), self._ClosureType(kind.value_kind))
if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(kind):
return "mojo.InterfaceRequest"
# TODO(calamity): Support associated interfaces properly.
- if (mojom.IsAssociatedInterfaceKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind)):
+ if (mojom.IsAssociatedInterfaceKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)):
return "mojo.AssociatedInterfacePtrInfo"
# TODO(calamity): Support associated interface requests properly.
- if (mojom.IsAssociatedInterfaceRequestKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
+ if (mojom.IsAssociatedInterfaceRequestKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
return "mojo.AssociatedInterfaceRequest"
# TODO(calamity): Support enums properly.
@@ -445,93 +515,147 @@ class Generator(generator.Generator):
# Indicates whether a kind of suitable to stringify and use as an Object
# property name. This is checked for map key types to allow most kinds of
# mojom maps to be represented as either a Map or an Object.
- return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind) or
- mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind) or
- mojom.IsEnumKind(kind))
-
- def _LiteClosureType(self, kind):
- if kind in mojom.PRIMITIVES:
- return _kind_to_closure_type[kind]
- if mojom.IsArrayKind(kind):
- return "Array<%s>" % self._LiteClosureTypeWithNullability(kind.kind)
- if mojom.IsMapKind(kind) and self._IsStringableKind(kind.key_kind):
- return "Object<%s, %s>" % (
- self._LiteClosureTypeWithNullability(kind.key_kind),
- self._LiteClosureTypeWithNullability(kind.value_kind))
- if mojom.IsMapKind(kind):
- return "Map<%s, %s>" % (
- self._LiteClosureTypeWithNullability(kind.key_kind),
- self._LiteClosureTypeWithNullability(kind.value_kind))
-
- if (mojom.IsAssociatedKind(kind) or mojom.IsInterfaceRequestKind(kind) or
- mojom.IsPendingRemoteKind(kind) or mojom.IsPendingReceiverKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
- named_kind = kind.kind
- else:
- named_kind = kind
-
- name = []
- if named_kind.module:
- name.append(named_kind.module.namespace)
- if named_kind.parent_kind:
- name.append(named_kind.parent_kind.name)
+ if kind == mojom.INT64 or kind == mojom.UINT64:
+ # JS BigInts are not stringable and cannot be used as Object property
+ # names.
+ return False
+ return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind)
+ or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind)
+ or mojom.IsEnumKind(kind))
+
+ def _GetTypeNameForNewBindings(self,
+ kind,
+ with_nullability=False,
+ for_module=False):
+ def recurse_with_nullability(kind):
+ return self._GetTypeNameForNewBindings(kind,
+ with_nullability=True,
+ for_module=for_module)
+
+ def get_type_name(kind):
+ if kind == mojom.INT64 or kind == mojom.UINT64:
+ return "bigint"
+ if kind in mojom.PRIMITIVES:
+ return _kind_to_closure_type[kind]
+ if mojom.IsArrayKind(kind):
+ return "Array<%s>" % recurse_with_nullability(kind.kind)
+ if mojom.IsMapKind(kind) and self._IsStringableKind(kind.key_kind):
+ return "Object<%s, %s>" % (recurse_with_nullability(
+ kind.key_kind), recurse_with_nullability(kind.value_kind))
+ if mojom.IsMapKind(kind):
+ return "Map<%s, %s>" % (recurse_with_nullability(
+ kind.key_kind), recurse_with_nullability(kind.value_kind))
+
+ if (mojom.IsAssociatedKind(kind) or mojom.IsInterfaceRequestKind(kind)
+ or mojom.IsPendingRemoteKind(kind)
+ or mojom.IsPendingReceiverKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
+ named_kind = kind.kind
+ else:
+ named_kind = kind
- if mojom.IsEnumKind(kind) and named_kind.parent_kind:
- name = ".".join(name)
- name += "_" + named_kind.name
- else:
- name.append("" + named_kind.name)
- name = ".".join(name)
+ name = []
+ qualified = (not for_module) or (self.module is not named_kind.module)
+ if qualified and named_kind.module:
+ name.append(named_kind.module.namespace)
+ if named_kind.parent_kind:
+ name.append(named_kind.parent_kind.name)
+
+ if mojom.IsEnumKind(kind) and named_kind.parent_kind:
+ name = ".".join(name)
+ name += "_" + named_kind.name
+ else:
+ name.append("" + named_kind.name)
+ name = ".".join(name)
+
+ if for_module:
+ name = name.replace(".", "_")
+
+ if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind)
+ or mojom.IsEnumKind(kind)):
+ return name
+ if mojom.IsInterfaceKind(kind) or mojom.IsPendingRemoteKind(kind):
+ return name + "Remote"
+ if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(
+ kind):
+ return name + "PendingReceiver"
+ # TODO(calamity): Support associated interfaces properly.
+ if (mojom.IsAssociatedInterfaceKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)):
+ return "Object"
+ # TODO(calamity): Support associated interface requests properly.
+ if (mojom.IsAssociatedInterfaceRequestKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
+ return "Object"
+ raise Exception("No valid closure type: %s" % kind)
+
+ if with_nullability:
+ return ('?' if mojom.IsNullableKind(kind) else '!') + get_type_name(kind)
+
+ return get_type_name(kind)
- if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or
- mojom.IsEnumKind(kind)):
- return name
- if mojom.IsInterfaceKind(kind) or mojom.IsPendingRemoteKind(kind):
- return name + "Remote"
- if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(kind):
- return name + "PendingReceiver"
- # TODO(calamity): Support associated interfaces properly.
- if (mojom.IsAssociatedInterfaceKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind)):
- return "Object"
- # TODO(calamity): Support associated interface requests properly.
- if (mojom.IsAssociatedInterfaceRequestKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
- return "Object"
+ def _LiteClosureType(self, kind):
+ return self._GetTypeNameForNewBindings(kind,
+ with_nullability=False,
+ for_module=False)
- raise Exception("No valid closure type: %s" % kind)
+ def _GetTypeInJsModule(self, kind):
+ return self._GetTypeNameForNewBindings(kind,
+ with_nullability=False,
+ for_module=True)
def _ClosureTypeWithNullability(self, kind):
return ("" if mojom.IsNullableKind(kind) else "!") + self._ClosureType(kind)
+ def _GetParamTypeNameForNewBindings(self, kind, for_module=False):
+ def get_type_name(kind):
+ if mojom.IsEnumKind(kind):
+ return "number"
+ prefix = "" if mojom.IsNullableKind(kind) else "!"
+ if mojom.IsArrayKind(kind):
+ return prefix + ("Array<%s>" % get_type_name(kind.kind))
+ if mojom.IsMapKind(kind) and self._IsStringableKind(kind.key_kind):
+ return "(%sMap<%s, %s>|%sObject<%s, %s>)" % (
+ prefix, get_type_name(kind.key_kind), get_type_name(
+ kind.value_kind), prefix, get_type_name(
+ kind.key_kind), get_type_name(kind.value_kind))
+ if mojom.IsMapKind(kind):
+ return "{}Map<{}, {}>".format(prefix, get_type_name(kind.key_kind),
+ get_type_name(kind.value_kind))
+ return prefix + self._GetTypeNameForNewBindings(kind,
+ for_module=for_module)
+
+ return get_type_name(kind)
+
def _LiteClosureParamType(self, kind):
- if mojom.IsEnumKind(kind):
- return "number"
- prefix = "" if mojom.IsNullableKind(kind) else "!"
- if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
- return prefix + "Object"
- if mojom.IsArrayKind(kind):
- return prefix + ("Array<%s>" %
- self._LiteClosureParamType(kind.kind))
- if mojom.IsMapKind(kind):
- return "%sMap<%s, %s>|%sObject<%s, %s>" % (
- prefix, self._LiteClosureParamType(kind.key_kind),
- self._LiteClosureParamType(kind.value_kind),
- prefix, self._LiteClosureParamType(kind.key_kind),
- self._LiteClosureParamType(kind.value_kind))
+ return self._GetParamTypeNameForNewBindings(kind, for_module=False)
- return prefix + self._LiteClosureType(kind)
+ def _GetParamTypeInJsModule(self, kind):
+ return self._GetParamTypeNameForNewBindings(kind, for_module=True)
def _LiteClosureTypeWithNullability(self, kind):
- return (("?" if mojom.IsNullableKind(kind) else "!") +
- self._LiteClosureType(kind))
+ return self._GetTypeNameForNewBindings(kind,
+ with_nullability=True,
+ for_module=False)
- def _LiteClosureFieldType(self, kind):
+ def _GetTypeInJsModuleWithNullability(self, kind):
+ return self._GetTypeNameForNewBindings(kind,
+ with_nullability=True,
+ for_module=True)
+
+ def _GetFieldTypeForNewBindings(self, kind, for_module=False):
if mojom.IsNullableKind(kind):
- return "(" + self._LiteClosureType(kind) + "|undefined)"
+ return "({}|undefined)".format(
+ self._GetTypeNameForNewBindings(kind, for_module=for_module))
else:
- return "!" + self._LiteClosureType(kind)
+ return "!" + self._GetTypeNameForNewBindings(kind, for_module=for_module)
+
+ def _LiteClosureFieldType(self, kind):
+ return self._GetFieldTypeForNewBindings(kind, for_module=False)
+
+ def _GetFieldTypeInJsModule(self, kind):
+ return self._GetFieldTypeForNewBindings(kind, for_module=True)
def _NamespaceDeclarations(self, namespace):
pieces = namespace.split('.')
@@ -542,6 +666,35 @@ class Generator(generator.Generator):
declarations.append('.'.join(declaration))
return declarations
+ def _GetNameInJsModule(self, kind):
+ qualifier = ""
+ if kind.module is not self.module and kind.module.namespace:
+ qualifier = kind.module.namespace + '.'
+ if kind.parent_kind:
+ qualifier += kind.parent_kind.name + '.'
+ return (qualifier + kind.name).replace('.', '_')
+
+ def _GetImportsForKind(self, kind):
+ qualified_name = self._GetNameInJsModule(kind)
+
+ def make_import(name, suffix=''):
+ class ImportInfo(object):
+ def __init__(self, name, alias):
+ self.name = name
+ self.alias = alias
+
+ return ImportInfo(name + suffix, qualified_name + suffix)
+
+ if (mojom.IsEnumKind(kind) or mojom.IsStructKind(kind)
+ or mojom.IsUnionKind(kind)):
+ return [make_import(kind.name), make_import(kind.name, 'Spec')]
+ if mojom.IsInterfaceKind(kind):
+ return [
+ make_import(kind.name, 'Remote'),
+ make_import(kind.name, 'PendingReceiver')
+ ]
+ assert False, kind.name
+
def _JavaScriptType(self, kind):
name = []
if kind.module and kind.module.path != self.module.path:
@@ -551,55 +704,67 @@ class Generator(generator.Generator):
name.append(kind.name)
return ".".join(name)
+ def _GetSpecType(self, kind, for_module=False):
+ def get_spec(kind):
+ if self._IsPrimitiveKind(kind):
+ return _kind_to_lite_js_type[kind]
+ if mojom.IsArrayKind(kind):
+ return "mojo.internal.Array(%s, %s)" % (get_spec(
+ kind.kind), "true" if mojom.IsNullableKind(kind.kind) else "false")
+ if mojom.IsMapKind(kind):
+ return "mojo.internal.Map(%s, %s, %s)" % (
+ get_spec(kind.key_kind), get_spec(kind.value_kind),
+ "true" if mojom.IsNullableKind(kind.value_kind) else "false")
+
+ if (mojom.IsAssociatedKind(kind) or mojom.IsInterfaceRequestKind(kind)
+ or mojom.IsPendingRemoteKind(kind)
+ or mojom.IsPendingReceiverKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
+ named_kind = kind.kind
+ else:
+ named_kind = kind
+
+ name = []
+ qualified = (not for_module) or (self.module is not named_kind.module)
+ if qualified and named_kind.module:
+ name.append(named_kind.module.namespace)
+ if named_kind.parent_kind:
+ parent_name = named_kind.parent_kind.name
+ if mojom.IsStructKind(named_kind.parent_kind) and not for_module:
+ parent_name += "Spec"
+ name.append(parent_name)
+ name.append(named_kind.name)
+ name = ".".join(name)
+ if for_module:
+ name = name.replace(".", "_")
+
+ if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind)
+ or mojom.IsEnumKind(kind)):
+ return "%sSpec.$" % name
+ if mojom.IsInterfaceKind(kind) or mojom.IsPendingRemoteKind(kind):
+ return "mojo.internal.InterfaceProxy(%sRemote)" % name
+ if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(
+ kind):
+ return "mojo.internal.InterfaceRequest(%sPendingReceiver)" % name
+ if (mojom.IsAssociatedInterfaceKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)):
+ # TODO(rockot): Implement associated interfaces.
+ return "mojo.internal.AssociatedInterfaceProxy(%sRemote)" % (name)
+ if (mojom.IsAssociatedInterfaceRequestKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
+ return "mojo.internal.AssociatedInterfaceRequest(%sPendingReceiver)" % (
+ name)
+
+ return name
+
+ return get_spec(kind)
+
def _LiteJavaScriptType(self, kind):
- if self._IsPrimitiveKind(kind):
- return _kind_to_lite_js_type[kind]
- if mojom.IsArrayKind(kind):
- return "mojo.internal.Array(%s, %s)" % (
- self._LiteJavaScriptType(kind.kind),
- "true" if mojom.IsNullableKind(kind.kind) else "false")
- if mojom.IsMapKind(kind):
- return "mojo.internal.Map(%s, %s, %s)" % (
- self._LiteJavaScriptType(kind.key_kind),
- self._LiteJavaScriptType(kind.value_kind),
- "true" if mojom.IsNullableKind(kind.value_kind) else "false")
-
- if (mojom.IsAssociatedKind(kind) or mojom.IsInterfaceRequestKind(kind) or
- mojom.IsPendingRemoteKind(kind) or mojom.IsPendingReceiverKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
- named_kind = kind.kind
- else:
- named_kind = kind
+ return self._GetSpecType(kind, for_module=False)
- name = []
- if named_kind.module:
- name.append(named_kind.module.namespace)
- if named_kind.parent_kind:
- parent_name = named_kind.parent_kind.name
- if mojom.IsStructKind(named_kind.parent_kind):
- parent_name += "Spec"
- name.append(parent_name)
- name.append(named_kind.name)
- name = ".".join(name)
-
- if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or
- mojom.IsEnumKind(kind)):
- return "%sSpec.$" % name
- if mojom.IsInterfaceKind(kind) or mojom.IsPendingRemoteKind(kind):
- return "mojo.internal.InterfaceProxy(%sRemote)" % name
- if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(kind):
- return "mojo.internal.InterfaceRequest(%sPendingReceiver)" % name
- if (mojom.IsAssociatedInterfaceKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind)):
- # TODO(rockot): Implement associated interfaces.
- return "mojo.internal.AssociatedInterfaceProxy(%sRemote)" % (name)
- if (mojom.IsAssociatedInterfaceRequestKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
- return "mojo.internal.AssociatedInterfaceRequest(%sPendingReceiver)" % (
- name)
-
- return name
+ def _GetSpecTypeInJsModule(self, kind):
+ return self._GetSpecType(kind, for_module=True)
def _LiteJavaScriptImportName(self, kind):
name = []
@@ -630,31 +795,39 @@ class Generator(generator.Generator):
return "new %sPtr()" % self._JavaScriptType(field.kind)
if mojom.IsPendingRemoteKind(field.kind):
return "new %sPtr()" % self._JavaScriptType(field.kind.kind)
- if (mojom.IsInterfaceRequestKind(field.kind) or
- mojom.IsPendingReceiverKind(field.kind)):
+ if (mojom.IsInterfaceRequestKind(field.kind)
+ or mojom.IsPendingReceiverKind(field.kind)):
return "new bindings.InterfaceRequest()"
- if (mojom.IsAssociatedInterfaceKind(field.kind) or
- mojom.IsPendingAssociatedRemoteKind(field.kind)):
+ if (mojom.IsAssociatedInterfaceKind(field.kind)
+ or mojom.IsPendingAssociatedRemoteKind(field.kind)):
return "new associatedBindings.AssociatedInterfacePtrInfo()"
- if (mojom.IsAssociatedInterfaceRequestKind(field.kind) or
- mojom.IsPendingAssociatedReceiverKind(field.kind)):
+ if (mojom.IsAssociatedInterfaceRequestKind(field.kind)
+ or mojom.IsPendingAssociatedReceiverKind(field.kind)):
return "new associatedBindings.AssociatedInterfaceRequest()"
if mojom.IsEnumKind(field.kind):
return "0"
raise Exception("No valid default: %s" % field)
- def _LiteJavaScriptDefaultValue(self, field):
+ def _GetDefaultValue(self, field, for_module=False):
if field.default:
if mojom.IsStructKind(field.kind):
assert field.default == "default"
- return "null";
- return self._ExpressionToTextLite(field.default)
+ return "null"
+ return self._ExpressionToTextLite(field.default, for_module=for_module)
+ if field.kind == mojom.INT64 or field.kind == mojom.UINT64:
+ return "BigInt(0)"
if field.kind in mojom.PRIMITIVES:
return _kind_to_javascript_default_value[field.kind]
if mojom.IsEnumKind(field.kind):
return "0"
return "null"
+ def _LiteJavaScriptDefaultValue(self, field):
+ return self._GetDefaultValue(field, for_module=False)
+
+ def _DefaultValueInJsModule(self, field):
+ return self._GetDefaultValue(field, for_module=True)
+
def _CodecType(self, kind):
if kind in mojom.PRIMITIVES:
return _kind_to_codec_type[kind]
@@ -665,8 +838,8 @@ class Generator(generator.Generator):
if mojom.IsUnionKind(kind):
return self._JavaScriptType(kind)
if mojom.IsArrayKind(kind):
- array_type = ("NullableArrayOf" if mojom.IsNullableKind(kind)
- else "ArrayOf")
+ array_type = ("NullableArrayOf"
+ if mojom.IsNullableKind(kind) else "ArrayOf")
array_length = "" if kind.length is None else ", %d" % kind.length
element_type = self._ElementCodecType(kind.kind)
return "new codec.%s(%s%s)" % (array_type, element_type, array_length)
@@ -679,17 +852,18 @@ class Generator(generator.Generator):
"NullableInterface" if mojom.IsNullableKind(kind) else "Interface",
self._JavaScriptType(kind.kind))
if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(kind):
- return "codec.%s" % (
- "NullableInterfaceRequest" if mojom.IsNullableKind(kind)
- else "InterfaceRequest")
- if (mojom.IsAssociatedInterfaceKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind)):
+ return "codec.%s" % ("NullableInterfaceRequest" if
+ mojom.IsNullableKind(kind) else "InterfaceRequest")
+ if (mojom.IsAssociatedInterfaceKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)):
return "codec.%s" % ("NullableAssociatedInterfacePtrInfo"
- if mojom.IsNullableKind(kind) else "AssociatedInterfacePtrInfo")
- if (mojom.IsAssociatedInterfaceRequestKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
+ if mojom.IsNullableKind(kind) else
+ "AssociatedInterfacePtrInfo")
+ if (mojom.IsAssociatedInterfaceRequestKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
return "codec.%s" % ("NullableAssociatedInterfaceRequest"
- if mojom.IsNullableKind(kind) else "AssociatedInterfaceRequest")
+ if mojom.IsNullableKind(kind) else
+ "AssociatedInterfaceRequest")
if mojom.IsEnumKind(kind):
return "new codec.Enum(%s)" % self._JavaScriptType(kind)
if mojom.IsMapKind(kind):
@@ -700,19 +874,18 @@ class Generator(generator.Generator):
raise Exception("No codec type for %s" % kind)
def _ElementCodecType(self, kind):
- return ("codec.PackedBool" if mojom.IsBoolKind(kind)
- else self._CodecType(kind))
+ return ("codec.PackedBool"
+ if mojom.IsBoolKind(kind) else self._CodecType(kind))
def _JavaScriptDecodeSnippet(self, kind):
- if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind) or
- mojom.IsAnyInterfaceKind(kind)):
+ if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind)
+ or mojom.IsAnyInterfaceKind(kind)):
return "decodeStruct(%s)" % self._CodecType(kind)
if mojom.IsStructKind(kind):
return "decodeStructPointer(%s)" % self._JavaScriptType(kind)
if mojom.IsMapKind(kind):
- return "decodeMapPointer(%s, %s)" % (
- self._ElementCodecType(kind.key_kind),
- self._ElementCodecType(kind.value_kind))
+ return "decodeMapPointer(%s, %s)" % (self._ElementCodecType(
+ kind.key_kind), self._ElementCodecType(kind.value_kind))
if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
return "decodeArrayPointer(codec.PackedBool)"
if mojom.IsArrayKind(kind):
@@ -724,19 +897,18 @@ class Generator(generator.Generator):
raise Exception("No decode snippet for %s" % kind)
def _JavaScriptEncodeSnippet(self, kind):
- if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind) or
- mojom.IsAnyInterfaceKind(kind)):
+ if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind)
+ or mojom.IsAnyInterfaceKind(kind)):
return "encodeStruct(%s, " % self._CodecType(kind)
if mojom.IsUnionKind(kind):
return "encodeStruct(%s, " % self._JavaScriptType(kind)
if mojom.IsStructKind(kind):
return "encodeStructPointer(%s, " % self._JavaScriptType(kind)
if mojom.IsMapKind(kind):
- return "encodeMapPointer(%s, %s, " % (
- self._ElementCodecType(kind.key_kind),
- self._ElementCodecType(kind.value_kind))
+ return "encodeMapPointer(%s, %s, " % (self._ElementCodecType(
+ kind.key_kind), self._ElementCodecType(kind.value_kind))
if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
- return "encodeArrayPointer(codec.PackedBool, ";
+ return "encodeArrayPointer(codec.PackedBool, "
if mojom.IsArrayKind(kind):
return "encodeArrayPointer(%s, " % self._CodecType(kind.kind)
if mojom.IsEnumKind(kind):
@@ -760,8 +932,7 @@ class Generator(generator.Generator):
nullable = self._JavaScriptNullableParam(field)
element_kind = field.kind.kind
element_size = pack.PackedField.GetSizeForKind(element_kind)
- expected_dimension_sizes = GetArrayExpectedDimensionSizes(
- field.kind)
+ expected_dimension_sizes = GetArrayExpectedDimensionSizes(field.kind)
element_type = self._ElementCodecType(element_kind)
return "%s, %s, %s, %s, 0" % \
(element_size, element_type, nullable,
@@ -783,7 +954,7 @@ class Generator(generator.Generator):
def _JavaScriptValidateMapParams(self, field):
nullable = self._JavaScriptNullableParam(field)
keys_type = self._ElementCodecType(field.kind.key_kind)
- values_kind = field.kind.value_kind;
+ values_kind = field.kind.value_kind
values_type = self._ElementCodecType(values_kind)
values_nullable = "true" if mojom.IsNullableKind(values_kind) else "false"
return "%s, %s, %s, %s" % \
@@ -811,23 +982,24 @@ class Generator(generator.Generator):
if isinstance(token, mojom.BuiltinValue):
if token.value == "double.INFINITY" or token.value == "float.INFINITY":
- return "Infinity";
+ return "Infinity"
if token.value == "double.NEGATIVE_INFINITY" or \
token.value == "float.NEGATIVE_INFINITY":
- return "-Infinity";
+ return "-Infinity"
if token.value == "double.NAN" or token.value == "float.NAN":
- return "NaN";
+ return "NaN"
return token
- def _ExpressionToTextLite(self, token):
+ def _ExpressionToTextLite(self, token, for_module=False):
if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
# Generate the following for:
# - Enums: NamespaceUid.Enum.CONSTANT_NAME
# - Struct: NamespaceUid.Struct_CONSTANT_NAME
name_prefix = []
- if token.module:
+ qualified = (not for_module) or (token.module is not self.module)
+ if token.module and qualified:
name_prefix.append(token.module.namespace)
if token.parent_kind:
name_prefix.append(token.parent_kind.name)
@@ -838,20 +1010,72 @@ class Generator(generator.Generator):
name.append(token.name)
separator = "."
- if mojom.IsStructKind(token.parent_kind):
+ if mojom.IsStructKind(token.parent_kind) or for_module:
separator = "_"
return ".".join(name_prefix) + separator + ".".join(name)
return self._ExpressionToText(token)
+ def _GetConstantValue(self, constant, for_module=False):
+ assert isinstance(constant, mojom.Constant)
+ text = self._ExpressionToTextLite(constant.value, for_module=for_module)
+ if constant.kind == mojom.INT64 or constant.kind == mojom.UINT64:
+ return "BigInt('{}')".format(text)
+ return text
+
+ def _GetConstantValueInJsModule(self, constant):
+ return self._GetConstantValue(constant, for_module=True)
+
def _GenerateHtmlImports(self):
result = []
for full_import in self.module.imports:
- result.append(os.path.relpath(full_import.path,
- os.path.dirname(self.module.path)))
+ result.append(
+ os.path.relpath(full_import.path, os.path.dirname(self.module.path)))
return result
+ def _GetJsModuleImports(self, for_webui_module=False):
+ this_module_path = _GetWebUiModulePath(self.module)
+ this_module_is_shared = bool(
+ this_module_path and this_module_path.startswith(_SHARED_MODULE_PREFIX))
+ imports = dict()
+ for spec, kind in self.module.imported_kinds.items():
+ if for_webui_module:
+ assert this_module_path is not None
+ base_path = _GetWebUiModulePath(kind.module)
+ assert base_path is not None
+ import_path = '{}{}-webui.js'.format(base_path,
+ os.path.basename(kind.module.path))
+ import_module_is_shared = import_path.startswith(_SHARED_MODULE_PREFIX)
+ if import_module_is_shared == this_module_is_shared:
+ # Either we're a non-shared resource importing another non-shared
+ # resource, or we're a shared resource importing another shared
+ # resource. In both cases, we assume a relative import path will
+ # suffice.
+ def strip_prefix(s, prefix):
+ if s.startswith(prefix):
+ return s[len(prefix):]
+ return s
+
+ import_path = urllib_request.pathname2url(
+ os.path.relpath(
+ strip_prefix(import_path, _SHARED_MODULE_PREFIX),
+ strip_prefix(this_module_path, _SHARED_MODULE_PREFIX)))
+ if (not import_path.startswith('.')
+ and not import_path.startswith('/')):
+ import_path = './' + import_path
+ else:
+ assert import_module_is_shared, \
+ 'Shared WebUI module "{}" cannot depend on non-shared WebUI ' \
+ 'module "{}"'.format(self.module.path, kind.module.path)
+ else:
+ import_path = self._GetRelativePath(kind.module.path) + '.m.js'
+
+ if import_path not in imports:
+ imports[import_path] = []
+ imports[import_path].append(kind)
+ return imports
+
def _GetStructsFromMethods(self):
result = []
for interface in self.module.interfaces:
@@ -863,20 +1087,17 @@ class Generator(generator.Generator):
def _FuzzHandleName(self, kind):
if mojom.IsInterfaceRequestKind(kind) or mojom.IsPendingReceiverKind(kind):
- return '{0}.{1}Request'.format(kind.kind.module.namespace,
- kind.kind.name)
+ return '{0}.{1}Request'.format(kind.kind.module.namespace, kind.kind.name)
elif mojom.IsInterfaceKind(kind):
- return '{0}.{1}Ptr'.format(kind.module.namespace,
- kind.name)
+ return '{0}.{1}Ptr'.format(kind.module.namespace, kind.name)
elif mojom.IsPendingRemoteKind(kind):
- return '{0}.{1}Ptr'.format(kind.kind.module.namespace,
- kind.kind.name)
- elif (mojom.IsAssociatedInterfaceRequestKind(kind) or
- mojom.IsPendingAssociatedReceiverKind(kind)):
+ return '{0}.{1}Ptr'.format(kind.kind.module.namespace, kind.kind.name)
+ elif (mojom.IsAssociatedInterfaceRequestKind(kind)
+ or mojom.IsPendingAssociatedReceiverKind(kind)):
return '{0}.{1}AssociatedRequest'.format(kind.kind.module.namespace,
kind.kind.name)
- elif (mojom.IsAssociatedInterfaceKind(kind) or
- mojom.IsPendingAssociatedRemoteKind(kind)):
+ elif (mojom.IsAssociatedInterfaceKind(kind)
+ or mojom.IsPendingAssociatedRemoteKind(kind)):
return '{0}.{1}AssociatedPtr'.format(kind.kind.module.namespace,
kind.kind.name)
elif mojom.IsSharedBufferKind(kind):
diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni
index a676fae5d22..8106c57ea0c 100644
--- a/chromium/mojo/public/tools/bindings/mojom.gni
+++ b/chromium/mojo/public/tools/bindings/mojom.gni
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/python.gni")
import("//third_party/closure_compiler/closure_args.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//third_party/protobuf/proto_library.gni")
@@ -77,7 +78,6 @@ mojom_parser_sources = [
"$_mojom_library_root/__init__.py",
"$_mojom_library_root/error.py",
"$_mojom_library_root/generate/__init__.py",
- "$_mojom_library_root/generate/constant_resolver.py",
"$_mojom_library_root/generate/generator.py",
"$_mojom_library_root/generate/module.py",
"$_mojom_library_root/generate/pack.py",
@@ -291,6 +291,21 @@ if (enable_scrambled_message_ids) {
# List of extra C++ templates that are used to generate additional source
# and/or header files. The templates should end with extension ".tmpl".
#
+# webui_module_path (optional)
+# The path or URL at which modules generated by this target will be
+# accessible to WebUI pages. This may either be an absolute path or
+# a full URL path starting with "chrome://resources/mojo".
+#
+# If an absolute path, a WebUI page may only import these modules if
+# they are manually packaged and mapped independently by that page's
+# WebUIDataSource. The mapped path must match the path given here.
+#
+# If this is is instead a URL string starting with
+# "chrome://resources/mojo", the generated resources must be added to
+# content_resources.grd and registered with
+# content::SharedResourcesDataSource with a corresponding path, at which
+# point they will be made available to all WebUI pages at the given URL.
+#
# The following parameters are used to support the component build. They are
# needed so that bindings which are linked with a component can use the same
# export settings for classes. The first three are for the chromium variant, and
@@ -500,12 +515,6 @@ template("mojom") {
sources_list = invoker.sources
}
- # Reset sources_assignment_filter for the BUILD.gn file to prevent
- # regression during the migration of Chromium away from the feature.
- # See docs/no_sources_assignment_filter.md for more information.
- # TODO(crbug.com/1018739): remove this when migration is done.
- set_sources_assignment_filter([])
-
# Listed sources may be relative to the current target dir, or they may be
# absolute paths, including paths to generated mojom files. While those are
# fine as-is for input references, deriving output paths can be more subtle.
@@ -621,7 +630,8 @@ template("mojom") {
enabled_features += [ "is_win" ]
}
- action(parser_target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(parser_target_name) {
script = mojom_parser_script
inputs = mojom_parser_sources + [ build_metadata_filename ]
sources = sources_list
@@ -643,7 +653,7 @@ template("mojom") {
# Resolve relative input mojom paths against both the root src dir and
# the root gen dir.
"--input-root",
- rebase_path("//"),
+ rebase_path("//."),
"--input-root",
rebase_path(root_gen_dir),
@@ -662,6 +672,13 @@ template("mojom") {
enabled_feature,
]
}
+
+ if (defined(invoker.webui_module_path)) {
+ args += [
+ "--add-module-metadata",
+ "webui_module_path=${invoker.webui_module_path}",
+ ]
+ }
}
}
@@ -731,7 +748,8 @@ template("mojom") {
}
}
- action(generator_cpp_message_ids_target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_cpp_message_ids_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = sources_list
@@ -770,7 +788,9 @@ template("mojom") {
}
generator_shared_target_name = "${target_name}_shared__generator"
- action(generator_shared_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_shared_target_name) {
visibility = [ ":*" ]
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
@@ -889,7 +909,9 @@ template("mojom") {
generator_mojolpm_proto_target_name =
"${target_name}_mojolpm_proto_generator"
- action(generator_mojolpm_proto_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_mojolpm_proto_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = invoker.sources
@@ -1078,7 +1100,9 @@ template("mojom") {
]
generator_target_name = "${target_name}${variant_suffix}__generator"
- action(generator_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_target_name) {
visibility = [ ":*" ]
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
@@ -1258,7 +1282,9 @@ template("mojom") {
}
write_file(_typemap_config_filename, _rebased_typemap_configs, "json")
_mojom_target_name = target_name
- action(_typemap_validator_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(_typemap_validator_target_name) {
script = "$mojom_generator_root/validate_typemap_config.py"
inputs = [ _typemap_config_filename ]
outputs = [ _typemap_stamp_filename ]
@@ -1269,7 +1295,8 @@ template("mojom") {
]
}
- action(type_mappings_target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(type_mappings_target_name) {
inputs =
mojom_generator_sources + jinja2_sources + [ _typemap_stamp_filename ]
outputs = [ type_mappings_path ]
@@ -1319,6 +1346,10 @@ template("mojom") {
full_name = get_label_info("$d", "label_no_toolchain")
public_deps += [ "${full_name}${variant_suffix}_headers" ]
}
+ if (defined(bindings_configuration.for_blink) &&
+ bindings_configuration.for_blink) {
+ public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ]
+ }
}
if (!force_source_set && defined(invoker.component_macro_prefix)) {
@@ -1438,7 +1469,8 @@ template("mojom") {
java_generator_target_name = target_name + "_java__generator"
if (sources_list != []) {
- action(java_generator_target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(java_generator_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = sources_list
@@ -1477,7 +1509,9 @@ template("mojom") {
}
java_srcjar_target_name = target_name + "_java_sources"
- action(java_srcjar_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(java_srcjar_target_name) {
script = "//build/android/gyp/zip.py"
inputs = []
if (output_file_base_paths != []) {
@@ -1536,7 +1570,9 @@ template("mojom") {
!use_typescript_for_target) {
if (sources_list != []) {
generator_js_target_name = "${target_name}_js__generator"
- action(generator_js_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_js_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = sources_list
@@ -1557,10 +1593,15 @@ template("mojom") {
outputs += [
"$root_gen_dir/$base_path.js",
"$root_gen_dir/$base_path.externs.js",
+ "$root_gen_dir/$base_path.m.js",
"$root_gen_dir/$base_path-lite.js",
"$root_gen_dir/$base_path.html",
"$root_gen_dir/$base_path-lite-for-compile.js",
]
+
+ if (defined(invoker.webui_module_path)) {
+ outputs += [ "$root_gen_dir/mojom-webui/$base_path-webui.js" ]
+ }
}
response_file_contents = filelist
@@ -1609,13 +1650,19 @@ template("mojom") {
foreach(base_path, output_file_base_paths) {
data += [
"$root_gen_dir/${base_path}.js",
+ "$root_gen_dir/${base_path}.m.js",
"$root_gen_dir/${base_path}-lite.js",
]
}
deps += [ ":$generator_js_target_name" ]
}
- data_deps = []
+ if (defined(invoker.disallow_native_types) &&
+ invoker.disallow_native_types) {
+ data_deps = []
+ } else {
+ data_deps = [ "//mojo/public/js:bindings_module" ]
+ }
foreach(d, all_deps) {
full_name = get_label_info(d, "label_no_toolchain")
data_deps += [ "${full_name}_js_data_deps" ]
@@ -1671,6 +1718,64 @@ template("mojom") {
group(js_library_for_compile_target_name) {
}
}
+
+ js_modules_target_name = "${target_name}_js_modules"
+ if (sources_list != []) {
+ js_library(js_modules_target_name) {
+ extra_public_deps = [ ":$generator_js_target_name" ]
+ sources = []
+ foreach(base_path, output_file_base_paths) {
+ sources += [ "$root_gen_dir/${base_path}.m.js" ]
+ }
+ externs_list = [
+ "${externs_path}/mojo_core.js",
+ "${externs_path}/pending.js",
+ ]
+ if (defined(invoker.disallow_native_types) &&
+ invoker.disallow_native_types) {
+ deps = []
+ } else {
+ deps = [ "//mojo/public/js:bindings_uncompiled" ]
+ }
+ foreach(d, all_deps) {
+ full_name = get_label_info(d, "label_no_toolchain")
+ deps += [ "${full_name}_js_modules" ]
+ }
+ }
+ } else {
+ group(js_modules_target_name) {
+ }
+ }
+
+ if (defined(invoker.webui_module_path)) {
+ webui_js_target_name = "${target_name}_webui_js"
+ if (sources_list != []) {
+ js_library(webui_js_target_name) {
+ extra_public_deps = [ ":$generator_js_target_name" ]
+ sources = []
+ foreach(base_path, output_file_base_paths) {
+ sources += [ "$root_gen_dir/mojom-webui/${base_path}-webui.js" ]
+ }
+ externs_list = [
+ "${externs_path}/mojo_core.js",
+ "${externs_path}/pending.js",
+ ]
+ if (defined(invoker.disallow_native_types) &&
+ invoker.disallow_native_types) {
+ deps = []
+ } else {
+ deps = [ "//mojo/public/js:bindings_uncompiled" ]
+ }
+ foreach(d, all_deps) {
+ full_name = get_label_info(d, "label_no_toolchain")
+ deps += [ "${full_name}_webui_js" ]
+ }
+ }
+ } else {
+ group(webui_js_target_name) {
+ }
+ }
+ }
}
if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) &&
use_typescript_for_target) {
@@ -1707,7 +1812,9 @@ template("mojom") {
# Generate Typescript bindings.
generator_ts_target_name =
"${target_name}_${dependency_type.name}__ts__generator"
- action(generator_ts_target_name) {
+
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_ts_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = sources_list
@@ -1774,7 +1881,8 @@ template("mojom") {
"${target_name}_${dependency_type.name}__js__generator"
generator_js_target_names += [ generator_js_target_name ]
- action(generator_js_target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(generator_js_target_name) {
script = "$mojom_generator_root/compile_typescript.py"
sources = ts_outputs
outputs = js_outputs
diff --git a/chromium/mojo/public/tools/mojom/mojom/BUILD.gn b/chromium/mojo/public/tools/mojom/mojom/BUILD.gn
index 7416ef19e3e..51facc0ccb8 100644
--- a/chromium/mojo/public/tools/mojom/mojom/BUILD.gn
+++ b/chromium/mojo/public/tools/mojom/mojom/BUILD.gn
@@ -8,7 +8,6 @@ group("mojom") {
"error.py",
"fileutil.py",
"generate/__init__.py",
- "generate/constant_resolver.py",
"generate/generator.py",
"generate/module.py",
"generate/pack.py",
diff --git a/chromium/mojo/public/tools/mojom/mojom/generate/constant_resolver.py b/chromium/mojo/public/tools/mojom/mojom/generate/constant_resolver.py
deleted file mode 100644
index 0dfd996e355..00000000000
--- a/chromium/mojo/public/tools/mojom/mojom/generate/constant_resolver.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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.
-"""Resolves the values used for constants and enums."""
-
-from itertools import ifilter
-
-from mojom.generate import module as mojom
-
-
-def ResolveConstants(module, expression_to_text):
- in_progress = set()
- computed = set()
-
- def GetResolvedValue(named_value):
- assert isinstance(named_value, (mojom.EnumValue, mojom.ConstantValue))
- if isinstance(named_value, mojom.EnumValue):
- field = next(
- ifilter(lambda field: field.name == named_value.name,
- named_value.enum.fields), None)
- if not field:
- raise RuntimeError(
- 'Unable to get computed value for field %s of enum %s' %
- (named_value.name, named_value.enum.name))
- if field not in computed:
- ResolveEnum(named_value.enum)
- return field.resolved_value
- else:
- ResolveConstant(named_value.constant)
- named_value.resolved_value = named_value.constant.resolved_value
- return named_value.resolved_value
-
- def ResolveConstant(constant):
- if constant in computed:
- return
- if constant in in_progress:
- raise RuntimeError('Circular dependency for constant: %s' % constant.name)
- in_progress.add(constant)
- if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
- resolved_value = GetResolvedValue(constant.value)
- else:
- resolved_value = expression_to_text(constant.value)
- constant.resolved_value = resolved_value
- in_progress.remove(constant)
- computed.add(constant)
-
- def ResolveEnum(enum):
- def ResolveEnumField(enum, field, default_value):
- if field in computed:
- return
- if field in in_progress:
- raise RuntimeError('Circular dependency for enum: %s' % enum.name)
- in_progress.add(field)
- if field.value:
- if isinstance(field.value, mojom.EnumValue):
- resolved_value = GetResolvedValue(field.value)
- elif isinstance(field.value, str):
- resolved_value = int(field.value, 0)
- else:
- raise RuntimeError('Unexpected value: %s' % field.value)
- else:
- resolved_value = default_value
- field.resolved_value = resolved_value
- in_progress.remove(field)
- computed.add(field)
-
- current_value = 0
- for field in enum.fields:
- ResolveEnumField(enum, field, current_value)
- current_value = field.resolved_value + 1
-
- for constant in module.constants:
- ResolveConstant(constant)
-
- for enum in module.enums:
- ResolveEnum(enum)
-
- for struct in module.structs:
- for constant in struct.constants:
- ResolveConstant(constant)
- for enum in struct.enums:
- ResolveEnum(enum)
- for field in struct.fields:
- if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
- field.default.resolved_value = GetResolvedValue(field.default)
-
- for interface in module.interfaces:
- for constant in interface.constants:
- ResolveConstant(constant)
- for enum in interface.enums:
- ResolveEnum(enum)
-
- return module
diff --git a/chromium/mojo/public/tools/mojom/mojom/generate/module.py b/chromium/mojo/public/tools/mojom/mojom/generate/module.py
index ebbc9b322ea..e76f66a8d24 100644
--- a/chromium/mojo/public/tools/mojom/mojom/generate/module.py
+++ b/chromium/mojo/public/tools/mojom/mojom/generate/module.py
@@ -13,6 +13,7 @@
# method.AddParameter('baz', 0, mojom.INT32)
import pickle
+from uuid import UUID
class BackwardCompatibilityChecker(object):
@@ -286,6 +287,7 @@ ATTRIBUTE_EXTENSIBLE = 'Extensible'
ATTRIBUTE_STABLE = 'Stable'
ATTRIBUTE_SYNC = 'Sync'
ATTRIBUTE_UNLIMITED_SIZE = 'UnlimitedSize'
+ATTRIBUTE_UUID = 'Uuid'
class NamedValue(object):
@@ -1188,6 +1190,20 @@ class Interface(ReferenceKind):
self.attributes) == (rhs.mojom_name, rhs.methods, rhs.enums,
rhs.constants, rhs.attributes))
+ @property
+ def uuid(self):
+ uuid_str = self.attributes.get(ATTRIBUTE_UUID) if self.attributes else None
+ if uuid_str is None:
+ return None
+
+ try:
+ u = UUID(uuid_str)
+ except:
+ raise ValueError('Invalid format for Uuid attribute on interface {}. '
+ 'Expected standard RFC 4122 string representation of '
+ 'a UUID.'.format(self.mojom_name))
+ return (int(u.hex[:16], 16), int(u.hex[16:], 16))
+
def __hash__(self):
return id(self)
@@ -1346,6 +1362,7 @@ class Module(object):
self.attributes = attributes
self.imports = []
self.imported_kinds = {}
+ self.metadata = {}
def __repr__(self):
# Gives us a decent __repr__ for modules.
diff --git a/chromium/mojo/public/tools/mojom/mojom_parser.py b/chromium/mojo/public/tools/mojom/mojom_parser.py
index 12adbfb9d3f..998304c3c99 100755
--- a/chromium/mojo/public/tools/mojom/mojom_parser.py
+++ b/chromium/mojo/public/tools/mojom/mojom_parser.py
@@ -98,7 +98,7 @@ def _GetModuleFilename(mojom_filename):
def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
- dependencies, loaded_modules):
+ dependencies, loaded_modules, module_metadata):
"""Recursively ensures that a module and its dependencies are loaded.
Args:
@@ -111,10 +111,8 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
by absolute file path.
loaded_modules: A mapping of all modules loaded so far, including non-input
modules that were pulled in as transitive dependencies of the inputs.
- import_set: The working set of mojom imports processed so far in this
- call stack. Used to detect circular dependencies.
- import_stack: An ordered list of imports processed so far in this call
- stack. Used to report circular dependencies.
+ module_metadata: Metadata to be attached to every module loaded by this
+ helper.
Returns:
None
@@ -129,7 +127,7 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
for dep_abspath, dep_path in dependencies[mojom_abspath]:
if dep_abspath not in loaded_modules:
_EnsureInputLoaded(dep_abspath, dep_path, abs_paths, asts, dependencies,
- loaded_modules)
+ loaded_modules, module_metadata)
imports = {}
for imp in asts[mojom_abspath].import_list:
@@ -137,6 +135,7 @@ def _EnsureInputLoaded(mojom_abspath, module_path, abs_paths, asts,
imports[path] = loaded_modules[abs_paths[path]]
loaded_modules[mojom_abspath] = translate.OrderedModule(
asts[mojom_abspath], module_path, imports)
+ loaded_modules[mojom_abspath].metadata = dict(module_metadata)
def _CollectAllowedImportsFromBuildMetadata(build_metadata_filename):
@@ -161,6 +160,7 @@ def _ParseMojoms(mojom_files,
input_root_paths,
output_root_path,
enabled_features,
+ module_metadata,
allowed_imports=None):
"""Parses a set of mojom files and produces serialized module outputs.
@@ -176,6 +176,8 @@ def _ParseMojoms(mojom_files,
modules for any transitive dependencies not listed in mojom_files.
enabled_features: A list of enabled feature names, controlling which AST
nodes are filtered by [EnableIf] attributes.
+ module_metadata: A list of 2-tuples representing metadata key-value pairs to
+ attach to each compiled module output.
Returns:
None.
@@ -236,7 +238,7 @@ def _ParseMojoms(mojom_files,
num_existing_modules_loaded = len(loaded_modules)
for mojom_abspath, mojom_path in mojom_files_to_parse.items():
_EnsureInputLoaded(mojom_abspath, mojom_path, abs_paths, loaded_mojom_asts,
- input_dependencies, loaded_modules)
+ input_dependencies, loaded_modules, module_metadata)
assert (num_existing_modules_loaded +
len(mojom_files_to_parse) == len(loaded_modules))
@@ -333,6 +335,16 @@ already present in the provided output root.""")
'build-time dependency checking for mojom imports, where each build '
'metadata file corresponds to a build target in the dependency graph of '
'a typical build system.')
+ arg_parser.add_argument(
+ '--add-module-metadata',
+ dest='module_metadata',
+ default=[],
+ action='append',
+ metavar='KEY=VALUE',
+ help='Adds a metadata key-value pair to the output module. This can be '
+ 'used by build toolchains to augment parsed mojom modules with product-'
+ 'specific metadata for later extraction and use by custom bindings '
+ 'generators.')
args, _ = arg_parser.parse_known_args(command_line)
if args.mojom_file_list:
@@ -353,8 +365,9 @@ already present in the provided output root.""")
else:
allowed_imports = None
+ module_metadata = map(lambda kvp: tuple(kvp.split('=')), args.module_metadata)
_ParseMojoms(mojom_files, input_roots, output_root, args.enabled_features,
- allowed_imports)
+ module_metadata, allowed_imports)
if __name__ == '__main__':