summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrockot <rockot@chromium.org>2015-04-10 15:53:32 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-10 22:53:53 +0000
commitc4010b0b30bb37e0a6916c3fb8eb97d44b024292 (patch)
treed1a6a6d53a98c81c80137c34c28a34c0312bf808
parentf67e4665f60197fa7aa06b3213eea5fbe716d8dd (diff)
downloadchromium_src-c4010b0b30bb37e0a6916c3fb8eb97d44b024292.zip
chromium_src-c4010b0b30bb37e0a6916c3fb8eb97d44b024292.tar.gz
chromium_src-c4010b0b30bb37e0a6916c3fb8eb97d44b024292.tar.bz2
Update mojo sdk to rev d459e688a608f6eda850a23bb5e308a76ea51a47
BUG=None TBR=jamesr@chromium.org Review URL: https://codereview.chromium.org/1051303002 Cr-Commit-Position: refs/heads/master@{#324704}
-rw-r--r--content/browser/geolocation/geolocation_service_impl.cc8
-rw-r--r--content/browser/presentation/presentation_service_impl.cc68
-rw-r--r--content/browser/presentation/presentation_service_impl.h25
-rw-r--r--third_party/mojo/mojom_bindings_generator.gypi1
-rw-r--r--third_party/mojo/mojom_bindings_generator_explicit.gypi1
-rw-r--r--third_party/mojo/src/mojo/public/BUILD.gn1
-rw-r--r--third_party/mojo/src/mojo/public/VERSION2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn21
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/array_internal.h21
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/array_serialization.h81
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h12
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/connector.h3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/router.cc10
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/router.h7
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/template_util.h4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/message.h33
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc301
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/router_unittest.cc14
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc1
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc286
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc10
-rw-r--r--third_party/mojo/src/mojo/public/go/application/application_impl.go167
-rw-r--r--third_party/mojo/src/mojo/public/go/application/connection.go174
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/decoder.go3
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/encoder.go2
-rw-r--r--third_party/mojo/src/mojo/public/go/system/message_pipe.go2
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/application/BUILD.gn4
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/BUILD.gn11
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/interface_control_messages.mojom89
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.data (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.data)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.expected (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.expected)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.data5
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.data6
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.data7
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.data7
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.data6
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.data6
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.data6
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.expected1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom19
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom1
-rw-r--r--third_party/mojo/src/mojo/public/js/validation_unittests.js22
-rw-r--r--third_party/mojo/src/mojo/public/tools/BUILD.gn22
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl66
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl9
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl10
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl16
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl7
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl15
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl5
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl20
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl14
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl5
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl31
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl32
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl28
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py8
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py29
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/mojom.gni28
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py2
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/dart_analyze.py5
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/gn/zip.py2
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/mojom_fetcher/mojom_fetcher.py196
-rw-r--r--third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/__init__.py0
-rw-r--r--third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/dependency.py97
-rw-r--r--third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/mojom_file.py18
-rw-r--r--third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/repository.py88
-rw-r--r--third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/content_handler/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom2
-rw-r--r--third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn4
-rw-r--r--third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn2
-rw-r--r--third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn2
99 files changed, 2057 insertions, 217 deletions
diff --git a/content/browser/geolocation/geolocation_service_impl.cc b/content/browser/geolocation/geolocation_service_impl.cc
index ffea846..7747cc4 100644
--- a/content/browser/geolocation/geolocation_service_impl.cc
+++ b/content/browser/geolocation/geolocation_service_impl.cc
@@ -69,6 +69,14 @@ GeolocationServiceImpl::GeolocationServiceImpl(
}
GeolocationServiceImpl::~GeolocationServiceImpl() {
+ // Make sure to respond to any pending callback even without a valid position.
+ if (!position_callback_.is_null()) {
+ if (!current_position_.valid) {
+ current_position_.error_code = MojoGeoposition::ErrorCode(
+ GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE);
+ }
+ ReportCurrentPosition();
+ }
}
void GeolocationServiceImpl::PauseUpdates() {
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index 9e2fd22..2d6769e 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -25,6 +25,7 @@ PresentationServiceImpl::PresentationServiceImpl(
: WebContentsObserver(web_contents),
render_frame_host_(render_frame_host),
delegate_(delegate),
+ is_start_session_pending_(false),
next_request_session_id_(0),
weak_factory_(this) {
DCHECK(render_frame_host_);
@@ -39,6 +40,7 @@ PresentationServiceImpl::PresentationServiceImpl(
PresentationServiceImpl::~PresentationServiceImpl() {
if (delegate_)
delegate_->RemoveObserver(this);
+ FlushNewSessionCallbacks();
}
// static
@@ -146,10 +148,13 @@ void PresentationServiceImpl::StartSession(
return;
}
- queued_start_session_requests_.push_back(make_linked_ptr(
- new StartSessionRequest(presentation_url, presentation_id, callback)));
- if (queued_start_session_requests_.size() == 1)
- DoStartSession(presentation_url, presentation_id, callback);
+ if (is_start_session_pending_) {
+ queued_start_session_requests_.push_back(make_linked_ptr(
+ new StartSessionRequest(presentation_url, presentation_id, callback)));
+ return;
+ }
+
+ DoStartSession(presentation_url, presentation_id, callback);
}
void PresentationServiceImpl::JoinSession(
@@ -175,15 +180,16 @@ void PresentationServiceImpl::JoinSession(
}
void PresentationServiceImpl::HandleQueuedStartSessionRequests() {
- DCHECK(!queued_start_session_requests_.empty());
- queued_start_session_requests_.pop_front();
- if (!queued_start_session_requests_.empty()) {
- const linked_ptr<StartSessionRequest>& request =
- queued_start_session_requests_.front();
- DoStartSession(request->presentation_url,
- request->presentation_id,
- request->callback);
+ if (queued_start_session_requests_.empty()) {
+ is_start_session_pending_ = false;
+ return;
}
+ linked_ptr<StartSessionRequest> request =
+ queued_start_session_requests_.front();
+ queued_start_session_requests_.pop_front();
+ DoStartSession(request->presentation_url(),
+ request->presentation_id(),
+ request->PassCallback());
}
int PresentationServiceImpl::RegisterNewSessionCallback(
@@ -194,11 +200,19 @@ int PresentationServiceImpl::RegisterNewSessionCallback(
return next_request_session_id_;
}
+void PresentationServiceImpl::FlushNewSessionCallbacks() {
+ for (auto& pending_entry : pending_session_cbs_) {
+ InvokeNewSessionMojoCallbackWithError(*pending_entry.second);
+ }
+ pending_session_cbs_.clear();
+}
+
void PresentationServiceImpl::DoStartSession(
const std::string& presentation_url,
const std::string& presentation_id,
const NewSessionMojoCallback& callback) {
int request_session_id = RegisterNewSessionCallback(callback);
+ is_start_session_pending_ = true;
delegate_->StartSession(
render_frame_host_->GetProcess()->GetID(),
render_frame_host_->GetRoutingID(),
@@ -361,20 +375,12 @@ void PresentationServiceImpl::Reset() {
default_presentation_url_.clear();
default_presentation_id_.clear();
- for (const auto& context_entry : availability_contexts_) {
- context_entry.second->OnScreenAvailabilityChanged(false);
- }
availability_contexts_.clear();
- for (auto& request_ptr : queued_start_session_requests_) {
- InvokeNewSessionMojoCallbackWithError(request_ptr->callback);
- }
queued_start_session_requests_.clear();
- for (auto& pending_entry : pending_session_cbs_) {
- InvokeNewSessionMojoCallbackWithError(*pending_entry.second);
- }
- pending_session_cbs_.clear();
+ FlushNewSessionCallbacks();
}
+// static
void PresentationServiceImpl::InvokeNewSessionMojoCallbackWithError(
const NewSessionMojoCallback& callback) {
callback.Run(
@@ -396,6 +402,8 @@ PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext(
PresentationServiceImpl::ScreenAvailabilityContext::
~ScreenAvailabilityContext() {
+ // Ensure that pending callbacks are flushed.
+ OnScreenAvailabilityChanged(false);
}
void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived(
@@ -452,12 +460,22 @@ PresentationServiceImpl::StartSessionRequest::StartSessionRequest(
const std::string& presentation_url,
const std::string& presentation_id,
const NewSessionMojoCallback& callback)
- : presentation_url(presentation_url),
- presentation_id(presentation_id),
- callback(callback) {
+ : presentation_url_(presentation_url),
+ presentation_id_(presentation_id),
+ callback_(callback) {
}
PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() {
+ // Ensure that a pending callback is not dropped.
+ if (!callback_.is_null())
+ InvokeNewSessionMojoCallbackWithError(callback_);
+}
+
+PresentationServiceImpl::NewSessionMojoCallback
+PresentationServiceImpl::StartSessionRequest::PassCallback() {
+ NewSessionMojoCallback callback = callback_;
+ callback_.reset();
+ return callback;
}
} // namespace content
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h
index 5b4972d..84962e7 100644
--- a/content/browser/presentation/presentation_service_impl.h
+++ b/content/browser/presentation/presentation_service_impl.h
@@ -110,15 +110,24 @@ class CONTENT_EXPORT PresentationServiceImpl
};
// Context for a StartSession request.
- struct CONTENT_EXPORT StartSessionRequest {
+ class CONTENT_EXPORT StartSessionRequest {
+ public:
StartSessionRequest(const std::string& presentation_url,
const std::string& presentation_id,
const NewSessionMojoCallback& callback);
~StartSessionRequest();
- const std::string presentation_url;
- const std::string presentation_id;
- const NewSessionMojoCallback callback;
+ // Retrieves the pending callback from this request, transferring ownership
+ // to the caller.
+ NewSessionMojoCallback PassCallback();
+
+ const std::string& presentation_url() const { return presentation_url_; }
+ const std::string& presentation_id() const { return presentation_id_; }
+
+ private:
+ const std::string presentation_url_;
+ const std::string presentation_id_;
+ NewSessionMojoCallback callback_;
};
friend class PresentationServiceImplTest;
@@ -235,8 +244,11 @@ class CONTENT_EXPORT PresentationServiceImpl
int RegisterNewSessionCallback(
const NewSessionMojoCallback& callback);
+ // Flushes all pending new session callbacks with error responses.
+ void FlushNewSessionCallbacks();
+
// Invokes |callback| with an error.
- void InvokeNewSessionMojoCallbackWithError(
+ static void InvokeNewSessionMojoCallbackWithError(
const NewSessionMojoCallback& callback);
// Gets the ScreenAvailabilityContext for |presentation_url|, or creates one
@@ -259,6 +271,9 @@ class CONTENT_EXPORT PresentationServiceImpl
// it is removed from head of the queue.
std::deque<linked_ptr<StartSessionRequest>> queued_start_session_requests_;
+ // Indicates that a StartSession request is currently being processed.
+ bool is_start_session_pending_;
+
int next_request_session_id_;
base::hash_map<int, linked_ptr<NewSessionMojoCallback>> pending_session_cbs_;
diff --git a/third_party/mojo/mojom_bindings_generator.gypi b/third_party/mojo/mojom_bindings_generator.gypi
index e18ab05..948ce059 100644
--- a/third_party/mojo/mojom_bindings_generator.gypi
+++ b/third_party/mojo/mojom_bindings_generator.gypi
@@ -57,6 +57,7 @@
'<@(mojom_import_args)',
'-o', '<(SHARED_INTERMEDIATE_DIR)',
'--java_output_directory=<(java_out_dir)',
+ '--dart_mojo_root=//third_party/mojo/src',
],
'message': 'Generating Mojo bindings from <(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
'process_outputs_as_sources': 1,
diff --git a/third_party/mojo/mojom_bindings_generator_explicit.gypi b/third_party/mojo/mojom_bindings_generator_explicit.gypi
index f65ec3e..3d2d80b 100644
--- a/third_party/mojo/mojom_bindings_generator_explicit.gypi
+++ b/third_party/mojo/mojom_bindings_generator_explicit.gypi
@@ -60,6 +60,7 @@
'<@(mojom_import_args)',
'-o', '<(SHARED_INTERMEDIATE_DIR)',
'--java_output_directory=<(java_out_dir)',
+ '--dart_mojo_root=//third_party/mojo/src',
],
'message': 'Generating Mojo bindings from <@(mojom_files)',
}
diff --git a/third_party/mojo/src/mojo/public/BUILD.gn b/third_party/mojo/src/mojo/public/BUILD.gn
index 9ee041e..576625f 100644
--- a/third_party/mojo/src/mojo/public/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/BUILD.gn
@@ -38,6 +38,7 @@ group("sdk") {
"cpp/environment:standalone",
"cpp/utility",
"interfaces/application",
+ "interfaces/bindings",
"js",
]
}
diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION
index 6979599..ba0a3bc 100644
--- a/third_party/mojo/src/mojo/public/VERSION
+++ b/third_party/mojo/src/mojo/public/VERSION
@@ -1 +1 @@
-912f52f69dadbe1e3cf9576f26731863770bcfc3 \ No newline at end of file
+d459e688a608f6eda850a23bb5e308a76ea51a47 \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
index 2dac828..f6a9b1b 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
@@ -9,16 +9,9 @@ mojo_sdk_source_set("bindings") {
"array.h",
"binding.h",
"error_handler.h",
- "interface_ptr_info.h",
"interface_ptr.h",
- "map.h",
- "message.h",
- "message_filter.h",
- "no_interface.h",
- "strong_binding.h",
- "string.h",
- "struct_ptr.h",
- "type_converter.h",
+ "interface_ptr_info.h",
+ "interface_request.h",
"lib/array_internal.cc",
"lib/array_internal.h",
"lib/array_serialization.h",
@@ -55,6 +48,14 @@ mojo_sdk_source_set("bindings") {
"lib/validate_params.h",
"lib/validation_errors.cc",
"lib/validation_errors.h",
+ "map.h",
+ "message.h",
+ "message_filter.h",
+ "no_interface.h",
+ "string.h",
+ "strong_binding.h",
+ "struct_ptr.h",
+ "type_converter.h",
]
deps = [
@@ -71,9 +72,9 @@ mojo_sdk_source_set("callback") {
sources = [
"callback.h",
"lib/callback_internal.h",
- "lib/template_util.h",
"lib/shared_data.h",
"lib/shared_ptr.h",
+ "lib/template_util.h",
]
mojo_sdk_deps = [ "mojo/public/cpp/system" ]
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_internal.h
index eb25e35..f56319b 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_internal.h
@@ -285,8 +285,13 @@ struct ArraySerializationHelper<P*, false> {
}
private:
+ template <typename T,
+ typename Params,
+ bool is_union = IsUnionDataType<T>::value>
+ struct ValidateCaller {};
+
template <typename T, typename Params>
- struct ValidateCaller {
+ struct ValidateCaller<T, Params, false> {
static bool Run(const void* data, BoundsChecker* bounds_checker) {
static_assert((IsSame<Params, NoValidateParams>::value),
"Struct type should not have array validate params");
@@ -295,8 +300,18 @@ struct ArraySerializationHelper<P*, false> {
}
};
+ template <typename T, typename Params>
+ struct ValidateCaller<T, Params, true> {
+ static bool Run(const void* data, BoundsChecker* bounds_checker) {
+ static_assert((IsSame<Params, NoValidateParams>::value),
+ "Union type should not have array validate params");
+
+ return T::Validate(data, bounds_checker, true);
+ }
+ };
+
template <typename Key, typename Value, typename Params>
- struct ValidateCaller<Map_Data<Key, Value>, Params> {
+ struct ValidateCaller<Map_Data<Key, Value>, Params, false> {
static bool Run(const void* data, BoundsChecker* bounds_checker) {
return Map_Data<Key, Value>::template Validate<Params>(data,
bounds_checker);
@@ -304,7 +319,7 @@ struct ArraySerializationHelper<P*, false> {
};
template <typename T, typename Params>
- struct ValidateCaller<Array_Data<T>, Params> {
+ struct ValidateCaller<Array_Data<T>, Params, false> {
static bool Run(const void* data, BoundsChecker* bounds_checker) {
return Array_Data<T>::template Validate<Params>(data, bounds_checker);
}
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_serialization.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_serialization.h
index eacf298..827cb3f 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_serialization.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -45,11 +45,16 @@ inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output);
namespace internal {
-template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value>
+template <typename E,
+ typename F,
+ bool move_only = IsMoveOnlyType<E>::value,
+ bool is_union =
+ IsUnionDataType<typename RemovePointer<F>::type>::value>
struct ArraySerializer;
+// Handles serialization and deserialization of arrays of pod types.
template <typename E, typename F>
-struct ArraySerializer<E, F, false> {
+struct ArraySerializer<E, F, false, false> {
static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer");
static size_t GetSerializedSize(const Array<E>& input) {
return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E));
@@ -74,8 +79,9 @@ struct ArraySerializer<E, F, false> {
}
};
+// Serializes and deserializes arrays of bools.
template <>
-struct ArraySerializer<bool, bool, false> {
+struct ArraySerializer<bool, bool, false, false> {
static size_t GetSerializedSize(const Array<bool>& input) {
return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8);
}
@@ -102,8 +108,9 @@ struct ArraySerializer<bool, bool, false> {
}
};
+// Serializes and deserializes arrays of handles.
template <typename H>
-struct ArraySerializer<ScopedHandleBase<H>, H, true> {
+struct ArraySerializer<ScopedHandleBase<H>, H, true, false> {
static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) {
return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H));
}
@@ -137,17 +144,17 @@ struct ArraySerializer<ScopedHandleBase<H>, H, true> {
// This template must only apply to pointer mojo entity (structs and arrays).
// This is done by ensuring that WrapperTraits<S>::DataType is a pointer.
template <typename S>
-struct ArraySerializer<S,
- typename internal::EnableIf<
- internal::IsPointer<typename internal::WrapperTraits<
- S>::DataType>::value,
- typename internal::WrapperTraits<S>::DataType>::type,
- true> {
- typedef typename internal::RemovePointer<
- typename internal::WrapperTraits<S>::DataType>::type S_Data;
+struct ArraySerializer<
+ S,
+ typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value,
+ typename WrapperTraits<S>::DataType>::type,
+ true,
+ false> {
+ typedef
+ typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data;
static size_t GetSerializedSize(const Array<S>& input) {
size_t size = sizeof(Array_Data<S_Data*>) +
- input.size() * sizeof(internal::StructPointer<S_Data>);
+ input.size() * sizeof(StructPointer<S_Data>);
for (size_t i = 0; i < input.size(); ++i)
size += GetSerializedSize_(input[i]);
return size;
@@ -172,9 +179,7 @@ struct ArraySerializer<S,
Array<S>* output) {
Array<S> result(input->size());
for (size_t i = 0; i < input->size(); ++i) {
- S element;
- Deserialize_(input->at(i), &element);
- result[i] = element.Pass();
+ Deserialize_(input->at(i), &result[i]);
}
output->Swap(&result);
}
@@ -184,7 +189,7 @@ struct ArraySerializer<S,
struct SerializeCaller {
static void Run(T input,
Buffer* buf,
- typename internal::WrapperTraits<T>::DataType* output) {
+ typename WrapperTraits<T>::DataType* output) {
static_assert((IsSame<Params, NoValidateParams>::value),
"Struct type should not have array validate params");
@@ -211,11 +216,49 @@ struct ArraySerializer<S,
};
};
+// Handles serialization and deserialization of arrays of unions.
+template <typename U, typename U_Data>
+struct ArraySerializer<U, U_Data, true, true> {
+ static size_t GetSerializedSize(const Array<U>& input) {
+ size_t size = sizeof(Array_Data<U_Data>);
+ for (size_t i = 0; i < input.size(); ++i) {
+ // GetSerializedSize_ will account for both the data in the union and the
+ // space in the array used to hold the union.
+ size += GetSerializedSize_(input[i], false);
+ }
+ return size;
+ }
+
+ template <bool element_is_nullable, typename ElementValidateParams>
+ static void SerializeElements(Array<U> input,
+ Buffer* buf,
+ Array_Data<U_Data>* output) {
+ for (size_t i = 0; i < input.size(); ++i) {
+ U_Data* result = output->storage() + i;
+ SerializeUnion_(input[i].Pass(), buf, &result, true);
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !element_is_nullable && output->at(i).is_null(),
+ VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ MakeMessageWithArrayIndex("null in array expecting valid unions",
+ input.size(), i));
+ }
+ }
+
+ static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) {
+ Array<U> result(input->size());
+ for (size_t i = 0; i < input->size(); ++i) {
+ Deserialize_(&input->at(i), &result[i]);
+ }
+ output->Swap(&result);
+ }
+};
+
+// Handles serialization and deserialization of arrays of strings.
template <>
struct ArraySerializer<String, String_Data*, false> {
static size_t GetSerializedSize(const Array<String>& input) {
- size_t size = sizeof(Array_Data<String_Data*>) +
- input.size() * sizeof(internal::StringPointer);
+ size_t size =
+ sizeof(Array_Data<String_Data*>) + input.size() * sizeof(StringPointer);
for (size_t i = 0; i < input.size(); ++i)
size += GetSerializedSize_(input[i]);
return size;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
index a8f95b2..4b5bb49 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -76,6 +76,18 @@ struct IsHandle {
enum { value = IsBaseOf<Handle, H>::value };
};
+template <typename T>
+struct IsUnionDataType {
+ template <typename U>
+ static YesType Test(const typename U::MojomUnionDataType*);
+
+ template <typename U>
+ static NoType Test(...);
+
+ static const bool value =
+ sizeof(Test<T>(0)) == sizeof(YesType) && !IsConst<T>::value;
+};
+
template <typename T, bool move_only = IsMoveOnlyType<T>::value>
struct WrapperTraits;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/connector.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/connector.h
index 7c1d445..dfbd514 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/connector.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/connector.h
@@ -63,6 +63,9 @@ class Connector : public MessageReceiver {
// a quiescent state.
ScopedMessagePipeHandle PassMessagePipe();
+ // Is the connector bound to a MessagePipe handle?
+ bool is_valid() const { return message_pipe_.is_valid(); }
+
// Waits for the next message on the pipe, blocking until one arrives or an
// error happens. Returns |true| if a message has been delivered, |false|
// otherwise.
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.cc
index da1e7e1..e64f1fa 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.cc
@@ -11,7 +11,7 @@ namespace internal {
// ----------------------------------------------------------------------------
-class ResponderThunk : public MessageReceiver {
+class ResponderThunk : public MessageReceiverWithStatus {
public:
explicit ResponderThunk(const SharedData<Router*>& router)
: router_(router), accept_was_invoked_(false) {}
@@ -44,6 +44,12 @@ class ResponderThunk : public MessageReceiver {
return result;
}
+ // MessageReceiverWithStatus implementation:
+ bool IsValid() override {
+ Router* router = router_.value();
+ return router && !router->encountered_error() && router->is_valid();
+ }
+
private:
SharedData<Router*> router_;
bool accept_was_invoked_;
@@ -118,7 +124,7 @@ void Router::EnableTestingMode() {
bool Router::HandleIncomingMessage(Message* message) {
if (message->has_flag(kMessageExpectsResponse)) {
if (incoming_receiver_) {
- MessageReceiver* responder = new ResponderThunk(weak_self_);
+ MessageReceiverWithStatus* responder = new ResponderThunk(weak_self_);
bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
if (!ok)
delete responder;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.h
index 8254bab..86b8897 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/router.h
@@ -24,7 +24,7 @@ class Router : public MessageReceiverWithResponder {
// Sets the receiver to handle messages read from the message pipe that do
// not have the kMessageIsResponse flag set.
- void set_incoming_receiver(MessageReceiverWithResponder* receiver) {
+ void set_incoming_receiver(MessageReceiverWithResponderStatus* receiver) {
incoming_receiver_ = receiver;
}
@@ -38,6 +38,9 @@ class Router : public MessageReceiverWithResponder {
// waiting to read from the pipe.
bool encountered_error() const { return connector_.encountered_error(); }
+ // Is the router bound to a MessagePipe handle?
+ bool is_valid() const { return connector_.is_valid(); }
+
void CloseMessagePipe() { connector_.CloseMessagePipe(); }
ScopedMessagePipeHandle PassMessagePipe() {
@@ -81,7 +84,7 @@ class Router : public MessageReceiverWithResponder {
FilterChain filters_;
Connector connector_;
SharedData<Router*> weak_self_;
- MessageReceiverWithResponder* incoming_receiver_;
+ MessageReceiverWithResponderStatus* incoming_receiver_;
ResponderMap responders_;
uint64_t next_request_id_;
bool testing_mode_;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/template_util.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/template_util.h
index a90ee44..9a5788c 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/template_util.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/template_util.h
@@ -100,7 +100,9 @@ struct IsBaseOf {
};
template <class T>
-struct RemovePointer {};
+struct RemovePointer {
+ typedef T type;
+};
template <class T>
struct RemovePointer<T*> {
typedef T type;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
index 0ae4eca..15c2d3d 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.cc
@@ -40,6 +40,8 @@ const char* ValidationErrorToString(ValidationError error) {
return "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION";
case VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID:
return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID";
+ case VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD:
+ return "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD";
case VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP:
return "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP";
case VALIDATION_ERROR_UNKNOWN_UNION_TAG:
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
index d09f63b..da93598 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -44,6 +44,8 @@ enum ValidationError {
// |flags| in the message header indicates that a request ID is required but
// there isn't one.
VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID,
+ // The |name| field in a message header contains an unexpected value.
+ VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD,
// Two parallel arrays which are supposed to represent a map have different
// lengths.
VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP,
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/message.h b/third_party/mojo/src/mojo/public/cpp/bindings/message.h
index 80cd6d5..b763d9a 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/message.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/message.h
@@ -106,6 +106,39 @@ class MessageReceiverWithResponder : public MessageReceiver {
MOJO_WARN_UNUSED_RESULT = 0;
};
+// A MessageReceiver that is also able to provide status about the state
+// of the underlying MessagePipe to which it will be forwarding messages
+// received via the |Accept()| call.
+class MessageReceiverWithStatus : public MessageReceiver {
+ public:
+ ~MessageReceiverWithStatus() override {}
+
+ // Returns |true| if this MessageReceiver is currently bound to a MessagePipe,
+ // the pipe has not been closed, and the pipe has not encountered an error.
+ virtual bool IsValid() = 0;
+};
+
+// An alternative to MessageReceiverWithResponder for cases in which it
+// is necessary for the implementor of this interface to know about the status
+// of the MessagePipe which will carry the responses.
+class MessageReceiverWithResponderStatus : public MessageReceiver {
+ public:
+ ~MessageReceiverWithResponderStatus() override {}
+
+ // A variant on Accept that registers a MessageReceiverWithStatus (known as
+ // the responder) to handle the response message generated from the given
+ // message. Any of the responder's methods (Accept or IsValid) may be called
+ // during AcceptWithResponder or some time after its return.
+ //
+ // NOTE: Upon returning true, AcceptWithResponder assumes ownership of
+ // |responder| and will delete it after calling |responder->Accept| or upon
+ // its own destruction.
+ //
+ virtual bool AcceptWithResponder(Message* message,
+ MessageReceiverWithStatus* responder)
+ MOJO_WARN_UNUSED_RESULT = 0;
+};
+
// Read a single message from the pipe and dispatch to the given receiver. The
// receiver may be null, in which case the message is simply discarded.
// Returns MOJO_RESULT_SHOULD_WAIT if the caller should wait on the handle to
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
index 6d09151..46c2e50 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -9,6 +9,7 @@ mojo_sdk_source_set("tests") {
sources = [
"array_unittest.cc",
+ "binding_callback_unittest.cc",
"binding_unittest.cc",
"bounds_checker_unittest.cc",
"buffer_unittest.cc",
@@ -26,7 +27,6 @@ mojo_sdk_source_set("tests") {
"string_unittest.cc",
"struct_unittest.cc",
"type_conversion_unittest.cc",
- "union_unittest.cc",
"validation_unittest.cc",
]
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc
new file mode 100644
index 0000000..19e36b7
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc
@@ -0,0 +1,301 @@
+// 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.
+
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/test_support/test_support.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// The tests in this file are designed to test the interaction between a
+// Callback and its associated Binding. If a Callback is deleted before
+// being used we DCHECK fail--unless the associated Binding has already
+// been closed or deleted. This contract must be explained to the Mojo
+// application developer. For example it is the developer's responsibility to
+// ensure that the Binding is destroyed before an unused Callback is destroyed.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+namespace mojo {
+namespace test {
+namespace {
+
+// A Runnable object that saves the last value it sees via the
+// provided int32_t*. Used on the client side.
+class ValueSaver {
+ public:
+ explicit ValueSaver(int32_t* last_value_seen)
+ : last_value_seen_(last_value_seen) {}
+ void Run(int32_t x) const { *last_value_seen_ = x; }
+
+ private:
+ int32_t* const last_value_seen_;
+};
+
+// An implementation of sample::Provider used on the server side.
+// It only implements one of the methods: EchoInt().
+// All it does is save the values and Callbacks it sees.
+class InterfaceImpl : public sample::Provider {
+ public:
+ InterfaceImpl()
+ : last_server_value_seen_(0),
+ callback_saved_(new Callback<void(int32_t)>()) {}
+
+ ~InterfaceImpl() override {
+ if (callback_saved_) {
+ delete callback_saved_;
+ }
+ }
+
+ // Run's the callback previously saved from the last invocation
+ // of |EchoInt()|.
+ bool RunCallback() {
+ if (callback_saved_) {
+ callback_saved_->Run(last_server_value_seen_);
+ return true;
+ }
+ return false;
+ }
+
+ // Delete's the previously saved callback.
+ void DeleteCallback() {
+ delete callback_saved_;
+ callback_saved_ = nullptr;
+ }
+
+ // sample::Provider implementation
+
+ // Saves its two input values in member variables and does nothing else.
+ void EchoInt(int32_t x, const Callback<void(int32_t)>& callback) override {
+ last_server_value_seen_ = x;
+ *callback_saved_ = callback;
+ }
+
+ void EchoString(const String& a,
+ const Callback<void(String)>& callback) override {
+ MOJO_CHECK(false) << "Not implemented.";
+ }
+
+ void EchoStrings(const String& a,
+ const String& b,
+ const Callback<void(String, String)>& callback) override {
+ MOJO_CHECK(false) << "Not implemented.";
+ }
+
+ void EchoMessagePipeHandle(
+ ScopedMessagePipeHandle a,
+ const Callback<void(ScopedMessagePipeHandle)>& callback) override {
+ MOJO_CHECK(false) << "Not implemented.";
+ }
+
+ void EchoEnum(sample::Enum a,
+ const Callback<void(sample::Enum)>& callback) override {
+ MOJO_CHECK(false) << "Not implemented.";
+ }
+
+ void resetLastServerValueSeen() { last_server_value_seen_ = 0; }
+
+ int32_t last_server_value_seen() const { return last_server_value_seen_; }
+
+ private:
+ int32_t last_server_value_seen_;
+ Callback<void(int32_t)>* callback_saved_;
+};
+
+class BindingCallbackTest : public testing::Test {
+ public:
+ ~BindingCallbackTest() override {}
+
+ protected:
+ int32_t last_client_callback_value_seen_;
+ sample::ProviderPtr interface_ptr_;
+
+ void PumpMessages() { loop_.RunUntilIdle(); }
+
+ private:
+ Environment env_;
+ RunLoop loop_;
+};
+
+// Tests that the InterfacePtr and the Binding can communicate with each
+// other normally.
+TEST_F(BindingCallbackTest, Basic) {
+ // Create the ServerImpl and the Binding.
+ InterfaceImpl server_impl;
+ Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
+
+ // Initialize the test values.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method.
+ interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(7, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Now run the Callback.
+ server_impl.RunCallback();
+ PumpMessages();
+
+ // Check that the client has now seen the correct value.
+ EXPECT_EQ(7, last_client_callback_value_seen_);
+
+ // Initialize the test values again.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method again.
+ interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(13, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Now run the Callback again.
+ server_impl.RunCallback();
+ PumpMessages();
+
+ // Check that the client has now seen the correct value again.
+ EXPECT_EQ(13, last_client_callback_value_seen_);
+}
+
+// Tests that running the Callback after the Binding has been deleted
+// results in a clean failure.
+TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
+ // Create the ServerImpl.
+ InterfaceImpl server_impl;
+ {
+ // Create the binding in an inner scope so it can be deleted first.
+ Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
+
+ // Initialize the test values.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method.
+ interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+ }
+ // The binding has now been destroyed and the pipe is closed.
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(7, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Now try to run the Callback. This should do nothing since the pipe
+ // is closed.
+ EXPECT_TRUE(server_impl.RunCallback());
+ PumpMessages();
+
+ // Check that the client has still not seen the correct value.
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Attempt to invoke the method again and confirm that an error was
+ // encountered.
+ interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+ EXPECT_TRUE(interface_ptr_.encountered_error());
+}
+
+// Tests that deleting a Callback without running it after the corresponding
+// binding has already been deleted does not result in a crash.
+TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
+ // Create the ServerImpl.
+ InterfaceImpl server_impl;
+ {
+ // Create the binding in an inner scope so it can be deleted first.
+ Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
+
+ // Initialize the test values.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method.
+ interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+ }
+ // The binding has now been destroyed and the pipe is closed.
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(7, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Delete the callback without running it. This should not
+ // cause a problem because the insfrastructure can detect that the
+ // binding has already been destroyed and the pipe is closed.
+ server_impl.DeleteCallback();
+}
+
+// Tests that closing a Binding allows us to delete a callback
+// without running it without encountering a crash.
+TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
+ // Create the ServerImpl and the Binding.
+ InterfaceImpl server_impl;
+ Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
+
+ // Initialize the test values.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method.
+ interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(7, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+ // Now close the Binding.
+ binding.Close();
+
+ // Delete the callback without running it. This should not
+ // cause a crash because the insfrastructure can detect that the
+ // binding has already been closed.
+ server_impl.DeleteCallback();
+
+ // Check that the client has still not seen the correct value.
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+}
+
+// Tests that deleting a Callback without using it before the
+// Binding has been destroyed or closed results in a DCHECK.
+// Temporarily disabled due to
+// https://code.google.com/p/chromium/issues/detail?id=472218
+TEST_F(BindingCallbackTest, DISABLED_DeleteCallbackBeforeBindingDeathTest) {
+ // Create the ServerImpl and the Binding.
+ InterfaceImpl server_impl;
+ Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
+
+ // Initialize the test values.
+ server_impl.resetLastServerValueSeen();
+ last_client_callback_value_seen_ = 0;
+
+ // Invoke the Echo method.
+ interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
+ PumpMessages();
+
+ // Check that server saw the correct value, but the client has not yet.
+ EXPECT_EQ(7, server_impl.last_server_value_seen());
+ EXPECT_EQ(0, last_client_callback_value_seen_);
+
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+ // Delete the callback without running it. This should cause a crash in debug
+ // builds due to a DCHECK.
+ EXPECT_DEATH(server_impl.DeleteCallback(),
+ "Check failed: !callback_was_dropped.");
+#endif
+}
+
+} // namespace
+} // namespace test
+} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
index a1fe8e6..f7c3cf6 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
@@ -43,6 +43,10 @@ class ProviderImpl : public sample::Provider {
callback.Run(a);
}
+ void EchoInt(int32_t a, const EchoIntCallback& callback) override {
+ callback.Run(a);
+ }
+
Binding<sample::Provider> binding_;
};
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/router_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/router_unittest.cc
index ed3792f..d3d8ccb 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/router_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/router_unittest.cc
@@ -47,19 +47,20 @@ class MessageAccumulator : public MessageReceiver {
internal::MessageQueue* queue_;
};
-class ResponseGenerator : public MessageReceiverWithResponder {
+class ResponseGenerator : public MessageReceiverWithResponderStatus {
public:
ResponseGenerator() {}
bool Accept(Message* message) override { return false; }
bool AcceptWithResponder(Message* message,
- MessageReceiver* responder) override {
+ MessageReceiverWithStatus* responder) override {
EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse));
bool result = SendResponse(
message->name(), message->request_id(),
reinterpret_cast<const char*>(message->payload()), responder);
+ EXPECT_TRUE(responder->IsValid());
delete responder;
return result;
}
@@ -84,7 +85,7 @@ class LazyResponseGenerator : public ResponseGenerator {
~LazyResponseGenerator() override { delete responder_; }
bool AcceptWithResponder(Message* message,
- MessageReceiver* responder) override {
+ MessageReceiverWithStatus* responder) override {
name_ = message->name();
request_id_ = message->request_id();
request_string_ =
@@ -95,6 +96,8 @@ class LazyResponseGenerator : public ResponseGenerator {
bool has_responder() const { return !!responder_; }
+ bool responder_is_valid() const { return responder_->IsValid(); }
+
// Send the response and delete the responder.
void CompleteWithResponse() { Complete(true); }
@@ -112,7 +115,7 @@ class LazyResponseGenerator : public ResponseGenerator {
responder_ = nullptr;
}
- MessageReceiver* responder_;
+ MessageReceiverWithStatus* responder_;
uint32_t name_;
uint64_t request_id_;
std::string request_string_;
@@ -261,6 +264,7 @@ TEST_F(RouterTest, LazyResponses) {
EXPECT_TRUE(message_queue.IsEmpty());
// Send the response.
+ EXPECT_TRUE(generator.responder_is_valid());
generator.CompleteWithResponse();
PumpMessages();
@@ -283,6 +287,7 @@ TEST_F(RouterTest, LazyResponses) {
EXPECT_TRUE(message_queue.IsEmpty());
// Send the second response.
+ EXPECT_TRUE(generator.responder_is_valid());
generator.CompleteWithResponse();
PumpMessages();
@@ -358,6 +363,7 @@ TEST_F(RouterTest, LateResponse) {
EXPECT_TRUE(generator.has_responder());
}
+ EXPECT_FALSE(generator.responder_is_valid());
generator.CompleteWithResponse(); // This should end up doing nothing.
}
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
index 7f5a376..3fb4a28 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -418,6 +418,5 @@ TEST_F(StructTest, Versioning_NewToOld) {
EXPECT_TRUE(output->Equals(*expected_output));
}
}
-
} // namespace test
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
index aba7faa..ef9bac1 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/array_serialization.h"
#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
#include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,12 +108,12 @@ TEST(UnionTest, SerializationPod) {
PodUnionPtr pod1(PodUnion::New());
pod1->set_f_int8(10);
- size_t size = GetSerializedSize_(pod1);
+ size_t size = GetSerializedSize_(pod1, false);
EXPECT_EQ(16U, size);
mojo::internal::FixedBuffer buf(size);
- internal::PodUnion_Data* data;
- Serialize_(pod1.Pass(), &buf, &data);
+ internal::PodUnion_Data* data = nullptr;
+ SerializeUnion_(pod1.Pass(), &buf, &data, false);
PodUnionPtr pod2;
Deserialize_(data, &pod2);
@@ -119,27 +123,68 @@ TEST(UnionTest, SerializationPod) {
EXPECT_EQ(pod2->which(), PodUnion::Tag::F_INT8);
}
-TEST(UnionTest, ValidationJustWorksPod) {
+TEST(UnionTest, PodValidation) {
PodUnionPtr pod(PodUnion::New());
pod->set_f_int8(10);
- size_t size = GetSerializedSize_(pod);
+ size_t size = GetSerializedSize_(pod, false);
EXPECT_EQ(16U, size);
mojo::internal::FixedBuffer buf(size);
- internal::PodUnion_Data* data;
- Serialize_(pod.Pass(), &buf, &data);
+ internal::PodUnion_Data* data = nullptr;
+ SerializeUnion_(pod.Pass(), &buf, &data, false);
void* raw_buf = buf.Leak();
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
- EXPECT_TRUE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_TRUE(
+ internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
free(raw_buf);
}
+TEST(UnionTest, SerializeNotNull) {
+ PodUnionPtr pod(PodUnion::New());
+ pod->set_f_int8(0);
+ size_t size = GetSerializedSize_(pod, false);
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data = nullptr;
+ SerializeUnion_(pod.Pass(), &buf, &data, false);
+ EXPECT_FALSE(data->is_null());
+}
+
+TEST(UnionTest, SerializeIsNullInlined) {
+ PodUnionPtr pod;
+ size_t size = GetSerializedSize_(pod, false);
+ EXPECT_EQ(16U, size);
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
+
+ // Check that dirty output buffers are handled correctly by serialization.
+ data->size = 16U;
+ data->tag = PodUnion::Tag::F_UINT16;
+ data->data.f_f_int16 = 20;
+
+ SerializeUnion_(pod.Pass(), &buf, &data, true);
+ EXPECT_TRUE(data->is_null());
+
+ PodUnionPtr pod2;
+ Deserialize_(data, &pod2);
+ EXPECT_TRUE(pod2.is_null());
+}
+
+TEST(UnionTest, SerializeIsNullNotInlined) {
+ PodUnionPtr pod;
+ size_t size = GetSerializedSize_(pod, false);
+ EXPECT_EQ(16U, size);
+ mojo::internal::FixedBuffer buf(size);
+ internal::PodUnion_Data* data = nullptr;
+ SerializeUnion_(pod.Pass(), &buf, &data, false);
+ EXPECT_EQ(nullptr, data);
+}
+
TEST(UnionTest, NullValidation) {
void* buf = nullptr;
mojo::internal::BoundsChecker bounds_checker(buf, 0, 0);
- EXPECT_TRUE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
+ EXPECT_TRUE(internal::PodUnion_Data::Validate(buf, &bounds_checker, false));
}
TEST(UnionTest, OutOfAlignmentValidation) {
@@ -154,7 +199,7 @@ TEST(UnionTest, OutOfAlignmentValidation) {
reinterpret_cast<internal::PodUnion_Data*>(buf);
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
- EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
+ EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker, false));
free(raw_buf);
}
@@ -166,7 +211,8 @@ TEST(UnionTest, OOBValidation) {
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
- EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_FALSE(
+ internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
free(raw_buf);
}
@@ -179,7 +225,8 @@ TEST(UnionTest, UnknownTagValidation) {
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
- EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_FALSE(
+ internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
free(raw_buf);
}
@@ -222,10 +269,10 @@ TEST(UnionTest, StringSerialization) {
String hello("hello world");
pod1->set_f_string(hello);
- size_t size = GetSerializedSize_(pod1);
+ size_t size = GetSerializedSize_(pod1, false);
mojo::internal::FixedBuffer buf(size);
- internal::ObjectUnion_Data* data;
- Serialize_(pod1.Pass(), &buf, &data);
+ internal::ObjectUnion_Data* data = nullptr;
+ SerializeUnion_(pod1.Pass(), &buf, &data, false);
ObjectUnionPtr pod2;
Deserialize_(data, &pod2);
@@ -234,7 +281,7 @@ TEST(UnionTest, StringSerialization) {
EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING);
}
-TEST(UnionTest, StringValidationNull) {
+TEST(UnionTest, NullStringValidation) {
Environment environment;
size_t size = sizeof(internal::ObjectUnion_Data);
mojo::internal::FixedBuffer buf(size);
@@ -244,11 +291,12 @@ TEST(UnionTest, StringValidationNull) {
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
- EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_FALSE(
+ internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
free(raw_buf);
}
-TEST(UnionTest, StringValidationPointerOverflow) {
+TEST(UnionTest, StringPointerOverflowValidation) {
Environment environment;
size_t size = sizeof(internal::ObjectUnion_Data);
mojo::internal::FixedBuffer buf(size);
@@ -258,11 +306,12 @@ TEST(UnionTest, StringValidationPointerOverflow) {
mojo::internal::BoundsChecker bounds_checker(data,
static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
- EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_FALSE(
+ internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
free(raw_buf);
}
-TEST(UnionTest, StringValidationValidateString) {
+TEST(UnionTest, StringValidateOOB) {
Environment environment;
size_t size = 32;
mojo::internal::FixedBuffer buf(size);
@@ -277,8 +326,203 @@ TEST(UnionTest, StringValidationValidateString) {
array_header->num_elements = 20;
mojo::internal::BoundsChecker bounds_checker(data, 32, 0);
void* raw_buf = buf.Leak();
- EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
+ EXPECT_FALSE(
+ internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
+}
+
+// TODO(azani): Move back in array_unittest.cc when possible.
+// Array tests
+TEST(UnionTest, PodUnionInArray) {
+ SmallStructPtr small_struct(SmallStruct::New());
+ small_struct->pod_union_array = Array<PodUnionPtr>(2);
+ small_struct->pod_union_array[0] = PodUnion::New();
+ small_struct->pod_union_array[1] = PodUnion::New();
+
+ small_struct->pod_union_array[0]->set_f_int8(10);
+ small_struct->pod_union_array[1]->set_f_int16(12);
+
+ EXPECT_EQ(10, small_struct->pod_union_array[0]->get_f_int8());
+ EXPECT_EQ(12, small_struct->pod_union_array[1]->get_f_int16());
+}
+
+TEST(UnionTest, PodUnionInArraySerialization) {
+ Environment environment;
+ Array<PodUnionPtr> array(2);
+ array[0] = PodUnion::New();
+ array[1] = PodUnion::New();
+
+ array[0]->set_f_int8(10);
+ array[1]->set_f_int16(12);
+ EXPECT_EQ(2U, array.size());
+
+ size_t size = GetSerializedSize_(array);
+ EXPECT_EQ(40U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ mojo::internal::Array_Data<internal::PodUnion_Data>* data;
+ SerializeArray_<mojo::internal::ArrayValidateParams<
+ 0, false, mojo::internal::NoValidateParams>>(array.Pass(), &buf, &data);
+
+ Array<PodUnionPtr> array2;
+ Deserialize_(data, &array2);
+
+ EXPECT_EQ(2U, array2.size());
+
+ EXPECT_EQ(10, array2[0]->get_f_int8());
+ EXPECT_EQ(12, array2[1]->get_f_int16());
+}
+
+TEST(UnionTest, PodUnionInArraySerializationWithNull) {
+ Environment environment;
+ Array<PodUnionPtr> array(2);
+ array[0] = PodUnion::New();
+
+ array[0]->set_f_int8(10);
+ EXPECT_EQ(2U, array.size());
+
+ size_t size = GetSerializedSize_(array);
+ EXPECT_EQ(40U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ mojo::internal::Array_Data<internal::PodUnion_Data>* data;
+ SerializeArray_<mojo::internal::ArrayValidateParams<
+ 0, true, mojo::internal::NoValidateParams>>(array.Pass(), &buf, &data);
+
+ Array<PodUnionPtr> array2;
+ Deserialize_(data, &array2);
+
+ EXPECT_EQ(2U, array2.size());
+
+ EXPECT_EQ(10, array2[0]->get_f_int8());
+ EXPECT_TRUE(array2[1].is_null());
+}
+
+// TODO(azani): Move back in struct_unittest.cc when possible.
+// Struct tests
+TEST(UnionTest, Clone_Union) {
+ Environment environment;
+ SmallStructPtr small_struct(SmallStruct::New());
+ small_struct->pod_union = PodUnion::New();
+ small_struct->pod_union->set_f_int8(10);
+
+ SmallStructPtr clone = small_struct.Clone();
+ EXPECT_EQ(10, clone->pod_union->get_f_int8());
+}
+
+// Serialization test of a struct with a union of plain old data.
+TEST(UnionTest, Serialization_UnionOfPods) {
+ Environment environment;
+ SmallStructPtr small_struct(SmallStruct::New());
+ small_struct->pod_union = PodUnion::New();
+ small_struct->pod_union->set_f_int32(10);
+
+ size_t size = GetSerializedSize_(small_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallStruct_Data* data = nullptr;
+ Serialize_(small_struct.Pass(), &buf, &data);
+
+ SmallStructPtr deserialized;
+ Deserialize_(data, &deserialized);
+
+ EXPECT_EQ(10, deserialized->pod_union->get_f_int32());
+}
+
+// Serialization test of a struct with a union of structs.
+TEST(UnionTest, Serialization_UnionOfObjects) {
+ Environment environment;
+ SmallObjStructPtr obj_struct(SmallObjStruct::New());
+ obj_struct->obj_union = ObjectUnion::New();
+ String hello("hello world");
+ obj_struct->obj_union->set_f_string(hello);
+
+ size_t size = GetSerializedSize_(obj_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallObjStruct_Data* data = nullptr;
+ Serialize_(obj_struct.Pass(), &buf, &data);
+
+ SmallObjStructPtr deserialized;
+ Deserialize_(data, &deserialized);
+
+ EXPECT_EQ(hello, deserialized->obj_union->get_f_string());
+}
+
+// Validation test of a struct with a union.
+TEST(UnionTest, Validation_UnionsInStruct) {
+ Environment environment;
+ SmallStructPtr small_struct(SmallStruct::New());
+ small_struct->pod_union = PodUnion::New();
+ small_struct->pod_union->set_f_int32(10);
+
+ size_t size = GetSerializedSize_(small_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallStruct_Data* data = nullptr;
+ Serialize_(small_struct.Pass(), &buf, &data);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+// Validation test of a struct union fails due to unknown union tag.
+TEST(UnionTest, Validation_PodUnionInStruct_Failure) {
+ Environment environment;
+ SmallStructPtr small_struct(SmallStruct::New());
+ small_struct->pod_union = PodUnion::New();
+ small_struct->pod_union->set_f_int32(10);
+
+ size_t size = GetSerializedSize_(small_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallStruct_Data* data = nullptr;
+ Serialize_(small_struct.Pass(), &buf, &data);
+ data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_FALSE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
}
+
+// Validation fails due to non-nullable null union in struct.
+TEST(UnionTest, Validation_NullUnion_Failure) {
+ Environment environment;
+ SmallStructNonNullableUnionPtr small_struct(
+ SmallStructNonNullableUnion::New());
+
+ size_t size = GetSerializedSize_(small_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallStructNonNullableUnion_Data* data =
+ internal::SmallStructNonNullableUnion_Data::New(&buf);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate(
+ raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
+// Validation passes with nullable null union.
+TEST(UnionTest, Validation_NullableUnion) {
+ Environment environment;
+ SmallStructPtr small_struct(SmallStruct::New());
+
+ size_t size = GetSerializedSize_(small_struct);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::SmallStruct_Data* data = nullptr;
+ Serialize_(small_struct.Pass(), &buf, &data);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
+ free(raw_buf);
+}
+
} // namespace test
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
index 8139fe4..c15ff02 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -371,6 +371,16 @@ TEST_F(ValidationTest, Conformance) {
RunValidationTests("conformance_", validators.GetHead());
}
+// This test is similar to the Conformance test but for responses.
+TEST_F(ValidationTest, ResponseConformance) {
+ DummyMessageReceiver dummy_receiver;
+ mojo::internal::FilterChain validators(&dummy_receiver);
+ validators.Append<mojo::internal::MessageHeaderValidator>();
+ validators.Append<ConformanceTestInterface::ResponseValidator_>();
+
+ RunValidationTests("resp_conformance_", validators.GetHead());
+}
+
// Test that InterfacePtr<X> applies the correct validators and they don't
// conflict with each other:
// - MessageHeaderValidator
diff --git a/third_party/mojo/src/mojo/public/go/application/application_impl.go b/third_party/mojo/src/mojo/public/go/application/application_impl.go
new file mode 100644
index 0000000..43a1eb8
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/application/application_impl.go
@@ -0,0 +1,167 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package application
+
+import (
+ "log"
+ "sync"
+
+ "mojo/public/go/bindings"
+ "mojo/public/go/system"
+
+ "mojo/public/interfaces/application/application"
+ sp "mojo/public/interfaces/application/service_provider"
+ "mojo/public/interfaces/application/shell"
+)
+
+// Delegate is an interface that your mojo application should implement.
+// All methods are called from the same goroutine to make sure that order of
+// calls matches the order of messages sent to underlying message pipe.
+type Delegate interface {
+ // Initialize is called exactly once before any other method.
+ Initialize(ctx Context)
+
+ // AcceptConnection is called when another application attempts to open
+ // a connection to this application. Close the connection if you no
+ // longer need it.
+ AcceptConnection(connection *Connection)
+
+ // Quit is called to request the application shut itself down
+ // gracefully.
+ Quit()
+}
+
+// Context is an interface to information about mojo application environment.
+type Context interface {
+ // URL returns the URL the application was found at, after all mappings,
+ // resolution, and redirects.
+ URL() string
+
+ // Args returns a list of initial configuration arguments, passed by the
+ // Shell.
+ Args() []string
+
+ // ConnectToApplication requests a new connection to an application. You
+ // should pass a list of services you want to provide to the requested
+ // application.
+ ConnectToApplication(remoteURL string, providedServices ...ServiceFactory) *OutgoingConnection
+}
+
+// ApplicationImpl is an utility class for communicating with the Shell, and
+// providing Services to clients.
+type ApplicationImpl struct {
+ shell *shell.ShellProxy
+ args []string
+ url string
+ // Pointer to the stub that runs this instance of ApplicationImpl.
+ runner *bindings.Stub
+ quitOnce sync.Once
+
+ delegate Delegate
+ // Protects connections, that can be modified concurrently because of
+ // ConnectToApplication calls.
+ mu sync.Mutex
+ connections []*Connection
+}
+
+// Run binds your mojo application to provided message pipe handle and runs it
+// until the application is terminated.
+func Run(delegate Delegate, applicationRequest system.MojoHandle) {
+ messagePipe := system.GetCore().AcquireNativeHandle(applicationRequest).ToMessagePipeHandle()
+ appRequest := application.ApplicationRequest{bindings.NewMessagePipeHandleOwner(messagePipe)}
+ impl := &ApplicationImpl{
+ delegate: delegate,
+ }
+ stub := application.NewApplicationStub(appRequest, impl, bindings.GetAsyncWaiter())
+ impl.runner = stub
+ for {
+ if err := stub.ServeRequest(); err != nil {
+ // TODO(rogulenko): don't log in case message pipe was closed
+ log.Println(err)
+ impl.RequestQuit()
+ break
+ }
+ }
+}
+
+// Mojo application implementation.
+func (impl *ApplicationImpl) Initialize(shellPointer shell.ShellPointer, args *[]string, url string) error {
+ impl.shell = shell.NewShellProxy(shellPointer, bindings.GetAsyncWaiter())
+ if args != nil {
+ impl.args = *args
+ }
+ impl.url = url
+ impl.delegate.Initialize(impl)
+ return nil
+}
+
+// Mojo application implementation.
+func (impl *ApplicationImpl) AcceptConnection(requestorURL string, services *sp.ServiceProviderRequest, exposedServices *sp.ServiceProviderPointer, resolvedURL string) error {
+ connection := newConnection(requestorURL, services, exposedServices, resolvedURL)
+ impl.delegate.AcceptConnection(connection)
+ impl.addConnection(connection)
+ return nil
+}
+
+// Mojo application implementation.
+func (impl *ApplicationImpl) RequestQuit() error {
+ impl.quitOnce.Do(func() {
+ impl.delegate.Quit()
+ impl.mu.Lock()
+ for _, c := range impl.connections {
+ c.Close()
+ }
+ impl.mu.Unlock()
+ impl.shell.Close_proxy()
+ impl.runner.Close()
+ })
+ return nil
+}
+
+// Context implementaion.
+func (impl *ApplicationImpl) URL() string {
+ return impl.url
+}
+
+// Context implementaion.
+func (impl *ApplicationImpl) Args() []string {
+ return impl.args
+}
+
+// Context implementaion.
+func (impl *ApplicationImpl) ConnectToApplication(remoteURL string, providedServices ...ServiceFactory) *OutgoingConnection {
+ servicesRequest, servicesPointer := sp.CreateMessagePipeForServiceProvider()
+ exposedServicesRequest, exposedServicesPointer := sp.CreateMessagePipeForServiceProvider()
+ if err := impl.shell.ConnectToApplication(remoteURL, &servicesRequest, &exposedServicesPointer); err != nil {
+ log.Printf("can't connect to %v: %v", remoteURL, err)
+ // In case of error message pipes sent through Shell are closed and
+ // the connection will work as if the remote application closed
+ // both ServiceProvider's pipes.
+ }
+ connection := newConnection(impl.url, &exposedServicesRequest, &servicesPointer, remoteURL)
+ impl.addConnection(connection)
+ return connection.ProvideServices(providedServices...)
+}
+
+// addConnection appends connections slice by a provided connection, removing
+// connections that have been closed.
+func (impl *ApplicationImpl) addConnection(c *Connection) {
+ impl.mu.Lock()
+ i := 0
+ for i < len(impl.connections) {
+ if impl.connections[i].isClosed {
+ last := len(impl.connections) - 1
+ impl.connections[i] = impl.connections[last]
+ impl.connections[last] = nil
+ impl.connections = impl.connections[:last]
+ } else {
+ i++
+ }
+ }
+ if !c.isClosed {
+ impl.connections = append(impl.connections, c)
+ }
+ impl.mu.Unlock()
+}
diff --git a/third_party/mojo/src/mojo/public/go/application/connection.go b/third_party/mojo/src/mojo/public/go/application/connection.go
new file mode 100644
index 0000000..5b2c629
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/application/connection.go
@@ -0,0 +1,174 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package application
+
+import (
+ "log"
+
+ "mojo/public/go/bindings"
+ "mojo/public/go/system"
+
+ sp "mojo/public/interfaces/application/service_provider"
+)
+
+type connectionInfo struct {
+ requestorURL string
+ connectionURL string
+}
+
+// RequestorURL returns the URL of application that established the connection.
+func (c *connectionInfo) RequestorURL() string {
+ return c.requestorURL
+}
+
+// ConnectionURL returns the URL that was used by the source application to
+// establish a connection to the destination application.
+func (c *connectionInfo) ConnectionURL() string {
+ return c.connectionURL
+}
+
+// ServiceRequest is an interface request for a specified mojo service.
+type ServiceRequest interface {
+ // Name returns the name of requested mojo service.
+ Name() string
+
+ // PassMessagePipe passes ownership of the underlying message pipe
+ // handle to the newly created handle object, invalidating the
+ // underlying handle object in the process.
+ PassMessagePipe() system.MessagePipeHandle
+}
+
+// ServiceFactory provides implementation of a mojo service.
+type ServiceFactory interface {
+ // Name returns the name of provided mojo service.
+ Name() string
+
+ // Create binds an implementation of mojo service to the provided
+ // message pipe and runs it.
+ Create(pipe system.MessagePipeHandle)
+}
+
+// Connection represents a connection to another application. An instance of
+// this struct is passed to Delegate's AcceptConnection() function each time a
+// connection is made to this application.
+type Connection struct {
+ connectionInfo
+ // Request for local services. Is valid until ProvideServices is called.
+ servicesRequest *sp.ServiceProviderRequest
+ // Indicates that ProvideServices function was already called.
+ servicesProvided bool
+ localServices *bindings.Stub
+ outgoingConnection *OutgoingConnection
+ isClosed bool
+}
+
+func newConnection(requestorURL string, services *sp.ServiceProviderRequest, exposedServices *sp.ServiceProviderPointer, resolvedURL string) *Connection {
+ info := connectionInfo{
+ requestorURL,
+ resolvedURL,
+ }
+ var remoteServices *sp.ServiceProviderProxy
+ if exposedServices != nil {
+ remoteServices = sp.NewServiceProviderProxy(*exposedServices, bindings.GetAsyncWaiter())
+ }
+ return &Connection{
+ connectionInfo: info,
+ servicesRequest: services,
+ outgoingConnection: &OutgoingConnection{
+ info,
+ remoteServices,
+ },
+ }
+}
+
+// ProvideServices starts a service provider on a separate goroutine that
+// provides given services to the remote application. Returns a pointer to
+// outgoing connection that can be used to connect to services provided by
+// remote application.
+// Panics if called more than once.
+func (c *Connection) ProvideServices(services ...ServiceFactory) *OutgoingConnection {
+ if c.servicesProvided {
+ panic("ProvideServices can be called only once")
+ }
+ c.servicesProvided = true
+ if c.servicesRequest == nil {
+ return c.outgoingConnection
+ }
+ if len(services) == 0 {
+ c.servicesRequest.PassMessagePipe().Close()
+ return c.outgoingConnection
+ }
+
+ provider := &serviceProviderImpl{
+ make(map[string]ServiceFactory),
+ }
+ for _, service := range services {
+ provider.AddService(service)
+ }
+ c.localServices = sp.NewServiceProviderStub(*c.servicesRequest, provider, bindings.GetAsyncWaiter())
+ go func() {
+ for {
+ if err := c.localServices.ServeRequest(); err != nil {
+ // TODO(rogulenko): don't log in case message pipe was closed
+ log.Println(err)
+ break
+ }
+ }
+ }()
+ return c.outgoingConnection
+}
+
+// Close closes both incoming and outgoing parts of the connection.
+func (c *Connection) Close() {
+ if c.servicesRequest != nil {
+ c.servicesRequest.Close()
+ }
+ if c.localServices != nil {
+ c.localServices.Close()
+ }
+ if c.outgoingConnection.remoteServices != nil {
+ c.outgoingConnection.remoteServices.Close_proxy()
+ }
+ c.isClosed = true
+}
+
+// OutgoingConnection represents outgoing part of connection to another
+// application. In order to close it close the |Connection| object that returned
+// this |OutgoingConnection|.
+type OutgoingConnection struct {
+ connectionInfo
+ remoteServices *sp.ServiceProviderProxy
+}
+
+// ConnectToService asks remote application to provide a service through the
+// message pipe endpoint supplied by the caller.
+func (c *OutgoingConnection) ConnectToService(request ServiceRequest) {
+ pipe := request.PassMessagePipe()
+ if c.remoteServices == nil {
+ pipe.Close()
+ return
+ }
+ c.remoteServices.ConnectToService(request.Name(), pipe)
+}
+
+// serviceProviderImpl is an implementation of mojo ServiceProvider interface.
+type serviceProviderImpl struct {
+ factories map[string]ServiceFactory
+}
+
+// Mojo ServiceProvider implementation.
+func (sp *serviceProviderImpl) ConnectToService(name string, messagePipe system.MessagePipeHandle) error {
+ factory, ok := sp.factories[name]
+ if !ok {
+ messagePipe.Close()
+ return nil
+ }
+ factory.Create(messagePipe)
+ return nil
+}
+
+func (sp *serviceProviderImpl) AddService(factory ServiceFactory) {
+ sp.factories[factory.Name()] = factory
+}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/decoder.go b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
index 34a230e..8f25c0b 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/decoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
@@ -290,7 +290,6 @@ func (d *Decoder) ReadString() (string, error) {
// ReadPointer reads a pointer and reassigns first unclaimed byte index if the
// pointer is not null.
func (d *Decoder) ReadPointer() (uint64, error) {
- oldEnd := d.state().offset
pointer, err := d.ReadUint64()
if err != nil {
return pointer, err
@@ -299,7 +298,7 @@ func (d *Decoder) ReadPointer() (uint64, error) {
return pointer, nil
}
- newEnd := uint64(oldEnd) + pointer
+ newEnd := uint64(d.state().offset-8) + pointer
if newEnd >= uint64(len(d.buf)) {
return 0, fmt.Errorf("trying to access out of range memory")
}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/encoder.go b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
index 542cc21..e0a24fd 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/encoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
@@ -305,6 +305,8 @@ func (e *Encoder) WriteString(value string) error {
// WritePointer writes a pointer to first unclaimed byte index.
func (e *Encoder) WritePointer() error {
+ e.state().alignOffsetToBytes()
+ e.state().offset = align(e.state().offset, 8)
return e.WriteUint64(uint64(e.end - e.state().offset))
}
diff --git a/third_party/mojo/src/mojo/public/go/system/message_pipe.go b/third_party/mojo/src/mojo/public/go/system/message_pipe.go
index 21b81ef..149b5be 100644
--- a/third_party/mojo/src/mojo/public/go/system/message_pipe.go
+++ b/third_party/mojo/src/mojo/public/go/system/message_pipe.go
@@ -49,7 +49,7 @@ func (h *messagePipe) WriteMessage(bytes []byte, handles []UntypedHandle, flags
if len(handles) != 0 {
rawHandles = make([]uint32, len(handles))
for i := 0; i < len(handles); i++ {
- rawHandles[i] = uint32(handles[i].NativeHandle())
+ rawHandles[i] = uint32(handles[i].ReleaseNativeHandle())
}
}
h.core.mu.Lock()
diff --git a/third_party/mojo/src/mojo/public/interfaces/application/BUILD.gn b/third_party/mojo/src/mojo/public/interfaces/application/BUILD.gn
index 5b15344..32a6987 100644
--- a/third_party/mojo/src/mojo/public/interfaces/application/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/interfaces/application/BUILD.gn
@@ -12,8 +12,8 @@ mojom("application") {
"shell.mojom",
]
- # This base dir ensures that Dart's Mojo SDK can be imported with, e.g.,
+ # The import_from ensures that Dart's Mojo SDK can be imported with, e.g.,
# import 'package:mojo/public/dart/core.dart' even when the Mojo SDK lives
# somewhere else in the source tree.
- base_dir = mojo_root
+ import_from = mojo_root
}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/BUILD.gn b/third_party/mojo/src/mojo/public/interfaces/bindings/BUILD.gn
new file mode 100644
index 0000000..cf8a118
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../tools/bindings/mojom.gni")
+
+mojom("bindings") {
+ sources = [
+ "interface_control_messages.mojom",
+ ]
+}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/interface_control_messages.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/interface_control_messages.mojom
new file mode 100644
index 0000000..1ddccfc
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/interface_control_messages.mojom
@@ -0,0 +1,89 @@
+// 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.
+
+module mojo.internal;
+
+// For each message pipe representing a user-defined interface, some control
+// functions are provided at the same end of the message pipe as the
+// user-defined interface, providing information about the user-defined
+// interface and controlling behavior of the message pipe.
+
+////////////////////////////////////////////////////////////////////////////////
+// Run@0xFFFFFFFF(RunInput input) => (RunOutput? output);
+//
+// This control function runs the input command. If the command is not
+// supported, |output| is set to null; otherwise |output| stores the result,
+// whose type depends on the input.
+//
+// TODO(yzshen): Once union support is ready, switch the following definition
+// to:
+// struct RunMessageParams {
+// RunInput input;
+// };
+// union RunInput {
+// QueryVersion query_version;
+// };
+//
+// struct RunResponseMessageParams {
+// RunOutput? output;
+// };
+// union RunOutput {
+// QueryVersionResult query_version_result;
+// };
+
+const uint32 kRunMessageId = 0xFFFFFFFF;
+
+struct RunMessageParams {
+ // The reserved fields make the layout compatible with the RunInput union
+ // described above.
+ uint32 reserved0; // Must be set to 16.
+ uint32 reserved1; // Must be set to 0;
+ QueryVersion query_version;
+};
+
+struct RunResponseMessageParams {
+ // The reserved fields make the layout compatible with the RunOutput union
+ // described above.
+ uint32 reserved0; // Must be set to 16.
+ uint32 reserved1; // Must be set to 0.
+ QueryVersionResult query_version_result;
+};
+
+// Queries the max supported version of the user-defined interface.
+struct QueryVersion {
+};
+struct QueryVersionResult {
+ uint32 version;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// RunOrClosePipe@0xFFFFFFFE(RunOrClosePipeInput input);
+//
+// This control function runs the input command. If the operation fails or the
+// command is not supported, the message pipe is closed.
+//
+// TODO(yzshen): Once union support is ready, switch the following definition
+// to:
+// struct RunOrClosePipeMessageParams {
+// RunOrClosePipeInput input;
+// };
+// union RunOrClosePipeInput {
+// RequireVersion require_version;
+// };
+
+const uint32 kRunOrClosePipeMessageId = 0xFFFFFFFE;
+
+struct RunOrClosePipeMessageParams {
+ // The reserved fields make the layout compatible with the RunOrClosePipeInput
+ // union described above.
+ uint32 reserved0; // Must be set to 16.
+ uint32 reserved1; // Must be set to 0.
+ RequireVersion require_version;
+};
+
+// If the specified version of the user-defined interface is not supported, the
+// function fails and the pipe is closed.
+struct RequireVersion {
+ uint32 version;
+};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
index dabc3f6..572b58a 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -18,7 +18,6 @@ mojom("test_interfaces") {
"sample_service.mojom",
"serialization_test_structs.mojom",
"test_structs.mojom",
- "test_unions.mojom",
"validation_test_interfaces.mojom",
]
}
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.data
index 6c9654b..6c9654b 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.data
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.expected
index 696c78d..696c78d 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flags.expected
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.expected
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.data
new file mode 100644
index 0000000..a1b034c
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.data
@@ -0,0 +1,5 @@
+[dist4]message_header // num_bytes
+[u4]2 // version number
+[u4]9999 // There is no Method9999.
+[u4]0 // flags
+[anchr]message_header \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.expected
new file mode 100644
index 0000000..a32d895
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.data
new file mode 100644
index 0000000..07cf4c1
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.data
@@ -0,0 +1,6 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]0 // name
+[u4]2 // flags: kMessageIsResponse is set in a request.
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.expected
new file mode 100644
index 0000000..696c78d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.data
new file mode 100644
index 0000000..2b59165
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.data
@@ -0,0 +1,7 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]0 // name
+[u4]1 // flags: kMessageExpectsResponse is set in a request
+ // for a method that does not take a response.
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.expected
new file mode 100644
index 0000000..696c78d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.data
new file mode 100644
index 0000000..1c80196
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.data
@@ -0,0 +1,7 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]12 // name
+[u4]0 // flags: kMessageExpectsResponse is not set but
+ // expected.
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.expected
new file mode 100644
index 0000000..696c78d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.data
new file mode 100644
index 0000000..d9ca38e
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.data
@@ -0,0 +1,6 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]12 // name
+[u4]0 // flags: kMessageIsResponse is not set in a response.
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.expected
new file mode 100644
index 0000000..696c78d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.data
new file mode 100644
index 0000000..7587fc5
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.data
@@ -0,0 +1,6 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]12 // name
+[u4]1 // flags: kMessageExpectsResponse is set in a response.
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.expected
new file mode 100644
index 0000000..696c78d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.data
new file mode 100644
index 0000000..cc9cc8b
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.data
@@ -0,0 +1,6 @@
+[dist4]message_header // num_bytes
+[u4]3 // version
+[u4]11 // name: Method11 does not have a response message.
+[u4]2 // flags: kMessageIsResponse
+[u8]1 // request_id
+[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.expected
new file mode 100644
index 0000000..65a48b3
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
index 52589a9..c3cd1b2a 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
@@ -18,4 +18,5 @@ interface Provider {
EchoStrings(string a, string b) => (string a, string b);
EchoMessagePipeHandle(handle<message_pipe> a) => (handle<message_pipe> a);
EchoEnum(Enum a) => (Enum a);
+ EchoInt(int32 a) => (int32 a);
};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
index eae8ce6..7250f65 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
@@ -23,3 +23,22 @@ union ObjectUnion {
int8 f_int8;
string f_string;
};
+
+struct DummyStruct {
+ int8 f_int8;
+};
+
+struct SmallStruct {
+ DummyStruct? dummy_struct;
+ PodUnion? pod_union;
+ array<PodUnion>? pod_union_array;
+ array<DummyStruct>? s_array;
+};
+
+struct SmallStructNonNullableUnion {
+ PodUnion pod_union;
+};
+
+struct SmallObjStruct {
+ ObjectUnion obj_union;
+};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
index 13d0b52..cd5e1aa 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
@@ -54,6 +54,7 @@ interface ConformanceTestInterface {
Method9(array<array<handle?>>? param0);
Method10(map<string, uint8> param0);
Method11(StructG param0);
+ Method12(float param0) => (float param0);
};
struct BasicStruct {
diff --git a/third_party/mojo/src/mojo/public/js/validation_unittests.js b/third_party/mojo/src/mojo/public/js/validation_unittests.js
index a04879c..4fdb5d4 100644
--- a/third_party/mojo/src/mojo/public/js/validation_unittests.js
+++ b/third_party/mojo/src/mojo/public/js/validation_unittests.js
@@ -225,11 +225,19 @@ define([
expect(testFiles.length).toBeGreaterThan(0);
for (var i = 0; i < testFiles.length; i++) {
- // TODO(hansmuller, yzshen): Temporarily skipping:
- // - array pointer overflow tests;
- // - struct versioning tests (tests with "mthd11" in the name).
+ // TODO(hansmuller) Temporarily skipping array pointer overflow tests
+ // because JS numbers are limited to 53 bits.
+ // TODO(yzshen) Skipping struct versioning tests (tests with "mthd11"
+ // in the name) because the feature is not supported in JS yet.
+ // TODO(rudominer): Temporarily skipping 'no-such-method',
+ // 'invalid_request_flags', and 'invalid_response_flags' until additional
+ // logic in *RequestValidator and *ResponseValidator is ported from
+ // cpp to js.
if (testFiles[i].indexOf("overflow") != -1 ||
- testFiles[i].indexOf("mthd11") != -1) {
+ testFiles[i].indexOf("mthd11") != -1 ||
+ testFiles[i].indexOf("no_such_method") != -1 ||
+ testFiles[i].indexOf("invalid_request_flags") != -1 ||
+ testFiles[i].indexOf("invalid_response_flags") != -1) {
console.log("[Skipping " + testFiles[i] + "]");
continue;
}
@@ -257,12 +265,6 @@ define([
expect(testFiles.length).toBeGreaterThan(0);
for (var i = 0; i < testFiles.length; i++) {
- // TODO(hansmuller): Temporarily skipping array pointer overflow tests.
- if (testFiles[i].indexOf("overflow") != -1) {
- console.log("[Skipping " + testFiles[i] + "]");
- continue;
- }
-
var testMessage = readTestMessage(testFiles[i]);
var handles = new Array(testMessage.handleCount);
var testMessagePipe = new core.createMessagePipe();
diff --git a/third_party/mojo/src/mojo/public/tools/BUILD.gn b/third_party/mojo/src/mojo/public/tools/BUILD.gn
index 607ee7a..c8ea1e3 100644
--- a/third_party/mojo/src/mojo/public/tools/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/tools/BUILD.gn
@@ -35,15 +35,25 @@ if (mojo_use_prebuilt_network_service) {
copy("copy_network_service_apptests") {
filename = "network_service_apptests.mojo"
- if (is_android) {
+ if (defined(mojo_prebuilt_network_service_apptests_location) &&
+ mojo_prebuilt_network_service_apptests_location != "") {
sources = [
- "prebuilt/network_service_apptests/android-arm/$filename",
+ "$mojo_prebuilt_network_service_apptests_location",
]
} else {
- assert(is_linux)
- sources = [
- "prebuilt/network_service_apptests/linux-x64/$filename",
- ]
+ if (is_android) {
+ assert(
+ cpu_arch == "arm",
+ "Only arm version prebuilt netowrk_service_apptests.mojo is available.")
+ sources = [
+ "prebuilt/network_service_apptests/android-arm/$filename",
+ ]
+ } else {
+ assert(is_linux)
+ sources = [
+ "prebuilt/network_service_apptests/linux-x64/$filename",
+ ]
+ }
}
outputs = [
"$root_out_dir/$filename",
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index 44d1428..fd6b643 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -46,7 +46,7 @@ class {{class_name}}_{{method.name}}_ForwardToCallback
const {{class_name}}::{{method.name}}Callback& callback)
: callback_(callback) {
}
- virtual bool Accept(mojo::Message* message) override;
+ bool Accept(mojo::Message* message) override;
private:
{{class_name}}::{{method.name}}Callback callback_;
MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ForwardToCallback);
@@ -115,31 +115,33 @@ class {{class_name}}_{{method.name}}_ProxyToResponder
: public {{class_name}}::{{method.name}}Callback::Runnable {
public:
virtual ~{{class_name}}_{{method.name}}_ProxyToResponder() {
+ // Is the Mojo application destroying the callback without running it
+ // and without first closing the pipe?
+ bool callback_was_dropped = responder_ && responder_->IsValid();
+ // If the Callback was dropped then deleting the responder will close
+ // the pipe so the calling application knows to stop waiting for a reply.
delete responder_;
- // TODO(rudominer) DCHECK if |was_run_| is false and we don't have evidence
- // that we are in a legitamte shutdown case such as the Connector detected
- // an error or Close() was invoked.
+ MOJO_DCHECK(!callback_was_dropped) << "The callback passed to "
+ "{{class_name}}::{{method.name}}({%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}callback) "
+ "was never run.";
}
{{class_name}}_{{method.name}}_ProxyToResponder(
uint64_t request_id,
- mojo::MessageReceiver* responder)
+ mojo::MessageReceiverWithStatus* responder)
: request_id_(request_id),
- responder_(responder),
- was_run_(false) {
+ responder_(responder) {
}
- virtual void Run({{interface_macros.declare_params("in_", method.response_parameters)}}) const override;
+ void Run({{interface_macros.declare_params("in_", method.response_parameters)}}) const override;
private:
uint64_t request_id_;
- mutable mojo::MessageReceiver* responder_;
- mutable bool was_run_;
+ mutable mojo::MessageReceiverWithStatus* responder_;
MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder);
};
void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{{interface_macros.declare_params("in_", method.response_parameters)}}) const {
- was_run_ = true;
{{struct_macros.get_serialized_size(response_params_struct, "in_%s")}}
mojo::internal::ResponseMessageBuilder builder(
{{message_name}}, size, request_id_);
@@ -159,6 +161,8 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
: sink_(nullptr) {
}
+{{class_name}}Stub::~{{interface.name}}Stub() {}
+
{#--- Stub definition #}
bool {{class_name}}Stub::Accept(mojo::Message* message) {
@@ -188,7 +192,7 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) {
}
bool {{class_name}}Stub::AcceptWithResponder(
- mojo::Message* message, mojo::MessageReceiver* responder) {
+ mojo::Message* message, mojo::MessageReceiverWithStatus* responder) {
{%- if interface.methods %}
switch (message->header()->name) {
{%- for method in interface.methods %}
@@ -227,16 +231,25 @@ bool {{class_name}}Stub::AcceptWithResponder(
bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
{%- if interface.methods %}
+ if (message->has_flag(mojo::internal::kMessageIsResponse)) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
+ return false;
+ }
switch (message->header()->name) {
{%- for method in interface.methods %}
case internal::k{{class_name}}_{{method.name}}_Name: {
{%- if method.response_parameters != None %}
- if (!message->has_flag(mojo::internal::kMessageExpectsResponse))
- break;
+ if (!message->has_flag(mojo::internal::kMessageExpectsResponse)) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
+ return false;
+ }
{%- else %}
- if (message->has_flag(mojo::internal::kMessageExpectsResponse) ||
- message->has_flag(mojo::internal::kMessageIsResponse)) {
- break;
+ if (message->has_flag(mojo::internal::kMessageExpectsResponse)) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
+ return false;
}
{%- endif %}
mojo::internal::BoundsChecker bounds_checker(
@@ -249,6 +262,12 @@ bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
break;
}
{%- endfor %}
+ default: {
+ // Unrecognized message.
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD);
+ return false;
+ }
}
{%- endif %}
@@ -264,11 +283,14 @@ bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
{%- if interface.methods %}
+ if (!message->has_flag(mojo::internal::kMessageIsResponse)) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
+ return false;
+ }
switch (message->header()->name) {
{%- for method in interface.methods if method.response_parameters != None %}
case internal::k{{class_name}}_{{method.name}}_Name: {
- if (!message->has_flag(mojo::internal::kMessageIsResponse))
- break;
mojo::internal::BoundsChecker bounds_checker(
message->payload(), message->payload_num_bytes(),
message->handles()->size());
@@ -279,6 +301,12 @@ bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
break;
}
{%- endfor %}
+ default: {
+ // Unrecognized message.
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD);
+ return false;
+ }
}
{%- endif %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
index 6b8e7c5..420f6e8 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
@@ -4,7 +4,7 @@ class {{interface.name}}Proxy : public {{interface.name}} {
explicit {{interface.name}}Proxy(mojo::MessageReceiverWithResponder* receiver);
{%- for method in interface.methods %}
- virtual void {{method.name}}(
+ void {{method.name}}(
{{interface_macros.declare_request_params("", method)}}
) override;
{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl
index 2239b69..29917ea 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl
@@ -2,5 +2,5 @@ class {{interface.name}}RequestValidator : public mojo::MessageFilter {
public:
explicit {{interface.name}}RequestValidator(mojo::MessageReceiver* sink = nullptr);
- virtual bool Accept(mojo::Message* message) override;
+ bool Accept(mojo::Message* message) override;
};
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl
index 801603d..5893bfd 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl
@@ -2,5 +2,5 @@ class {{interface.name}}ResponseValidator : public mojo::MessageFilter {
public:
explicit {{interface.name}}ResponseValidator(mojo::MessageReceiver* sink = nullptr);
- virtual bool Accept(mojo::Message* message) override;
+ bool Accept(mojo::Message* message) override;
};
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
index afc6504..05a2495 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
@@ -1,12 +1,13 @@
-class {{interface.name}}Stub : public mojo::MessageReceiverWithResponder {
+class {{interface.name}}Stub : public mojo::MessageReceiverWithResponderStatus {
public:
{{interface.name}}Stub();
+ ~{{interface.name}}Stub() override;
void set_sink({{interface.name}}* sink) { sink_ = sink; }
{{interface.name}}* sink() { return sink_; }
- virtual bool Accept(mojo::Message* message) override;
- virtual bool AcceptWithResponder(mojo::Message* message,
- mojo::MessageReceiver* responder) override;
+ bool Accept(mojo::Message* message) override;
+ bool AcceptWithResponder(mojo::Message* message,
+ mojo::MessageReceiverWithStatus* responder) override;
private:
{{interface.name}}* sink_;
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
index d9a398a..b4b4df8 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
@@ -50,15 +50,17 @@ class {{union.name}}_Data;
#pragma pack(push, 1)
+{#--- Unions must be declared first because they can be members of structs #}
+{#--- Union class declarations #}
+{% for union in unions %}
+{% include "union_declaration.tmpl" %}
+{%- endfor %}
+
{#--- Class declarations #}
{% for struct in structs %}
{% include "struct_declaration.tmpl" %}
{%- endfor %}
-{% for union in unions %}
-{% include "union_declaration.tmpl" %}
-{%- endfor %}
-
#pragma pack(pop)
} // namespace internal
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 0312002..503e19d 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -63,6 +63,12 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{% endif %}
{%- endfor %}
+{#--- Unions must be declared first because they can be members of structs #}
+{#--- Unions #}
+{% for union in unions %}
+{% include "wrapper_union_class_declaration.tmpl" %}
+{%- endfor %}
+
{#--- NOTE: Non-inlined structs may have pointers to inlined structs, so we #}
{#--- need to fully define inlined structs ahead of the others. #}
@@ -80,11 +86,6 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{% endif %}
{%- endfor %}
-{#--- Unions #}
-{% for union in unions %}
-{% include "wrapper_union_class_declaration.tmpl" %}
-{%- endfor %}
-
{#--- Interfaces -#}
{% for interface in interfaces %}
{% include "interface_declaration.tmpl" %}
@@ -110,18 +111,17 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{% include "interface_response_validator_declaration.tmpl" %}
{%- endfor %}
-{%- import "serialization_macros.tmpl" as serialization_macros %}
{#--- Struct Serialization Helpers -#}
{% if structs %}
{% for struct in structs %}
-{{ serialization_macros.declare_serialization(struct.name) }}
+{% include "struct_serialization_declaration.tmpl" %}
{%- endfor %}
{%- endif %}
{#--- Union Serialization Helpers -#}
{% if unions %}
{% for union in unions %}
-{{ serialization_macros.declare_serialization(union.name) }}
+{% include "union_serialization_declaration.tmpl" %}
{%- endfor %}
{%- endif %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl
deleted file mode 100644
index 2be038c..0000000
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/serialization_macros.tmpl
+++ /dev/null
@@ -1,7 +0,0 @@
-{%- macro declare_serialization(name) %}
-size_t GetSerializedSize_(const {{name}}Ptr& input);
-void Serialize_({{name}}Ptr input, mojo::internal::Buffer* buffer,
- internal::{{name}}_Data** output);
-void Deserialize_(internal::{{name}}_Data* input,
- {{name}}Ptr* output);
-{%- endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
index 79a0bc4..32755cf 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -11,17 +11,23 @@
{%- set kind = packed_field.field.kind %}
{%- set wrapper_type = kind|cpp_wrapper_type %}
{%- if not kind|is_nullable_kind %}
+{%- if kind|is_union_kind %}
+ if (object->{{name}}.is_null()) {
+{%- else %}
if (!object->{{name}}.offset) {
+{%- endif %}
ReportValidationError(
mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null {{name}} field in {{struct.name}} struct");
return false;
}
{%- endif %}
+{%- if not kind|is_union_kind %}
if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) {
ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER);
return false;
}
+{%- endif %}
{%- if kind|is_array_kind or kind|is_string_kind %}
if (!{{wrapper_type}}::Data_::Validate<
{{kind|get_array_validate_params|indent(10)}}>(
@@ -36,6 +42,9 @@
if (!{{kind|get_name_for_kind}}::Data_::Validate(
mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
bounds_checker)) {
+{%- elif kind|is_union_kind %}
+ if (!{{kind|get_name_for_kind}}::Data_::Validate(
+ &object->{{name}}, bounds_checker, true)) {
{%- else %}
if (!{{wrapper_type}}::Data_::Validate(
mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
@@ -139,7 +148,7 @@ void {{class_name}}::EncodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
MOJO_CHECK(header_.version == {{struct.versions[-1].version}});
{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%- if pf.field.kind|is_object_kind %}
+{%- if pf.field.kind|is_object_kind and not pf.field.kind|is_union_kind %}
mojo::internal::Encode(&{{pf.field.name}}, handles);
{%- elif pf.field.kind|is_any_handle_kind %}
mojo::internal::EncodeHandle(&{{pf.field.name}}, handles);
@@ -165,7 +174,9 @@ void {{class_name}}::DecodePointersAndHandles(
if (header_.version < {{pf.min_version}})
return;
{%- endif %}
-{%- if kind|is_object_kind %}
+{%- if kind|is_union_kind %}
+ // TODO(azani): Decode handles in union.
+{%- elif kind|is_object_kind %}
mojo::internal::Decode(&{{name}}, handles);
{%- else %}
mojo::internal::DecodeHandle(&{{name}}, handles);
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
index 03911b9..e8a625b 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -14,7 +14,11 @@
{%- macro get_serialized_size(struct, input_field_pattern) -%}
size_t size = sizeof(internal::{{struct.name}}_Data);
{%- for pf in struct.packed.packed_fields_in_ordinal_order if pf.field.kind|is_object_kind %}
+{%- if pf.field.kind|is_union_kind %}
+ size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}}, true);
+{%- else %}
size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}});
+{%- endif %}
{%- endfor %}
{%- endmacro -%}
@@ -46,12 +50,19 @@
{%- elif kind|is_map_kind %}
mojo::SerializeMap_<{{kind.value_kind|get_map_validate_params|indent(24)}}>(
mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
+{%- elif kind|is_union_kind %}
+ internal::{{kind.name}}_Data* {{name}}_ptr = &{{output}}->{{name}};
+ SerializeUnion_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{name}}_ptr, true);
{%- else %}
Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
{%- endif %}
{%- if not kind|is_nullable_kind %}
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+{%- if kind|is_union_kind %}
+ {{output}}->{{name}}.is_null(),
+{%- else %}
!{{output}}->{{name}}.ptr,
+{%- endif %}
mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null {{name}} in {{struct_display_name}}");
{%- endif %}
@@ -103,7 +114,11 @@
break;
{%- endif %}
{%- if kind|is_object_kind %}
+{%- if kind|is_union_kind %}
+ Deserialize_(&{{input}}->{{name}}, &{{output_field}});
+{%- else %}
Deserialize_({{input}}->{{name}}.ptr, &{{output_field}});
+{%- endif %}
{%- elif kind|is_interface_kind or kind|is_interface_request_kind %}
{{output_field}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&{{input}}->{{name}})));
{%- elif kind|is_any_handle_kind %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
new file mode 100644
index 0000000..604be86
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -0,0 +1,5 @@
+size_t GetSerializedSize_(const {{struct.name}}Ptr& input);
+void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer,
+ internal::{{struct.name}}_Data** output);
+void Deserialize_(internal::{{struct.name}}_Data* input,
+ {{struct.name}}Ptr* output);
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index 6e6fe95..bc77c11 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -4,10 +4,22 @@
class {{class_name}} {
public:
+ // Used to identify Mojom Union Data Classes.
+ typedef void MojomUnionDataType;
static {{class_name}}* New(mojo::internal::Buffer* buf);
+ {{class_name}}();
+ // Do nothing in the destructor since it won't be called.
+ ~{{class_name}}() {}
static bool Validate(const void* data,
- mojo::internal::BoundsChecker* bounds_checker);
+ mojo::internal::BoundsChecker* bounds_checker,
+ bool inlined);
+
+ bool is_null() const {
+ return size == 0;
+ }
+
+ void set_null();
enum class {{enum_name}} : uint32_t {
{% for field in union.fields %}
@@ -33,16 +45,12 @@ class {{class_name}} {
uint64_t unknown;
};
- uint32_t reserved;
+ uint32_t size;
{{enum_name}} tag;
Union_ data;
void EncodePointersAndHandles(std::vector<mojo::Handle>* handles);
void DecodePointersAndHandles(std::vector<mojo::Handle>* handles);
-
- private:
- {{class_name}}();
- ~{{class_name}}() = delete;
};
static_assert(sizeof({{class_name}}) == 16,
"Bad sizeof({{class_name}})");
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
index c9ea5d0..23e5cfd 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -9,7 +9,8 @@
// static
bool {{class_name}}::Validate(const void* data,
- mojo::internal::BoundsChecker* bounds_checker) {
+ mojo::internal::BoundsChecker* bounds_checker,
+ bool inlined) {
if (!data) {
return true;
}
@@ -19,7 +20,10 @@ bool {{class_name}}::Validate(const void* data,
return false;
}
- if (!bounds_checker->ClaimMemory(data, sizeof({{class_name}}))) {
+ // If the union is inlined in another structure its memory was already claimed.
+ // This ONLY applies to the union itself, NOT anything which the union points
+ // to.
+ if (!inlined && !bounds_checker->ClaimMemory(data, sizeof({{class_name}}))) {
ReportValidationError(
mojo::internal::VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
return false;
@@ -40,6 +44,12 @@ bool {{class_name}}::Validate(const void* data,
}
}
+void {{class_name}}::set_null() {
+ size = 0U;
+ tag = static_cast<{{enum_name}}>(0);
+ data.unknown = 0U;
+}
+
{{class_name}}::{{class_name}}() {
}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
new file mode 100644
index 0000000..404eb83
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -0,0 +1,5 @@
+size_t GetSerializedSize_(const {{union.name}}Ptr& input, bool inlined);
+void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buffer,
+ internal::{{union.name}}_Data** output, bool inlined);
+void Deserialize_(internal::{{union.name}}_Data* input,
+ {{union.name}}Ptr* output);
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
index 8b82f7f..f928eba 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -1,8 +1,12 @@
-size_t GetSerializedSize_(const {{union.name}}Ptr& input) {
+size_t GetSerializedSize_(const {{union.name}}Ptr& input, bool inlined) {
+ size_t size = 0U;
+ if (!inlined) {
+ size += sizeof(internal::{{union.name}}_Data);
+ }
+
if (!input)
- return 0;
+ return size;
- size_t size = sizeof(internal::{{union.name}}_Data);
switch (input->which()) {
{% for field in union.fields %}
{% if field.kind|is_string_kind %}
@@ -17,14 +21,17 @@ size_t GetSerializedSize_(const {{union.name}}Ptr& input) {
return size;
}
-
-void Serialize_({{union.name}}Ptr input, mojo::internal::Buffer* buf,
- internal::{{union.name}}_Data** output) {
+void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buf,
+ internal::{{union.name}}_Data** output, bool inlined) {
+ internal::{{union.name}}_Data* result = *output;
if (input) {
+ if (!inlined) {
+ result = internal::{{union.name}}_Data::New(buf);
+ }
mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get());
- internal::{{union.name}}_Data* result =
- internal::{{union.name}}_Data::New(buf);
// TODO(azani): Handle unknown and objects.
+ // Set the not-null flag.
+ result->size = 16;
result->tag = input->which();
switch (input->which()) {
{% for field in union.fields %}
@@ -38,15 +45,17 @@ void Serialize_({{union.name}}Ptr input, mojo::internal::Buffer* buf,
break;
{%- endfor %}
}
- *output = result;
+ } else if (inlined) {
+ result->set_null();
} else {
- *output = nullptr;
+ result = nullptr;
}
+ *output = result;
}
void Deserialize_(internal::{{union.name}}_Data* input,
{{union.name}}Ptr* output) {
- if (input) {
+ if (input && !input->is_null()) {
{{union.name}}Ptr result({{union.name}}::New());
mojo::internal::UnionAccessor<{{union.name}}> result_acc(result.get());
switch (input->tag) {
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
index da93e07..c171aa3 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
@@ -18,7 +18,7 @@
{{struct.name}}Ptr {{struct.name}}::Clone() const {
{{struct.name}}Ptr rv(New());
{%- for field in struct.fields %}
-{%- if field.kind|is_struct_kind or field.kind|is_array_kind or field.kind|is_map_kind %}
+{%- if field.kind|is_object_kind and not field.kind|is_string_kind %}
rv->{{field.name}} = {{field.name}}.Clone();
{%- else %}
rv->{{field.name}} = {{field.name}};
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl
index 21b643e..d6b869e 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl
@@ -10,7 +10,7 @@ import 'package:mojo/public/dart/bindings.dart' as bindings;
import 'package:mojo/public/dart/core.dart' as core;
{%- for import in imports %}
-import 'package:{{import.module.path}}.dart' as {{import.unique_name}};
+import 'package:{{import.rebased_path}}.dart' as {{import.unique_name}};
{%- endfor %}
{%- include "module_definition.tmpl" %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
index 4d3f54d..6d9b653 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
@@ -74,9 +74,11 @@ if (decoder{{level+1}} == null) {
{%- macro struct_def(struct) %}
class {{struct|name}} extends bindings.Struct {
- static const int kStructSize = {{struct.versions[-1].num_bytes}};
- static const bindings.StructDataHeader kDefaultStructInfo =
- const bindings.StructDataHeader(kStructSize, {{struct.versions[-1].version}});
+ static const List<bindings.StructDataHeader> kVersions = const [
+{%- for version in struct.versions %}
+ const bindings.StructDataHeader({{version.num_bytes}}, {{version.version}}){% if not loop.last %},{% endif %}
+{%- endfor %}
+ ];
{#--- Enums #}
{%- from "enum_definition.tmpl" import enum_def %}
@@ -95,7 +97,7 @@ class {{struct|name}} extends bindings.Struct {
{{packed_field.field.kind|dart_type}} {{packed_field.field|name}} = {{packed_field.field|default_value}};
{%- endfor %}
- {{struct|name}}() : super(kStructSize);
+ {{struct|name}}() : super(kVersions.last.size);
static {{struct|name}} deserialize(bindings.Message message) {
return decode(new bindings.Decoder(message));
@@ -108,14 +110,24 @@ class {{struct|name}} extends bindings.Struct {
{{struct|name}} result = new {{struct|name}}();
var mainDataHeader = decoder0.decodeStructDataHeader();
- if ((mainDataHeader.size < kStructSize) ||
- (mainDataHeader.version < {{struct.versions[-1].version}})) {
- throw new bindings.MojoCodecError('Malformed header');
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size != kVersions[i].size)
+ throw new bindings.MojoCodecError(
+ 'Header doesn\'t correspond to any known version.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
- {
+ if (mainDataHeader.version >= {{packed_field.min_version}}) {
{{decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(6)}}
}
{%- endfor %}
@@ -125,9 +137,9 @@ class {{struct|name}} extends bindings.Struct {
void encode(bindings.Encoder encoder) {
{%- if not struct.bytes %}
- encoder.getStructEncoderAtOffset(kDefaultStructInfo);
+ encoder.getStructEncoderAtOffset(kVersions.last);
{%- else %}
- var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
+ var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
{%- endif %}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
index c96441e..25435e3 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
@@ -42,9 +42,37 @@ type {{interface|name}} interface {
{% endfor %}
}
+var {{interface|name(False)}}_Name = "{{interface.module.namespace|replace(".","::")}}::{{interface.name}}"
+
type {{interface|name}}Request bindings.InterfaceRequest
+
+func (r *{{interface|name}}Request) Name() string {
+ return {{interface|name(False)}}_Name
+}
+
type {{interface|name}}Pointer bindings.InterfacePointer
+func (p *{{interface|name}}Pointer) Name() string {
+ return {{interface|name(False)}}_Name
+}
+
+type {{interface|name}}ServiceFactory struct{
+ Delegate {{interface|name}}Factory
+}
+
+type {{interface|name}}Factory interface {
+ Create(request {{interface|name}}Request)
+}
+
+func (f *{{interface|name}}ServiceFactory) Name() string {
+ return {{interface|name(False)}}_Name
+}
+
+func (f *{{interface|name}}ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
+ request := {{interface|name}}Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
+ f.Delegate.Create(request)
+}
+
// CreateMessagePipeFor{{interface|name}} creates a message pipe for use with the
// {{interface|name}} interface with a {{interface|name}}Request on one end and a {{interface|name}}Pointer on the other.
func CreateMessagePipeFor{{interface|name}}() ({{interface|name}}Request, {{interface|name}}Pointer) {
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 8b7e219..f38aecb 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -75,6 +75,8 @@ def GetCppType(kind):
GetCppType(kind.key_kind), GetCppType(kind.value_kind))
if mojom.IsStructKind(kind):
return "%s_Data*" % GetNameForKind(kind, internal=True)
+ if mojom.IsUnionKind(kind):
+ return "%s_Data" % GetNameForKind(kind, internal=True)
if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
return "mojo::MessagePipeHandle"
if mojom.IsEnumKind(kind):
@@ -91,7 +93,7 @@ def GetCppPodType(kind):
def GetCppArrayArgWrapperType(kind):
if mojom.IsEnumKind(kind):
return GetNameForKind(kind)
- if mojom.IsStructKind(kind):
+ if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
return "%sPtr" % GetNameForKind(kind)
if mojom.IsArrayKind(kind):
return "mojo::Array<%s> " % GetCppArrayArgWrapperType(kind.kind)
@@ -147,7 +149,7 @@ def GetCppResultWrapperType(kind):
def GetCppWrapperType(kind):
if mojom.IsEnumKind(kind):
return GetNameForKind(kind)
- if mojom.IsStructKind(kind):
+ if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
return "%sPtr" % GetNameForKind(kind)
if mojom.IsArrayKind(kind):
return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
@@ -206,6 +208,8 @@ def GetCppFieldType(kind):
if mojom.IsStructKind(kind):
return ("mojo::internal::StructPointer<%s_Data>" %
GetNameForKind(kind, internal=True))
+ if mojom.IsUnionKind(kind):
+ return "%s_Data" % GetNameForKind(kind, internal=True)
if mojom.IsArrayKind(kind):
return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind)
if mojom.IsMapKind(kind):
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
index 2b562f2..fb1cfd4 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
@@ -4,6 +4,7 @@
"""Generates dart source files from a mojom.Module."""
+import os
import re
import mojom.generate.generator as generator
@@ -373,10 +374,10 @@ class Generator(generator.Generator):
'struct_from_method': generator.GetStructFromMethod,
}
- def GetParameters(self):
+ def GetParameters(self, args):
return {
"namespace": self.module.namespace,
- "imports": self.GetImports(),
+ "imports": self.GetImports(args),
"kinds": self.module.kinds,
"enums": self.module.enums,
"module": self.module,
@@ -387,14 +388,20 @@ class Generator(generator.Generator):
}
@UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)
- def GenerateLibModule(self):
- return self.GetParameters()
+ def GenerateLibModule(self, args):
+ return self.GetParameters(args)
def GenerateFiles(self, args):
- self.Write(self.GenerateLibModule(),
+ self.Write(self.GenerateLibModule(args),
self.MatchMojomFilePath("%s.dart" % self.module.name))
- def GetImports(self):
+ def GetImports(self, args):
+ mojo_root_arg = next(
+ (x for x in args if x.startswith("--dart_mojo_root")), "")
+ (_, _, mojo_root_path) = mojo_root_arg.partition("=")
+ if not mojo_root_path.startswith("//"):
+ raise Exception("Malformed mojo SDK root: " + mojo_root_path)
+ mojo_root_path = mojo_root_path[2:] # strip //
used_names = set()
for each_import in self.module.imports:
simple_name = each_import["module_name"].split(".")[0]
@@ -410,6 +417,16 @@ class Generator(generator.Generator):
used_names.add(unique_name)
each_import["unique_name"] = unique_name + '_mojom'
counter += 1
+
+ # At this point, a module's path is reletive to the root of the repo.
+ # However, imports of libraries from the Mojo SDK are always reletive to
+ # root of the Mojo SDK, which may be different from the root of the repo.
+ # This code uses the --dart_mojo_root argument to ensure that Mojo SDK
+ # imports are reletive to the Mojo SDK root.
+ path = each_import['module'].path
+ if os.path.commonprefix([mojo_root_path, path]) == mojo_root_path:
+ path = os.path.relpath(path, mojo_root_path)
+ each_import["rebased_path"] = path
return self.module.imports
def GetImportedInterfaces(self):
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
index 9273186..f841b848 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
@@ -263,6 +263,8 @@ def GetImports(module):
if len(all_structs) > 0 or len(module.interfaces) > 0:
_imports['fmt'] = 'fmt'
_imports['mojo/public/go/bindings'] = 'bindings'
+ if len(module.interfaces) > 0:
+ _imports['mojo/public/go/system'] = 'system'
if len(all_structs) > 0:
_imports['sort'] = 'sort'
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
index dd68501..6c03ea6 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
+++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
@@ -61,20 +61,21 @@ template("mojom") {
"$generator_root/generators/cpp_templates/interface_request_validator_declaration.tmpl",
"$generator_root/generators/cpp_templates/interface_response_validator_declaration.tmpl",
"$generator_root/generators/cpp_templates/interface_stub_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/module-internal.h.tmpl",
"$generator_root/generators/cpp_templates/module.cc.tmpl",
"$generator_root/generators/cpp_templates/module.h.tmpl",
- "$generator_root/generators/cpp_templates/module-internal.h.tmpl",
- "$generator_root/generators/cpp_templates/serialization_macros.tmpl",
"$generator_root/generators/cpp_templates/struct_declaration.tmpl",
"$generator_root/generators/cpp_templates/struct_definition.tmpl",
- "$generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
"$generator_root/generators/cpp_templates/struct_macros.tmpl",
- "$generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
- "$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
+ "$generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
"$generator_root/generators/cpp_templates/union_declaration.tmpl",
"$generator_root/generators/cpp_templates/union_definition.tmpl",
+ "$generator_root/generators/cpp_templates/union_serialization_declaration.tmpl",
"$generator_root/generators/cpp_templates/union_serialization_definition.tmpl",
"$generator_root/generators/cpp_templates/validation_macros.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
"$generator_root/generators/cpp_templates/wrapper_union_class_declaration.tmpl",
"$generator_root/generators/cpp_templates/wrapper_union_class_definition.tmpl",
"$generator_root/generators/dart_templates/enum_definition.tmpl",
@@ -101,8 +102,8 @@ template("mojom") {
"$generator_root/generators/js_templates/module.amd.tmpl",
"$generator_root/generators/js_templates/module_definition.tmpl",
"$generator_root/generators/js_templates/struct_definition.tmpl",
- "$generator_root/generators/python_templates/module_macros.tmpl",
"$generator_root/generators/python_templates/module.py.tmpl",
+ "$generator_root/generators/python_templates/module_macros.tmpl",
"$generator_root/generators/mojom_cpp_generator.py",
"$generator_root/generators/mojom_dart_generator.py",
"$generator_root/generators/mojom_go_generator.py",
@@ -180,6 +181,7 @@ template("mojom") {
generator_js_outputs + generator_python_outputs
args = [
"{{source}}",
+ "--dart_mojo_root=${mojo_root}",
"--use_bundled_pylibs",
"-d",
rebase_path("//", root_build_dir),
@@ -334,21 +336,21 @@ template("mojom") {
output,
]
- invoker_base_dir = ""
- if (defined(invoker.base_dir)) {
- invoker_base_dir =
- rebase_path(invoker.base_dir, "$root_build_dir/../../", ".")
+ invoker_import_from = ""
+ if (defined(invoker.import_from)) {
+ invoker_import_from =
+ rebase_path(invoker.import_from, "$root_build_dir/../../", ".")
}
- rebase_base_dir =
- rebase_path("$root_build_dir/gen/$invoker_base_dir", root_build_dir)
+ rebase_import_from =
+ rebase_path("$root_build_dir/gen/$invoker_import_from", root_build_dir)
if (defined(invoker.sources)) {
rebase_inputs = rebase_path(inputs, root_build_dir)
}
rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
- "--base-dir=$rebase_base_dir",
+ "--base-dir=$rebase_import_from",
"--zip-inputs=$rebase_zip_inputs",
"--output=$rebase_output",
]
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
index 4e522c9..9c72cfa 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
@@ -45,6 +45,8 @@ class PackedField(object):
def GetSizeForKind(cls, kind):
if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct)):
return 8
+ if isinstance(kind, mojom.Union):
+ return 16
if (isinstance(kind, mojom.Interface) or
isinstance(kind, mojom.InterfaceRequest)):
kind = mojom.MSGPIPE
diff --git a/third_party/mojo/src/mojo/public/tools/dart_analyze.py b/third_party/mojo/src/mojo/public/tools/dart_analyze.py
index c200783..f26ddbf 100755
--- a/third_party/mojo/src/mojo/public/tools/dart_analyze.py
+++ b/third_party/mojo/src/mojo/public/tools/dart_analyze.py
@@ -20,6 +20,9 @@ import tempfile
import zipfile
_ANALYZING_PATTERN = re.compile(r'^Analyzing \[')
+_NO_ISSUES_FOUND_PATTERN = re.compile(r'^No issues found')
+_PART_WARNINGS_PATTERN = re.compile(
+ r'.*is a part and can not|^Only libraries can be analyzed')
_ERRORS_AND_WARNINGS_PATTERN = re.compile(
r'^[0-9]+ errors? and [0-9]+ warnings? found.')
_ERRORS_PATTERN = re.compile(r'^([0-9]+|No) (error|warning|issue)s? found.')
@@ -59,6 +62,8 @@ def main(args):
raw_lines.pop()
filtered_lines = [i for i in raw_lines if (
not re.match(_ANALYZING_PATTERN, i) and
+ not re.match(_NO_ISSUES_FOUND_PATTERN, i) and
+ not re.match(_PART_WARNINGS_PATTERN, i) and
not re.match(_ERRORS_AND_WARNINGS_PATTERN, i) and
not re.match(_ERRORS_PATTERN, i))]
for line in filtered_lines:
diff --git a/third_party/mojo/src/mojo/public/tools/gn/zip.py b/third_party/mojo/src/mojo/public/tools/gn/zip.py
index 506eb9e..a73f801 100755
--- a/third_party/mojo/src/mojo/public/tools/gn/zip.py
+++ b/third_party/mojo/src/mojo/public/tools/gn/zip.py
@@ -15,7 +15,7 @@ import zipfile
def DoZip(inputs, zip_inputs, output, base_dir):
files = []
- with zipfile.ZipFile(output, 'w') as outfile:
+ with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as outfile:
for f in inputs:
file_name = os.path.relpath(f, base_dir)
files.append(file_name)
diff --git a/third_party/mojo/src/mojo/public/tools/mojom_fetcher/mojom_fetcher.py b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/mojom_fetcher.py
new file mode 100755
index 0000000..b0283e3
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/mojom_fetcher.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+# 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.
+
+"""Tool to manage external mojom interfaces."""
+
+import argparse
+import errno
+import logging
+import os
+import sys
+import urllib2
+
+# Local library
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ "pylib"))
+# Bindings library
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ "..", "bindings", "pylib"))
+# Requests library
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ "..", "..", "..", "..", "third_party",
+ "requests", "src"))
+
+import requests
+
+from fetcher.repository import Repository
+from fetcher.dependency import Dependency
+from mojom.parse.parser import Parse, ParseError
+
+
+class UrlRewriterException(Exception):
+ """Exception when processing URL rewrite rules."""
+ pass
+
+class UrlRewriter(object):
+ """UrlRewriter rewrites URLs according to the provided mappings.
+
+ Note that mappings are not followed transitively. If mappings contains
+ {"a": "b", "b": "c"}, then UrlRewriter.rewrite("a") will return "b", not "c".
+ """
+
+ def __init__(self, mappings):
+ self._mappings = mappings
+ for target in self._mappings.values():
+ for source in self._mappings.keys():
+ if source in target or target in source:
+ raise UrlRewriterException(
+ "%s and %s share a common subpath" % (source, target))
+
+ def rewrite(self, path):
+ for origin, destination in self._mappings.items():
+ if path.startswith(origin):
+ return destination + path[len(origin):]
+ return path
+
+
+class MojomFetcher(object):
+ def __init__(self, repository, url_rewriter):
+ self._repository = repository
+ self._url_rewriter = url_rewriter
+
+ def _requests_get(self, url):
+ return requests.get(url, verify=True)
+
+ def _os_makedirs(self, dirs):
+ try:
+ os.makedirs(dirs)
+ except OSError as e:
+ # The directory may already exist, we don't care.
+ if e.errno != errno.EEXIST:
+ raise
+
+ def _open(self, f, mode="r"):
+ return open(f, mode)
+
+ def _download_dependencies(self, dependencies):
+ """Takes the list of mojom dependencies and download the external ones.
+ Returns the number of successfully downloaded dependencies."""
+
+ downloaded = 0
+ for dep in dependencies:
+ if self._maybe_download_dep(dep):
+ downloaded += 1
+ return downloaded
+
+ def _maybe_download_dep(self, dep):
+ if not dep.maybe_is_a_url():
+ return False
+
+ for candidate in dep.generate_candidate_urls():
+ url = self._url_rewriter.rewrite(candidate)
+ response = self._requests_get("https://" + url)
+ if not response.ok:
+ # If we get an error, it just mean that this candidate URL is not
+ # correct. We must try the other ones before giving up.
+ logging.debug("Error while downloading %s (%s)", candidate, url)
+ continue
+ # This is an external dependency
+ directory = os.path.dirname(candidate)
+ full_directory = os.path.join(self._repository.get_external_directory(),
+ directory)
+ try:
+ self._os_makedirs(full_directory)
+ except OSError as e:
+ # The directory may already exist, we don't care.
+ if e.errno != errno.EEXIST:
+ raise
+ with self._open(os.path.join(self._repository.get_external_directory(),
+ candidate), "w") as f:
+ data = response.content
+ try:
+ Parse(data, candidate)
+ except ParseError:
+ logging.warn("File at %s is not a mojom", url)
+ break
+ f.write(data)
+ return True
+ return False
+
+ def discover(self):
+ """Discover missing .mojom dependencies and download them."""
+ while True:
+ missing_deps = self._repository.get_missing_dependencies()
+ downloaded = self._download_dependencies(missing_deps)
+ if downloaded == 0:
+ return 0
+
+ def get(self, dep):
+ dependency = Dependency(self._repository, ".", dep)
+ downloaded = self._download_dependencies([dependency])
+ if downloaded != 0:
+ return self.discover()
+ else:
+ return -1
+
+ def update(self):
+ dependencies = [Dependency(self._repository, ".", f)
+ for f in self._repository.get_external_urls()]
+ # TODO(etiennej): We may want to suggest to the user to delete
+ # un-downloadable dependencies.
+ downloaded = self._download_dependencies(dependencies)
+ if downloaded != 0:
+ return self.discover()
+ else:
+ return -1
+
+def _main(args):
+ if args.prefix_rewrite:
+ rewrite_rules = dict([x.split(':', 1) for x in args.prefix_rewrite])
+ else:
+ rewrite_rules = {}
+ rewriter = UrlRewriter(rewrite_rules)
+ repository_path = os.path.abspath(args.repository_path)
+ repository = Repository(repository_path, args.external_dir)
+ fetcher = MojomFetcher(repository, rewriter)
+ if args.action == 'discover':
+ return fetcher.discover()
+ elif args.action == 'get':
+ return fetcher.get(args.url)
+ elif args.action == 'update':
+ return fetcher.update()
+ else:
+ logging.error("No matching action %s", args.action[0])
+ return -1
+
+def main():
+ logging.basicConfig(level=logging.ERROR)
+ parser = argparse.ArgumentParser(description='Download mojom dependencies.')
+ parser.add_argument('--repository-path', type=str, action='store',
+ default='.', help='The path to the client repository.')
+ parser.add_argument('--external-dir', type=str, action='store',
+ default='external',
+ help='Directory for external interfaces')
+ parser.add_argument('--prefix-rewrite', type=str, action='append',
+ help='If present, "origin:destination" pairs. "origin" '
+ 'prefixes will be rewritten as "destination". May be '
+ 'used several times. Rewrites are not transitive.')
+
+ subparsers = parser.add_subparsers(dest='action', help='action')
+ parser_get = subparsers.add_parser(
+ 'get', help='Get the specified URL and all its transitive dependencies')
+ parser_get.add_argument('url', type=str, nargs=1,
+ help='URL to download for get action')
+ subparsers.add_parser(
+ 'discover',
+ help='Recursively discover and download new external dependencies')
+ subparsers.add_parser('update', help='Update all external dependencies')
+
+ args = parser.parse_args()
+ return _main(args)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/__init__.py b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/__init__.py
diff --git a/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/dependency.py b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/dependency.py
new file mode 100644
index 0000000..a4716e4
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/dependency.py
@@ -0,0 +1,97 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+
+class Dependency(object):
+ """Dependency represents an import request from one mojom file to another.
+ """
+ def __init__(self, repository, importer, imported):
+ self._repository = repository
+ self._importer_filename = os.path.normpath(importer)
+ self._imported_filename = os.path.normpath(imported)
+
+ def __str__(self):
+ return str(self.__dict__)
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def get_importer(self):
+ """Returns the name and full path of the file doing the import."""
+ return self._importer_filename
+
+ def get_imported(self):
+ """Returns the imported file (filename and path)."""
+ return self._imported_filename
+
+ def is_sdk_dep(self):
+ """Returns whether this dependency is from the mojo SDK."""
+ return (self._imported_filename.startswith("mojo/public/") or
+ self._imported_filename.startswith("//mojo/public/"))
+
+ def _is_in_external(self):
+ """Returns whether this dependency is under the external directory."""
+ common = os.path.commonprefix((self._repository.get_external_directory(),
+ self._importer_filename))
+ return common == self._repository.get_external_directory()
+
+ def maybe_is_a_url(self):
+ """Returns whether this dependency may be pointing to a downloadable
+ ressource."""
+ if self._is_in_external() and not self.is_sdk_dep():
+ # External dependencies may refer to other dependencies by relative path,
+ # so they can always be URLs.
+ return True
+
+ base, _ = self._imported_filename.split(os.path.sep, 1)
+ if not '.' in base:
+ # There is no dot separator in the first part of the path; it cannot be a
+ # URL.
+ return False
+ return True
+
+ def generate_candidate_urls(self):
+ """Generates possible paths where to download this dependency. It is
+ expected that at most one of them should work."""
+ candidates = []
+
+ base, _ = self._imported_filename.split(os.path.sep, 1)
+ if '.' in base and not base.startswith('.'):
+ # This import may be an absolute URL path (without scheme).
+ candidates.append(self._imported_filename)
+
+ # External dependencies may refer to other dependencies by relative path.
+ if self._is_in_external():
+ directory = os.path.relpath(os.path.dirname(self._importer_filename),
+ self._repository.get_external_directory())
+
+ # This is to handle the case where external dependencies use
+ # imports relative to a directory upper in the directory structure. As we
+ # don't know which directory, we need to go through all of them.
+ while len(directory) > 0:
+ candidates.append(os.path.join(directory, self._imported_filename))
+ directory = os.path.dirname(directory)
+ return candidates
+
+ def get_search_path_for_dependency(self):
+ """Return all possible search paths for this dependency."""
+
+ # Root directory and external directory are always included.
+ search_paths = set([self._repository.get_repo_root_directory(),
+ self._repository.get_external_directory()])
+ # Local import paths
+ search_paths.add(os.path.dirname(self._importer_filename))
+
+ if self._is_in_external():
+ directory = os.path.dirname(self._importer_filename)
+
+ # This is to handle the case where external dependencies use
+ # imports relative to a directory upper in the directory structure. As we
+ # don't know which directory, we need to go through all of them.
+ while self._repository.get_external_directory() in directory:
+ search_paths.add(directory)
+ directory = os.path.dirname(directory)
+ return search_paths
diff --git a/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/mojom_file.py b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/mojom_file.py
new file mode 100644
index 0000000..ad8c969
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/mojom_file.py
@@ -0,0 +1,18 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from fetcher.dependency import Dependency
+
+
+class MojomFile(object):
+ """Mojom represents an interface file at a given location in the
+ repository."""
+ def __init__(self, repository, name):
+ self.name = name
+ self._repository = repository
+ self.deps = []
+
+ def add_dependency(self, dependency):
+ """Declare a new dependency of this mojom."""
+ self.deps.append(Dependency(self._repository, self.name, dependency))
diff --git a/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/repository.py b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/repository.py
new file mode 100644
index 0000000..dde99b2
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/mojom_fetcher/pylib/fetcher/repository.py
@@ -0,0 +1,88 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from fetcher.dependency import Dependency
+from mojom.parse.parser import Parse
+
+
+class Repository(object):
+ """Repository represents a code repository on the local disc."""
+ def __init__(self, root_dir, external_dir):
+ """root_dir represents the root of the repository;
+ external_dir is the relative path of the external directory within the
+ repository (so, relative to root_dir)
+ """
+ self._root_dir = os.path.normpath(root_dir)
+ self._external_dir = external_dir
+
+ def get_repo_root_directory(self):
+ return self._root_dir
+
+ def get_external_directory(self):
+ return os.path.join(self._root_dir, self._external_dir)
+
+ def _os_walk(self, root_directory):
+ # This method is included for dependency injection
+ return os.walk(root_directory)
+
+ def _open(self, filename):
+ # This method is included for dependency injection
+ return open(filename)
+
+ def _get_all_mojom_in_directory(self, root_directory):
+ mojoms = []
+ for dirname, _, files in self._os_walk(root_directory):
+ for f in files:
+ if f.endswith(".mojom"):
+ mojoms.append(os.path.join(dirname,f))
+ return mojoms
+
+ def _resolve_dependencies(self, dependencies, mojoms):
+ """Resolve dependencies between discovered mojoms, so we know which are the
+ missing ones."""
+ missing = []
+ for dependency in dependencies:
+ found = False
+ for search_path in dependency.get_search_path_for_dependency():
+ if os.path.normpath(
+ os.path.join(search_path,
+ dependency.get_imported())) in mojoms:
+ found = True
+ break
+ if not found:
+ missing.append(dependency)
+ return missing
+
+ def get_missing_dependencies(self):
+ """get_missing_dependencies returns a set of dependencies that are required
+ by mojoms in this repository but not available.
+ """
+ # Update the list of available mojoms in this repository.
+ mojoms = set(self._get_all_mojom_in_directory(self._root_dir))
+
+ # Find all declared dependencies
+ needed_deps = set([])
+ for mojom in mojoms:
+ with self._open(mojom) as f:
+ source = f.read()
+ tree = Parse(source, mojom)
+ for dep in tree.import_list:
+ needed_deps.add(Dependency(self, dep.filename, dep.import_filename))
+
+ missing_deps = self._resolve_dependencies(needed_deps, mojoms)
+
+ return missing_deps
+
+ def get_external_urls(self):
+ """Get all external mojom files in this repository, by urls (without
+ scheme)."""
+ mojoms = set(self._get_all_mojom_in_directory(
+ self.get_external_directory()))
+ urls = []
+ for mojom in mojoms:
+ urls.append(os.path.relpath(mojom, self.get_external_directory()))
+ return urls
+
diff --git a/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn b/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn
index 2b29c1a..f2c1ba8 100644
--- a/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn
@@ -15,4 +15,6 @@ mojom("interfaces") {
deps = [
"../../../geometry/public/interfaces",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn b/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn
index 16fe33b..4edbf63 100644
--- a/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn
@@ -9,4 +9,6 @@ mojom("interfaces") {
sources = [
"clipboard.mojom",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/content_handler/public/interfaces/BUILD.gn b/third_party/mojo_services/src/content_handler/public/interfaces/BUILD.gn
index c58507a..ad1bb9a 100644
--- a/third_party/mojo_services/src/content_handler/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/content_handler/public/interfaces/BUILD.gn
@@ -23,4 +23,6 @@ mojom("interfaces") {
]
mojo_sdk_deps = [ "mojo/public/interfaces/application" ]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn b/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn
index 9047ee2..217eb27 100644
--- a/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn
@@ -9,4 +9,6 @@ mojom("interfaces") {
sources = [
"geometry.mojom",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn b/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn
index ec061df..b782146 100644
--- a/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn
@@ -19,4 +19,6 @@ mojom("interfaces") {
deps = [
"../../../geometry/public/interfaces",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn b/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn
index 79aa6a6..a02039e 100644
--- a/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn
@@ -24,4 +24,6 @@ mojom("interfaces") {
deps = [
"$mojo_network_service_root/network/public/interfaces",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn b/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn
index 5ef09eb..5f0f22d 100644
--- a/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn
@@ -17,4 +17,6 @@ mojom("interfaces") {
deps = [
"../../../geometry/public/interfaces",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom b/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom
index 0086265..9fa36303 100644
--- a/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom
+++ b/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom
@@ -70,6 +70,8 @@ struct Event {
EventType action;
// TODO(sky): parts of this should move to PointerData.
EventFlags flags;
+ // Time the event was delivered. The time is in milliseconds and corresponds
+ // to the uptime of the machine.
int64 time_stamp;
KeyData? key_data;
PointerData? pointer_data;
diff --git a/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn b/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn
index 86ff870..5603e17 100644
--- a/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn
@@ -18,4 +18,6 @@ mojom("interfaces") {
"../../../input_events/public/interfaces",
"../../../surfaces/public/interfaces:surface_id",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn b/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn
index 19b9f8a..61158f3 100644
--- a/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn
@@ -21,4 +21,6 @@ mojom("interfaces") {
deps = [
"$mojo_network_service_root/network/public/interfaces",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn b/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn
index 7902a7a..36c8707 100644
--- a/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn
@@ -20,10 +20,14 @@ mojom("interfaces") {
"../../../gpu/public/interfaces",
"../../../native_viewport/public/interfaces",
]
+
+ import_from = mojo_root
}
mojom("surface_id") {
sources = [
"surface_id.mojom",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn b/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn
index 177066b..eff5f62 100644
--- a/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn
@@ -22,4 +22,6 @@ mojom("interfaces") {
"../../../native_viewport/public/interfaces",
"../../../surfaces/public/interfaces:surface_id",
]
+
+ import_from = mojo_root
}
diff --git a/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn b/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn
index b97f069..3cf56dad 100644
--- a/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn
+++ b/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn
@@ -19,4 +19,6 @@ mojom("interfaces") {
"../../../geometry/public/interfaces",
"../../../input_events/public/interfaces",
]
+
+ import_from = mojo_root
}