diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-07-14 17:41:05 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:37:36 +0000 |
commit | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch) | |
tree | 6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/mojo | |
parent | 7366110654eec46f21b6824f302356426f48cd74 (diff) | |
download | qtwebengine-chromium-399c965b6064c440ddcf4015f5f8e9d131c7a0a6.tar.gz |
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/mojo')
448 files changed, 7306 insertions, 16568 deletions
diff --git a/chromium/mojo/BUILD.gn b/chromium/mojo/BUILD.gn index 218ba9140bf..c78e40108ed 100644 --- a/chromium/mojo/BUILD.gn +++ b/chromium/mojo/BUILD.gn @@ -10,7 +10,6 @@ group("mojo") { deps = [ ":tests", "//mojo/common", - "//mojo/services", ] if (!(is_linux && target_cpu == "x86")) { @@ -24,7 +23,7 @@ group("mojo") { deps += [ "//mojo/android" ] } - deps += [ "//mojo/shell:all" ] + deps += [ "//services/shell:all" ] } group("tests") { @@ -32,6 +31,7 @@ group("tests") { deps = [ "//ipc/mojo:ipc_mojo_unittests", "//mojo/common:mojo_common_unittests", + "//mojo/converters/blink:blink_converters_unittests", "//mojo/converters/surfaces/tests:mojo_surfaces_lib_unittests", "//mojo/edk/js/test:js_integration_tests", "//mojo/edk/js/test:js_unittests", @@ -41,8 +41,8 @@ group("tests") { "//mojo/edk/test:mojo_public_bindings_unittests", "//mojo/edk/test:mojo_public_system_perftests", "//mojo/edk/test:mojo_public_system_unittests", - "//mojo/shell/public/cpp/tests:mojo_public_application_unittests", - "//mojo/shell/runner/host:mojo_runner_host_unittests", - "//mojo/shell/tests", + "//services/shell/public/cpp/tests:mojo_public_application_unittests", + "//services/shell/runner/host:mojo_runner_host_unittests", + "//services/shell/tests", ] } diff --git a/chromium/mojo/DEPS b/chromium/mojo/DEPS index ff1852de7ce..a6592005c85 100644 --- a/chromium/mojo/DEPS +++ b/chromium/mojo/DEPS @@ -2,4 +2,6 @@ include_rules = [ "+base", "+build", "+testing", + + "+services/shell", ] diff --git a/chromium/mojo/OWNERS b/chromium/mojo/OWNERS index e4e22be3873..7252d2bba11 100644 --- a/chromium/mojo/OWNERS +++ b/chromium/mojo/OWNERS @@ -2,3 +2,4 @@ amistry@chromium.org ben@chromium.org rockot@chromium.org sky@chromium.org +yzshen@chromium.org diff --git a/chromium/mojo/README.md b/chromium/mojo/README.md index c2e8add6e35..ea2f94066cd 100644 --- a/chromium/mojo/README.md +++ b/chromium/mojo/README.md @@ -5,4 +5,4 @@ Mojo is an effort to extract a common platform out of Chrome's renderer and plugin processes that can support multiple types of sandboxed content, such as HTML, Pepper, or NaCl. -(Mojo primer for Chromium developers)[/docs/mojo_in_chromium.md]. +[Mojo primer for Chromium developers](https://www.chromium.org/developers/design-documents/mojo). diff --git a/chromium/mojo/android/BUILD.gn b/chromium/mojo/android/BUILD.gn index 020ef6dc7a5..50a619d5b44 100644 --- a/chromium/mojo/android/BUILD.gn +++ b/chromium/mojo/android/BUILD.gn @@ -98,6 +98,8 @@ android_library("mojo_javatests") { "//base:base_java", "//base:base_java_test_support", "//mojo/public/interfaces/bindings/tests:test_interfaces_java", + "//mojo/public/interfaces/bindings/tests:test_mojom_import2_java", + "//mojo/public/interfaces/bindings/tests:test_mojom_import_java", "//mojo/public/java:bindings", "//mojo/public/java:system", ] @@ -141,4 +143,5 @@ instrumentation_test_apk("mojo_test_apk") { native_libs = [ "libmojo_java_unittests.so" ] apk_name = "MojoTest" android_manifest = "javatests/AndroidManifest.xml" + isolate_file = "../mojo_test_apk.isolate" } diff --git a/chromium/mojo/android/system/core_impl.cc b/chromium/mojo/android/system/core_impl.cc index d30d6a1765c..5c47ef613e5 100644 --- a/chromium/mojo/android/system/core_impl.cc +++ b/chromium/mojo/android/system/core_impl.cc @@ -7,13 +7,14 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/android/base_jni_registrar.h" #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" #include "base/android/library_loader/library_loader_hooks.h" #include "base/android/scoped_java_ref.h" #include "base/bind.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "jni/CoreImpl_jni.h" #include "mojo/message_pump/handle_watcher.h" @@ -39,7 +40,7 @@ void AsyncWaitCallback(mojo::common::HandleWatcher* watcher, void* data, MojoResult result) { delete watcher; - scoped_ptr<AsyncWaitCallbackData> callback_data( + std::unique_ptr<AsyncWaitCallbackData> callback_data( static_cast<AsyncWaitCallbackData*>(data)); mojo::android::Java_CoreImpl_onAsyncWaitResult( base::android::AttachCurrentThread(), @@ -401,7 +402,7 @@ static void CancelAsyncWait(JNIEnv* env, // the data_ptr. return; } - scoped_ptr<AsyncWaitCallbackData> deleter( + std::unique_ptr<AsyncWaitCallbackData> deleter( reinterpret_cast<AsyncWaitCallbackData*>(data_ptr)); delete reinterpret_cast<common::HandleWatcher*>( static_cast<MojoAsyncWaitID>(id)); diff --git a/chromium/mojo/common/BUILD.gn b/chromium/mojo/common/BUILD.gn index bffb6124ae5..7ef74fd5e6b 100644 --- a/chromium/mojo/common/BUILD.gn +++ b/chromium/mojo/common/BUILD.gn @@ -2,15 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") group("common") { public_deps = [ ":common_base", + ":common_custom_types", ":url_type_converters", ] } +# GYP version: mojo/mojo_base.gyp:mojo_common_custom_types +mojom("common_custom_types") { + sources = [ + "common_custom_types.mojom", + ] +} + # GYP version: mojo/mojo_base.gyp:mojo_common_lib component("common_base") { output_name = "mojo_common_lib" @@ -36,7 +45,6 @@ component("common_base") { deps = [ "//base", "//base/third_party/dynamic_annotations", - "//mojo/message_pump", "//mojo/public/c/system:for_component", "//mojo/public/cpp/bindings", ] @@ -58,16 +66,27 @@ source_set("url_type_converters") { ] } +# GYP version: mojo/mojo_base.gyp:mojo_test_common_custom_types +mojom("test_common_custom_types") { + sources = [ + "test_common_custom_types.mojom", + ] + public_deps = [ + ":common_custom_types", + ] +} + # GYP version: mojo/mojo_base.gyp:mojo_common_unittests test("mojo_common_unittests") { deps = [ ":common", + ":common_custom_types", + ":test_common_custom_types", "//base", "//base:message_loop_tests", "//base/test:test_support", "//mojo/edk/test:run_all_unittests", "//mojo/edk/test:test_support", - "//mojo/message_pump", "//mojo/public/cpp/bindings", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", @@ -75,18 +94,9 @@ test("mojo_common_unittests") { ] sources = [ - # The message_pump tests are so small and some what related to this code - # that we put them here. - "../message_pump/handle_watcher_unittest.cc", - "../message_pump/message_pump_mojo_unittest.cc", + "common_custom_types_unittest.cc", "common_type_converters_unittest.cc", ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } } test("mojo_common_perftests") { @@ -94,18 +104,7 @@ test("mojo_common_perftests") { ":common", "//base", "//mojo/edk/test:run_all_perftests", - "//mojo/message_pump", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", ] - - sources = [ - "../message_pump/handle_watcher_perftest.cc", - ] - - if (is_linux && !is_component_build) { - # This test dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } } diff --git a/chromium/mojo/common/DEPS b/chromium/mojo/common/DEPS index 21f3b0da977..588c68dbff9 100644 --- a/chromium/mojo/common/DEPS +++ b/chromium/mojo/common/DEPS @@ -1,17 +1,16 @@ include_rules = [ # common must not depend on embedder. "-mojo", - "+mojo/shell/public/cpp", + "+services/shell/public/cpp", "+mojo/common", - "+mojo/message_pump", "+mojo/public", ] specific_include_rules = { "trace_controller_impl\.h": [ - "+mojo/services/tracing/public/interfaces/tracing.mojom.h" + "+services/tracing/public/interfaces/tracing.mojom.h" ], "tracing_impl\.h": [ - "+mojo/services/tracing/public/interfaces/tracing.mojom.h" + "+services/tracing/public/interfaces/tracing.mojom.h" ], } diff --git a/chromium/mojo/common/common_custom_types.mojom b/chromium/mojo/common/common_custom_types.mojom new file mode 100644 index 00000000000..10ebe058be8 --- /dev/null +++ b/chromium/mojo/common/common_custom_types.mojom @@ -0,0 +1,8 @@ +// Copyright 2016 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.common.mojom; + +[Native] +struct FilePath; diff --git a/chromium/mojo/common/common_custom_types.typemap b/chromium/mojo/common/common_custom_types.typemap new file mode 100644 index 00000000000..fc2c767a84f --- /dev/null +++ b/chromium/mojo/common/common_custom_types.typemap @@ -0,0 +1,12 @@ +# Copyright 2016 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. + +mojom = "//mojo/common/common_custom_types.mojom" +public_headers = [ "//base/files/file_path.h" ] +traits_headers = [ "//ipc/ipc_message_utils.h" ] +deps = [ + "//ipc", +] + +type_mappings = [ "mojo.common.mojom.FilePath=base::FilePath" ] diff --git a/chromium/mojo/common/common_custom_types_unittest.cc b/chromium/mojo/common/common_custom_types_unittest.cc new file mode 100644 index 00000000000..2223c26c2d0 --- /dev/null +++ b/chromium/mojo/common/common_custom_types_unittest.cc @@ -0,0 +1,52 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "mojo/common/common_custom_types.mojom.h" +#include "mojo/common/test_common_custom_types.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace common { +namespace test { + +class TestFilePathImpl : public TestFilePath { + public: + explicit TestFilePathImpl(TestFilePathRequest request) + : binding_(this, std::move(request)) {} + + // TestFilePath implementation: + void BounceFilePath(const base::FilePath& in, + const BounceFilePathCallback& callback) override { + callback.Run(in); + } + + private: + mojo::Binding<TestFilePath> binding_; +}; + +TEST(CommonCustomTypesTest, FilePath) { + base::MessageLoop message_loop; + base::RunLoop run_loop; + + TestFilePathPtr ptr; + TestFilePathImpl impl(GetProxy(&ptr)); + + base::FilePath dir(FILE_PATH_LITERAL("hello")); + base::FilePath file = dir.Append(FILE_PATH_LITERAL("world")); + + ptr->BounceFilePath(file, [&run_loop, &file](const base::FilePath& out) { + EXPECT_EQ(file, out); + run_loop.Quit(); + }); + + run_loop.Run(); +} + +} // namespace test +} // namespace common +} // namespace mojo diff --git a/chromium/mojo/common/data_pipe_drainer.cc b/chromium/mojo/common/data_pipe_drainer.cc index e652e846be0..1133e1165b8 100644 --- a/chromium/mojo/common/data_pipe_drainer.cc +++ b/chromium/mojo/common/data_pipe_drainer.cc @@ -17,7 +17,9 @@ DataPipeDrainer::DataPipeDrainer(Client* client, mojo::ScopedDataPipeConsumerHandle source) : client_(client), source_(std::move(source)), weak_factory_(this) { DCHECK(client_); - ReadData(); + handle_watcher_.Start( + source_.get(), MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&DataPipeDrainer::WaitComplete, weak_factory_.GetWeakPtr())); } DataPipeDrainer::~DataPipeDrainer() {} @@ -30,22 +32,13 @@ void DataPipeDrainer::ReadData() { if (rv == MOJO_RESULT_OK) { client_->OnDataAvailable(buffer, num_bytes); EndReadDataRaw(source_.get(), num_bytes); - WaitForData(); - } else if (rv == MOJO_RESULT_SHOULD_WAIT) { - WaitForData(); } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { client_->OnDataComplete(); - } else { + } else if (rv != MOJO_RESULT_SHOULD_WAIT) { DCHECK(false) << "Unhandled MojoResult: " << rv; } } -void DataPipeDrainer::WaitForData() { - handle_watcher_.Start( - source_.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, - base::Bind(&DataPipeDrainer::WaitComplete, weak_factory_.GetWeakPtr())); -} - void DataPipeDrainer::WaitComplete(MojoResult result) { ReadData(); } diff --git a/chromium/mojo/common/data_pipe_drainer.h b/chromium/mojo/common/data_pipe_drainer.h index 7a737163310..d0366fac358 100644 --- a/chromium/mojo/common/data_pipe_drainer.h +++ b/chromium/mojo/common/data_pipe_drainer.h @@ -10,8 +10,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/message_pump/handle_watcher.h" #include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/watcher.h" namespace mojo { namespace common { @@ -32,12 +32,11 @@ class MOJO_COMMON_EXPORT DataPipeDrainer { private: void ReadData(); - void WaitForData(); void WaitComplete(MojoResult result); Client* client_; mojo::ScopedDataPipeConsumerHandle source_; - mojo::common::HandleWatcher handle_watcher_; + mojo::Watcher handle_watcher_; base::WeakPtrFactory<DataPipeDrainer> weak_factory_; diff --git a/chromium/mojo/common/test_common_custom_types.mojom b/chromium/mojo/common/test_common_custom_types.mojom new file mode 100644 index 00000000000..0d2f165a809 --- /dev/null +++ b/chromium/mojo/common/test_common_custom_types.mojom @@ -0,0 +1,12 @@ +// Copyright 2016 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.common.test; + +import "mojo/common/common_custom_types.mojom"; + +interface TestFilePath { + BounceFilePath(mojo.common.mojom.FilePath in) + => (mojo.common.mojom.FilePath out); +}; diff --git a/chromium/mojo/common/typemaps.gni b/chromium/mojo/common/typemaps.gni new file mode 100644 index 00000000000..4c3809ddf83 --- /dev/null +++ b/chromium/mojo/common/typemaps.gni @@ -0,0 +1,5 @@ +# Copyright 2016 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. + +typemaps = [ "//mojo/common/common_custom_types.typemap" ] diff --git a/chromium/mojo/converters/blink/BUILD.gn b/chromium/mojo/converters/blink/BUILD.gn index 7f6b412e8b8..bc32145575a 100644 --- a/chromium/mojo/converters/blink/BUILD.gn +++ b/chromium/mojo/converters/blink/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//testing/test.gni") + component("blink") { output_name = "mojo_blink_lib" @@ -15,8 +17,26 @@ component("blink") { deps = [ "//base", - "//components/mus/public/interfaces", "//mojo/public/c/system:for_component", + "//mojo/public/cpp/bindings:bindings", + "//third_party/WebKit/public:blink", + "//ui/events", + "//ui/events:dom_keycode_converter", + ] +} + +test("blink_converters_unittests") { + sources = [ + "blink_input_events_type_converters_unittest.cc", + ] + deps = [ + ":blink", + "//base:message_loop_tests", + "//base/test:run_all_unittests", + "//base/test:test_support", + "//mojo/edk/test:test_support", + "//mojo/public/cpp/bindings:bindings", + "//testing/gtest", "//third_party/WebKit/public:blink", "//ui/events", ] diff --git a/chromium/mojo/converters/blink/DEPS b/chromium/mojo/converters/blink/DEPS index 95de851ef23..6678b7cae28 100644 --- a/chromium/mojo/converters/blink/DEPS +++ b/chromium/mojo/converters/blink/DEPS @@ -1,6 +1,5 @@ include_rules = [ "+base", - "+components/mus/public", "+third_party/WebKit/public", "+ui/events" ] diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters.cc b/chromium/mojo/converters/blink/blink_input_events_type_converters.cc index c7857c92417..9c7e63911ea 100644 --- a/chromium/mojo/converters/blink/blink_input_events_type_converters.cc +++ b/chromium/mojo/converters/blink/blink_input_events_type_converters.cc @@ -8,125 +8,120 @@ #include "base/logging.h" #include "base/time/time.h" -#include "components/mus/public/interfaces/input_event_constants.mojom.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/base_event_utils.h" #include "ui/events/event.h" +#include "ui/events/keycodes/dom/keycode_converter.h" namespace mojo { namespace { -double EventTimeToWebEventTime(const mus::mojom::EventPtr& event) { - return base::TimeDelta::FromInternalValue(event->time_stamp).InSecondsF(); +double EventTimeToWebEventTime(const ui::Event& event) { + return base::TimeDelta::FromInternalValue( + event.time_stamp().ToInternalValue()) + .InSecondsF(); } int EventFlagsToWebEventModifiers(int flags) { int modifiers = 0; - if (flags & mus::mojom::kEventFlagShiftDown) + if (flags & ui::EF_SHIFT_DOWN) modifiers |= blink::WebInputEvent::ShiftKey; - if (flags & mus::mojom::kEventFlagControlDown) + if (flags & ui::EF_CONTROL_DOWN) modifiers |= blink::WebInputEvent::ControlKey; - if (flags & mus::mojom::kEventFlagAltDown) + if (flags & ui::EF_ALT_DOWN) modifiers |= blink::WebInputEvent::AltKey; // TODO(beng): MetaKey/META_MASK - if (flags & mus::mojom::kEventFlagLeftMouseButton) + if (flags & ui::EF_LEFT_MOUSE_BUTTON) modifiers |= blink::WebInputEvent::LeftButtonDown; - if (flags & mus::mojom::kEventFlagMiddleMouseButton) + if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) modifiers |= blink::WebInputEvent::MiddleButtonDown; - if (flags & mus::mojom::kEventFlagRightMouseButton) + if (flags & ui::EF_RIGHT_MOUSE_BUTTON) modifiers |= blink::WebInputEvent::RightButtonDown; - if (flags & mus::mojom::kEventFlagCapsLockOn) + if (flags & ui::EF_CAPS_LOCK_ON) modifiers |= blink::WebInputEvent::CapsLockOn; return modifiers; } int EventFlagsToWebInputEventModifiers(int flags) { - return (flags & mus::mojom::kEventFlagShiftDown - ? blink::WebInputEvent::ShiftKey - : 0) | - (flags & mus::mojom::kEventFlagControlDown - ? blink::WebInputEvent::ControlKey - : 0) | - (flags & mus::mojom::kEventFlagCapsLockOn - ? blink::WebInputEvent::CapsLockOn - : 0) | - (flags & mus::mojom::kEventFlagAltDown ? blink::WebInputEvent::AltKey - : 0); + return (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) | + (flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) | + (flags & ui::EF_CAPS_LOCK_ON ? blink::WebInputEvent::CapsLockOn : 0) | + (flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0); } int GetClickCount(int flags) { - if (flags & mus::mojom::kMouseEventFlagIsTripleClick) + if (flags & ui::EF_IS_TRIPLE_CLICK) return 3; - else if (flags & mus::mojom::kMouseEventFlagIsDoubleClick) + else if (flags & ui::EF_IS_DOUBLE_CLICK) return 2; return 1; } -void SetWebMouseEventLocation(const mus::mojom::LocationData& location_data, +void SetWebMouseEventLocation(const ui::LocatedEvent& located_event, blink::WebMouseEvent* web_event) { - web_event->x = static_cast<int>(location_data.x); - web_event->y = static_cast<int>(location_data.y); - web_event->globalX = static_cast<int>(location_data.screen_x); - web_event->globalY = static_cast<int>(location_data.screen_y); + web_event->x = static_cast<int>(located_event.x()); + web_event->y = static_cast<int>(located_event.y()); + web_event->globalX = static_cast<int>(located_event.root_location_f().x()); + web_event->globalY = static_cast<int>(located_event.root_location_f().y()); } -scoped_ptr<blink::WebInputEvent> BuildWebMouseEventFrom( - const mus::mojom::EventPtr& event) { - scoped_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent); - // TODO(crbug.com/593375): Set pointerType from event->pointer_data->kind +std::unique_ptr<blink::WebInputEvent> BuildWebMouseEventFrom( + const ui::PointerEvent& event) { + std::unique_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent); - if (event->pointer_data && event->pointer_data->location) - SetWebMouseEventLocation(*(event->pointer_data->location), web_event.get()); + web_event->pointerType = blink::WebPointerProperties::PointerType::Mouse; + SetWebMouseEventLocation(event, web_event.get()); - web_event->modifiers = EventFlagsToWebEventModifiers(event->flags); + web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); web_event->timeStampSeconds = EventTimeToWebEventTime(event); web_event->button = blink::WebMouseEvent::ButtonNone; - if (event->flags & mus::mojom::kEventFlagLeftMouseButton) + if (event.flags() & ui::EF_LEFT_MOUSE_BUTTON) web_event->button = blink::WebMouseEvent::ButtonLeft; - if (event->flags & mus::mojom::kEventFlagMiddleMouseButton) + if (event.flags() & ui::EF_MIDDLE_MOUSE_BUTTON) web_event->button = blink::WebMouseEvent::ButtonMiddle; - if (event->flags & mus::mojom::kEventFlagRightMouseButton) + if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON) web_event->button = blink::WebMouseEvent::ButtonRight; - switch (event->action) { - case mus::mojom::EventType::POINTER_DOWN: + switch (event.type()) { + case ui::ET_POINTER_DOWN: web_event->type = blink::WebInputEvent::MouseDown; break; - case mus::mojom::EventType::POINTER_UP: + case ui::ET_POINTER_UP: web_event->type = blink::WebInputEvent::MouseUp; break; - case mus::mojom::EventType::POINTER_MOVE: + case ui::ET_POINTER_MOVED: web_event->type = blink::WebInputEvent::MouseMove; break; - case mus::mojom::EventType::MOUSE_EXIT: + case ui::ET_MOUSE_EXITED: web_event->type = blink::WebInputEvent::MouseLeave; break; default: - NOTIMPLEMENTED() << "Received unexpected event: " << event->action; + NOTIMPLEMENTED() << "Received unexpected event: " << event.type(); break; } - web_event->clickCount = GetClickCount(event->flags); + web_event->clickCount = GetClickCount(event.flags()); return std::move(web_event); } -scoped_ptr<blink::WebInputEvent> BuildWebKeyboardEvent( - const mus::mojom::EventPtr& event) { - scoped_ptr<blink::WebKeyboardEvent> web_event(new blink::WebKeyboardEvent); +std::unique_ptr<blink::WebInputEvent> BuildWebKeyboardEvent( + const ui::KeyEvent& event) { + std::unique_ptr<blink::WebKeyboardEvent> web_event( + new blink::WebKeyboardEvent); - web_event->modifiers = EventFlagsToWebInputEventModifiers(event->flags); + web_event->modifiers = EventFlagsToWebInputEventModifiers(event.flags()); web_event->timeStampSeconds = EventTimeToWebEventTime(event); - switch (event->action) { - case mus::mojom::EventType::KEY_PRESSED: - web_event->type = event->key_data->is_char - ? blink::WebInputEvent::Char - : blink::WebInputEvent::RawKeyDown; + switch (event.type()) { + case ui::ET_KEY_PRESSED: + web_event->type = event.is_char() ? blink::WebInputEvent::Char + : blink::WebInputEvent::RawKeyDown; break; - case mus::mojom::EventType::KEY_RELEASED: + case ui::ET_KEY_RELEASED: web_event->type = blink::WebInputEvent::KeyUp; break; default: @@ -136,61 +131,89 @@ scoped_ptr<blink::WebInputEvent> BuildWebKeyboardEvent( if (web_event->modifiers & blink::WebInputEvent::AltKey) web_event->isSystemKey = true; - web_event->windowsKeyCode = - static_cast<int>(event->key_data->windows_key_code); - web_event->nativeKeyCode = event->key_data->native_key_code; - web_event->text[0] = event->key_data->text; - web_event->unmodifiedText[0] = event->key_data->unmodified_text; + web_event->windowsKeyCode = event.GetLocatedWindowsKeyboardCode(); + web_event->nativeKeyCode = + ui::KeycodeConverter::DomCodeToNativeKeycode(event.code()); + web_event->text[0] = event.GetText(); + web_event->unmodifiedText[0] = event.GetUnmodifiedText(); web_event->setKeyIdentifierFromWindowsKeyCode(); return std::move(web_event); } -scoped_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom( - const mus::mojom::EventPtr& event) { - DCHECK(event->pointer_data && event->pointer_data->wheel_data); - const mus::mojom::WheelData& wheel_data = *event->pointer_data->wheel_data; - scoped_ptr<blink::WebMouseWheelEvent> web_event( +std::unique_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom( + const ui::MouseWheelEvent& event) { + std::unique_ptr<blink::WebMouseWheelEvent> web_event( new blink::WebMouseWheelEvent); web_event->type = blink::WebInputEvent::MouseWheel; web_event->button = blink::WebMouseEvent::ButtonNone; - web_event->modifiers = EventFlagsToWebEventModifiers(event->flags); + web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); web_event->timeStampSeconds = EventTimeToWebEventTime(event); - SetWebMouseEventLocation(*(event->pointer_data->location), web_event.get()); + SetWebMouseEventLocation(event, web_event.get()); // TODO(rjkroege): Update the following code once Blink supports // DOM Level 3 wheel events // (http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents) - web_event->deltaX = wheel_data.delta_x; - web_event->deltaY = wheel_data.delta_y; + web_event->deltaX = event.x_offset(); + web_event->deltaY = event.y_offset(); web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta; web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta; - // TODO(rjkroege): Mandoline currently only generates WHEEL_MODE_LINE - // wheel events so the other modes are not yet tested. Verify that - // the implementation is correct. - switch (wheel_data.mode) { - case mus::mojom::WheelMode::PIXEL: - web_event->hasPreciseScrollingDeltas = true; - web_event->scrollByPage = false; - web_event->canScroll = true; + // TODO(moshayedi): ui::WheelEvent currently only supports WHEEL_MODE_LINE. + // Add support for other wheel modes once ui::WheelEvent has support for them. + web_event->hasPreciseScrollingDeltas = false; + web_event->scrollByPage = false; + web_event->canScroll = true; + + return std::move(web_event); +} + +void SetWebTouchEventLocation(const ui::PointerEvent& event, + blink::WebTouchPoint* touch) { + touch->position.x = event.x(); + touch->position.y = event.y(); + touch->screenPosition.x = event.root_location_f().x(); + touch->screenPosition.y = event.root_location_f().y(); +} + +std::unique_ptr<blink::WebInputEvent> BuildWebTouchEvent( + const ui::PointerEvent& event) { + std::unique_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent); + blink::WebTouchPoint* touch = &web_event->touches[event.pointer_id()]; + + // TODO(jonross): we will need to buffer input events, as blink expects all + // active touch points to be in each WebInputEvent (crbug.com/578160) + SetWebTouchEventLocation(event, touch); + touch->pointerType = blink::WebPointerProperties::PointerType::Touch; + touch->radiusX = event.pointer_details().radius_x; + touch->radiusY = event.pointer_details().radius_y; + + web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); + web_event->timeStampSeconds = EventTimeToWebEventTime(event); + web_event->uniqueTouchEventId = ui::GetNextTouchEventId(); + + switch (event.type()) { + case ui::ET_POINTER_DOWN: + web_event->type = blink::WebInputEvent::TouchStart; + touch->state = blink::WebTouchPoint::StatePressed; break; - case mus::mojom::WheelMode::LINE: - web_event->hasPreciseScrollingDeltas = false; - web_event->scrollByPage = false; - web_event->canScroll = true; + case ui::ET_POINTER_UP: + web_event->type = blink::WebInputEvent::TouchEnd; + touch->state = blink::WebTouchPoint::StateReleased; break; - case mus::mojom::WheelMode::PAGE: - web_event->hasPreciseScrollingDeltas = false; - web_event->scrollByPage = true; - web_event->canScroll = true; + case ui::ET_POINTER_MOVED: + web_event->type = blink::WebInputEvent::TouchMove; + touch->state = blink::WebTouchPoint::StateMoved; break; - case mus::mojom::WheelMode::SCALING: - web_event->hasPreciseScrollingDeltas = false; - web_event->scrollByPage = false; - web_event->canScroll = false; + case ui::ET_POINTER_CANCELLED: + web_event->type = blink::WebInputEvent::TouchCancel; + touch->state = blink::WebTouchPoint::StateCancelled; + break; + default: + NOTIMPLEMENTED() << "Received non touch pointer event action: " + << event.type(); break; } @@ -200,29 +223,31 @@ scoped_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom( } // namespace // static -scoped_ptr<blink::WebInputEvent> -TypeConverter<scoped_ptr<blink::WebInputEvent>, mus::mojom::EventPtr>::Convert( - const mus::mojom::EventPtr& event) { - switch (event->action) { - case mus::mojom::EventType::POINTER_DOWN: - case mus::mojom::EventType::POINTER_UP: - case mus::mojom::EventType::POINTER_CANCEL: - case mus::mojom::EventType::POINTER_MOVE: - case mus::mojom::EventType::MOUSE_EXIT: - if (event->pointer_data && - event->pointer_data->kind == mus::mojom::PointerKind::MOUSE) { - return BuildWebMouseEventFrom(event); - } - return nullptr; - case mus::mojom::EventType::WHEEL: - return BuildWebMouseWheelEventFrom(event); - case mus::mojom::EventType::KEY_PRESSED: - case mus::mojom::EventType::KEY_RELEASED: - return BuildWebKeyboardEvent(event); - case mus::mojom::EventType::UNKNOWN: +std::unique_ptr<blink::WebInputEvent> +TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert( + const ui::Event& event) { + DCHECK(event.IsKeyEvent() || event.IsPointerEvent() || + event.IsMouseWheelEvent()); + switch (event.type()) { + case ui::ET_POINTER_DOWN: + case ui::ET_POINTER_UP: + case ui::ET_POINTER_CANCELLED: + case ui::ET_POINTER_MOVED: + case ui::ET_POINTER_EXITED: + if (event.IsMousePointerEvent()) + return BuildWebMouseEventFrom(*event.AsPointerEvent()); + else if (event.IsTouchPointerEvent()) + return BuildWebTouchEvent(*event.AsPointerEvent()); + else + return nullptr; + case ui::ET_MOUSEWHEEL: + return BuildWebMouseWheelEventFrom(*event.AsMouseWheelEvent()); + case ui::ET_KEY_PRESSED: + case ui::ET_KEY_RELEASED: + return BuildWebKeyboardEvent(*event.AsKeyEvent()); + default: return nullptr; } - return nullptr; } } // namespace mojo diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters.h b/chromium/mojo/converters/blink/blink_input_events_type_converters.h index bb1dce1f93c..3231eab0ed4 100644 --- a/chromium/mojo/converters/blink/blink_input_events_type_converters.h +++ b/chromium/mojo/converters/blink/blink_input_events_type_converters.h @@ -5,21 +5,25 @@ #ifndef MOJO_CONVERTERS_BLINK_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_ #define MOJO_CONVERTERS_BLINK_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_ -#include "base/memory/scoped_ptr.h" -#include "components/mus/public/interfaces/input_events.mojom.h" +#include <memory> + #include "mojo/converters/blink/mojo_blink_export.h" +#include "mojo/public/cpp/bindings/type_converter.h" namespace blink { class WebInputEvent; } +namespace ui { +class Event; +} + namespace mojo { template <> struct MOJO_BLINK_EXPORT - TypeConverter<scoped_ptr<blink::WebInputEvent>, mus::mojom::EventPtr> { - static scoped_ptr<blink::WebInputEvent> Convert( - const mus::mojom::EventPtr& input); + TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event> { + static std::unique_ptr<blink::WebInputEvent> Convert(const ui::Event& input); }; } // namespace mojo diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc b/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc new file mode 100644 index 00000000000..7c6c2c14bb8 --- /dev/null +++ b/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc @@ -0,0 +1,140 @@ +// Copyright 2016 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/converters/blink/blink_input_events_type_converters.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/event.h" + +namespace mojo { + +TEST(BlinkInputEventsConvertersTest, KeyEvent) { + struct { + ui::KeyEvent event; + blink::WebInputEvent::Type web_type; + int web_modifiers; + } tests[] = { + {ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE), + blink::WebInputEvent::RawKeyDown, 0x0}, + {ui::KeyEvent(L'B', ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN), + blink::WebInputEvent::Char, + blink::WebInputEvent::ShiftKey | blink::WebInputEvent::ControlKey}, + {ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::EF_ALT_DOWN), + blink::WebInputEvent::KeyUp, blink::WebInputEvent::AltKey}}; + + for (size_t i = 0; i < arraysize(tests); i++) { + const std::unique_ptr<blink::WebInputEvent> web_event( + TypeConverter<std::unique_ptr<blink::WebInputEvent>, + ui::Event>::Convert(tests[i].event)); + ASSERT_TRUE(web_event); + ASSERT_TRUE(blink::WebInputEvent::isKeyboardEventType(web_event->type)); + ASSERT_EQ(tests[i].web_type, web_event->type); + ASSERT_EQ(tests[i].web_modifiers, web_event->modifiers); + + const blink::WebKeyboardEvent* web_key_event = + static_cast<const blink::WebKeyboardEvent*>(web_event.get()); + ASSERT_EQ(static_cast<int>(tests[i].event.GetLocatedWindowsKeyboardCode()), + web_key_event->windowsKeyCode); + } +} + +TEST(BlinkInputEventsConvertersTest, WheelEvent) { + const int kDeltaX = 14; + const int kDeltaY = -3; + ui::MouseWheelEvent ui_event( + ui::MouseEvent(ui::ET_MOUSEWHEEL, gfx::Point(), gfx::Point(), + base::TimeDelta(), 0, 0), + kDeltaX, kDeltaY); + const std::unique_ptr<blink::WebInputEvent> web_event( + TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert( + ui_event)); + ASSERT_TRUE(web_event); + ASSERT_EQ(blink::WebInputEvent::MouseWheel, web_event->type); + ASSERT_EQ(0, web_event->modifiers); + + const blink::WebMouseWheelEvent* web_wheel_event = + static_cast<const blink::WebMouseWheelEvent*>(web_event.get()); + ASSERT_EQ(kDeltaX, web_wheel_event->deltaX); + ASSERT_EQ(kDeltaY, web_wheel_event->deltaY); +} + +TEST(BlinkInputEventsConvertersTest, MousePointerEvent) { + struct { + ui::EventType ui_type; + blink::WebInputEvent::Type web_type; + int ui_modifiers; + int web_modifiers; + gfx::Point location; + gfx::Point screen_location; + } tests[] = { + {ui::ET_MOUSE_PRESSED, blink::WebInputEvent::MouseDown, 0x0, 0x0, + gfx::Point(3, 5), gfx::Point(113, 125)}, + {ui::ET_MOUSE_RELEASED, blink::WebInputEvent::MouseUp, + ui::EF_LEFT_MOUSE_BUTTON, blink::WebInputEvent::LeftButtonDown, + gfx::Point(100, 1), gfx::Point(50, 1)}, + {ui::ET_MOUSE_MOVED, blink::WebInputEvent::MouseMove, + ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, + blink::WebInputEvent::MiddleButtonDown | + blink::WebInputEvent::RightButtonDown, + gfx::Point(13, 3), gfx::Point(53, 3)}, + }; + + for (size_t i = 0; i < arraysize(tests); i++) { + ui::PointerEvent ui_event(ui::MouseEvent( + tests[i].ui_type, tests[i].location, tests[i].screen_location, + base::TimeDelta(), tests[i].ui_modifiers, 0)); + const std::unique_ptr<blink::WebInputEvent> web_event( + TypeConverter<std::unique_ptr<blink::WebInputEvent>, + ui::Event>::Convert(ui_event)); + ASSERT_TRUE(web_event); + ASSERT_TRUE(blink::WebInputEvent::isMouseEventType(web_event->type)); + ASSERT_EQ(tests[i].web_type, web_event->type); + ASSERT_EQ(tests[i].web_modifiers, web_event->modifiers); + + const blink::WebMouseEvent* web_mouse_event = + static_cast<const blink::WebMouseEvent*>(web_event.get()); + ASSERT_EQ(tests[i].location.x(), web_mouse_event->x); + ASSERT_EQ(tests[i].location.y(), web_mouse_event->y); + ASSERT_EQ(tests[i].screen_location.x(), web_mouse_event->globalX); + ASSERT_EQ(tests[i].screen_location.y(), web_mouse_event->globalY); + } +} + +TEST(BlinkInputEventsConvertersTest, TouchPointerEvent) { + struct { + ui::EventType ui_type; + blink::WebInputEvent::Type web_type; + gfx::Point location; + int touch_id; + float radius_x; + float radius_y; + } tests[] = { + {ui::ET_TOUCH_PRESSED, blink::WebInputEvent::TouchStart, gfx::Point(3, 5), + 1, 4.5, 5.5}, + {ui::ET_TOUCH_RELEASED, blink::WebInputEvent::TouchEnd, + gfx::Point(100, 1), 2, 3.0, 3.0}, + }; + + for (size_t i = 0; i < arraysize(tests); i++) { + ui::PointerEvent ui_event(ui::TouchEvent( + tests[i].ui_type, tests[i].location, 0, tests[i].touch_id, + base::TimeDelta(), tests[i].radius_x, tests[i].radius_y, 0.0, 0.0)); + const std::unique_ptr<blink::WebInputEvent> web_event( + TypeConverter<std::unique_ptr<blink::WebInputEvent>, + ui::Event>::Convert(ui_event)); + ASSERT_TRUE(web_event); + ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type)); + ASSERT_EQ(tests[i].web_type, web_event->type); + ASSERT_EQ(0, web_event->modifiers); + + const blink::WebTouchEvent* web_touch_event = + static_cast<const blink::WebTouchEvent*>(web_event.get()); + const blink::WebTouchPoint* web_touch_point = + &web_touch_event->touches[tests[i].touch_id]; + ASSERT_EQ(tests[i].radius_x, web_touch_point->radiusX); + ASSERT_EQ(tests[i].radius_y, web_touch_point->radiusY); + } +} +} // namespace mojo diff --git a/chromium/mojo/converters/input_events/input_events_type_converters.cc b/chromium/mojo/converters/input_events/input_events_type_converters.cc index 840c3e28c63..3bf8a2799b7 100644 --- a/chromium/mojo/converters/input_events/input_events_type_converters.cc +++ b/chromium/mojo/converters/input_events/input_events_type_converters.cc @@ -325,8 +325,8 @@ mus::mojom::EventPtr TypeConverter<mus::mojom::EventPtr, ui::KeyEvent>::Convert( } // static -scoped_ptr<ui::Event> -TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( +std::unique_ptr<ui::Event> +TypeConverter<std::unique_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( const mus::mojom::EventPtr& input) { gfx::PointF location; gfx::PointF screen_location; @@ -340,7 +340,7 @@ TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( switch (input->action) { case mus::mojom::EventType::KEY_PRESSED: case mus::mojom::EventType::KEY_RELEASED: { - scoped_ptr<ui::KeyEvent> key_event; + std::unique_ptr<ui::KeyEvent> key_event; if (input->key_data->is_char) { key_event.reset(new ui::KeyEvent( static_cast<base::char16>(input->key_data->character), @@ -355,11 +355,11 @@ TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( static_cast<ui::KeyboardCode>(input->key_data->key_code), input->flags)); } - key_event->SetExtendedKeyEventData(scoped_ptr<ui::ExtendedKeyEventData>( - new MojoExtendedKeyEventData( - static_cast<int32_t>(input->key_data->windows_key_code), - input->key_data->text, - input->key_data->unmodified_text))); + key_event->SetExtendedKeyEventData( + std::unique_ptr<ui::ExtendedKeyEventData>( + new MojoExtendedKeyEventData( + static_cast<int32_t>(input->key_data->windows_key_code), + input->key_data->text, input->key_data->unmodified_text))); return std::move(key_event); } case mus::mojom::EventType::POINTER_DOWN: @@ -370,7 +370,7 @@ TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( switch (input->pointer_data->kind) { case mus::mojom::PointerKind::MOUSE: { // TODO: last flags isn't right. Need to send changed_flags. - scoped_ptr<ui::MouseEvent> event(new ui::MouseEvent( + std::unique_ptr<ui::MouseEvent> event(new ui::MouseEvent( MojoMouseEventTypeToUIEvent(input), gfx::Point(), gfx::Point(), ui::EventTimeForNow(), ui::EventFlags(input->flags), ui::EventFlags(input->flags))); @@ -380,7 +380,7 @@ TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( } break; case mus::mojom::PointerKind::TOUCH: { DCHECK(input->pointer_data->brush_data); - scoped_ptr<ui::TouchEvent> touch_event(new ui::TouchEvent( + std::unique_ptr<ui::TouchEvent> touch_event(new ui::TouchEvent( MojoTouchEventTypeToUIEvent(input), gfx::Point(), ui::EventFlags(input->flags), input->pointer_data->pointer_id, base::TimeDelta::FromInternalValue(input->time_stamp), @@ -398,13 +398,13 @@ TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( } break; case mus::mojom::EventType::WHEEL: { DCHECK(input->pointer_data && input->pointer_data->wheel_data); - scoped_ptr<ui::MouseEvent> pre_wheel_event(new ui::MouseEvent( + std::unique_ptr<ui::MouseEvent> pre_wheel_event(new ui::MouseEvent( MojoWheelEventTypeToUIEvent(input), gfx::Point(), gfx::Point(), ui::EventTimeForNow(), ui::EventFlags(input->flags), ui::EventFlags(input->flags))); pre_wheel_event->set_location_f(location); pre_wheel_event->set_root_location_f(screen_location); - scoped_ptr<ui::MouseEvent> wheel_event(new ui::MouseWheelEvent( + std::unique_ptr<ui::MouseEvent> wheel_event(new ui::MouseWheelEvent( *pre_wheel_event, static_cast<int>(input->pointer_data->wheel_data->delta_x), static_cast<int>(input->pointer_data->wheel_data->delta_y))); diff --git a/chromium/mojo/converters/input_events/input_events_type_converters.h b/chromium/mojo/converters/input_events/input_events_type_converters.h index 5f3223c69a1..02ac0d8ed44 100644 --- a/chromium/mojo/converters/input_events/input_events_type_converters.h +++ b/chromium/mojo/converters/input_events/input_events_type_converters.h @@ -5,7 +5,8 @@ #ifndef MOJO_CONVERTERS_INPUT_EVENTS_INPUT_EVENTS_TYPE_CONVERTERS_H_ #define MOJO_CONVERTERS_INPUT_EVENTS_INPUT_EVENTS_TYPE_CONVERTERS_H_ -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "components/mus/public/interfaces/input_events.mojom.h" #include "mojo/converters/input_events/mojo_input_events_export.h" #include "ui/events/event.h" @@ -39,8 +40,8 @@ struct MOJO_INPUT_EVENTS_EXPORT template <> struct MOJO_INPUT_EVENTS_EXPORT - TypeConverter<scoped_ptr<ui::Event>, mus::mojom::EventPtr> { - static scoped_ptr<ui::Event> Convert(const mus::mojom::EventPtr& input); + TypeConverter<std::unique_ptr<ui::Event>, mus::mojom::EventPtr> { + static std::unique_ptr<ui::Event> Convert(const mus::mojom::EventPtr& input); }; } // namespace mojo diff --git a/chromium/mojo/converters/surfaces/surfaces_type_converters.cc b/chromium/mojo/converters/surfaces/surfaces_type_converters.cc index ba512e412b8..684bdd95646 100644 --- a/chromium/mojo/converters/surfaces/surfaces_type_converters.cc +++ b/chromium/mojo/converters/surfaces/surfaces_type_converters.cc @@ -73,7 +73,6 @@ namespace mojo { #value " enum value must match") ASSERT_ENUM_VALUES_EQUAL(DEBUG_BORDER); -ASSERT_ENUM_VALUES_EQUAL(IO_SURFACE_CONTENT); ASSERT_ENUM_VALUES_EQUAL(PICTURE_CONTENT); ASSERT_ENUM_VALUES_EQUAL(RENDER_PASS); ASSERT_ENUM_VALUES_EQUAL(SOLID_COLOR); @@ -201,7 +200,8 @@ bool ConvertDrawQuad(const QuadPtr& input, texture_quad_state->uv_bottom_right.To<gfx::PointF>(), texture_quad_state->background_color.To<SkColor>(), &texture_quad_state->vertex_opacity.storage()[0], - texture_quad_state->y_flipped, texture_quad_state->nearest_neighbor); + texture_quad_state->y_flipped, texture_quad_state->nearest_neighbor, + texture_quad_state->secure_output_only); break; } case mus::mojom::Material::TILED_CONTENT: { @@ -377,6 +377,7 @@ QuadPtr TypeConverter<QuadPtr, cc::DrawQuad>::Convert( } texture_state->vertex_opacity = std::move(vertex_opacity); texture_state->y_flipped = texture_quad->y_flipped; + texture_state->secure_output_only = texture_quad->secure_output_only; quad->texture_quad_state = std::move(texture_state); break; } @@ -473,11 +474,11 @@ PassPtr TypeConverter<PassPtr, cc::RenderPass>::Convert( } // static -scoped_ptr<cc::RenderPass> ConvertToRenderPass( +std::unique_ptr<cc::RenderPass> ConvertToRenderPass( const PassPtr& input, const CompositorFrameMetadataPtr& metadata, CustomSurfaceConverter* custom_converter) { - scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create( + std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create( input->shared_quad_states.size(), input->quads.size()); pass->SetAll(input->id.To<cc::RenderPassId>(), input->output_rect.To<gfx::Rect>(), @@ -496,14 +497,14 @@ scoped_ptr<cc::RenderPass> ConvertToRenderPass( } if (!ConvertDrawQuad(quad, metadata, *sqs_iter, pass.get(), custom_converter)) - return scoped_ptr<cc::RenderPass>(); + return std::unique_ptr<cc::RenderPass>(); } return pass; } // static -scoped_ptr<cc::RenderPass> -TypeConverter<scoped_ptr<cc::RenderPass>, PassPtr>::Convert( +std::unique_ptr<cc::RenderPass> +TypeConverter<std::unique_ptr<cc::RenderPass>, PassPtr>::Convert( const PassPtr& input) { mus::mojom::CompositorFrameMetadataPtr metadata; return ConvertToRenderPass(input, metadata, @@ -603,22 +604,23 @@ TypeConverter<CompositorFramePtr, cc::CompositorFrame>::Convert( } // static -scoped_ptr<cc::CompositorFrame> ConvertToCompositorFrame( +std::unique_ptr<cc::CompositorFrame> ConvertToCompositorFrame( const CompositorFramePtr& input, CustomSurfaceConverter* custom_converter) { - scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData); + std::unique_ptr<cc::DelegatedFrameData> frame_data( + new cc::DelegatedFrameData); frame_data->device_scale_factor = 1.f; frame_data->resource_list = input->resources.To<cc::TransferableResourceArray>(); frame_data->render_pass_list.reserve(input->passes.size()); for (size_t i = 0; i < input->passes.size(); ++i) { - scoped_ptr<cc::RenderPass> pass = ConvertToRenderPass( + std::unique_ptr<cc::RenderPass> pass = ConvertToRenderPass( input->passes[i], input->metadata, custom_converter); if (!pass) - return scoped_ptr<cc::CompositorFrame>(); + return std::unique_ptr<cc::CompositorFrame>(); frame_data->render_pass_list.push_back(std::move(pass)); } - scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame); + std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame); cc::CompositorFrameMetadata metadata = input->metadata.To<cc::CompositorFrameMetadata>(); frame->delegated_frame_data = std::move(frame_data); @@ -626,9 +628,9 @@ scoped_ptr<cc::CompositorFrame> ConvertToCompositorFrame( } // static -scoped_ptr<cc::CompositorFrame> -TypeConverter<scoped_ptr<cc::CompositorFrame>, CompositorFramePtr>::Convert( - const CompositorFramePtr& input) { +std::unique_ptr<cc::CompositorFrame> +TypeConverter<std::unique_ptr<cc::CompositorFrame>, + CompositorFramePtr>::Convert(const CompositorFramePtr& input) { return ConvertToCompositorFrame(input, nullptr); } diff --git a/chromium/mojo/converters/surfaces/surfaces_type_converters.h b/chromium/mojo/converters/surfaces/surfaces_type_converters.h index e24a55c1eb7..96efcf3b4dc 100644 --- a/chromium/mojo/converters/surfaces/surfaces_type_converters.h +++ b/chromium/mojo/converters/surfaces/surfaces_type_converters.h @@ -5,7 +5,8 @@ #ifndef MOJO_CONVERTERS_SURFACES_SURFACES_TYPE_CONVERTERS_H_ #define MOJO_CONVERTERS_SURFACES_SURFACES_TYPE_CONVERTERS_H_ -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "cc/resources/returned_resource.h" #include "cc/resources/transferable_resource.h" #include "cc/surfaces/surface_id.h" @@ -77,7 +78,7 @@ struct MOJO_SURFACES_EXPORT const cc::SharedQuadState& input); }; -scoped_ptr<cc::RenderPass> ConvertToRenderPass( +std::unique_ptr<cc::RenderPass> ConvertToRenderPass( const mus::mojom::PassPtr& input, const mus::mojom::CompositorFrameMetadataPtr& metadata, CustomSurfaceConverter* custom_converter); @@ -89,8 +90,9 @@ struct MOJO_SURFACES_EXPORT TypeConverter<mus::mojom::PassPtr, cc::RenderPass> { template <> struct MOJO_SURFACES_EXPORT - TypeConverter<scoped_ptr<cc::RenderPass>, mus::mojom::PassPtr> { - static scoped_ptr<cc::RenderPass> Convert(const mus::mojom::PassPtr& input); + TypeConverter<std::unique_ptr<cc::RenderPass>, mus::mojom::PassPtr> { + static std::unique_ptr<cc::RenderPass> Convert( + const mus::mojom::PassPtr& input); }; // Types from compositor_frame.mojom @@ -135,9 +137,9 @@ struct MOJO_SURFACES_EXPORT const mus::mojom::CompositorFrameMetadataPtr& input); }; -MOJO_SURFACES_EXPORT scoped_ptr<cc::CompositorFrame> ConvertToCompositorFrame( - const mus::mojom::CompositorFramePtr& input, - CustomSurfaceConverter* custom_converter); +MOJO_SURFACES_EXPORT std::unique_ptr<cc::CompositorFrame> +ConvertToCompositorFrame(const mus::mojom::CompositorFramePtr& input, + CustomSurfaceConverter* custom_converter); template <> struct MOJO_SURFACES_EXPORT @@ -147,9 +149,9 @@ struct MOJO_SURFACES_EXPORT }; template <> -struct MOJO_SURFACES_EXPORT TypeConverter<scoped_ptr<cc::CompositorFrame>, +struct MOJO_SURFACES_EXPORT TypeConverter<std::unique_ptr<cc::CompositorFrame>, mus::mojom::CompositorFramePtr> { - static scoped_ptr<cc::CompositorFrame> Convert( + static std::unique_ptr<cc::CompositorFrame> Convert( const mus::mojom::CompositorFramePtr& input); }; diff --git a/chromium/mojo/edk/embedder/BUILD.gn b/chromium/mojo/edk/embedder/BUILD.gn index cca7230c9c1..02fc32cab3a 100644 --- a/chromium/mojo/edk/embedder/BUILD.gn +++ b/chromium/mojo/edk/embedder/BUILD.gn @@ -145,7 +145,6 @@ source_set("embedder_unittests") { "//mojo/edk/system", "//mojo/edk/system:test_utils", "//mojo/edk/test:test_support", - "//mojo/message_pump", "//testing/gtest", ] } diff --git a/chromium/mojo/edk/embedder/embedder.cc b/chromium/mojo/edk/embedder/embedder.cc index 793b7083f08..38c789cd7c4 100644 --- a/chromium/mojo/edk/embedder/embedder.cc +++ b/chromium/mojo/edk/embedder/embedder.cc @@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string_number_conversions.h" #include "base/task_runner.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "crypto/random.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_channel_pair.h" diff --git a/chromium/mojo/edk/embedder/embedder.h b/chromium/mojo/edk/embedder/embedder.h index 6a9b30525c3..edb6c3212de 100644 --- a/chromium/mojo/edk/embedder/embedder.h +++ b/chromium/mojo/edk/embedder/embedder.h @@ -7,12 +7,12 @@ #include <stddef.h> +#include <memory> #include <string> #include "base/callback.h" #include "base/command_line.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory_handle.h" #include "base/process/process_handle.h" #include "base/task_runner.h" diff --git a/chromium/mojo/edk/embedder/embedder_unittest.cc b/chromium/mojo/edk/embedder/embedder_unittest.cc index c781f42ed1a..0904799ac44 100644 --- a/chromium/mojo/edk/embedder/embedder_unittest.cc +++ b/chromium/mojo/edk/embedder/embedder_unittest.cc @@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/files/file.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/shared_memory.h" @@ -22,7 +23,6 @@ #include "mojo/edk/embedder/test_embedder.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/test/mojo_test_base.h" -#include "mojo/message_pump/message_pump_mojo.h" #include "mojo/public/c/system/core.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -198,13 +198,7 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { #if !defined(OS_IOS) -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels -#else -#define MAYBE_MultiprocessChannels MultiprocessChannels -#endif // defined(OS_ANDROID) -TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { +TEST_F(EmbedderTest, MultiprocessChannels) { RUN_CHILD_ON_PIPE(MultiprocessChannelsClient, server_mp) // 1. Write a message to |server_mp| (attaching nothing). WriteMessage(server_mp, "hello"); @@ -290,21 +284,12 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessChannelsClient, EmbedderTest, ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MultiprocessBaseSharedMemory DISABLED_MultiprocessBaseSharedMemory -#else -#define MAYBE_MultiprocessBaseSharedMemory MultiprocessBaseSharedMemory -#endif // defined(OS_ANDROID) -TEST_F(EmbedderTest, MAYBE_MultiprocessBaseSharedMemory) { +TEST_F(EmbedderTest, MultiprocessBaseSharedMemory) { RUN_CHILD_ON_PIPE(MultiprocessSharedMemoryClient, server_mp) // 1. Create a base::SharedMemory object and create a mojo shared buffer // from it. base::SharedMemoryCreateOptions options; options.size = 123; -#if defined(OS_MACOSX) && !defined(OS_IOS) - options.type = base::SharedMemoryHandle::POSIX; -#endif base::SharedMemory shared_memory; ASSERT_TRUE(shared_memory.Create(options)); base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( @@ -384,7 +369,6 @@ TEST_F(EmbedderTest, MultiprocessMachSharedMemory) { // buffer from it. base::SharedMemoryCreateOptions options; options.size = 123; - options.type = base::SharedMemoryHandle::MACH; base::SharedMemory shared_memory; ASSERT_TRUE(shared_memory.Create(options)); base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( @@ -422,41 +406,52 @@ TEST_F(EmbedderTest, MultiprocessMachSharedMemory) { END_CHILD() } -const base::SharedMemoryHandle::Type kTestHandleTypes[] = { - base::SharedMemoryHandle::MACH, - base::SharedMemoryHandle::POSIX, - base::SharedMemoryHandle::POSIX, - base::SharedMemoryHandle::MACH, +enum class HandleType { + POSIX, + MACH, + MACH_NULL, +}; + +const HandleType kTestHandleTypes[] = { + HandleType::MACH, + HandleType::MACH_NULL, + HandleType::POSIX, + HandleType::POSIX, + HandleType::MACH, }; -// Test that we can mix file descriptor and mach port handles. +// Test that we can mix file descriptors and mach port handles. TEST_F(EmbedderTest, MultiprocessMixMachAndFds) { const size_t kShmSize = 1234; RUN_CHILD_ON_PIPE(MultiprocessMixMachAndFdsClient, server_mp) - // 1. Create the base::SharedMemory objects and mojo handles from them. + // 1. Create fds or Mach objects and mojo handles from them. MojoHandle platform_handles[arraysize(kTestHandleTypes)]; for (size_t i = 0; i < arraysize(kTestHandleTypes); i++) { const auto type = kTestHandleTypes[i]; - base::SharedMemoryCreateOptions options; - options.size = kShmSize; - options.type = type; - base::SharedMemory shared_memory; - ASSERT_TRUE(shared_memory.Create(options)); - base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( - shared_memory.handle()); ScopedPlatformHandle scoped_handle; - if (type == base::SharedMemoryHandle::POSIX) - scoped_handle.reset(PlatformHandle(shm_handle.GetFileDescriptor().fd)); - else + if (type == HandleType::POSIX) { + // The easiest source of fds is opening /dev/null. + base::File file(base::FilePath("/dev/null"), + base::File::FLAG_OPEN | base::File::FLAG_WRITE); + ASSERT_TRUE(file.IsValid()); + scoped_handle.reset(PlatformHandle(file.TakePlatformFile())); + EXPECT_EQ(PlatformHandle::Type::POSIX, scoped_handle.get().type); + } else if (type == HandleType::MACH_NULL) { + scoped_handle.reset(PlatformHandle( + static_cast<mach_port_t>(MACH_PORT_NULL))); + EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); + } else { + base::SharedMemoryCreateOptions options; + options.size = kShmSize; + base::SharedMemory shared_memory; + ASSERT_TRUE(shared_memory.Create(options)); + base::SharedMemoryHandle shm_handle = + base::SharedMemory::DuplicateHandle(shared_memory.handle()); scoped_handle.reset(PlatformHandle(shm_handle.GetMemoryObject())); + EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); + } ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper( std::move(scoped_handle), platform_handles + i)); - - // Map the shared memory object and write the type into it. 'P' for POSIX, - // and 'M' for Mach. - ASSERT_TRUE(shared_memory.Map(kShmSize)); - static_cast<char*>(shared_memory.memory())[0] = - type == base::SharedMemoryHandle::POSIX ? 'P' : 'M'; } // 2. Send all the handles to the child. @@ -470,8 +465,7 @@ TEST_F(EmbedderTest, MultiprocessMixMachAndFds) { DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient, EmbedderTest, client_mp) { - const int kNumHandles = 4; - const size_t kShmSize = 1234; + const int kNumHandles = arraysize(kTestHandleTypes); MojoHandle platform_handles[kNumHandles]; // 1. Read from |client_mp|, which should have a message containing @@ -479,29 +473,24 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient, EmbedderTest, EXPECT_EQ("hello", ReadMessageWithHandles(client_mp, platform_handles, kNumHandles)); - // 2. Extract each handle, map it, and verify the type. + // 2. Extract each handle, and verify the type. for (int i = 0; i < kNumHandles; i++) { + const auto type = kTestHandleTypes[i]; ScopedPlatformHandle scoped_handle; ASSERT_EQ(MOJO_RESULT_OK, PassWrappedPlatformHandle(platform_handles[i], &scoped_handle)); - base::SharedMemoryHandle shm_handle; - char type = 0; - if (scoped_handle.get().type == PlatformHandle::Type::POSIX) { - shm_handle = base::SharedMemoryHandle(scoped_handle.release().handle, - false); - type = 'P'; + if (type == HandleType::POSIX) { + EXPECT_NE(0, scoped_handle.get().handle); + EXPECT_EQ(PlatformHandle::Type::POSIX, scoped_handle.get().type); + } else if (type == HandleType::MACH_NULL) { + EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL), + scoped_handle.get().port); + EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); } else { - shm_handle = base::SharedMemoryHandle(scoped_handle.release().port, - kShmSize, base::GetCurrentProcId()); - type = 'M'; + EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), + scoped_handle.get().port); + EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); } - - // Verify the type order. - EXPECT_EQ(kTestHandleTypes[i], shm_handle.GetType()); - - base::SharedMemory shared_memory(shm_handle, false); - ASSERT_TRUE(shared_memory.Map(kShmSize)); - EXPECT_EQ(type, static_cast<char*>(shared_memory.memory())[0]); } // 3. Say bye! diff --git a/chromium/mojo/edk/embedder/entrypoints.cc b/chromium/mojo/edk/embedder/entrypoints.cc index 6acd98571dd..fdd881a5998 100644 --- a/chromium/mojo/edk/embedder/entrypoints.cc +++ b/chromium/mojo/edk/embedder/entrypoints.cc @@ -53,6 +53,22 @@ MojoResult MojoCancelWatch(MojoHandle handle, uintptr_t context) { return g_core->CancelWatch(handle, context); } +MojoResult MojoAllocMessage(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message) { + return g_core->AllocMessage(num_bytes, handles, num_handles, flags, message); +} + +MojoResult MojoFreeMessage(MojoMessageHandle message) { + return g_core->FreeMessage(message); +} + +MojoResult MojoGetMessageBuffer(MojoMessageHandle message, void** buffer) { + return g_core->GetMessageBuffer(message, buffer); +} + MojoResult MojoCreateWaitSet(MojoHandle* wait_set_handle) { return g_core->CreateWaitSet(wait_set_handle); } @@ -93,6 +109,12 @@ MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, num_handles, flags); } +MojoResult MojoWriteMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags) { + return g_core->WriteMessageNew(message_pipe_handle, message, flags); +} + MojoResult MojoReadMessage(MojoHandle message_pipe_handle, void* bytes, uint32_t* num_bytes, @@ -103,6 +125,16 @@ MojoResult MojoReadMessage(MojoHandle message_pipe_handle, message_pipe_handle, bytes, num_bytes, handles, num_handles, flags); } +MojoResult MojoReadMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags) { + return g_core->ReadMessageNew( + message_pipe_handle, message, num_bytes, handles, num_handles, flags); +} + MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { return g_core->FuseMessagePipes(handle0, handle1); } diff --git a/chromium/mojo/edk/embedder/platform_channel_pair.h b/chromium/mojo/edk/embedder/platform_channel_pair.h index 591592bdb84..f80de89cedd 100644 --- a/chromium/mojo/edk/embedder/platform_channel_pair.h +++ b/chromium/mojo/edk/embedder/platform_channel_pair.h @@ -5,8 +5,9 @@ #ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ #define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ +#include <memory> + #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/process/launch.h" #include "build/build_config.h" #include "mojo/edk/embedder/scoped_platform_handle.h" diff --git a/chromium/mojo/edk/embedder/platform_channel_utils_posix.h b/chromium/mojo/edk/embedder/platform_channel_utils_posix.h index e08f2a16b1a..8b24bd028f8 100644 --- a/chromium/mojo/edk/embedder/platform_channel_utils_posix.h +++ b/chromium/mojo/edk/embedder/platform_channel_utils_posix.h @@ -9,8 +9,8 @@ #include <sys/types.h> // For |ssize_t|. #include <deque> +#include <memory> -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/system/system_impl_export.h" diff --git a/chromium/mojo/edk/embedder/platform_handle.cc b/chromium/mojo/edk/embedder/platform_handle.cc index 5709b1e4685..b6b2cd22d1f 100644 --- a/chromium/mojo/edk/embedder/platform_handle.cc +++ b/chromium/mojo/edk/embedder/platform_handle.cc @@ -36,6 +36,32 @@ void PlatformHandle::CloseIfNecessary() { } #endif // defined(OS_MACOSX) && !defined(OS_IOS) #elif defined(OS_WIN) + if (owning_process != base::GetCurrentProcessHandle()) { + // This handle may have been duplicated to a new target process but not yet + // sent there. In this case CloseHandle should NOT be called. From MSDN + // documentation for DuplicateHandle[1]: + // + // Normally the target process closes a duplicated handle when that + // process is finished using the handle. To close a duplicated handle + // from the source process, call DuplicateHandle with the following + // parameters: + // + // * Set hSourceProcessHandle to the target process from the + // call that created the handle. + // * Set hSourceHandle to the duplicated handle to close. + // * Set lpTargetHandle to NULL. + // * Set dwOptions to DUPLICATE_CLOSE_SOURCE. + // + // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251 + // + // NOTE: It's possible for this operation to fail if the owning process + // was terminated or is in the process of being terminated. Either way, + // there is nothing we can reasonably do about failure, so we ignore it. + DuplicateHandle(owning_process, handle, NULL, &handle, 0, FALSE, + DUPLICATE_CLOSE_SOURCE); + return; + } + bool success = !!CloseHandle(handle); DPCHECK(success); handle = INVALID_HANDLE_VALUE; diff --git a/chromium/mojo/edk/embedder/platform_handle.h b/chromium/mojo/edk/embedder/platform_handle.h index 3c945c69dff..675dd1fe9c8 100644 --- a/chromium/mojo/edk/embedder/platform_handle.h +++ b/chromium/mojo/edk/embedder/platform_handle.h @@ -10,6 +10,8 @@ #if defined(OS_WIN) #include <windows.h> + +#include "base/process/process_handle.h" #elif defined(OS_MACOSX) && !defined(OS_IOS) #include <mach/mach.h> #endif @@ -58,13 +60,18 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { #elif defined(OS_WIN) struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { PlatformHandle() : handle(INVALID_HANDLE_VALUE) {} - explicit PlatformHandle(HANDLE handle) : handle(handle) {} + explicit PlatformHandle(HANDLE handle) + : handle(handle), owning_process(base::GetCurrentProcessHandle()) {} void CloseIfNecessary(); bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } HANDLE handle; + + // A Windows HANDLE may be duplicated to another process but not yet sent to + // that process. This tracks the handle's owning process. + base::ProcessHandle owning_process; }; #else #error "Platform not yet supported." diff --git a/chromium/mojo/edk/embedder/platform_handle_utils_win.cc b/chromium/mojo/edk/embedder/platform_handle_utils_win.cc index eebfdeb7abd..32ed49afc18 100644 --- a/chromium/mojo/edk/embedder/platform_handle_utils_win.cc +++ b/chromium/mojo/edk/embedder/platform_handle_utils_win.cc @@ -15,6 +15,7 @@ ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { DCHECK(platform_handle.is_valid()); HANDLE new_handle; + CHECK_NE(platform_handle.handle, INVALID_HANDLE_VALUE); if (!DuplicateHandle(GetCurrentProcess(), platform_handle.handle, GetCurrentProcess(), &new_handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) diff --git a/chromium/mojo/edk/embedder/platform_handle_vector.h b/chromium/mojo/edk/embedder/platform_handle_vector.h index 2bea729ab24..9892b23cac0 100644 --- a/chromium/mojo/edk/embedder/platform_handle_vector.h +++ b/chromium/mojo/edk/embedder/platform_handle_vector.h @@ -5,9 +5,9 @@ #ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ #define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ +#include <memory> #include <vector> -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/embedder/platform_handle_utils.h" #include "mojo/edk/system/system_impl_export.h" @@ -27,7 +27,7 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { }; using ScopedPlatformHandleVectorPtr = - scoped_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>; + std::unique_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>; } // namespace edk } // namespace mojo diff --git a/chromium/mojo/edk/embedder/platform_shared_buffer.cc b/chromium/mojo/edk/embedder/platform_shared_buffer.cc index a29a7abd761..467e5e6a8a1 100644 --- a/chromium/mojo/edk/embedder/platform_shared_buffer.cc +++ b/chromium/mojo/edk/embedder/platform_shared_buffer.cc @@ -9,6 +9,7 @@ #include <utility> #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/memory/shared_memory.h" #include "base/process/process_handle.h" #include "base/sys_info.h" @@ -27,14 +28,7 @@ ScopedPlatformHandle SharedMemoryToPlatformHandle( #elif defined(OS_WIN) return ScopedPlatformHandle(PlatformHandle(memory_handle.GetHandle())); #else - if (memory_handle.GetType() == base::SharedMemoryHandle::MACH) { - return ScopedPlatformHandle(PlatformHandle( - memory_handle.GetMemoryObject())); - } else { - DCHECK(memory_handle.GetType() == base::SharedMemoryHandle::POSIX); - return ScopedPlatformHandle(PlatformHandle( - memory_handle.GetFileDescriptor().fd)); - } + return ScopedPlatformHandle(PlatformHandle(memory_handle.GetMemoryObject())); #endif } @@ -74,6 +68,27 @@ PlatformSharedBuffer* PlatformSharedBuffer::CreateFromPlatformHandle( } // static +PlatformSharedBuffer* PlatformSharedBuffer::CreateFromPlatformHandlePair( + size_t num_bytes, + ScopedPlatformHandle rw_platform_handle, + ScopedPlatformHandle ro_platform_handle) { + DCHECK_GT(num_bytes, 0u); + DCHECK(rw_platform_handle.is_valid()); + DCHECK(ro_platform_handle.is_valid()); + + PlatformSharedBuffer* rv = new PlatformSharedBuffer(num_bytes, false); + if (!rv->InitFromPlatformHandlePair(std::move(rw_platform_handle), + std::move(ro_platform_handle))) { + // We can't just delete it directly, due to the "in destructor" (debug) + // check. + scoped_refptr<PlatformSharedBuffer> deleter(rv); + return nullptr; + } + + return rv; +} + +// static PlatformSharedBuffer* PlatformSharedBuffer::CreateFromSharedMemoryHandle( size_t num_bytes, bool read_only, @@ -91,10 +106,10 @@ size_t PlatformSharedBuffer::GetNumBytes() const { } bool PlatformSharedBuffer::IsReadOnly() const { - return read_only_; + return read_only_; } -scoped_ptr<PlatformSharedBufferMapping> PlatformSharedBuffer::Map( +std::unique_ptr<PlatformSharedBufferMapping> PlatformSharedBuffer::Map( size_t offset, size_t length) { if (!IsValidMap(offset, length)) @@ -115,7 +130,7 @@ bool PlatformSharedBuffer::IsValidMap(size_t offset, size_t length) { return true; } -scoped_ptr<PlatformSharedBufferMapping> PlatformSharedBuffer::MapNoCheck( +std::unique_ptr<PlatformSharedBufferMapping> PlatformSharedBuffer::MapNoCheck( size_t offset, size_t length) { DCHECK(IsValidMap(offset, length)); @@ -128,10 +143,10 @@ scoped_ptr<PlatformSharedBufferMapping> PlatformSharedBuffer::MapNoCheck( if (handle == base::SharedMemory::NULLHandle()) return nullptr; - scoped_ptr<PlatformSharedBufferMapping> mapping( + std::unique_ptr<PlatformSharedBufferMapping> mapping( new PlatformSharedBufferMapping(handle, read_only_, offset, length)); if (mapping->Map()) - return make_scoped_ptr(mapping.release()); + return base::WrapUnique(mapping.release()); return nullptr; } @@ -170,6 +185,16 @@ base::SharedMemoryHandle PlatformSharedBuffer::DuplicateSharedMemoryHandle() { PlatformSharedBuffer* PlatformSharedBuffer::CreateReadOnlyDuplicate() { DCHECK(shared_memory_); + + if (ro_shared_memory_) { + base::AutoLock locker(lock_); + base::SharedMemoryHandle handle; + handle = base::SharedMemory::DuplicateHandle(ro_shared_memory_->handle()); + if (handle == base::SharedMemory::NULLHandle()) + return nullptr; + return CreateFromSharedMemoryHandle(num_bytes_, true, handle); + } + base::SharedMemoryHandle handle; bool success; { @@ -196,9 +221,6 @@ bool PlatformSharedBuffer::Init() { options.size = num_bytes_; // By default, we can share as read-only. options.share_read_only = true; -#if defined(OS_MACOSX) && !defined(OS_IOS) - options.type = base::SharedMemoryHandle::MACH; -#endif shared_memory_.reset(new base::SharedMemory); return shared_memory_->Create(options); @@ -213,12 +235,8 @@ bool PlatformSharedBuffer::InitFromPlatformHandle( base::GetCurrentProcId()); #elif defined(OS_MACOSX) && !defined(OS_IOS) base::SharedMemoryHandle handle; - if (platform_handle.get().type == PlatformHandle::Type::MACH) { - handle = base::SharedMemoryHandle( - platform_handle.release().port, num_bytes_, base::GetCurrentProcId()); - } else { - handle = base::SharedMemoryHandle(platform_handle.release().handle, false); - } + handle = base::SharedMemoryHandle(platform_handle.release().port, num_bytes_, + base::GetCurrentProcId()); #else base::SharedMemoryHandle handle(platform_handle.release().handle, false); #endif @@ -227,6 +245,26 @@ bool PlatformSharedBuffer::InitFromPlatformHandle( return true; } +bool PlatformSharedBuffer::InitFromPlatformHandlePair( + ScopedPlatformHandle rw_platform_handle, + ScopedPlatformHandle ro_platform_handle) { +#if defined(OS_WIN) || defined(OS_MACOSX) + NOTREACHED(); + return false; +#else + DCHECK(!shared_memory_); + + base::SharedMemoryHandle handle(rw_platform_handle.release().handle, false); + shared_memory_.reset(new base::SharedMemory(handle, false)); + + base::SharedMemoryHandle ro_handle(ro_platform_handle.release().handle, + false); + ro_shared_memory_.reset(new base::SharedMemory(ro_handle, true)); + + return true; +#endif +} + void PlatformSharedBuffer::InitFromSharedMemoryHandle( base::SharedMemoryHandle handle) { DCHECK(!shared_memory_); diff --git a/chromium/mojo/edk/embedder/platform_shared_buffer.h b/chromium/mojo/edk/embedder/platform_shared_buffer.h index 1cfcd3a9aca..45be7233c4f 100644 --- a/chromium/mojo/edk/embedder/platform_shared_buffer.h +++ b/chromium/mojo/edk/embedder/platform_shared_buffer.h @@ -7,9 +7,10 @@ #include <stddef.h> +#include <memory> + #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/memory/shared_memory_handle.h" #include "base/synchronization/lock.h" @@ -45,6 +46,14 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer bool read_only, ScopedPlatformHandle platform_handle); + // Creates a shared buffer of size |num_bytes| from the existing pair of + // read/write and read-only handles |rw_platform_handle| and + // |ro_platform_handle|. Returns null on failure. + static PlatformSharedBuffer* CreateFromPlatformHandlePair( + size_t num_bytes, + ScopedPlatformHandle rw_platform_handle, + ScopedPlatformHandle ro_platform_handle); + // Creates a shared buffer of size |num_bytes| from the existing shared memory // handle |handle|. static PlatformSharedBuffer* CreateFromSharedMemoryHandle( @@ -61,15 +70,16 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|] // must be contained in [0, |num_bytes|], and |length| must be at least 1. // Returns null on failure. - scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset, size_t length); + std::unique_ptr<PlatformSharedBufferMapping> Map(size_t offset, + size_t length); // Checks if |offset| and |length| are valid arguments. bool IsValidMap(size_t offset, size_t length); // Like |Map()|, but doesn't check its arguments (which should have been // preflighted using |IsValidMap()|). - scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset, - size_t length); + std::unique_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset, + size_t length); // Duplicates the underlying platform handle and passes it to the caller. ScopedPlatformHandle DuplicatePlatformHandle(); @@ -102,13 +112,20 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer // claimed |num_bytes_|.) bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle); + bool InitFromPlatformHandlePair(ScopedPlatformHandle rw_platform_handle, + ScopedPlatformHandle ro_platform_handle); + void InitFromSharedMemoryHandle(base::SharedMemoryHandle handle); const size_t num_bytes_; const bool read_only_; base::Lock lock_; - scoped_ptr<base::SharedMemory> shared_memory_; + std::unique_ptr<base::SharedMemory> shared_memory_; + + // A separate read-only shared memory for platforms that need it (i.e. Linux + // with sync broker). + std::unique_ptr<base::SharedMemory> ro_shared_memory_; DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer); }; diff --git a/chromium/mojo/edk/embedder/platform_shared_buffer_unittest.cc b/chromium/mojo/edk/embedder/platform_shared_buffer_unittest.cc index 098ff26a816..f1593f06c44 100644 --- a/chromium/mojo/edk/embedder/platform_shared_buffer_unittest.cc +++ b/chromium/mojo/edk/embedder/platform_shared_buffer_unittest.cc @@ -7,9 +7,9 @@ #include <stddef.h> #include <limits> +#include <memory> #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/sys_info.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,7 +36,8 @@ TEST(PlatformSharedBufferTest, Basic) { // Map it all, scribble some stuff, and then unmap it. { EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes)); - scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kNumBytes)); + std::unique_ptr<PlatformSharedBufferMapping> mapping( + buffer->Map(0, kNumBytes)); ASSERT_TRUE(mapping); ASSERT_TRUE(mapping->GetBase()); int* stuff = static_cast<int*>(mapping->GetBase()); @@ -51,7 +52,7 @@ TEST(PlatformSharedBufferTest, Basic) { { ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes)); // Use |MapNoCheck()| this time. - scoped_ptr<PlatformSharedBufferMapping> mapping1( + std::unique_ptr<PlatformSharedBufferMapping> mapping1( buffer->MapNoCheck(0, kNumBytes)); ASSERT_TRUE(mapping1); ASSERT_TRUE(mapping1->GetBase()); @@ -59,7 +60,7 @@ TEST(PlatformSharedBufferTest, Basic) { for (size_t i = 0; i < kNumInts; i++) EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i; - scoped_ptr<PlatformSharedBufferMapping> mapping2( + std::unique_ptr<PlatformSharedBufferMapping> mapping2( buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int))); ASSERT_TRUE(mapping2); ASSERT_TRUE(mapping2->GetBase()); @@ -83,7 +84,7 @@ TEST(PlatformSharedBufferTest, Basic) { // it to be. { EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int))); - scoped_ptr<PlatformSharedBufferMapping> mapping( + std::unique_ptr<PlatformSharedBufferMapping> mapping( buffer->Map(sizeof(int), kNumBytes - sizeof(int))); ASSERT_TRUE(mapping); ASSERT_TRUE(mapping->GetBase()); @@ -152,8 +153,8 @@ TEST(PlatformSharedBufferTest, TooBig) { // using the address as the key for unmapping. TEST(PlatformSharedBufferTest, MappingsDistinct) { scoped_refptr<PlatformSharedBuffer> buffer(PlatformSharedBuffer::Create(100)); - scoped_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100)); - scoped_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100)); + std::unique_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100)); + std::unique_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100)); EXPECT_NE(mapping1->GetBase(), mapping2->GetBase()); } @@ -162,7 +163,8 @@ TEST(PlatformSharedBufferTest, BufferZeroInitialized) { for (size_t i = 0; i < arraysize(kSizes); i++) { scoped_refptr<PlatformSharedBuffer> buffer( PlatformSharedBuffer::Create(kSizes[i])); - scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kSizes[i])); + std::unique_ptr<PlatformSharedBufferMapping> mapping( + buffer->Map(0, kSizes[i])); for (size_t j = 0; j < kSizes[i]; j++) { // "Assert" instead of "expect" so we don't spam the output with thousands // of failures if we fail. @@ -173,8 +175,8 @@ TEST(PlatformSharedBufferTest, BufferZeroInitialized) { } TEST(PlatformSharedBufferTest, MappingsOutliveBuffer) { - scoped_ptr<PlatformSharedBufferMapping> mapping1; - scoped_ptr<PlatformSharedBufferMapping> mapping2; + std::unique_ptr<PlatformSharedBufferMapping> mapping1; + std::unique_ptr<PlatformSharedBufferMapping> mapping2; { scoped_refptr<PlatformSharedBuffer> buffer( @@ -194,9 +196,6 @@ TEST(PlatformSharedBufferTest, FromSharedMemoryHandle) { const size_t kBufferSize = 1234; base::SharedMemoryCreateOptions options; options.size = kBufferSize; -#if defined(OS_MACOSX) && !defined(OS_IOS) - options.type = base::SharedMemoryHandle::POSIX; -#endif base::SharedMemory shared_memory; ASSERT_TRUE(shared_memory.Create(options)); ASSERT_TRUE(shared_memory.Map(kBufferSize)); @@ -208,7 +207,7 @@ TEST(PlatformSharedBufferTest, FromSharedMemoryHandle) { kBufferSize, false /* read_only */, shm_handle)); ASSERT_TRUE(simple_buffer); - scoped_ptr<PlatformSharedBufferMapping> mapping = + std::unique_ptr<PlatformSharedBufferMapping> mapping = simple_buffer->Map(0, kBufferSize); ASSERT_TRUE(mapping); diff --git a/chromium/mojo/edk/embedder/test_embedder.cc b/chromium/mojo/edk/embedder/test_embedder.cc index bb4430c8907..9658010586f 100644 --- a/chromium/mojo/edk/embedder/test_embedder.cc +++ b/chromium/mojo/edk/embedder/test_embedder.cc @@ -4,8 +4,9 @@ #include "mojo/edk/embedder/test_embedder.h" +#include <memory> + #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" diff --git a/chromium/mojo/edk/js/BUILD.gn b/chromium/mojo/edk/js/BUILD.gn index 005416d778b..429a8c09355 100644 --- a/chromium/mojo/edk/js/BUILD.gn +++ b/chromium/mojo/edk/js/BUILD.gn @@ -42,7 +42,6 @@ source_set("js") { ] deps = [ - "//mojo/message_pump", "//mojo/public/cpp/system", ] } diff --git a/chromium/mojo/edk/js/core.cc b/chromium/mojo/edk/js/core.cc index f1fc9167e89..c8ccc37c536 100644 --- a/chromium/mojo/edk/js/core.cc +++ b/chromium/mojo/edk/js/core.cc @@ -145,12 +145,10 @@ MojoResult WriteMessage( raw_handles.empty() ? NULL : &raw_handles[0], static_cast<uint32_t>(raw_handles.size()), flags); - // MojoWriteMessage takes ownership of the handles upon success, so - // release them here. - if (rv == MOJO_RESULT_OK) { - for (size_t i = 0; i < handles.size(); ++i) - ignore_result(handles[i]->release()); - } + // MojoWriteMessage takes ownership of the handles, so release them here. + for (size_t i = 0; i < handles.size(); ++i) + ignore_result(handles[i]->release()); + return rv; } diff --git a/chromium/mojo/edk/js/drain_data.cc b/chromium/mojo/edk/js/drain_data.cc index 3b0a195e552..ca5fdf44097 100644 --- a/chromium/mojo/edk/js/drain_data.cc +++ b/chromium/mojo/edk/js/drain_data.cc @@ -41,7 +41,7 @@ DrainData::~DrainData() { void DrainData::WaitForData() { handle_watcher_.Start( - handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, + handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, base::Bind(&DrainData::DataReady, base::Unretained(this))); } diff --git a/chromium/mojo/edk/js/drain_data.h b/chromium/mojo/edk/js/drain_data.h index 13af286631d..917ca05f2a9 100644 --- a/chromium/mojo/edk/js/drain_data.h +++ b/chromium/mojo/edk/js/drain_data.h @@ -7,8 +7,8 @@ #include "base/memory/scoped_vector.h" #include "gin/runner.h" -#include "mojo/message_pump/handle_watcher.h" #include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/watcher.h" #include "v8/include/v8.h" namespace mojo { @@ -50,7 +50,7 @@ class DrainData { v8::Isolate* isolate_; ScopedDataPipeConsumerHandle handle_; - common::HandleWatcher handle_watcher_; + Watcher handle_watcher_; base::WeakPtr<gin::Runner> runner_; v8::UniquePersistent<v8::Promise::Resolver> resolver_; ScopedVector<DataBuffer> data_buffers_; diff --git a/chromium/mojo/edk/system/BUILD.gn b/chromium/mojo/edk/system/BUILD.gn index 5d83bb6c84f..f151219fb32 100644 --- a/chromium/mojo/edk/system/BUILD.gn +++ b/chromium/mojo/edk/system/BUILD.gn @@ -23,6 +23,7 @@ component("system") { sources = [ "async_waiter.cc", "async_waiter.h", + "atomic_flag.h", "awakable.h", "awakable_list.cc", "awakable_list.h", @@ -51,6 +52,8 @@ component("system") { "handle_table.h", "mapping_table.cc", "mapping_table.h", + "message_for_transit.cc", + "message_for_transit.h", "message_pipe_dispatcher.cc", "message_pipe_dispatcher.h", "node_channel.cc", @@ -173,6 +176,7 @@ test("mojo_system_unittests") { "//base/test:test_support", "//mojo/edk/embedder:embedder_unittests", "//mojo/edk/system", + "//mojo/edk/system/ports:tests", "//mojo/edk/test:run_all_unittests", "//mojo/edk/test:test_support", "//testing/gtest", diff --git a/chromium/mojo/edk/system/atomic_flag.h b/chromium/mojo/edk/system/atomic_flag.h new file mode 100644 index 00000000000..6bdcfaaddd9 --- /dev/null +++ b/chromium/mojo/edk/system/atomic_flag.h @@ -0,0 +1,57 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ +#define MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ + +#include "base/atomicops.h" +#include "base/macros.h" + +namespace mojo { +namespace edk { + +// AtomicFlag is a boolean flag that can be set and tested atomically. It is +// intended to be used to fast-path checks where the common case would normally +// release the governing mutex immediately after checking. +// +// Example usage: +// void DoFoo(Bar* bar) { +// AutoLock l(lock_); +// queue_.push_back(bar); +// flag_.Set(true); +// } +// +// void Baz() { +// if (!flag_) // Assume this is the common case. +// return; +// +// AutoLock l(lock_); +// ... drain queue_ ... +// flag_.Set(false); +// } +class AtomicFlag { + public: + AtomicFlag() : flag_(0) {} + ~AtomicFlag() {} + + void Set(bool value) { + base::subtle::Release_Store(&flag_, value ? 1 : 0); + } + + bool Get() const { + return base::subtle::Acquire_Load(&flag_) ? true : false; + } + + operator const bool() const { return Get(); } + + private: + base::subtle::Atomic32 flag_; + + DISALLOW_COPY_AND_ASSIGN(AtomicFlag); +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ diff --git a/chromium/mojo/edk/system/broker_host_posix.cc b/chromium/mojo/edk/system/broker_host_posix.cc index 7a5c54e551e..9c4eeae1c34 100644 --- a/chromium/mojo/edk/system/broker_host_posix.cc +++ b/chromium/mojo/edk/system/broker_host_posix.cc @@ -61,18 +61,24 @@ void BrokerHost::SendChannel(ScopedPlatformHandle handle) { void BrokerHost::OnBufferRequest(size_t num_bytes) { scoped_refptr<PlatformSharedBuffer> buffer; + scoped_refptr<PlatformSharedBuffer> read_only_buffer; if (num_bytes <= kMaxSharedBufferSize) { buffer = PlatformSharedBuffer::Create(num_bytes); + if (buffer) + read_only_buffer = buffer->CreateReadOnlyDuplicate(); + if (!read_only_buffer) + buffer = nullptr; } else { LOG(ERROR) << "Shared buffer request too large: " << num_bytes; } Channel::MessagePtr message = CreateBrokerMessage( - BrokerMessageType::BUFFER_RESPONSE, buffer ? 1 : 0, nullptr); + BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, nullptr); if (buffer) { ScopedPlatformHandleVectorPtr handles; - handles.reset(new PlatformHandleVector(1)); + handles.reset(new PlatformHandleVector(2)); handles->at(0) = buffer->PassPlatformHandle().release(); + handles->at(1) = read_only_buffer->PassPlatformHandle().release(); message->SetHandles(std::move(handles)); } diff --git a/chromium/mojo/edk/system/broker_posix.cc b/chromium/mojo/edk/system/broker_posix.cc index 3cbb953f1cb..5400ed2a287 100644 --- a/chromium/mojo/edk/system/broker_posix.cc +++ b/chromium/mojo/edk/system/broker_posix.cc @@ -109,11 +109,13 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) { std::deque<PlatformHandle> incoming_platform_handles; if (WaitForBrokerMessage(sync_channel_.get(), - BrokerMessageType::BUFFER_RESPONSE, 1, + BrokerMessageType::BUFFER_RESPONSE, 2, &incoming_platform_handles)) { - return PlatformSharedBuffer::CreateFromPlatformHandle( - num_bytes, false /* read_only */, - ScopedPlatformHandle(incoming_platform_handles.front())); + ScopedPlatformHandle rw_handle(incoming_platform_handles.front()); + incoming_platform_handles.pop_front(); + ScopedPlatformHandle ro_handle(incoming_platform_handles.front()); + return PlatformSharedBuffer::CreateFromPlatformHandlePair( + num_bytes, std::move(rw_handle), std::move(ro_handle)); } return nullptr; diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/edk/system/channel.cc index 107a446133e..e802527619f 100644 --- a/chromium/mojo/edk/system/channel.cc +++ b/chromium/mojo/edk/system/channel.cc @@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/aligned_memory.h" +#include "base/process/process_handle.h" #include "mojo/edk/embedder/platform_handle.h" #if defined(OS_MACOSX) && !defined(OS_IOS) @@ -53,7 +54,10 @@ Channel::Message::Message(size_t payload_size, // serialised into the message buffer. Since there could be a mix of fds and // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), // so that the original ordering of handles can be re-created. - extra_header_size = max_handles * sizeof(MachPortsEntry); + if (max_handles) { + extra_header_size = + sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); + } #endif // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. if (extra_header_size % kChannelMessageAlignment) { @@ -96,10 +100,14 @@ Channel::Message::Message(size_t payload_size, for (size_t i = 0; i < max_handles_; ++i) handles()[i] = PlatformHandle(); #elif defined(OS_MACOSX) && !defined(OS_IOS) - mach_ports_ = reinterpret_cast<MachPortsEntry*>(mutable_extra_header()); + mach_ports_header_ = + reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); + mach_ports_header_->num_ports = 0; // Initialize all handles to invalid values. - for (size_t i = 0; i < max_handles_; ++i) - mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; + for (size_t i = 0; i < max_handles_; ++i) { + mach_ports_header_->entries[i] = + {0, static_cast<uint32_t>(MACH_PORT_NULL)}; + } #endif } } @@ -132,7 +140,8 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data, return nullptr; } - if (header->num_bytes < header->num_header_bytes) { + if (header->num_bytes < header->num_header_bytes || + header->num_header_bytes < sizeof(Header)) { DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " << header->num_header_bytes; return nullptr; @@ -142,9 +151,15 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data, #if defined(OS_WIN) uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); #elif defined(OS_MACOSX) && !defined(OS_IOS) - uint32_t max_handles = extra_header_size / sizeof(MachPortsEntry); + if (extra_header_size < sizeof(MachPortsExtraHeader)) { + DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < " + << sizeof(MachPortsExtraHeader); + return nullptr; + } + uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) / + sizeof(MachPortsEntry); #endif - if (header->num_handles > max_handles) { + if (header->num_handles > max_handles || max_handles > kMaxAttachedHandles) { DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > " << max_handles; return nullptr; @@ -247,16 +262,21 @@ void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { #if defined(OS_MACOSX) && !defined(OS_IOS) size_t mach_port_index = 0; - for (size_t i = 0; i < max_handles_; ++i) - mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; - for (size_t i = 0; i < handle_vector_->size(); i++) { - if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || - (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { - mach_port_t port = (*handle_vector_)[i].port; - mach_ports_[mach_port_index].index = i; - mach_ports_[mach_port_index].mach_port = port; - mach_port_index++; + if (mach_ports_header_) { + for (size_t i = 0; i < max_handles_; ++i) { + mach_ports_header_->entries[i] = + {0, static_cast<uint32_t>(MACH_PORT_NULL)}; + } + for (size_t i = 0; i < handle_vector_->size(); i++) { + if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || + (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { + mach_port_t port = (*handle_vector_)[i].port; + mach_ports_header_->entries[mach_port_index].index = i; + mach_ports_header_->entries[mach_port_index].mach_port = port; + mach_port_index++; + } } + mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index); } #endif } @@ -272,8 +292,13 @@ ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { header_->num_handles = 0; return moved_handles; #elif defined(OS_MACOSX) && !defined(OS_IOS) - for (size_t i = 0; i < max_handles_; ++i) - mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; + if (mach_ports_header_) { + for (size_t i = 0; i < max_handles_; ++i) { + mach_ports_header_->entries[i] = + {0, static_cast<uint32_t>(MACH_PORT_NULL)}; + } + mach_ports_header_->num_ports = 0; + } header_->num_handles = 0; return std::move(handle_vector_); #else @@ -319,12 +344,22 @@ bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, DLOG(ERROR) << "Refusing to duplicate invalid handle."; continue; } + DCHECK_EQ(handles[i].owning_process, from_process); BOOL result = DuplicateHandle( from_process, handles[i].handle, to_process, - reinterpret_cast<HANDLE*>(handles + i), 0, FALSE, + &handles[i].handle, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - if (!result) + if (result) { + handles[i].owning_process = to_process; + } else { success = false; + + // If handle duplication fails, the source handle will already be closed + // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with + // an invalid handle. + handles[i].handle = INVALID_HANDLE_VALUE; + handles[i].owning_process = base::GetCurrentProcessHandle(); + } } return success; } @@ -344,6 +379,9 @@ bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, // Discard() marks occupied bytes as discarded, signifying that their contents // can be forgotten or overwritten. // +// Realign() moves occupied bytes to the front of the buffer so that those +// occupied bytes are properly aligned. +// // The most common Channel behavior in practice should result in very few // allocations and copies, as memory is claimed and discarded shortly after // being reserved, and future reservations will immediately reuse discarded @@ -426,6 +464,13 @@ class Channel::ReadBuffer { } } + void Realign() { + size_t num_bytes = num_occupied_bytes(); + memmove(data_, occupied_bytes(), num_bytes); + num_discarded_bytes_ = 0; + num_occupied_bytes_ = num_bytes; + } + private: char* data_ = nullptr; @@ -467,6 +512,13 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { bool did_dispatch_message = false; read_buffer_->Claim(bytes_read); while (read_buffer_->num_occupied_bytes() >= sizeof(Message::Header)) { + // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could + // happen on architectures that don't allow misaligned words access (i.e. + // anything other than x86). Only re-align when necessary to avoid copies. + if (reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()) % + kChannelMessageAlignment != 0) + read_buffer_->Realign(); + // We have at least enough data available for a MessageHeader. const Message::Header* header = reinterpret_cast<const Message::Header*>( read_buffer_->occupied_bytes()); diff --git a/chromium/mojo/edk/system/channel.h b/chromium/mojo/edk/system/channel.h index 74b62da8664..ab93431a443 100644 --- a/chromium/mojo/edk/system/channel.h +++ b/chromium/mojo/edk/system/channel.h @@ -25,7 +25,7 @@ class Channel : public base::RefCountedThreadSafe<Channel> { public: struct Message; - using MessagePtr = scoped_ptr<Message>; + using MessagePtr = std::unique_ptr<Message>; // A message to be written to a channel. struct Message { @@ -69,13 +69,28 @@ class Channel : public base::RefCountedThreadSafe<Channel> { #if defined(OS_MACOSX) && !defined(OS_IOS) struct MachPortsEntry { + // Index of Mach port in the original vector of PlatformHandles. uint16_t index; + + // Mach port name. uint32_t mach_port; static_assert(sizeof(mach_port_t) <= sizeof(uint32_t), "mach_port_t must be no larger than uint32_t"); }; static_assert(sizeof(MachPortsEntry) == 6, "sizeof(MachPortsEntry) must be 6 bytes"); + + // Structure of the extra header field when present on OSX. + struct MachPortsExtraHeader { + // Actual number of Mach ports encoded in the extra header. + uint16_t num_ports; + + // Array of encoded Mach ports. If |num_ports| > 0, |entires[0]| through + // to |entries[num_ports-1]| inclusive are valid. + MachPortsEntry entries[0]; + }; + static_assert(sizeof(MachPortsExtraHeader) == 2, + "sizeof(MachPortsExtraHeader) must be 2 bytes"); #endif #pragma pack(pop) @@ -155,7 +170,7 @@ class Channel : public base::RefCountedThreadSafe<Channel> { #if defined(OS_MACOSX) && !defined(OS_IOS) // On OSX, handles are serialised into the extra header section. - MachPortsEntry* mach_ports_ = nullptr; + MachPortsExtraHeader* mach_ports_header_ = nullptr; #endif DISALLOW_COPY_AND_ASSIGN(Message); @@ -258,7 +273,7 @@ class Channel : public base::RefCountedThreadSafe<Channel> { class ReadBuffer; Delegate* delegate_; - const scoped_ptr<ReadBuffer> read_buffer_; + const std::unique_ptr<ReadBuffer> read_buffer_; DISALLOW_COPY_AND_ASSIGN(Channel); }; diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/edk/system/channel_posix.cc index 772a608698b..72c559bf6aa 100644 --- a/chromium/mojo/edk/system/channel_posix.cc +++ b/chromium/mojo/edk/system/channel_posix.cc @@ -16,7 +16,6 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" @@ -145,14 +144,12 @@ class ChannelPosix : public Channel, // On OSX, we can have mach ports which are located in the extra header // section. using MachPortsEntry = Channel::Message::MachPortsEntry; - CHECK(extra_header_size >= num_handles * sizeof(MachPortsEntry)); - size_t num_mach_ports = 0; - const MachPortsEntry* mach_ports = - reinterpret_cast<const MachPortsEntry*>(extra_header); - for (size_t i = 0; i < num_handles; i++) { - if (mach_ports[i].mach_port != MACH_PORT_NULL) - num_mach_ports++; - } + using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader; + CHECK(extra_header_size >= + sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry)); + const MachPortsExtraHeader* mach_ports_header = + reinterpret_cast<const MachPortsExtraHeader*>(extra_header); + size_t num_mach_ports = mach_ports_header->num_ports; CHECK(num_mach_ports <= num_handles); if (incoming_platform_handles_.size() + num_mach_ports < num_handles) { handles->reset(); @@ -160,6 +157,7 @@ class ChannelPosix : public Channel, } handles->reset(new PlatformHandleVector(num_handles)); + const MachPortsEntry* mach_ports = mach_ports_header->entries; for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) { if (mach_port_index < num_mach_ports && mach_ports[mach_port_index].index == i) { @@ -476,8 +474,8 @@ class ChannelPosix : public Channel, scoped_refptr<base::TaskRunner> io_task_runner_; // These watchers must only be accessed on the IO thread. - scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; - scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; + std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; + std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; std::deque<PlatformHandle> incoming_platform_handles_; diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/edk/system/channel_win.cc index 465ba62dbba..38744ab99b1 100644 --- a/chromium/mojo/edk/system/channel_win.cc +++ b/chromium/mojo/edk/system/channel_win.cc @@ -16,7 +16,6 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" @@ -80,13 +79,7 @@ class ChannelWin : public Channel, self_(this), handle_(std::move(handle)), io_task_runner_(io_task_runner) { - sentinel_ = ~reinterpret_cast<uintptr_t>(this); CHECK(handle_.is_valid()); - memset(&read_context_, 0, sizeof(read_context_)); - read_context_.handler = this; - - memset(&write_context_, 0, sizeof(write_context_)); - write_context_.handler = this; } void Start() override { @@ -139,13 +132,7 @@ class ChannelWin : public Channel, private: // May run on any thread. - ~ChannelWin() override { - // This is intentionally not 0. If another object is constructed on top of - // this memory, it is likely to initialise values to 0. Using a non-zero - // value lets us detect the difference between just destroying, and - // re-allocating the memory. - sentinel_ = UINTPTR_MAX; - } + ~ChannelWin() override {} void StartOnIOThread() { base::MessageLoop::current()->AddDestructionObserver(this); @@ -181,7 +168,6 @@ class ChannelWin : public Channel, // base::MessageLoop::DestructionObserver: void WillDestroyCurrentMessageLoop() override { - CheckValid(); DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); if (self_) ShutDownOnIOThread(); @@ -191,7 +177,6 @@ class ChannelWin : public Channel, void OnIOCompleted(base::MessageLoopForIO::IOContext* context, DWORD bytes_transfered, DWORD error) override { - CheckValid(); if (error != ERROR_SUCCESS) { OnError(); } else if (context == &read_context_) { @@ -286,10 +271,6 @@ class ChannelWin : public Channel, return WriteNoLock(outgoing_messages_.front()); } - void CheckValid() const { - CHECK_EQ(reinterpret_cast<uintptr_t>(this), ~sentinel_); - } - // Keeps the Channel alive at least until explicit shutdown on the IO thread. scoped_refptr<Channel> self_; @@ -307,12 +288,6 @@ class ChannelWin : public Channel, bool reject_writes_ = false; std::deque<MessageView> outgoing_messages_; - // A value that is unlikely to be valid if this object is destroyed and the - // memory overwritten by something else. When this is valid, its value will be - // ~|this|. - // TODO(amistry): Remove before M50 branch point. - uintptr_t sentinel_; - DISALLOW_COPY_AND_ASSIGN(ChannelWin); }; diff --git a/chromium/mojo/edk/system/core.cc b/chromium/mojo/edk/system/core.cc index b3602d7c5f4..65a64e8fda8 100644 --- a/chromium/mojo/edk/system/core.cc +++ b/chromium/mojo/edk/system/core.cc @@ -13,9 +13,10 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/rand_util.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "crypto/random.h" #include "mojo/edk/embedder/embedder.h" @@ -27,6 +28,7 @@ #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" #include "mojo/edk/system/data_pipe_producer_dispatcher.h" #include "mojo/edk/system/handle_signals_state.h" +#include "mojo/edk/system/message_for_transit.h" #include "mojo/edk/system/message_pipe_dispatcher.h" #include "mojo/edk/system/platform_handle_dispatcher.h" #include "mojo/edk/system/ports/node.h" @@ -246,6 +248,7 @@ ScopedMessagePipeHandle Core::CreateMessagePipe( ScopedMessagePipeHandle Core::CreateParentMessagePipe( const std::string& token) { + RequestContext request_context; ports::PortRef port0, port1; GetNodeController()->node()->CreatePortPair(&port0, &port1); MojoHandle handle = AddDispatcher( @@ -256,6 +259,7 @@ ScopedMessagePipeHandle Core::CreateParentMessagePipe( } ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) { + RequestContext request_context; ports::PortRef port0, port1; GetNodeController()->node()->CreatePortPair(&port0, &port1); MojoHandle handle = AddDispatcher( @@ -271,7 +275,8 @@ MojoResult Core::AsyncWait(MojoHandle handle, scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); DCHECK(dispatcher); - scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); + std::unique_ptr<AsyncWaiter> waiter = + base::WrapUnique(new AsyncWaiter(callback)); MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); if (rv == MOJO_RESULT_OK) ignore_result(waiter.release()); @@ -357,6 +362,76 @@ MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) { return dispatcher->CancelWatch(context); } +MojoResult Core::AllocMessage(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message) { + if (!message) + return MOJO_RESULT_INVALID_ARGUMENT; + + if (num_handles == 0) { // Fast path: no handles. + std::unique_ptr<MessageForTransit> msg; + MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0); + if (rv != MOJO_RESULT_OK) + return rv; + + *message = reinterpret_cast<MojoMessageHandle>(msg.release()); + return MOJO_RESULT_OK; + } + + if (!handles) + return MOJO_RESULT_INVALID_ARGUMENT; + + if (num_handles > kMaxHandlesPerMessage) + return MOJO_RESULT_RESOURCE_EXHAUSTED; + + std::vector<Dispatcher::DispatcherInTransit> dispatchers; + { + base::AutoLock lock(handles_lock_); + MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); + if (rv != MOJO_RESULT_OK) { + handles_.CancelTransit(dispatchers); + return rv; + } + } + DCHECK_EQ(num_handles, dispatchers.size()); + + std::unique_ptr<MessageForTransit> msg; + MojoResult rv = MessageForTransit::Create( + &msg, num_bytes, dispatchers.data(), num_handles); + + { + base::AutoLock lock(handles_lock_); + if (rv == MOJO_RESULT_OK) { + handles_.CompleteTransitAndClose(dispatchers); + *message = reinterpret_cast<MojoMessageHandle>(msg.release()); + } else { + handles_.CancelTransit(dispatchers); + } + } + + return rv; +} + +MojoResult Core::FreeMessage(MojoMessageHandle message) { + if (!message) + return MOJO_RESULT_INVALID_ARGUMENT; + + delete reinterpret_cast<MessageForTransit*>(message); + + return MOJO_RESULT_OK; +} + +MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) { + if (!message) + return MOJO_RESULT_INVALID_ARGUMENT; + + *buffer = reinterpret_cast<MessageForTransit*>(message)->mutable_bytes(); + + return MOJO_RESULT_OK; +} + MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) { RequestContext request_context; if (!wait_set_handle) @@ -472,48 +547,36 @@ MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, const MojoHandle* handles, uint32_t num_handles, MojoWriteMessageFlags flags) { - RequestContext request_context; - auto dispatcher = GetDispatcher(message_pipe_handle); - if (!dispatcher) + if (num_bytes && !bytes) return MOJO_RESULT_INVALID_ARGUMENT; - if (num_handles == 0) // Fast path: no handles. - return dispatcher->WriteMessage(bytes, num_bytes, nullptr, 0, flags); - - CHECK(handles); - - if (num_handles > kMaxHandlesPerMessage) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - for (size_t i = 0; i < num_handles; ++i) { - if (message_pipe_handle == handles[i]) - return MOJO_RESULT_BUSY; + MojoMessageHandle message; + MojoResult rv = AllocMessage(num_bytes, handles, num_handles, + MOJO_ALLOC_MESSAGE_FLAG_NONE, &message); + if (rv != MOJO_RESULT_OK) + return rv; + + if (num_bytes) { + void* buffer = nullptr; + rv = GetMessageBuffer(message, &buffer); + DCHECK_EQ(rv, MOJO_RESULT_OK); + memcpy(buffer, bytes, num_bytes); } - std::vector<Dispatcher::DispatcherInTransit> dispatchers; - { - base::AutoLock lock(handles_lock_); - MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); - if (rv != MOJO_RESULT_OK) { - handles_.CancelTransit(dispatchers); - return rv; - } - } - DCHECK_EQ(num_handles, dispatchers.size()); - - MojoResult rv = dispatcher->WriteMessage( - bytes, num_bytes, dispatchers.data(), num_handles, flags); + return WriteMessageNew(message_pipe_handle, message, flags); +} - { - base::AutoLock lock(handles_lock_); - if (rv == MOJO_RESULT_OK) { - handles_.CompleteTransitAndClose(dispatchers); - } else { - handles_.CancelTransit(dispatchers); - } - } +MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags) { + RequestContext request_context; + std::unique_ptr<MessageForTransit> message_for_transit( + reinterpret_cast<MessageForTransit*>(message)); + auto dispatcher = GetDispatcher(message_pipe_handle); + if (!dispatcher) + return MOJO_RESULT_INVALID_ARGUMENT; - return rv; + return dispatcher->WriteMessage(std::move(message_for_transit), flags); } MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, @@ -522,13 +585,45 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, MojoHandle* handles, uint32_t* num_handles, MojoReadMessageFlags flags) { - RequestContext request_context; CHECK((!num_handles || !*num_handles || handles) && (!num_bytes || !*num_bytes || bytes)); + RequestContext request_context; + auto dispatcher = GetDispatcher(message_pipe_handle); + if (!dispatcher) + return MOJO_RESULT_INVALID_ARGUMENT; + std::unique_ptr<MessageForTransit> message; + MojoResult rv = + dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags, + false /* ignore_num_bytes */); + if (rv != MOJO_RESULT_OK) + return rv; + + if (message && message->num_bytes()) + memcpy(bytes, message->bytes(), message->num_bytes()); + + return MOJO_RESULT_OK; +} + +MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags) { + CHECK(message); + CHECK(!num_handles || !*num_handles || handles); + RequestContext request_context; auto dispatcher = GetDispatcher(message_pipe_handle); if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; - return dispatcher->ReadMessage(bytes, num_bytes, handles, num_handles, flags); + std::unique_ptr<MessageForTransit> msg; + MojoResult rv = + dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags, + true /* ignore_num_bytes */); + if (rv != MOJO_RESULT_OK) + return rv; + *message = reinterpret_cast<MojoMessageHandle>(msg.release()); + return MOJO_RESULT_OK; } MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { @@ -761,7 +856,7 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; - scoped_ptr<PlatformSharedBufferMapping> mapping; + std::unique_ptr<PlatformSharedBufferMapping> mapping; MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); if (result != MOJO_RESULT_OK) return result; @@ -860,7 +955,7 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, // static void Core::PassNodeControllerToIOThread( - scoped_ptr<NodeController> node_controller) { + std::unique_ptr<NodeController> node_controller) { // It's OK to leak this reference. At this point we know the IO loop is still // running, and we know the NodeController will observe its eventual // destruction. This tells the NodeController to delete itself when that diff --git a/chromium/mojo/edk/system/core.h b/chromium/mojo/edk/system/core.h index 18da0ba375c..7871480e72c 100644 --- a/chromium/mojo/edk/system/core.h +++ b/chromium/mojo/edk/system/core.h @@ -5,12 +5,12 @@ #ifndef MOJO_EDK_SYSTEM_CORE_H_ #define MOJO_EDK_SYSTEM_CORE_H_ +#include <memory> #include <vector> #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory_handle.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" @@ -144,6 +144,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { MojoWatchCallback callback, uintptr_t context); MojoResult CancelWatch(MojoHandle handle, uintptr_t context); + MojoResult AllocMessage(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message); + MojoResult FreeMessage(MojoMessageHandle message); + MojoResult GetMessageBuffer(MojoMessageHandle message, void** buffer); // These methods correspond to the API functions defined in // "mojo/public/c/system/wait_set.h": @@ -171,12 +178,21 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { const MojoHandle* handles, uint32_t num_handles, MojoWriteMessageFlags flags); + MojoResult WriteMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags); MojoResult ReadMessage(MojoHandle message_pipe_handle, void* bytes, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, MojoReadMessageFlags flags); + MojoResult ReadMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags); MojoResult FuseMessagePipes(MojoHandle handle0, MojoHandle handle1); // These methods correspond to the API functions defined in @@ -236,7 +252,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { // Used to pass ownership of our NodeController over to the IO thread in the // event that we're torn down before said thread. static void PassNodeControllerToIOThread( - scoped_ptr<NodeController> node_controller); + std::unique_ptr<NodeController> node_controller); // Guards node_controller_. // @@ -250,7 +266,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { // This is lazily initialized on first access. Always use GetNodeController() // to access it. - scoped_ptr<NodeController> node_controller_; + std::unique_ptr<NodeController> node_controller_; base::Lock handles_lock_; HandleTable handles_; diff --git a/chromium/mojo/edk/system/core_test_base.cc b/chromium/mojo/edk/system/core_test_base.cc index 635501aa2c7..e98a55d2ad1 100644 --- a/chromium/mojo/edk/system/core_test_base.cc +++ b/chromium/mojo/edk/system/core_test_base.cc @@ -16,6 +16,7 @@ #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/dispatcher.h" +#include "mojo/edk/system/message_for_transit.h" namespace mojo { namespace edk { @@ -41,27 +42,25 @@ class MockDispatcher : public Dispatcher { } MojoResult WriteMessage( - const void* bytes, - uint32_t num_bytes, - const DispatcherInTransit* dispatchers, - uint32_t num_dispatchers, + std::unique_ptr<MessageForTransit> message, MojoWriteMessageFlags /*flags*/) override { info_->IncrementWriteMessageCallCount(); - if (num_bytes > GetConfiguration().max_message_num_bytes) + if (message->num_bytes() > GetConfiguration().max_message_num_bytes) return MOJO_RESULT_RESOURCE_EXHAUSTED; - if (dispatchers) + if (message->num_handles()) return MOJO_RESULT_UNIMPLEMENTED; return MOJO_RESULT_OK; } - MojoResult ReadMessage(void* bytes, + MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message, uint32_t* num_bytes, MojoHandle* handle, uint32_t* num_handles, - MojoReadMessageFlags /*flags*/) override { + MojoReadMessageFlags /*flags*/, + bool ignore_num_bytes) override { info_->IncrementReadMessageCallCount(); if (num_handles) diff --git a/chromium/mojo/edk/system/core_unittest.cc b/chromium/mojo/edk/system/core_unittest.cc index 7eeabc03e2f..a25c7af3d08 100644 --- a/chromium/mojo/edk/system/core_unittest.cc +++ b/chromium/mojo/edk/system/core_unittest.cc @@ -327,6 +327,18 @@ TEST_F(CoreTest, InvalidArguments) { MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(0u, info.GetWriteMessageCallCount()); + // Null |bytes| with non-zero message size. + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + core()->WriteMessage(h, nullptr, 1, nullptr, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(0u, info.GetWriteMessageCallCount()); + + // Null |handles| with non-zero handle count. + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + core()->WriteMessage(h, nullptr, 0, nullptr, 1, + MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(0u, info.GetWriteMessageCallCount()); + // Huge handle count (plausibly big). ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, core()->WriteMessage( @@ -349,19 +361,21 @@ TEST_F(CoreTest, InvalidArguments) { MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - // Can't send a handle over itself. + // Can't send a handle over itself. Note that this will also cause |h| to be + // closed. handles[0] = h; ASSERT_EQ( - MOJO_RESULT_BUSY, + MOJO_RESULT_INVALID_ARGUMENT, core()->WriteMessage(h, nullptr, 0, handles, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(0u, info.GetWriteMessageCallCount()); + h = CreateMockHandle(&info); + MockHandleInfo info2; - MojoHandle h2 = CreateMockHandle(&info2); // This is "okay", but |MockDispatcher| doesn't implement it. - handles[0] = h2; + handles[0] = CreateMockHandle(&info2); ASSERT_EQ( MOJO_RESULT_UNIMPLEMENTED, core()->WriteMessage(h, nullptr, 0, handles, 1, @@ -369,32 +383,33 @@ TEST_F(CoreTest, InvalidArguments) { ASSERT_EQ(1u, info.GetWriteMessageCallCount()); // One of the |handles| is still invalid. + handles[0] = CreateMockHandle(&info2); ASSERT_EQ( MOJO_RESULT_INVALID_ARGUMENT, core()->WriteMessage(h, nullptr, 0, handles, 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - // One of the |handles| is the same as |handle|. + // One of the |handles| is the same as |h|. Both handles are closed. + handles[0] = CreateMockHandle(&info2); handles[1] = h; ASSERT_EQ( - MOJO_RESULT_BUSY, + MOJO_RESULT_INVALID_ARGUMENT, core()->WriteMessage(h, nullptr, 0, handles, 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetWriteMessageCallCount()); + h = CreateMockHandle(&info); + // Can't send a handle twice in the same message. - handles[1] = h2; + handles[0] = CreateMockHandle(&info2); + handles[1] = handles[0]; ASSERT_EQ( MOJO_RESULT_BUSY, core()->WriteMessage(h, nullptr, 0, handles, 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - // Note: Since we never successfully sent anything with it, |h2| should - // still be valid. - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h2)); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); } @@ -430,7 +445,11 @@ TEST_F(CoreTest, InvalidArguments) { // (for required pointer arguments) will still cause death, but perhaps not // predictably. TEST_F(CoreTest, InvalidArgumentsDeath) { +#if defined(OFFICIAL_BUILD) + const char kMemoryCheckFailedRegex[] = ""; +#else const char kMemoryCheckFailedRegex[] = "Check failed"; +#endif // |WaitMany()|: { @@ -462,22 +481,6 @@ TEST_F(CoreTest, InvalidArgumentsDeath) { kMemoryCheckFailedRegex); } - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Null |handles| with nonzero |num_handles|. - ASSERT_DEATH_IF_SUPPORTED( - core()->WriteMessage(h, nullptr, 0, nullptr, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - // |ReadMessage()|: // Only check arguments checked by |Core|, namely |handle|, |handles|, and // |num_handles|. @@ -711,21 +714,23 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { // Make sure that you can't pass either of the message pipe's handles over // itself. - ASSERT_EQ(MOJO_RESULT_BUSY, + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->WriteMessage(h_passing[0], kHello, kHelloSize, &h_passing[0], 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->WriteMessage(h_passing[0], kHello, kHelloSize, &h_passing[1], 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); MojoHandle h_passed[2]; - MojoCreateMessagePipeOptions options; - options.struct_size = sizeof(MojoCreateMessagePipeOptions); - options.flags = MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE; ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(&options, &h_passed[0], &h_passed[1])); + core()->CreateMessagePipe(nullptr, &h_passed[0], &h_passed[1])); // Make sure that |h_passed[]| work properly. ASSERT_EQ(MOJO_RESULT_OK, diff --git a/chromium/mojo/edk/system/data_pipe.cc b/chromium/mojo/edk/system/data_pipe.cc deleted file mode 100644 index 09c3be87198..00000000000 --- a/chromium/mojo/edk/system/data_pipe.cc +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/data_pipe.h" - -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include <algorithm> -#include <limits> - -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/options_validation.h" -#include "mojo/edk/system/raw_channel.h" -#include "mojo/edk/system/transport_data.h" - -namespace mojo { -namespace edk { - -namespace { - -const uint32_t kInvalidDataPipeHandleIndex = static_cast<uint32_t>(-1); - -struct MOJO_ALIGNAS(8) SerializedDataPipeHandleDispatcher { - MOJO_ALIGNAS(4) - uint32_t platform_handle_index; // (Or |kInvalidDataPipeHandleIndex|.) - - // These are from MojoCreateDataPipeOptions - MOJO_ALIGNAS(4) MojoCreateDataPipeOptionsFlags flags; - MOJO_ALIGNAS(4) uint32_t element_num_bytes; - MOJO_ALIGNAS(4) uint32_t capacity_num_bytes; - - MOJO_ALIGNAS(4) - uint32_t shared_memory_handle_index; // (Or |kInvalidDataPipeHandleIndex|.) - MOJO_ALIGNAS(4) uint32_t shared_memory_size; -}; - -} // namespace - -MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { - MojoCreateDataPipeOptions result = { - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - 1u, - static_cast<uint32_t>( - GetConfiguration().default_data_pipe_capacity_bytes)}; - return result; -} - -MojoResult DataPipe::ValidateCreateOptions( - const MojoCreateDataPipeOptions* in_options, - MojoCreateDataPipeOptions* out_options) { - const MojoCreateDataPipeOptionsFlags kKnownFlags = - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; - - *out_options = GetDefaultCreateOptions(); - if (!in_options) - return MOJO_RESULT_OK; - - UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes, - reader)) - return MOJO_RESULT_OK; - if (reader.options().element_num_bytes == 0) - return MOJO_RESULT_INVALID_ARGUMENT; - out_options->element_num_bytes = reader.options().element_num_bytes; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes, - reader) || - reader.options().capacity_num_bytes == 0) { - // Round the default capacity down to a multiple of the element size (but at - // least one element). - size_t default_data_pipe_capacity_bytes = - GetConfiguration().default_data_pipe_capacity_bytes; - out_options->capacity_num_bytes = - std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes - - (default_data_pipe_capacity_bytes % - out_options->element_num_bytes)), - out_options->element_num_bytes); - return MOJO_RESULT_OK; - } - if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - if (reader.options().capacity_num_bytes > - GetConfiguration().max_data_pipe_capacity_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - out_options->capacity_num_bytes = reader.options().capacity_num_bytes; - - return MOJO_RESULT_OK; -} - -void DataPipe::StartSerialize(bool have_channel_handle, - bool have_shared_memory, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = sizeof(SerializedDataPipeHandleDispatcher); - *max_platform_handles = 0; - if (have_channel_handle) - (*max_platform_handles)++; - if (have_shared_memory) - (*max_platform_handles)++; -} - -void DataPipe::EndSerialize(const MojoCreateDataPipeOptions& options, - ScopedPlatformHandle channel_handle, - ScopedPlatformHandle shared_memory_handle, - size_t shared_memory_size, - void* destination, - size_t* actual_size, - PlatformHandleVector* platform_handles) { - SerializedDataPipeHandleDispatcher* serialization = - static_cast<SerializedDataPipeHandleDispatcher*>(destination); - if (channel_handle.is_valid()) { - DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); - serialization->platform_handle_index = - static_cast<uint32_t>(platform_handles->size()); - platform_handles->push_back(channel_handle.release()); - } else { - serialization->platform_handle_index = kInvalidDataPipeHandleIndex; - } - - serialization->flags = options.flags; - serialization->element_num_bytes = options.element_num_bytes; - serialization->capacity_num_bytes = options.capacity_num_bytes; - - serialization->shared_memory_size = static_cast<uint32_t>(shared_memory_size); - if (serialization->shared_memory_size) { - DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); - serialization->shared_memory_handle_index = - static_cast<uint32_t>(platform_handles->size()); - platform_handles->push_back(shared_memory_handle.release()); - } else { - serialization->shared_memory_handle_index = kInvalidDataPipeHandleIndex; - } - - *actual_size = sizeof(SerializedDataPipeHandleDispatcher); -} - -ScopedPlatformHandle DataPipe::Deserialize( - const void* source, - size_t size, - PlatformHandleVector* platform_handles, - MojoCreateDataPipeOptions* options, - ScopedPlatformHandle* shared_memory_handle, - size_t* shared_memory_size) { - if (size != sizeof(SerializedDataPipeHandleDispatcher)) { - LOG(ERROR) << "Invalid serialized data pipe dispatcher (bad size)"; - return ScopedPlatformHandle(); - } - - const SerializedDataPipeHandleDispatcher* serialization = - static_cast<const SerializedDataPipeHandleDispatcher*>(source); - size_t platform_handle_index = serialization->platform_handle_index; - - // Starts off invalid, which is what we want. - PlatformHandle platform_handle; - if (platform_handle_index != kInvalidDataPipeHandleIndex) { - if (!platform_handles || - platform_handle_index >= platform_handles->size()) { - LOG(ERROR) - << "Invalid serialized data pipe dispatcher (missing handles)"; - return ScopedPlatformHandle(); - } - - // We take ownership of the handle, so we have to invalidate the one in - // |platform_handles|. - std::swap(platform_handle, (*platform_handles)[platform_handle_index]); - } - - options->struct_size = sizeof(MojoCreateDataPipeOptions); - options->flags = serialization->flags; - options->element_num_bytes = serialization->element_num_bytes; - options->capacity_num_bytes = serialization->capacity_num_bytes; - - if (shared_memory_size) { - *shared_memory_size = serialization->shared_memory_size; - if (*shared_memory_size) { - DCHECK(serialization->shared_memory_handle_index != - kInvalidDataPipeHandleIndex); - if (!platform_handles || - serialization->shared_memory_handle_index >= - platform_handles->size()) { - LOG(ERROR) << "Invalid serialized data pipe dispatcher " - << "(missing handles)"; - return ScopedPlatformHandle(); - } - - PlatformHandle temp_shared_memory_handle; - std::swap(temp_shared_memory_handle, - (*platform_handles)[serialization->shared_memory_handle_index]); - *shared_memory_handle = - ScopedPlatformHandle(temp_shared_memory_handle); - } - } - - size -= sizeof(SerializedDataPipeHandleDispatcher); - - return ScopedPlatformHandle(platform_handle); -} - -} // namespace edk -} // namespace mojo diff --git a/chromium/mojo/edk/system/data_pipe.h b/chromium/mojo/edk/system/data_pipe.h deleted file mode 100644 index 24281898a95..00000000000 --- a/chromium/mojo/edk/system/data_pipe.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_H_ -#define MOJO_EDK_SYSTEM_DATA_PIPE_H_ - -#include <stddef.h> - -#include "base/compiler_specific.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { -class RawChannel; - -// Shared code between DataPipeConsumerDispatcher and -// DataPipeProducerDispatcher. -class MOJO_SYSTEM_IMPL_EXPORT DataPipe { - public: - // The default options for |MojoCreateDataPipe()|. (Real uses should obtain - // this via |ValidateCreateOptions()| with a null |in_options|; this is - // exposed directly for testing convenience.) - static MojoCreateDataPipeOptions GetDefaultCreateOptions(); - - // Validates and/or sets default options for |MojoCreateDataPipeOptions|. If - // non-null, |in_options| must point to a struct of at least - // |in_options->struct_size| bytes. |out_options| must point to a (current) - // |MojoCreateDataPipeOptions| and will be entirely overwritten on success (it - // may be partly overwritten on failure). - static MojoResult ValidateCreateOptions( - const MojoCreateDataPipeOptions* in_options, - MojoCreateDataPipeOptions* out_options); - - // Helper methods used by DataPipeConsumerDispatcher and - // DataPipeProducerDispatcher for serialization and deserialization. - static void StartSerialize(bool have_channel_handle, - bool have_shared_memory, - size_t* max_size, - size_t* max_platform_handles); - static void EndSerialize(const MojoCreateDataPipeOptions& options, - ScopedPlatformHandle channel_handle, - ScopedPlatformHandle shared_memory_handle, - size_t shared_memory_size, - void* destination, - size_t* actual_size, - PlatformHandleVector* platform_handles); - static ScopedPlatformHandle Deserialize( - const void* source, - size_t size, - PlatformHandleVector* platform_handles, - MojoCreateDataPipeOptions* options, - ScopedPlatformHandle* shared_memory_handle, - size_t* shared_memory_size); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_DATA_PIPE_H_ diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc index 158b0e17e3e..23cb2e0368d 100644 --- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc @@ -518,16 +518,12 @@ void DataPipeConsumerDispatcher::UpdateSignalsStateNoLock() { size_t previous_bytes_available = bytes_available_; ports::PortStatus port_status; - if (node_controller_->node()->GetStatus(control_port_, &port_status) != - ports::OK || - !port_status.receiving_messages) { + int rv = node_controller_->node()->GetStatus(control_port_, &port_status); + if (rv != ports::OK || !port_status.receiving_messages) { DVLOG(1) << "Data pipe consumer " << pipe_id_ << " is aware of peer closure" << " [control_port=" << control_port_.name() << "]"; - peer_closed_ = true; - } - - if (port_status.has_messages && !in_transit_) { + } else if (rv == ports::OK && port_status.has_messages && !in_transit_) { ports::ScopedMessage message; do { int rv = node_controller_->node()->GetMessageIf(control_port_, nullptr, diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h index 945aa073eea..6a7fb1c5b03 100644 --- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h @@ -8,9 +8,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/embedder/platform_shared_buffer.h" @@ -103,7 +104,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final AwakableList awakable_list_; scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_; - scoped_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_; + std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_; ScopedPlatformHandle buffer_handle_for_transit_; bool in_two_phase_read_ = false; diff --git a/chromium/mojo/edk/system/data_pipe_control_message.cc b/chromium/mojo/edk/system/data_pipe_control_message.cc index e81df6a95d6..23873b82903 100644 --- a/chromium/mojo/edk/system/data_pipe_control_message.cc +++ b/chromium/mojo/edk/system/data_pipe_control_message.cc @@ -15,7 +15,7 @@ void SendDataPipeControlMessage(NodeController* node_controller, const ports::PortRef& port, DataPipeCommand command, uint32_t num_bytes) { - scoped_ptr<PortsMessage> message = + std::unique_ptr<PortsMessage> message = PortsMessage::NewUserMessage(sizeof(DataPipeControlMessage), 0, 0); CHECK(message); @@ -24,7 +24,7 @@ void SendDataPipeControlMessage(NodeController* node_controller, data->command = command; data->num_bytes = num_bytes; - int rv = node_controller->SendMessage(port, &message); + int rv = node_controller->SendMessage(port, std::move(message)); if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { DLOG(ERROR) << "Unexpected failure sending data pipe control message: " << rv; diff --git a/chromium/mojo/edk/system/data_pipe_control_message.h b/chromium/mojo/edk/system/data_pipe_control_message.h index 7552dd01dc0..82ee594ea94 100644 --- a/chromium/mojo/edk/system/data_pipe_control_message.h +++ b/chromium/mojo/edk/system/data_pipe_control_message.h @@ -7,7 +7,8 @@ #include <stdint.h> -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/ports/port_ref.h" #include "mojo/public/c/system/macros.h" diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc index 364b898e236..d056e7dbc83 100644 --- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc @@ -496,16 +496,12 @@ void DataPipeProducerDispatcher::UpdateSignalsStateNoLock() { size_t previous_capacity = available_capacity_; ports::PortStatus port_status; - if (node_controller_->node()->GetStatus(control_port_, &port_status) != - ports::OK || - !port_status.receiving_messages) { + int rv = node_controller_->node()->GetStatus(control_port_, &port_status); + if (rv != ports::OK || !port_status.receiving_messages) { DVLOG(1) << "Data pipe producer " << pipe_id_ << " is aware of peer closure" << " [control_port=" << control_port_.name() << "]"; - peer_closed_ = true; - } - - if (port_status.has_messages && !in_transit_) { + } else if (rv == ports::OK && port_status.has_messages && !in_transit_) { ports::ScopedMessage message; do { int rv = node_controller_->node()->GetMessageIf(control_port_, nullptr, diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h index cfdeb965ac4..a55234a1dfe 100644 --- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h +++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h @@ -8,9 +8,10 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/embedder/platform_shared_buffer.h" @@ -107,7 +108,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final bool buffer_requested_ = false; scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_; - scoped_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_; + std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_; ScopedPlatformHandle buffer_handle_for_transit_; bool in_transit_ = false; diff --git a/chromium/mojo/edk/system/data_pipe_unittest.cc b/chromium/mojo/edk/system/data_pipe_unittest.cc index 944340bb269..526444c6d58 100644 --- a/chromium/mojo/edk/system/data_pipe_unittest.cc +++ b/chromium/mojo/edk/system/data_pipe_unittest.cc @@ -5,11 +5,12 @@ #include <stddef.h> #include <stdint.h> +#include <memory> + #include "base/bind.h" #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/platform_channel_pair.h" @@ -1657,13 +1658,7 @@ bool ReadAllData(MojoHandle consumer, #if !defined(OS_IOS) -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_Multiprocess DISABLED_Multiprocess -#else -#define MAYBE_Multiprocess Multiprocess -#endif // defined(OS_ANDROID) -TEST_F(DataPipeTest, MAYBE_Multiprocess) { +TEST_F(DataPipeTest, Multiprocess) { const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kMultiprocessTestData)); const MojoCreateDataPipeOptions options = { @@ -1836,13 +1831,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SendConsumerAndCloseProducer DISABLED_SendConsumerAndCloseProducer -#else -#define MAYBE_SendConsumerAndCloseProducer SendConsumerAndCloseProducer -#endif // defined(OS_ANDROID) -TEST_F(DataPipeTest, MAYBE_SendConsumerAndCloseProducer) { +TEST_F(DataPipeTest, SendConsumerAndCloseProducer) { // Create a new data pipe. MojoHandle p, c; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p ,&c)); @@ -1885,13 +1874,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_CreateInChild DISABLED_CreateInChild -#else -#define MAYBE_CreateInChild CreateInChild -#endif // defined(OS_ANDROID) -TEST_F(DataPipeTest, MAYBE_CreateInChild) { +TEST_F(DataPipeTest, CreateInChild) { RUN_CHILD_ON_PIPE(CreateAndWrite, child) MojoHandle c; std::string expected_message = ReadMessageWithHandles(child, &c, 1); diff --git a/chromium/mojo/edk/system/dispatcher.cc b/chromium/mojo/edk/system/dispatcher.cc index 6705542ecf7..7d701b24428 100644 --- a/chromium/mojo/edk/system/dispatcher.cc +++ b/chromium/mojo/edk/system/dispatcher.cc @@ -32,19 +32,17 @@ MojoResult Dispatcher::CancelWatch(uintptr_t context) { return MOJO_RESULT_INVALID_ARGUMENT; } -MojoResult Dispatcher::WriteMessage(const void* bytes, - uint32_t num_bytes, - const DispatcherInTransit* dispatchers, - uint32_t num_dispatchers, +MojoResult Dispatcher::WriteMessage(std::unique_ptr<MessageForTransit> message, MojoWriteMessageFlags flags) { return MOJO_RESULT_INVALID_ARGUMENT; } -MojoResult Dispatcher::ReadMessage(void* bytes, +MojoResult Dispatcher::ReadMessage(std::unique_ptr<MessageForTransit>* message, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, - MojoReadMessageFlags flags) { + MojoReadMessageFlags flags, + bool read_any_size) { return MOJO_RESULT_INVALID_ARGUMENT; } @@ -58,7 +56,7 @@ MojoResult Dispatcher::MapBuffer( uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr<PlatformSharedBufferMapping>* mapping) { + std::unique_ptr<PlatformSharedBufferMapping>* mapping) { return MOJO_RESULT_INVALID_ARGUMENT; } diff --git a/chromium/mojo/edk/system/dispatcher.h b/chromium/mojo/edk/system/dispatcher.h index e8bcf330c64..9dca67fa45f 100644 --- a/chromium/mojo/edk/system/dispatcher.h +++ b/chromium/mojo/edk/system/dispatcher.h @@ -8,12 +8,12 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <ostream> #include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/embedder/platform_shared_buffer.h" @@ -31,6 +31,7 @@ namespace edk { class Awakable; class Dispatcher; +class MessageForTransit; using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; @@ -76,17 +77,15 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher ///////////// Message pipe API ///////////// - virtual MojoResult WriteMessage(const void* bytes, - uint32_t num_bytes, - const DispatcherInTransit* dispatchers, - uint32_t num_dispatchers, + virtual MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message, MojoWriteMessageFlags flags); - virtual MojoResult ReadMessage(void* bytes, + virtual MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, - MojoReadMessageFlags flags); + MojoReadMessageFlags flags, + bool read_any_size); ///////////// Shared buffer API ///////////// @@ -101,7 +100,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr<PlatformSharedBufferMapping>* mapping); + std::unique_ptr<PlatformSharedBufferMapping>* mapping); ///////////// Data pipe consumer API ///////////// diff --git a/chromium/mojo/edk/system/mach_port_relay.cc b/chromium/mojo/edk/system/mach_port_relay.cc index 2dd40e51aae..ddd633c8a45 100644 --- a/chromium/mojo/edk/system/mach_port_relay.cc +++ b/chromium/mojo/edk/system/mach_port_relay.cc @@ -11,12 +11,59 @@ #include "base/logging.h" #include "base/mac/mach_port_util.h" #include "base/mac/scoped_mach_port.h" +#include "base/metrics/histogram_macros.h" #include "base/process/process.h" #include "mojo/edk/embedder/platform_handle_vector.h" namespace mojo { namespace edk { +namespace { + +// Errors that can occur in the broker (privileged parent) process. +// These match tools/metrics/histograms.xml. +// This enum is append-only. +enum class BrokerUMAError : int { + SUCCESS = 0, + // Couldn't get a task port for the process with a given pid. + ERROR_TASK_FOR_PID = 1, + // Couldn't make a port with receive rights in the destination process. + ERROR_MAKE_RECEIVE_PORT = 2, + // Couldn't change the attributes of a Mach port. + ERROR_SET_ATTRIBUTES = 3, + // Couldn't extract a right from the destination. + ERROR_EXTRACT_DEST_RIGHT = 4, + // Couldn't send a Mach port in a call to mach_msg(). + ERROR_SEND_MACH_PORT = 5, + // Couldn't extract a right from the source. + ERROR_EXTRACT_SOURCE_RIGHT = 6, + ERROR_MAX +}; + +// Errors that can occur in a child process. +// These match tools/metrics/histograms.xml. +// This enum is append-only. +enum class ChildUMAError : int { + SUCCESS = 0, + // An error occurred while trying to receive a Mach port with mach_msg(). + ERROR_RECEIVE_MACH_MESSAGE = 1, + ERROR_MAX +}; + +void ReportBrokerError(BrokerUMAError error) { + UMA_HISTOGRAM_ENUMERATION("Mojo.MachPortRelay.BrokerError", + static_cast<int>(error), + static_cast<int>(BrokerUMAError::ERROR_MAX)); +} + +void ReportChildError(ChildUMAError error) { + UMA_HISTOGRAM_ENUMERATION("Mojo.MachPortRelay.ChildError", + static_cast<int>(error), + static_cast<int>(ChildUMAError::ERROR_MAX)); +} + +} // namespace + // static bool MachPortRelay::ReceivePorts(PlatformHandleVector* handles) { DCHECK(handles); @@ -27,15 +74,22 @@ bool MachPortRelay::ReceivePorts(PlatformHandleVector* handles) { if (handle->type != PlatformHandle::Type::MACH_NAME) continue; + if (handle->port == MACH_PORT_NULL) { + handle->type = PlatformHandle::Type::MACH; + continue; + } + base::mac::ScopedMachReceiveRight message_port(handle->port); base::mac::ScopedMachSendRight received_port( base::ReceiveMachPort(message_port.get())); if (received_port.get() == MACH_PORT_NULL) { + ReportChildError(ChildUMAError::ERROR_RECEIVE_MACH_MESSAGE); handle->port = MACH_PORT_NULL; LOG(ERROR) << "Error receiving mach port"; return false; } + ReportChildError(ChildUMAError::SUCCESS); handle->port = received_port.release(); handle->type = PlatformHandle::Type::MACH; } @@ -57,8 +111,13 @@ bool MachPortRelay::SendPortsToProcess(Channel::Message* message, base::ProcessHandle process) { DCHECK(message); mach_port_t task_port = port_provider_->TaskForPid(process); - if (task_port == MACH_PORT_NULL) + if (task_port == MACH_PORT_NULL) { + // Callers check the port provider for the task port before calling this + // function, in order to queue pending messages. Therefore, if this fails, + // it should be considered a genuine, bona fide, electrified, six-car error. + ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID); return false; + } size_t num_sent = 0; bool error = false; @@ -72,15 +131,39 @@ bool MachPortRelay::SendPortsToProcess(Channel::Message* message, if (handle->type != PlatformHandle::Type::MACH) continue; + if (handle->port == MACH_PORT_NULL) { + handle->type = PlatformHandle::Type::MACH_NAME; + num_sent++; + continue; + } + mach_port_name_t intermediate_port; - DCHECK(handle->port != MACH_PORT_NULL); + base::MachCreateError error_code; intermediate_port = base::CreateIntermediateMachPort( - task_port, base::mac::ScopedMachSendRight(handle->port), nullptr); + task_port, base::mac::ScopedMachSendRight(handle->port), &error_code); if (intermediate_port == MACH_PORT_NULL) { + BrokerUMAError uma_error; + switch (error_code) { + case base::MachCreateError::ERROR_MAKE_RECEIVE_PORT: + uma_error = BrokerUMAError::ERROR_MAKE_RECEIVE_PORT; + break; + case base::MachCreateError::ERROR_SET_ATTRIBUTES: + uma_error = BrokerUMAError::ERROR_SET_ATTRIBUTES; + break; + case base::MachCreateError::ERROR_EXTRACT_DEST_RIGHT: + uma_error = BrokerUMAError::ERROR_EXTRACT_DEST_RIGHT; + break; + case base::MachCreateError::ERROR_SEND_MACH_PORT: + uma_error = BrokerUMAError::ERROR_SEND_MACH_PORT; + break; + } + ReportBrokerError(uma_error); handle->port = MACH_PORT_NULL; error = true; break; } + + ReportBrokerError(BrokerUMAError::SUCCESS); handle->port = intermediate_port; handle->type = PlatformHandle::Type::MACH_NAME; num_sent++; @@ -96,8 +179,10 @@ bool MachPortRelay::ExtractPortRights(Channel::Message* message, DCHECK(message); mach_port_t task_port = port_provider_->TaskForPid(process); - if (task_port == MACH_PORT_NULL) + if (task_port == MACH_PORT_NULL) { + ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID); return false; + } size_t num_received = 0; bool error = false; @@ -111,6 +196,12 @@ bool MachPortRelay::ExtractPortRights(Channel::Message* message, if (handle->type != PlatformHandle::Type::MACH_NAME) continue; + if (handle->port == MACH_PORT_NULL) { + handle->type = PlatformHandle::Type::MACH; + num_received++; + continue; + } + mach_port_t extracted_right = MACH_PORT_NULL; mach_msg_type_name_t extracted_right_type; kern_return_t kr = @@ -118,10 +209,12 @@ bool MachPortRelay::ExtractPortRights(Channel::Message* message, MACH_MSG_TYPE_MOVE_SEND, &extracted_right, &extracted_right_type); if (kr != KERN_SUCCESS) { + ReportBrokerError(BrokerUMAError::ERROR_EXTRACT_SOURCE_RIGHT); error = true; break; } + ReportBrokerError(BrokerUMAError::SUCCESS); DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND), extracted_right_type); handle->port = extracted_right; diff --git a/chromium/mojo/edk/system/mapping_table.cc b/chromium/mojo/edk/system/mapping_table.cc index 46afe5a56bb..850944306ea 100644 --- a/chromium/mojo/edk/system/mapping_table.cc +++ b/chromium/mojo/edk/system/mapping_table.cc @@ -20,7 +20,7 @@ MappingTable::~MappingTable() { } MojoResult MappingTable::AddMapping( - scoped_ptr<PlatformSharedBufferMapping> mapping) { + std::unique_ptr<PlatformSharedBufferMapping> mapping) { DCHECK(mapping); if (address_to_mapping_map_.size() >= diff --git a/chromium/mojo/edk/system/mapping_table.h b/chromium/mojo/edk/system/mapping_table.h index 120f9cad73d..00167e36048 100644 --- a/chromium/mojo/edk/system/mapping_table.h +++ b/chromium/mojo/edk/system/mapping_table.h @@ -7,11 +7,11 @@ #include <stdint.h> +#include <memory> #include <vector> #include "base/containers/hash_tables.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" @@ -38,7 +38,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable { // Tries to add a mapping. (Takes ownership of the mapping in all cases; on // failure, it will be destroyed.) - MojoResult AddMapping(scoped_ptr<PlatformSharedBufferMapping> mapping); + MojoResult AddMapping(std::unique_ptr<PlatformSharedBufferMapping> mapping); MojoResult RemoveMapping(void* address); private: diff --git a/chromium/mojo/edk/system/message_for_transit.cc b/chromium/mojo/edk/system/message_for_transit.cc new file mode 100644 index 00000000000..26658e161c6 --- /dev/null +++ b/chromium/mojo/edk/system/message_for_transit.cc @@ -0,0 +1,136 @@ +// Copyright 2016 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/edk/system/message_for_transit.h" + +#include <vector> + +#include "mojo/edk/embedder/platform_handle_vector.h" + +namespace mojo { +namespace edk { + +namespace { + +static_assert(sizeof(MessageForTransit::MessageHeader) % 8 == 0, + "Invalid MessageHeader size."); +static_assert(sizeof(MessageForTransit::DispatcherHeader) % 8 == 0, + "Invalid DispatcherHeader size."); + +} // namespace + +MessageForTransit::~MessageForTransit() {} + +// static +MojoResult MessageForTransit::Create( + std::unique_ptr<MessageForTransit>* message, + uint32_t num_bytes, + const Dispatcher::DispatcherInTransit* dispatchers, + uint32_t num_dispatchers) { + // A structure for retaining information about every Dispatcher that will be + // sent with this message. + struct DispatcherInfo { + uint32_t num_bytes; + uint32_t num_ports; + uint32_t num_handles; + }; + + // This is only the base header size. It will grow as we accumulate the + // size of serialized state for each dispatcher. + size_t header_size = sizeof(MessageHeader) + + num_dispatchers * sizeof(DispatcherHeader); + size_t num_ports = 0; + size_t num_handles = 0; + + std::vector<DispatcherInfo> dispatcher_info(num_dispatchers); + for (size_t i = 0; i < num_dispatchers; ++i) { + Dispatcher* d = dispatchers[i].dispatcher.get(); + d->StartSerialize(&dispatcher_info[i].num_bytes, + &dispatcher_info[i].num_ports, + &dispatcher_info[i].num_handles); + header_size += dispatcher_info[i].num_bytes; + num_ports += dispatcher_info[i].num_ports; + num_handles += dispatcher_info[i].num_handles; + } + + // We now have enough information to fully allocate the message storage. + std::unique_ptr<PortsMessage> msg = PortsMessage::NewUserMessage( + header_size + num_bytes, num_ports, num_handles); + if (!msg) + return MOJO_RESULT_RESOURCE_EXHAUSTED; + + // Populate the message header with information about serialized dispatchers. + // + // The front of the message is always a MessageHeader followed by a + // DispatcherHeader for each dispatcher to be sent. + MessageHeader* header = + static_cast<MessageHeader*>(msg->mutable_payload_bytes()); + DispatcherHeader* dispatcher_headers = + reinterpret_cast<DispatcherHeader*>(header + 1); + + // Serialized dispatcher state immediately follows the series of + // DispatcherHeaders. + char* dispatcher_data = + reinterpret_cast<char*>(dispatcher_headers + num_dispatchers); + + header->num_dispatchers = num_dispatchers; + + // |header_size| is the total number of bytes preceding the message payload, + // including all dispatcher headers and serialized dispatcher state. + DCHECK_LE(header_size, std::numeric_limits<uint32_t>::max()); + header->header_size = static_cast<uint32_t>(header_size); + + if (num_dispatchers > 0) { + ScopedPlatformHandleVectorPtr handles( + new PlatformHandleVector(num_handles)); + size_t port_index = 0; + size_t handle_index = 0; + bool fail = false; + for (size_t i = 0; i < num_dispatchers; ++i) { + Dispatcher* d = dispatchers[i].dispatcher.get(); + DispatcherHeader* dh = &dispatcher_headers[i]; + const DispatcherInfo& info = dispatcher_info[i]; + + // Fill in the header for this dispatcher. + dh->type = static_cast<int32_t>(d->GetType()); + dh->num_bytes = info.num_bytes; + dh->num_ports = info.num_ports; + dh->num_platform_handles = info.num_handles; + + // Fill in serialized state, ports, and platform handles. We'll cancel + // the send if the dispatcher implementation rejects for some reason. + if (!d->EndSerialize(static_cast<void*>(dispatcher_data), + msg->mutable_ports() + port_index, + handles->data() + handle_index)) { + fail = true; + break; + } + + dispatcher_data += info.num_bytes; + port_index += info.num_ports; + handle_index += info.num_handles; + } + + if (fail) { + // Release any platform handles we've accumulated. Their dispatchers + // retain ownership when message creation fails, so these are not actually + // leaking. + handles->clear(); + return MOJO_RESULT_INVALID_ARGUMENT; + } + + // Take ownership of all the handles and move them into message storage. + msg->SetHandles(std::move(handles)); + } + + message->reset(new MessageForTransit(std::move(msg))); + return MOJO_RESULT_OK; +} + +MessageForTransit::MessageForTransit(std::unique_ptr<PortsMessage> message) + : message_(std::move(message)) { +} + +} // namespace edk +} // namespace mojo diff --git a/chromium/mojo/edk/system/message_for_transit.h b/chromium/mojo/edk/system/message_for_transit.h new file mode 100644 index 00000000000..be035b04794 --- /dev/null +++ b/chromium/mojo/edk/system/message_for_transit.h @@ -0,0 +1,113 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ +#define MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ + +#include <stdint.h> + +#include <memory> + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "mojo/edk/system/dispatcher.h" +#include "mojo/edk/system/ports_message.h" +#include "mojo/edk/system/system_impl_export.h" + +namespace mojo { +namespace edk { + +// MessageForTransit holds onto a PortsMessage which may be sent via +// |MojoWriteMessage()| or which may have been received on a pipe endpoint. +// Instances of this class are exposed to Mojo system API consumers via the +// opaque pointers used with |MojoCreateMessage()|, |MojoDestroyMessage()|, +// |MojoWriteMessageNew()|, and |MojoReadMessageNew()|. +class MOJO_SYSTEM_IMPL_EXPORT MessageForTransit { + public: +#pragma pack(push, 1) + // Header attached to every message. + struct MessageHeader { + // The number of serialized dispatchers included in this header. + uint32_t num_dispatchers; + + // Total size of the header, including serialized dispatcher data. + uint32_t header_size; + }; + + // Header for each dispatcher in a message, immediately following the message + // header. + struct DispatcherHeader { + // The type of the dispatcher, correpsonding to the Dispatcher::Type enum. + int32_t type; + + // The size of the serialized dispatcher, not including this header. + uint32_t num_bytes; + + // The number of ports needed to deserialize this dispatcher. + uint32_t num_ports; + + // The number of platform handles needed to deserialize this dispatcher. + uint32_t num_platform_handles; + }; +#pragma pack(pop) + + ~MessageForTransit(); + + // A static constructor for building outbound messages. + static MojoResult Create( + std::unique_ptr<MessageForTransit>* message, + uint32_t num_bytes, + const Dispatcher::DispatcherInTransit* dispatchers, + uint32_t num_dispatchers); + + // A static constructor for wrapping inbound messages. + static std::unique_ptr<MessageForTransit> WrapPortsMessage( + std::unique_ptr<PortsMessage> message) { + return base::WrapUnique(new MessageForTransit(std::move(message))); + } + + const void* bytes() const { + DCHECK(message_); + return static_cast<const void*>( + static_cast<const char*>(message_->payload_bytes()) + + header()->header_size); + } + + void* mutable_bytes() { + DCHECK(message_); + return static_cast<void*>( + static_cast<char*>(message_->mutable_payload_bytes()) + + header()->header_size); + } + + size_t num_bytes() const { + size_t header_size = header()->header_size; + DCHECK_GE(message_->num_payload_bytes(), header_size); + return message_->num_payload_bytes() - header_size; + } + + size_t num_handles() const { return header()->num_dispatchers; } + + std::unique_ptr<PortsMessage> TakePortsMessage() { + return std::move(message_); + } + + private: + explicit MessageForTransit(std::unique_ptr<PortsMessage> message); + + const MessageForTransit::MessageHeader* header() const { + DCHECK(message_); + return static_cast<const MessageForTransit::MessageHeader*>( + message_->payload_bytes()); + } + + std::unique_ptr<PortsMessage> message_; + + DISALLOW_COPY_AND_ASSIGN(MessageForTransit); +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.cc b/chromium/mojo/edk/system/message_pipe_dispatcher.cc index 7e6555dfeda..42c9af0025e 100644 --- a/chromium/mojo/edk/system/message_pipe_dispatcher.cc +++ b/chromium/mojo/edk/system/message_pipe_dispatcher.cc @@ -5,12 +5,13 @@ #include "mojo/edk/system/message_pipe_dispatcher.h" #include <limits> +#include <memory> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" +#include "mojo/edk/system/message_for_transit.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/ports_message.h" #include "mojo/edk/system/request_context.h" @@ -20,36 +21,10 @@ namespace edk { namespace { -#pragma pack(push, 1) - -// Header attached to every message sent over a message pipe. -struct MessageHeader { - // The number of serialized dispatchers included in this header. - uint32_t num_dispatchers; - - // Total size of the header, including serialized dispatcher data. - uint32_t header_size; -}; - -static_assert(sizeof(MessageHeader) % 8 == 0, "Invalid MessageHeader size."); - -// Header for each dispatcher, immediately following the message header. -struct DispatcherHeader { - // The type of the dispatcher, correpsonding to the Dispatcher::Type enum. - int32_t type; +using DispatcherHeader = MessageForTransit::DispatcherHeader; +using MessageHeader = MessageForTransit::MessageHeader; - // The size of the serialized dispatcher, not including this header. - uint32_t num_bytes; - - // The number of ports needed to deserialize this dispatcher. - uint32_t num_ports; - - // The number of platform handles needed to deserialize this dispatcher. - uint32_t num_platform_handles; -}; - -static_assert(sizeof(DispatcherHeader) % 8 == 0, - "Invalid DispatcherHeader size."); +#pragma pack(push, 1) struct SerializedState { uint64_t pipe_id; @@ -107,7 +82,7 @@ bool MessagePipeDispatcher::Fuse(MessagePipeDispatcher* other) { { base::AutoLock lock(signal_lock_); port0 = port_; - port_closed_ = true; + port_closed_.Set(true); awakables_.CancelAll(); } @@ -115,7 +90,7 @@ bool MessagePipeDispatcher::Fuse(MessagePipeDispatcher* other) { { base::AutoLock lock(other->signal_lock_); port1 = other->port_; - other->port_closed_ = true; + other->port_closed_.Set(true); other->awakables_.CancelAll(); } @@ -157,185 +132,63 @@ MojoResult MessagePipeDispatcher::CancelWatch(uintptr_t context) { } MojoResult MessagePipeDispatcher::WriteMessage( - const void* bytes, - uint32_t num_bytes, - const DispatcherInTransit* dispatchers, - uint32_t num_dispatchers, + std::unique_ptr<MessageForTransit> message, MojoWriteMessageFlags flags) { + if (port_closed_ || in_transit_) + return MOJO_RESULT_INVALID_ARGUMENT; - { - base::AutoLock lock(signal_lock_); - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - } - - // A structure for retaining information about every Dispatcher we're about - // to send. This information is collected by calling StartSerialize() on - // each dispatcher in sequence. - struct DispatcherInfo { - uint32_t num_bytes; - uint32_t num_ports; - uint32_t num_handles; - }; - - // This is only the base header size. It will grow as we accumulate the - // size of serialized state for each dispatcher. - size_t header_size = sizeof(MessageHeader) + - num_dispatchers * sizeof(DispatcherHeader); - - size_t num_ports = 0; - size_t num_handles = 0; - - std::vector<DispatcherInfo> dispatcher_info(num_dispatchers); - for (size_t i = 0; i < num_dispatchers; ++i) { - Dispatcher* d = dispatchers[i].dispatcher.get(); - d->StartSerialize(&dispatcher_info[i].num_bytes, - &dispatcher_info[i].num_ports, - &dispatcher_info[i].num_handles); - header_size += dispatcher_info[i].num_bytes; - num_ports += dispatcher_info[i].num_ports; - num_handles += dispatcher_info[i].num_handles; - } - - // We now have enough information to fully allocate the message storage. - scoped_ptr<PortsMessage> message = PortsMessage::NewUserMessage( - header_size + num_bytes, num_ports, num_handles); - DCHECK(message); - - // Populate the message header with information about serialized dispatchers. - // - // The front of the message is always a MessageHeader followed by a - // DispatcherHeader for each dispatcher to be sent. - MessageHeader* header = - static_cast<MessageHeader*>(message->mutable_payload_bytes()); - DispatcherHeader* dispatcher_headers = - reinterpret_cast<DispatcherHeader*>(header + 1); - - // Serialized dispatcher state immediately follows the series of - // DispatcherHeaders. - char* dispatcher_data = - reinterpret_cast<char*>(dispatcher_headers + num_dispatchers); - - header->num_dispatchers = num_dispatchers; - - // |header_size| is the total number of bytes preceding the message payload, - // including all dispatcher headers and serialized dispatcher state. - DCHECK_LE(header_size, std::numeric_limits<uint32_t>::max()); - header->header_size = static_cast<uint32_t>(header_size); - - bool cancel_transit = false; - if (num_dispatchers > 0) { - ScopedPlatformHandleVectorPtr handles( - new PlatformHandleVector(num_handles)); - size_t port_index = 0; - size_t handle_index = 0; - for (size_t i = 0; i < num_dispatchers; ++i) { - Dispatcher* d = dispatchers[i].dispatcher.get(); - DispatcherHeader* dh = &dispatcher_headers[i]; - const DispatcherInfo& info = dispatcher_info[i]; - - // Fill in the header for this dispatcher. - dh->type = static_cast<int32_t>(d->GetType()); - dh->num_bytes = info.num_bytes; - dh->num_ports = info.num_ports; - dh->num_platform_handles = info.num_handles; - - // Fill in serialized state, ports, and platform handles. We'll cancel - // the send if the dispatcher implementation rejects for some reason. - if (!d->EndSerialize(static_cast<void*>(dispatcher_data), - message->mutable_ports() + port_index, - handles->data() + handle_index)) { - cancel_transit = true; - break; - } - - dispatcher_data += info.num_bytes; - port_index += info.num_ports; - handle_index += info.num_handles; - } + size_t num_bytes = message->num_bytes(); + int rv = node_controller_->SendMessage(port_, message->TakePortsMessage()); - if (!cancel_transit) { - // Take ownership of all the handles and move them into message storage. - message->SetHandles(std::move(handles)); - } else { - // Release any platform handles we've accumulated. Their dispatchers - // retain ownership when transit is canceled, so these are not actually - // leaking. - handles->clear(); - } - } + DVLOG(1) << "Sent message on pipe " << pipe_id_ << " endpoint " << endpoint_ + << " [port=" << port_.name() << "; rv=" << rv + << "; num_bytes=" << num_bytes << "]"; - MojoResult result = MOJO_RESULT_OK; - if (!cancel_transit) { - // Copy the message body. - void* message_body = static_cast<void*>( - static_cast<char*>(message->mutable_payload_bytes()) + header_size); - memcpy(message_body, bytes, num_bytes); - - int rv = node_controller_->SendMessage(port_, &message); - - DVLOG(1) << "Sent message on pipe " << pipe_id_ << " endpoint " << endpoint_ - << " [port=" << port_.name() << "; rv=" << rv - << "; num_bytes=" << num_bytes << "]"; - - if (rv != ports::OK) { - if (rv == ports::ERROR_PORT_UNKNOWN || - rv == ports::ERROR_PORT_STATE_UNEXPECTED || - rv == ports::ERROR_PORT_CANNOT_SEND_PEER) { - result = MOJO_RESULT_INVALID_ARGUMENT; - } else if (rv == ports::ERROR_PORT_PEER_CLOSED) { - base::AutoLock lock(signal_lock_); - awakables_.AwakeForStateChange(GetHandleSignalsStateNoLock()); - result = MOJO_RESULT_FAILED_PRECONDITION; - } else { - NOTREACHED(); - result = MOJO_RESULT_UNKNOWN; - } - cancel_transit = true; - } else { - DCHECK(!message); + if (rv != ports::OK) { + if (rv == ports::ERROR_PORT_UNKNOWN || + rv == ports::ERROR_PORT_STATE_UNEXPECTED || + rv == ports::ERROR_PORT_CANNOT_SEND_PEER) { + return MOJO_RESULT_INVALID_ARGUMENT; + } else if (rv == ports::ERROR_PORT_PEER_CLOSED) { + base::AutoLock lock(signal_lock_); + awakables_.AwakeForStateChange(GetHandleSignalsStateNoLock()); + return MOJO_RESULT_FAILED_PRECONDITION; } - } - if (cancel_transit) { - // We ended up not sending the message. Release all the platform handles. - // Their dipatchers retain ownership when transit is canceled, so these are - // not actually leaking. - DCHECK(message); - Channel::MessagePtr m = message->TakeChannelMessage(); - ScopedPlatformHandleVectorPtr handles = m->TakeHandles(); - if (handles) - handles->clear(); + NOTREACHED(); + return MOJO_RESULT_UNKNOWN; } - return result; + return MOJO_RESULT_OK; } -MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - { - base::AutoLock lock(signal_lock_); - // We can't read from a port that's closed or in transit! - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - } +MojoResult MessagePipeDispatcher::ReadMessage( + std::unique_ptr<MessageForTransit>* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags, + bool read_any_size) { + // We can't read from a port that's closed or in transit! + if (port_closed_ || in_transit_) + return MOJO_RESULT_INVALID_ARGUMENT; bool no_space = false; bool may_discard = flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD; bool invalid_message = false; - // Ensure the provided buffers are large enough to hold the next message. - // GetMessageIf provides an atomic way to test the next message without - // committing to removing it from the port's underlying message queue until - // we are sure we can consume it. + // Grab a message if the provided handles buffer is large enough. If the input + // |num_bytes| is provided and |read_any_size| is false, we also ensure + // that it specifies a size at least as large as the next available payload. + // + // If |read_any_size| is true, the input value of |*num_bytes| is ignored. + // This flag exists to support both new and old API behavior. ports::ScopedMessage ports_message; int rv = node_controller_->node()->GetMessageIf( port_, - [num_bytes, num_handles, &no_space, &may_discard, &invalid_message]( + [read_any_size, num_bytes, num_handles, &no_space, &may_discard, + &invalid_message]( const ports::Message& next_message) { const PortsMessage& message = static_cast<const PortsMessage&>(next_message); @@ -367,8 +220,8 @@ MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, *num_handles = handles_available; } - if (bytes_to_read < bytes_available || - handles_to_read < handles_available) { + if (handles_to_read < handles_available || + (!read_any_size && bytes_to_read < bytes_available)) { no_space = true; return may_discard; } @@ -390,9 +243,9 @@ MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, } if (no_space) { - // Either |*num_bytes| or |*num_handles| wasn't sufficient to hold this - // message's data. The message will still be in queue unless - // MOJO_READ_MESSAGE_FLAG_MAY_DISCARD was set. + // |*num_handles| (and/or |*num_bytes| if |read_any_size| is false) wasn't + // sufficient to hold this message's data. The message will still be in + // queue unless MOJO_READ_MESSAGE_FLAG_MAY_DISCARD was set. return MOJO_RESULT_RESOURCE_EXHAUSTED; } @@ -412,11 +265,11 @@ MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, // Alright! We have a message and the caller has provided sufficient storage // in which to receive it. - scoped_ptr<PortsMessage> message( + std::unique_ptr<PortsMessage> msg( static_cast<PortsMessage*>(ports_message.release())); const MessageHeader* header = - static_cast<const MessageHeader*>(message->payload_bytes()); + static_cast<const MessageHeader*>(msg->payload_bytes()); const DispatcherHeader* dispatcher_headers = reinterpret_cast<const DispatcherHeader*>(header + 1); @@ -440,28 +293,26 @@ MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, Type type = static_cast<Type>(dh.type); size_t next_payload_index = data_payload_index + dh.num_bytes; - if (message->num_payload_bytes() < next_payload_index || + if (msg->num_payload_bytes() < next_payload_index || next_payload_index < data_payload_index) { return MOJO_RESULT_UNKNOWN; } size_t next_port_index = port_index + dh.num_ports; - if (message->num_ports() < next_port_index || - next_port_index < port_index) + if (msg->num_ports() < next_port_index || next_port_index < port_index) return MOJO_RESULT_UNKNOWN; size_t next_platform_handle_index = platform_handle_index + dh.num_platform_handles; - if (message->num_handles() < next_platform_handle_index || + if (msg->num_handles() < next_platform_handle_index || next_platform_handle_index < platform_handle_index) { return MOJO_RESULT_UNKNOWN; } PlatformHandle* out_handles = - message->num_handles() ? message->handles() + platform_handle_index - : nullptr; + msg->num_handles() ? msg->handles() + platform_handle_index : nullptr; dispatchers[i].dispatcher = Dispatcher::Deserialize( - type, dispatcher_data, dh.num_bytes, message->ports() + port_index, + type, dispatcher_data, dh.num_bytes, msg->ports() + port_index, dh.num_ports, out_handles, dh.num_platform_handles); if (!dispatchers[i].dispatcher) return MOJO_RESULT_UNKNOWN; @@ -477,12 +328,8 @@ MojoResult MessagePipeDispatcher::ReadMessage(void* bytes, return MOJO_RESULT_UNKNOWN; } - // Copy message bytes. - DCHECK_GE(message->num_payload_bytes(), header->header_size); - const char* payload = reinterpret_cast<const char*>(message->payload_bytes()); - memcpy(bytes, payload + header->header_size, - message->num_payload_bytes() - header->header_size); - + CHECK(msg); + *message = MessageForTransit::WrapPortsMessage(std::move(msg)); return MOJO_RESULT_OK; } @@ -574,7 +421,7 @@ bool MessagePipeDispatcher::BeginTransit() { base::AutoLock lock(signal_lock_); if (in_transit_ || port_closed_) return false; - in_transit_ = true; + in_transit_.Set(true); return in_transit_; } @@ -582,14 +429,14 @@ void MessagePipeDispatcher::CompleteTransitAndClose() { node_controller_->SetPortObserver(port_, nullptr); base::AutoLock lock(signal_lock_); - in_transit_ = false; port_transferred_ = true; + in_transit_.Set(false); CloseNoLock(); } void MessagePipeDispatcher::CancelTransit() { base::AutoLock lock(signal_lock_); - in_transit_ = false; + in_transit_.Set(false); // Something may have happened while we were waiting for potential transit. awakables_.AwakeForStateChange(GetHandleSignalsStateNoLock()); @@ -626,7 +473,7 @@ MojoResult MessagePipeDispatcher::CloseNoLock() { if (port_closed_ || in_transit_) return MOJO_RESULT_INVALID_ARGUMENT; - port_closed_ = true; + port_closed_.Set(true); awakables_.CancelAll(); if (!port_transferred_) { @@ -676,22 +523,23 @@ void MessagePipeDispatcher::OnPortStatusChanged() { #if !defined(NDEBUG) ports::PortStatus port_status; - node_controller_->node()->GetStatus(port_, &port_status); - if (port_status.has_messages) { - ports::ScopedMessage unused; - size_t message_size = 0; - node_controller_->node()->GetMessageIf( - port_, [&message_size](const ports::Message& message) { - message_size = message.num_payload_bytes(); - return false; - }, &unused); - DVLOG(1) << "New message detected on message pipe " << pipe_id_ - << " endpoint " << endpoint_ << " [port=" << port_.name() - << "; size=" << message_size << "]"; - } - if (port_status.peer_closed) { - DVLOG(1) << "Peer closure detected on message pipe " << pipe_id_ - << " endpoint " << endpoint_ << " [port=" << port_.name() << "]"; + if (node_controller_->node()->GetStatus(port_, &port_status) == ports::OK) { + if (port_status.has_messages) { + ports::ScopedMessage unused; + size_t message_size = 0; + node_controller_->node()->GetMessageIf( + port_, [&message_size](const ports::Message& message) { + message_size = message.num_payload_bytes(); + return false; + }, &unused); + DVLOG(1) << "New message detected on message pipe " << pipe_id_ + << " endpoint " << endpoint_ << " [port=" << port_.name() + << "; size=" << message_size << "]"; + } + if (port_status.peer_closed) { + DVLOG(1) << "Peer closure detected on message pipe " << pipe_id_ + << " endpoint " << endpoint_ << " [port=" << port_.name() << "]"; + } } #endif diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.h b/chromium/mojo/edk/system/message_pipe_dispatcher.h index b457ab99f63..fddd0fd8cf8 100644 --- a/chromium/mojo/edk/system/message_pipe_dispatcher.h +++ b/chromium/mojo/edk/system/message_pipe_dispatcher.h @@ -7,12 +7,14 @@ #include <stdint.h> +#include <memory> #include <queue> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "mojo/edk/system/atomic_flag.h" #include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/dispatcher.h" +#include "mojo/edk/system/message_for_transit.h" #include "mojo/edk/system/ports/port_ref.h" namespace mojo { @@ -51,16 +53,14 @@ class MessagePipeDispatcher : public Dispatcher { const Watcher::WatchCallback& callback, uintptr_t context) override; MojoResult CancelWatch(uintptr_t context) override; - MojoResult WriteMessage(const void* bytes, - uint32_t num_bytes, - const DispatcherInTransit* dispatchers, - uint32_t num_dispatchers, + MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message, MojoWriteMessageFlags flags) override; - MojoResult ReadMessage(void* bytes, + MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, - MojoReadMessageFlags flags) override; + MojoReadMessageFlags flags, + bool read_any_size) override; HandleSignalsState GetHandleSignalsState() const override; MojoResult AddAwakable(Awakable* awakable, MojoHandleSignals signals, @@ -107,10 +107,10 @@ class MessagePipeDispatcher : public Dispatcher { // This is not the same is |port_transferred_|. It's only held true between // BeginTransit() and Complete/CancelTransit(). - bool in_transit_ = false; + AtomicFlag in_transit_; bool port_transferred_ = false; - bool port_closed_ = false; + AtomicFlag port_closed_; AwakableList awakables_; DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher); diff --git a/chromium/mojo/edk/system/message_pipe_perftest.cc b/chromium/mojo/edk/system/message_pipe_perftest.cc index 569ee1f2127..a6ce3709e53 100644 --- a/chromium/mojo/edk/system/message_pipe_perftest.cc +++ b/chromium/mojo/edk/system/message_pipe_perftest.cc @@ -5,12 +5,16 @@ #include <stddef.h> #include <stdint.h> +#include <memory> #include <utility> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/logging.h" +#include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/test/perf_time_logger.h" +#include "base/threading/thread.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/handle_signals_state.h" @@ -25,11 +29,9 @@ namespace mojo { namespace edk { namespace { -class MultiprocessMessagePipePerfTest : public test::MojoTestBase { +class MessagePipePerfTest : public test::MojoTestBase { public: - MultiprocessMessagePipePerfTest() - : message_count_(0), - message_size_(0) {} + MessagePipePerfTest() : message_count_(0), message_size_(0) {} void SetUpMeasurement(int message_count, size_t message_size) { message_count_ = message_count; @@ -76,73 +78,90 @@ class MultiprocessMessagePipePerfTest : public test::MojoTestBase { logger.Done(); } + protected: + void RunPingPongServer(MojoHandle mp) { + // This values are set to align with one at ipc_pertests.cc for comparison. + const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832}; + const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000}; + + for (size_t i = 0; i < 5; i++) { + SetUpMeasurement(kMessageCount[i], kMsgSize[i]); + Measure(mp); + } + + SendQuitMessage(mp); + } + + static int RunPingPongClient(MojoHandle mp) { + std::string buffer(1000000, '\0'); + int rv = 0; + while (true) { + // Wait for our end of the message pipe to be readable. + HandleSignalsState hss; + MojoResult result = + MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &hss); + if (result != MOJO_RESULT_OK) { + rv = result; + break; + } + + uint32_t read_size = static_cast<uint32_t>(buffer.size()); + CHECK_EQ(MojoReadMessage(mp, &buffer[0], + &read_size, nullptr, + 0, MOJO_READ_MESSAGE_FLAG_NONE), + MOJO_RESULT_OK); + + // Empty message indicates quit. + if (read_size == 0) + break; + + CHECK_EQ(MojoWriteMessage(mp, &buffer[0], + read_size, + nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), + MOJO_RESULT_OK); + } + + return rv; + } + private: int message_count_; size_t message_size_; std::string payload_; std::string read_buffer_; - scoped_ptr<base::PerfTimeLogger> perf_logger_; + std::unique_ptr<base::PerfTimeLogger> perf_logger_; + + DISALLOW_COPY_AND_ASSIGN(MessagePipePerfTest); }; +TEST_F(MessagePipePerfTest, PingPong) { + MojoHandle server_handle, client_handle; + CreateMessagePipe(&server_handle, &client_handle); + + base::Thread client_thread("PingPongClient"); + client_thread.Start(); + client_thread.task_runner()->PostTask( + FROM_HERE, + base::Bind(base::IgnoreResult(&RunPingPongClient), client_handle)); + + RunPingPongServer(server_handle); +} + // For each message received, sends a reply message with the same contents // repeated twice, until the other end is closed or it receives "quitquitquit" // (which it doesn't reply to). It'll return the number of messages received, // not including any "quitquitquit" message, modulo 100. -DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MultiprocessMessagePipePerfTest, - h) { - std::string buffer(1000000, '\0'); - int rv = 0; - while (true) { - // Wait for our end of the message pipe to be readable. - HandleSignalsState hss; - MojoResult result = - MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &hss); - if (result != MOJO_RESULT_OK) { - rv = result; - break; - } - - uint32_t read_size = static_cast<uint32_t>(buffer.size()); - CHECK_EQ(MojoReadMessage(h, &buffer[0], - &read_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - // Empty message indicates quit. - if (read_size == 0) - break; - - CHECK_EQ(MojoWriteMessage(h, &buffer[0], - read_size, - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - return rv; +DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MessagePipePerfTest, h) { + return RunPingPongClient(h); } // Repeatedly sends messages as previous one got replied by the child. // Waits for the child to close its end before quitting once specified // number of messages has been sent. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PingPong DISABLED_PingPong -#else -#define MAYBE_PingPong PingPong -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipePerfTest, MAYBE_PingPong) { +TEST_F(MessagePipePerfTest, MultiprocessPingPong) { RUN_CHILD_ON_PIPE(PingPongClient, h) - // This values are set to align with one at ipc_pertests.cc for comparison. - const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832}; - const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000}; - - for (size_t i = 0; i < 5; i++) { - SetUpMeasurement(kMessageCount[i], kMsgSize[i]); - Measure(h); - } - - SendQuitMessage(h); + RunPingPongServer(h); END_CHILD() } diff --git a/chromium/mojo/edk/system/message_pipe_unittest.cc b/chromium/mojo/edk/system/message_pipe_unittest.cc index bfafbb740d1..fcfaeca1790 100644 --- a/chromium/mojo/edk/system/message_pipe_unittest.cc +++ b/chromium/mojo/edk/system/message_pipe_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <stdint.h> +#include <string.h> #include "base/memory/ref_counted.h" #include "mojo/edk/system/test_utils.h" @@ -409,6 +410,72 @@ TEST_F(MessagePipeTest, BasicWaiting) { ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); } +TEST_F(MessagePipeTest, InvalidMessageObjects) { + // null message + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoFreeMessage(MOJO_MESSAGE_HANDLE_INVALID)); + + // null message + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoGetMessageBuffer(MOJO_MESSAGE_HANDLE_INVALID, nullptr)); + + // Non-zero num_handles with null handles array. + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoAllocMessage(0, nullptr, 1, MOJO_ALLOC_MESSAGE_FLAG_NONE, + nullptr)); +} + +TEST_F(MessagePipeTest, AllocAndFreeMessage) { + const std::string kMessage = "Hello, world."; + MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID; + ASSERT_EQ(MOJO_RESULT_OK, + MojoAllocMessage(static_cast<uint32_t>(kMessage.size()), nullptr, 0, + MOJO_ALLOC_MESSAGE_FLAG_NONE, &message)); + ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); + ASSERT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); +} + +TEST_F(MessagePipeTest, WriteAndReadMessageObject) { + const std::string kMessage = "Hello, world."; + MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, + MojoAllocMessage(static_cast<uint32_t>(kMessage.size()), nullptr, 0, + MOJO_ALLOC_MESSAGE_FLAG_NONE, &message)); + ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); + + void* buffer = nullptr; + EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer)); + ASSERT_TRUE(buffer); + memcpy(buffer, kMessage.data(), kMessage.size()); + + MojoHandle a, b; + CreateMessagePipe(&a, &b); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWriteMessageNew(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + + EXPECT_EQ(MOJO_RESULT_OK, + MojoWait(b, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, + nullptr)); + uint32_t num_bytes = 0; + uint32_t num_handles = 0; + EXPECT_EQ(MOJO_RESULT_OK, + MojoReadMessageNew(b, &message, &num_bytes, nullptr, &num_handles, + MOJO_READ_MESSAGE_FLAG_NONE)); + ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); + EXPECT_EQ(static_cast<uint32_t>(kMessage.size()), num_bytes); + EXPECT_EQ(0u, num_handles); + + EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer)); + ASSERT_TRUE(buffer); + + EXPECT_EQ(0, strncmp(static_cast<const char*>(buffer), kMessage.data(), + num_bytes)); + + EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); +} + #if !defined(OS_IOS) const size_t kPingPongHandlesPerIteration = 50; @@ -467,13 +534,7 @@ TEST_F(MessagePipeTest, DISABLED_DataPipeProducerHandlePingPong) { MojoClose(p[i]); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SharedBufferHandlePingPong DISABLED_SharedBufferHandlePingPong -#else -#define MAYBE_SharedBufferHandlePingPong SharedBufferHandlePingPong -#endif -TEST_F(MessagePipeTest, MAYBE_SharedBufferHandlePingPong) { +TEST_F(MessagePipeTest, SharedBufferHandlePingPong) { MojoHandle buffers[kPingPongHandlesPerIteration]; for (size_t i = 0; i <kPingPongHandlesPerIteration; ++i) EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 1, &buffers[i])); diff --git a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 1d07d0f650a..946322c9b97 100644 --- a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -115,14 +115,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) { return rv; } -// Sends "hello" to child, and expects "hellohello" back. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_Basic DISABLED_Basic -#else -#define MAYBE_Basic Basic -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { +TEST_F(MultiprocessMessagePipeTest, Basic) { RUN_CHILD_ON_PIPE(EchoEcho, h) std::string hello("hello"); ASSERT_EQ(MOJO_RESULT_OK, @@ -158,15 +151,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { END_CHILD_AND_EXPECT_EXIT_CODE(1 % 100); } -// Sends a bunch of messages to the child. Expects them "repeated" back. Waits -// for the child to close its end before quitting. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_QueueMessages DISABLED_QueueMessages -#else -#define MAYBE_QueueMessages QueueMessages -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { +TEST_F(MultiprocessMessagePipeTest, QueueMessages) { static const size_t kNumMessages = 1001; RUN_CHILD_ON_PIPE(EchoEcho, h) for (size_t i = 0; i < kNumMessages; i++) { @@ -292,13 +277,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer, MultiprocessMessagePipeTest, return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing -#else -#define MAYBE_SharedBufferPassing SharedBufferPassing -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { +TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) { RUN_CHILD_ON_PIPE(CheckSharedBuffer, h) // Make a shared buffer. MojoCreateSharedBufferOptions options; @@ -529,13 +508,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) { return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MessagePipePassing DISABLED_MessagePipePassing -#else -#define MAYBE_MessagePipePassing MessagePipePassing -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { +TEST_F(MultiprocessMessagePipeTest, MessagePipePassing) { RUN_CHILD_ON_PIPE(CheckMessagePipe, h) MojoCreateSharedBufferOptions options; options.struct_size = sizeof(options); @@ -577,14 +550,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { END_CHILD() } -// Like above test, but verifies passing the other MP handle works as well. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing -#else -#define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { +TEST_F(MultiprocessMessagePipeTest, MessagePipeTwoPassing) { RUN_CHILD_ON_PIPE(CheckMessagePipe, h) MojoHandle mp1, mp2; ASSERT_EQ(MOJO_RESULT_OK, @@ -672,13 +638,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) { return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer -#else -#define MAYBE_DataPipeConsumer DataPipeConsumer -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { +TEST_F(MultiprocessMessagePipeTest, DataPipeConsumer) { RUN_CHILD_ON_PIPE(DataPipeConsumer, h) MojoCreateSharedBufferOptions options; options.struct_size = sizeof(options); @@ -772,13 +732,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient, MultiprocessMessagePipeTest, return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MultiprocessChannelPipe DISABLED_MultiprocessChannelPipe -#else -#define MAYBE_MultiprocessChannelPipe MultiprocessChannelPipe -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_MultiprocessChannelPipe) { +TEST_F(MultiprocessMessagePipeTest, MultiprocessChannelPipe) { RUN_CHILD_ON_PIPE(ChannelEchoClient, h) VerifyEcho(h, "in an interstellar burst"); VerifyEcho(h, "i am back to save the universe"); @@ -803,13 +757,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient, MultiprocessMessagePipeTest, return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassMessagePipeCrossProcess DISABLED_PassMessagePipeCrossProcess -#else -#define MAYBE_PassMessagePipeCrossProcess PassMessagePipeCrossProcess -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_PassMessagePipeCrossProcess) { +TEST_F(MultiprocessMessagePipeTest, PassMessagePipeCrossProcess) { MojoHandle p0, p1; CreateMessagePipe(&p0, &p1); RUN_CHILD_ON_PIPE(EchoServiceClient, h) @@ -866,14 +814,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient, return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassMoarMessagePipesCrossProcess \ - DISABLED_PassMoarMessagePipesCrossProcess -#else -#define MAYBE_PassMoarMessagePipesCrossProcess PassMoarMessagePipesCrossProcess -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_PassMoarMessagePipesCrossProcess) { +TEST_F(MultiprocessMessagePipeTest, PassMoarMessagePipesCrossProcess) { MojoHandle echo_factory_proxy, echo_factory_request; CreateMessagePipe(&echo_factory_proxy, &echo_factory_request); @@ -918,14 +859,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_PassMoarMessagePipesCrossProcess) { CloseHandle(echo_proxy_c); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_ChannelPipesWithMultipleChildren \ - DISABLED_ChannelPipesWithMultipleChildren -#else -#define MAYBE_ChannelPipesWithMultipleChildren ChannelPipesWithMultipleChildren -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_ChannelPipesWithMultipleChildren) { +TEST_F(MultiprocessMessagePipeTest, ChannelPipesWithMultipleChildren) { RUN_CHILD_ON_PIPE(ChannelEchoClient, a) RUN_CHILD_ON_PIPE(ChannelEchoClient, b) VerifyEcho(a, "hello child 0"); @@ -955,13 +889,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient, EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PingPongPipe DISABLED_PingPongPipe -#else -#define MAYBE_PingPongPipe PingPongPipe -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_PingPongPipe) { +TEST_F(MultiprocessMessagePipeTest, PingPongPipe) { MojoHandle p0, p1; CreateMessagePipe(&p0, &p1); @@ -1060,13 +988,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient, MultiprocessMessagePipeTest, return 0; } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_ChildToChildPipes DISABLED_ChildToChildPipes -#else -#define MAYBE_ChildToChildPipes ChildToChildPipes -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_ChildToChildPipes) { +TEST_F(MultiprocessMessagePipeTest, ChildToChildPipes) { RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) CommandDrivenClientController a(h0); @@ -1091,13 +1013,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_ChildToChildPipes) { END_CHILD() } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MoreChildToChildPipes DISABLED_MoreChildToChildPipes -#else -#define MAYBE_MoreChildToChildPipes MoreChildToChildPipes -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_MoreChildToChildPipes) { +TEST_F(MultiprocessMessagePipeTest, MoreChildToChildPipes) { RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) RUN_CHILD_ON_PIPE(CommandDrivenClient, h2) @@ -1183,13 +1099,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer, MOJO_DEADLINE_INDEFINITE, nullptr)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SendPipeThenClosePeer DISABLED_SendPipeThenClosePeer -#else -#define MAYBE_SendPipeThenClosePeer SendPipeThenClosePeer -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_SendPipeThenClosePeer) { +TEST_F(MultiprocessMessagePipeTest, SendPipeThenClosePeer) { RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeer, h) MojoHandle a, b; CreateMessagePipe(&a, &b); @@ -1266,13 +1176,7 @@ TEST_F(MultiprocessMessagePipeTest, } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SendClosePeerSend DISABLED_SendClosePeerSend -#else -#define MAYBE_SendClosePeerSend SendClosePeerSend -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_SendClosePeerSend) { +TEST_F(MultiprocessMessagePipeTest, SendClosePeerSend) { MojoHandle a, b; CreateMessagePipe(&a, &b); @@ -1315,13 +1219,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient, EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_WriteCloseSendPeer DISABLED_WriteCloseSendPeer -#else -#define MAYBE_WriteCloseSendPeer WriteCloseSendPeer -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_WriteCloseSendPeer) { +TEST_F(MultiprocessMessagePipeTest, WriteCloseSendPeer) { MojoHandle pipe[2]; CreateMessagePipe(&pipe[0], &pipe[1]); @@ -1361,13 +1259,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BootstrapMessagePipeAsyncClient, VerifyEcho(pipe.get().value(), "goodbye"); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_BootstrapMessagePipeAsync DISABLED_BootstrapMessagePipeAsync -#else -#define MAYBE_BootstrapMessagePipeAsync BootstrapMessagePipeAsync -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_BootstrapMessagePipeAsync) { +TEST_F(MultiprocessMessagePipeTest, BootstrapMessagePipeAsync) { // Tests that new cross-process message pipes can be created synchronously // using asynchronous negotiation over an arbitrary platform channel. RUN_CHILD_ON_PIPE(BootstrapMessagePipeAsyncClient, child) diff --git a/chromium/mojo/edk/system/node_channel.cc b/chromium/mojo/edk/system/node_channel.cc index bde3fba91de..7a0fbb9373c 100644 --- a/chromium/mojo/edk/system/node_channel.cc +++ b/chromium/mojo/edk/system/node_channel.cc @@ -194,6 +194,7 @@ void NodeChannel::ShutDown() { void NodeChannel::SetRemoteProcessHandle(base::ProcessHandle process_handle) { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); base::AutoLock lock(remote_process_handle_lock_); + CHECK_NE(remote_process_handle_, base::GetCurrentProcessHandle()); remote_process_handle_ = process_handle; } @@ -406,11 +407,20 @@ void NodeChannel::OnChannelMessage(const void* payload, { base::AutoLock lock(remote_process_handle_lock_); if (handles && remote_process_handle_ != base::kNullProcessHandle) { + // Note that we explicitly mark the handles as being owned by the sending + // process before rewriting them, in order to accommodate RewriteHandles' + // internal sanity checks. + for (auto& handle : *handles) + handle.owning_process = remote_process_handle_; if (!Channel::Message::RewriteHandles(remote_process_handle_, base::GetCurrentProcessHandle(), handles->data(), handles->size())) { DLOG(ERROR) << "Received one or more invalid handles."; } + } else if (handles) { + // Handles received by an unknown process must already be owned by us. + for (auto& handle : *handles) + handle.owning_process = base::GetCurrentProcessHandle(); } } #elif defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/edk/system/node_controller.cc index 40c57eeac58..822165a9975 100644 --- a/chromium/mojo/edk/system/node_controller.cc +++ b/chromium/mojo/edk/system/node_controller.cc @@ -14,6 +14,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/process/process_handle.h" +#include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "crypto/random.h" #include "mojo/edk/embedder/embedder_internal.h" @@ -173,13 +174,9 @@ void NodeController::ClosePort(const ports::PortRef& port) { } int NodeController::SendMessage(const ports::PortRef& port, - scoped_ptr<PortsMessage>* message) { - ports::ScopedMessage ports_message(message->release()); - int rv = node_->SendMessage(port, &ports_message); - if (rv != ports::OK) { - DCHECK(ports_message); - message->reset(static_cast<PortsMessage*>(ports_message.release())); - } + std::unique_ptr<PortsMessage> message) { + ports::ScopedMessage ports_message(message.release()); + int rv = node_->SendMessage(port, std::move(ports_message)); AcceptIncomingMessages(); return rv; @@ -193,10 +190,19 @@ void NodeController::ReservePort(const std::string& token, base::AutoLock lock(reserved_ports_lock_); auto result = reserved_ports_.insert(std::make_pair(token, port)); DCHECK(result.second); + + // Safeguard against unpredictable and exceptional cases where a reservation + // holder may disappear without ever claiming their reservation. + io_task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&NodeController::CancelReservation, + base::Unretained(this), token), + base::TimeDelta::FromMinutes(1)); } void NodeController::MergePortIntoParent(const std::string& token, const ports::PortRef& port) { + bool was_merged = false; { // This request may be coming from within the process that reserved the // "parent" side (e.g. for Chrome single-process mode), so if this token is @@ -206,9 +212,13 @@ void NodeController::MergePortIntoParent(const std::string& token, if (it != reserved_ports_.end()) { node_->MergePorts(port, name_, it->second.name()); reserved_ports_.erase(it); - return; + was_merged = true; } } + if (was_merged) { + AcceptIncomingMessages(); + return; + } scoped_refptr<NodeChannel> parent; { @@ -251,6 +261,7 @@ void NodeController::RequestShutdown(const base::Closure& callback) { { base::AutoLock lock(shutdown_lock_); shutdown_callback_ = callback; + shutdown_callback_flag_.Set(true); } AttemptShutdownIfRequested(); @@ -475,7 +486,7 @@ void NodeController::SendPeerMessage(const ports::NodeName& name, } void NodeController::AcceptIncomingMessages() { - for (;;) { + while (incoming_messages_flag_) { // TODO: We may need to be more careful to avoid starving the rest of the // thread here. Revisit this if it turns out to be a problem. One // alternative would be to schedule a task to continue pumping messages @@ -490,6 +501,7 @@ void NodeController::AcceptIncomingMessages() { // the size is 0. So avoid creating it until it is necessary. std::queue<ports::ScopedMessage> messages; std::swap(messages, incoming_messages_); + incoming_messages_flag_.Set(false); messages_lock_.Release(); while (!messages.empty()) { @@ -535,6 +547,19 @@ void NodeController::DropAllPeers() { delete this; } +void NodeController::CancelReservation(const std::string& token) { + ports::PortRef reserved_port; + { + base::AutoLock lock(reserved_ports_lock_); + auto iter = reserved_ports_.find(token); + if (iter == reserved_ports_.end()) // Already claimed! + return; + reserved_port = iter->second; + reserved_ports_.erase(iter); + } + node_->ClosePort(reserved_port); +} + void NodeController::GenerateRandomPortName(ports::PortName* port_name) { GenerateRandomName(port_name); } @@ -553,6 +578,7 @@ void NodeController::ForwardMessage(const ports::NodeName& node, // AcceptMessage, we flush the queue after calling any of those methods. base::AutoLock lock(messages_lock_); incoming_messages_.emplace(std::move(message)); + incoming_messages_flag_.Set(true); } else { SendPeerMessage(node, std::move(message)); } @@ -875,6 +901,8 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node, DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); if (!channel_handle.is_valid()) { + node_->LostConnectionToNode(name); + DLOG(ERROR) << "Could not be introduced to peer " << name; base::AutoLock lock(peers_lock_); pending_peer_messages_.erase(name); @@ -911,6 +939,12 @@ void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, // process before going out (see NodeChannel::WriteChannelMessage). // // TODO: We could avoid double-duplication. + // + // Note that we explicitly mark the handles as being owned by the sending + // process before rewriting them, in order to accommodate RewriteHandles' + // internal sanity checks. + for (size_t i = 0; i < message->num_handles(); ++i) + message->handles()[i].owning_process = from_process; if (!Channel::Message::RewriteHandles(from_process, base::GetCurrentProcessHandle(), message->handles(), @@ -978,17 +1012,22 @@ void NodeController::DestroyOnIOThreadShutdown() { } void NodeController::AttemptShutdownIfRequested() { + if (!shutdown_callback_flag_) + return; + base::Closure callback; { base::AutoLock lock(shutdown_lock_); if (shutdown_callback_.is_null()) return; if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) { - DVLOG(2) << "Unable to cleanly shut down node " << name_ << "."; + DVLOG(2) << "Unable to cleanly shut down node " << name_; return; } + callback = shutdown_callback_; shutdown_callback_.Reset(); + shutdown_callback_flag_.Set(false); } DCHECK(!callback.is_null()); diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/edk/system/node_controller.h index 463a72926f9..e2207ca3913 100644 --- a/chromium/mojo/edk/system/node_controller.h +++ b/chromium/mojo/edk/system/node_controller.h @@ -5,6 +5,7 @@ #ifndef MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_ #define MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_ +#include <memory> #include <queue> #include <unordered_map> #include <unordered_set> @@ -14,13 +15,12 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/task_runner.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/system/atomic_flag.h" #include "mojo/edk/system/node_channel.h" -#include "mojo/edk/system/ports/hash_functions.h" #include "mojo/edk/system/ports/name.h" #include "mojo/edk/system/ports/node.h" #include "mojo/edk/system/ports/node_delegate.h" @@ -87,10 +87,9 @@ class NodeController : public ports::NodeDelegate, // it ensures the port's observer has also been removed. void ClosePort(const ports::PortRef& port); - // Sends a message on a port to its peer. If message send fails, |message| - // is left intact. Otherwise ownership is transferred and it's reset. + // Sends a message on a port to its peer. int SendMessage(const ports::PortRef& port_ref, - scoped_ptr<PortsMessage>* message); + std::unique_ptr<PortsMessage> message); // Reserves a local port |port| associated with |token|. A peer holding a copy // of |token| can merge one of its own ports into this one. @@ -138,6 +137,7 @@ class NodeController : public ports::NodeDelegate, ports::ScopedMessage message); void AcceptIncomingMessages(); void DropAllPeers(); + void CancelReservation(const std::string& token); // ports::NodeDelegate: void GenerateRandomPortName(ports::PortName* port_name) override; @@ -197,7 +197,7 @@ class NodeController : public ports::NodeDelegate, // These are safe to access from any thread as long as the Node is alive. Core* const core_; const ports::NodeName name_; - const scoped_ptr<ports::Node> node_; + const std::unique_ptr<ports::Node> node_; scoped_refptr<base::TaskRunner> io_task_runner_; // Guards |peers_| and |pending_peer_messages_|. @@ -248,6 +248,8 @@ class NodeController : public ports::NodeDelegate, // Guards |incoming_messages_|. base::Lock messages_lock_; std::queue<ports::ScopedMessage> incoming_messages_; + // Flag to fast-path checking |incoming_messages_|. + AtomicFlag incoming_messages_flag_; // Guards |shutdown_callback_|. base::Lock shutdown_lock_; @@ -256,6 +258,8 @@ class NodeController : public ports::NodeDelegate, // begin polling the Node to see if clean shutdown is possible any time the // Node's state is modified by the controller. base::Closure shutdown_callback_; + // Flag to fast-path checking |shutdown_callback_|. + AtomicFlag shutdown_callback_flag_; // All other fields below must only be accessed on the I/O thread, i.e., the // thread on which core_->io_task_runner() runs tasks. @@ -269,13 +273,13 @@ class NodeController : public ports::NodeDelegate, #if defined(OS_POSIX) && !defined(OS_MACOSX) // Broker for sync shared buffer creation (non-Mac posix-only) in children. - scoped_ptr<Broker> broker_; + std::unique_ptr<Broker> broker_; #endif #if defined(OS_MACOSX) && !defined(OS_IOS) base::Lock mach_port_relay_lock_; // Relay for transferring mach ports to/from children. - scoped_ptr<MachPortRelay> mach_port_relay_; + std::unique_ptr<MachPortRelay> mach_port_relay_; #endif DISALLOW_COPY_AND_ASSIGN(NodeController); diff --git a/chromium/mojo/edk/system/options_validation_unittest.cc b/chromium/mojo/edk/system/options_validation_unittest.cc index d2c81808dae..a01a92cfb10 100644 --- a/chromium/mojo/edk/system/options_validation_unittest.cc +++ b/chromium/mojo/edk/system/options_validation_unittest.cc @@ -95,7 +95,11 @@ TEST(OptionsValidationTest, Invalid) { // (for required pointer arguments) will still cause death, but perhaps not // predictably. TEST(OptionsValidationTest, InvalidDeath) { +#if defined(OFFICIAL_BUILD) + const char kMemoryCheckFailedRegex[] = ""; +#else const char kMemoryCheckFailedRegex[] = "Check failed"; +#endif // Null: EXPECT_DEATH_IF_SUPPORTED( diff --git a/chromium/mojo/edk/system/ports/BUILD.gn b/chromium/mojo/edk/system/ports/BUILD.gn index 173a17ba5e4..239b3a4400b 100644 --- a/chromium/mojo/edk/system/ports/BUILD.gn +++ b/chromium/mojo/edk/system/ports/BUILD.gn @@ -8,7 +8,6 @@ source_set("ports") { sources = [ "event.cc", "event.h", - "hash_functions.h", "message.cc", "message.h", "message_queue.cc", @@ -29,7 +28,9 @@ source_set("ports") { ] } -test("mojo_system_ports_unittests") { +source_set("tests") { + testonly = true + sources = [ "ports_unittest.cc", ] @@ -38,7 +39,6 @@ test("mojo_system_ports_unittests") { ":ports", "//base", "//base/test:test_support", - "//mojo/edk/test:run_all_unittests", "//testing/gtest", ] } diff --git a/chromium/mojo/edk/system/ports/hash_functions.h b/chromium/mojo/edk/system/ports/hash_functions.h deleted file mode 100644 index 3c91cb35929..00000000000 --- a/chromium/mojo/edk/system/ports/hash_functions.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_HASH_FUNCTIONS_H_ -#define MOJO_EDK_SYSTEM_PORTS_HASH_FUNCTIONS_H_ - -#include <functional> - -#include "mojo/edk/system/ports/name.h" - -namespace std { - -template <> -struct hash<mojo::edk::ports::PortName> { - std::size_t operator()(const mojo::edk::ports::PortName& name) const { - size_t h1 = hash<uint64_t>()(name.v1); - size_t h2 = hash<uint64_t>()(name.v2); - return h1 ^ (h2 << 1); - } -}; - -template <> -struct hash<mojo::edk::ports::NodeName> { - std::size_t operator()(const mojo::edk::ports::NodeName& name) const { - size_t h1 = hash<uint64_t>()(name.v1); - size_t h2 = hash<uint64_t>()(name.v2); - return h1 ^ (h2 << 1); - } -}; - -} // namespace std - -#endif // MOJO_EDK_SYSTEM_PORTS_HASH_FUNCTIONS_H_ diff --git a/chromium/mojo/edk/system/ports/message.h b/chromium/mojo/edk/system/ports/message.h index 926ce752a84..95fa04676ce 100644 --- a/chromium/mojo/edk/system/ports/message.h +++ b/chromium/mojo/edk/system/ports/message.h @@ -7,7 +7,8 @@ #include <stddef.h> -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "mojo/edk/system/ports/name.h" namespace mojo { @@ -83,7 +84,7 @@ class Message { size_t num_payload_bytes_ = 0; }; -using ScopedMessage = scoped_ptr<Message>; +using ScopedMessage = std::unique_ptr<Message>; } // namespace ports } // namespace edk diff --git a/chromium/mojo/edk/system/ports/name.h b/chromium/mojo/edk/system/ports/name.h index 8a9307d9cd3..1082719f6df 100644 --- a/chromium/mojo/edk/system/ports/name.h +++ b/chromium/mojo/edk/system/ports/name.h @@ -10,6 +10,8 @@ #include <ostream> #include <tuple> +#include "base/hash.h" + namespace mojo { namespace edk { namespace ports { @@ -51,4 +53,22 @@ const NodeName kInvalidNodeName = {0, 0}; } // namespace edk } // namespace mojo +namespace std { + +template <> +struct hash<mojo::edk::ports::PortName> { + std::size_t operator()(const mojo::edk::ports::PortName& name) const { + return base::HashInts64(name.v1, name.v2); + } +}; + +template <> +struct hash<mojo::edk::ports::NodeName> { + std::size_t operator()(const mojo::edk::ports::NodeName& name) const { + return base::HashInts64(name.v1, name.v2); + } +}; + +} // namespace std + #endif // MOJO_EDK_SYSTEM_PORTS_NAME_H_ diff --git a/chromium/mojo/edk/system/ports/node.cc b/chromium/mojo/edk/system/ports/node.cc index 266ee84b4f5..75e9857731d 100644 --- a/chromium/mojo/edk/system/ports/node.cc +++ b/chromium/mojo/edk/system/ports/node.cc @@ -6,6 +6,8 @@ #include <string.h> +#include <utility> + #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -28,6 +30,8 @@ bool CanAcceptMoreMessages(const Port* port) { // Have we already doled out the last message (i.e., do we expect to NOT // receive further messages)? uint64_t next_sequence_num = port->message_queue.next_sequence_num(); + if (port->state == Port::kClosed) + return false; if (port->peer_closed || port->remove_proxy_on_last_message) { if (port->last_sequence_num_to_receive == next_sequence_num - 1) return false; @@ -211,13 +215,13 @@ int Node::ClosePort(const PortRef& port_ref) { // If the port being closed still has unread messages, then we need to take // care to close those ports so as to avoid leaking memory. port->message_queue.GetReferencedPorts(&referenced_port_names); + + ErasePort_Locked(port_ref.name()); } DVLOG(2) << "Sending ObserveClosure from " << port_ref.name() << "@" << name_ << " to " << peer_port_name << "@" << peer_node_name; - ErasePort(port_ref.name()); - delegate_->ForwardMessage( peer_node_name, NewInternalMessage(peer_port_name, EventType::kObserveClosure, data)); @@ -269,7 +273,7 @@ int Node::GetMessageIf(const PortRef& port_ref, if (!CanAcceptMoreMessages(port)) return ERROR_PORT_PEER_CLOSED; - port->message_queue.GetNextMessageIf(selector, message); + port->message_queue.GetNextMessageIf(std::move(selector), message); } // Allow referenced ports to trigger PortStatusChanged calls. @@ -291,48 +295,22 @@ int Node::GetMessageIf(const PortRef& port_ref, return OK; } -int Node::SendMessage(const PortRef& port_ref, ScopedMessage* message) { - ScopedMessage& m = *message; - for (size_t i = 0; i < m->num_ports(); ++i) { - if (m->ports()[i] == port_ref.name()) - return ERROR_PORT_CANNOT_SEND_SELF; - } - - Port* port = port_ref.port(); - { - // We must acquire |ports_lock_| before grabbing any port locks, because - // WillSendMessage_Locked may need to lock multiple ports out of order. - base::AutoLock ports_lock(ports_lock_); - base::AutoLock lock(port->lock); - - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - if (port->peer_closed) - return ERROR_PORT_PEER_CLOSED; - - int rv = WillSendMessage_Locked(port, port_ref.name(), m.get()); - if (rv != OK) - return rv; - - // Beyond this point there's no sense in returning anything but OK. Even if - // message forwarding or acceptance fails, there's nothing the embedder can - // do to recover. Assume that failure beyond this point must be treated as a - // transport failure. +int Node::SendMessage(const PortRef& port_ref, ScopedMessage message) { + int rv = SendMessageInternal(port_ref, &message); + if (rv != OK) { + // If send failed, close all carried ports. Note that we're careful not to + // close the sending port itself if it happened to be one of the encoded + // ports (an invalid but possible condition.) + for (size_t i = 0; i < message->num_ports(); ++i) { + if (message->ports()[i] == port_ref.name()) + continue; - if (port->peer_node_name != name_) { - delegate_->ForwardMessage(port->peer_node_name, std::move(m)); - return OK; + PortRef port; + if (GetPort(message->ports()[i], &port) == OK) + ClosePort(port); } } - - int rv = AcceptMessage(std::move(m)); - if (rv != OK) { - // See comment above for why we don't return an error in this case. - DVLOG(2) << "AcceptMessage failed: " << rv; - } - - return OK; + return rv; } int Node::AcceptMessage(ScopedMessage message) { @@ -365,6 +343,7 @@ int Node::MergePorts(const PortRef& port_ref, const NodeName& destination_node_name, const PortName& destination_port_name) { Port* port = port_ref.port(); + MergePortEventData data; { // |ports_lock_| must be held for WillSendPort_Locked below. base::AutoLock ports_lock(ports_lock_); @@ -375,15 +354,14 @@ int Node::MergePorts(const PortRef& port_ref, // Send the port-to-merge over to the destination node so it can be merged // into the port cycle atomically there. - MergePortEventData data; data.new_port_name = port_ref.name(); WillSendPort_Locked(port, destination_node_name, &data.new_port_name, &data.new_port_descriptor); - delegate_->ForwardMessage( - destination_node_name, - NewInternalMessage(destination_port_name, - EventType::kMergePort, data)); } + delegate_->ForwardMessage( + destination_node_name, + NewInternalMessage(destination_port_name, + EventType::kMergePort, data)); return OK; } @@ -577,6 +555,17 @@ int Node::OnObserveProxy(const PortName& port_name, scoped_refptr<Port> port = GetPort(port_name); if (!port) { DVLOG(1) << "ObserveProxy: " << port_name << "@" << name_ << " not found"; + + if (port_name != event.proxy_port_name && + port_name != event.proxy_to_port_name) { + // The receiving port may have been removed while this message was in + // transit. In this case, we restart the ObserveProxy circulation from + // the referenced proxy port to avoid leaking the proxy. + delegate_->ForwardMessage( + event.proxy_node_name, + NewInternalMessage( + event.proxy_port_name, EventType::kObserveProxy, event)); + } return OK; } @@ -689,6 +678,9 @@ int Node::OnObserveClosure(const PortName& port_name, // ObserveProxyAck. bool notify_delegate = false; + ObserveClosureEventData forwarded_data; + NodeName peer_node_name; + PortName peer_port_name; { // We must acquire |ports_lock_| before the port lock because it must be // held for MaybeRemoveProxy_Locked. @@ -708,8 +700,6 @@ int Node::OnObserveClosure(const PortName& port_name, // cares about it. This ensures that any dead-end proxies beyond that port // are notified to remove themselves. - ObserveClosureEventData forwarded_data; - if (port->state == Port::kReceiving) { notify_delegate = true; @@ -739,11 +729,14 @@ int Node::OnObserveClosure(const PortName& port_name, << " (last_sequence_num=" << forwarded_data.last_sequence_num << ")"; - delegate_->ForwardMessage( - port->peer_node_name, - NewInternalMessage(port->peer_port_name, - EventType::kObserveClosure, forwarded_data)); + peer_node_name = port->peer_node_name; + peer_port_name = port->peer_port_name; } + delegate_->ForwardMessage( + peer_node_name, + NewInternalMessage(peer_port_name, EventType::kObserveClosure, + forwarded_data)); + if (notify_delegate) { PortRef port_ref(port_name, port); delegate_->PortStatusChanged(port_ref); @@ -754,8 +747,6 @@ int Node::OnObserveClosure(const PortName& port_name, int Node::OnMergePort(const PortName& port_name, const MergePortEventData& event) { scoped_refptr<Port> port = GetPort(port_name); - if (!port) - return ERROR_PORT_UNKNOWN; DVLOG(1) << "MergePort at " << port_name << "@" << name_ << " (state=" << port->state << ") merging with proxy " << event.new_port_name @@ -773,7 +764,7 @@ int Node::OnMergePort(const PortName& port_name, int rv = AcceptPort(event.new_port_name, event.new_port_descriptor); if (rv != OK) { close_target_port = true; - } else { + } else if (port) { // BeginProxying_Locked may call MaybeRemoveProxy_Locked, which in turn // needs to hold |ports_lock_|. We also acquire multiple port locks within. base::AutoLock ports_lock(ports_lock_); @@ -798,6 +789,8 @@ int Node::OnMergePort(const PortName& port_name, close_new_port = true; close_target_port = true; } + } else { + close_new_port = true; } if (close_target_port) { @@ -830,11 +823,6 @@ int Node::AddPortWithName(const PortName& port_name, return OK; } -void Node::ErasePort(const PortName& port_name) { - base::AutoLock lock(ports_lock_); - return ErasePort_Locked(port_name); -} - void Node::ErasePort_Locked(const PortName& port_name) { ports_lock_.AssertAcquired(); ports_.erase(port_name); @@ -855,6 +843,53 @@ scoped_refptr<Port> Node::GetPort_Locked(const PortName& port_name) { return iter->second; } +int Node::SendMessageInternal(const PortRef& port_ref, ScopedMessage* message) { + ScopedMessage& m = *message; + for (size_t i = 0; i < m->num_ports(); ++i) { + if (m->ports()[i] == port_ref.name()) + return ERROR_PORT_CANNOT_SEND_SELF; + } + + Port* port = port_ref.port(); + NodeName peer_node_name; + { + // We must acquire |ports_lock_| before grabbing any port locks, because + // WillSendMessage_Locked may need to lock multiple ports out of order. + base::AutoLock ports_lock(ports_lock_); + base::AutoLock lock(port->lock); + + if (port->state != Port::kReceiving) + return ERROR_PORT_STATE_UNEXPECTED; + + if (port->peer_closed) + return ERROR_PORT_PEER_CLOSED; + + int rv = WillSendMessage_Locked(port, port_ref.name(), m.get()); + if (rv != OK) + return rv; + + // Beyond this point there's no sense in returning anything but OK. Even if + // message forwarding or acceptance fails, there's nothing the embedder can + // do to recover. Assume that failure beyond this point must be treated as a + // transport failure. + + peer_node_name = port->peer_node_name; + } + + if (peer_node_name != name_) { + delegate_->ForwardMessage(peer_node_name, std::move(m)); + return OK; + } + + int rv = AcceptMessage(std::move(m)); + if (rv != OK) { + // See comment above for why we don't return an error in this case. + DVLOG(2) << "AcceptMessage failed: " << rv; + } + + return OK; +} + int Node::MergePorts_Locked(const PortRef& port0_ref, const PortRef& port1_ref) { Port* port0 = port0_ref.port(); @@ -884,7 +919,6 @@ int Node::MergePorts_Locked(const PortRef& port0_ref, std::swap(port0->peer_node_name, port1->peer_node_name); std::swap(port0->peer_port_name, port1->peer_port_name); - std::swap(port0->peer_closed, port1->peer_closed); port0->state = Port::kBuffering; if (port0->peer_closed) @@ -926,7 +960,6 @@ int Node::MergePorts_Locked(const PortRef& port0_ref, // state by undoing the peer swap. std::swap(port0->peer_node_name, port1->peer_node_name); std::swap(port0->peer_port_name, port1->peer_port_name); - std::swap(port0->peer_closed, port1->peer_closed); port0->remove_proxy_on_last_message = false; port1->remove_proxy_on_last_message = false; port0->state = Port::kReceiving; diff --git a/chromium/mojo/edk/system/ports/node.h b/chromium/mojo/edk/system/ports/node.h index 2dc513c0c5f..e06942aff6f 100644 --- a/chromium/mojo/edk/system/ports/node.h +++ b/chromium/mojo/edk/system/ports/node.h @@ -15,7 +15,6 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "mojo/edk/system/ports/event.h" -#include "mojo/edk/system/ports/hash_functions.h" #include "mojo/edk/system/ports/message.h" #include "mojo/edk/system/ports/name.h" #include "mojo/edk/system/ports/port.h" @@ -114,10 +113,7 @@ class Node { // Sends a message from the specified port to its peer. Note that the message // notification may arrive synchronously (via PortStatusChanged() on the // delegate) if the peer is local to this Node. - // - // If send fails for any reason, |message| is left unchanged. On success, - // ownserhip is transferred and |message| is reset. - int SendMessage(const PortRef& port_ref, ScopedMessage* message); + int SendMessage(const PortRef& port_ref, ScopedMessage message); // Corresponding to NodeDelegate::ForwardMessage. int AcceptMessage(ScopedMessage message); @@ -158,11 +154,11 @@ class Node { int AddPortWithName(const PortName& port_name, const scoped_refptr<Port>& port); - void ErasePort(const PortName& port_name); void ErasePort_Locked(const PortName& port_name); scoped_refptr<Port> GetPort(const PortName& port_name); scoped_refptr<Port> GetPort_Locked(const PortName& port_name); + int SendMessageInternal(const PortRef& port_ref, ScopedMessage* message); int MergePorts_Locked(const PortRef& port0_ref, const PortRef& port1_ref); void WillSendPort_Locked(Port* port, const NodeName& to_node_name, diff --git a/chromium/mojo/edk/system/ports/port.h b/chromium/mojo/edk/system/ports/port.h index 7e28e1294f8..ea53d43b5f0 100644 --- a/chromium/mojo/edk/system/ports/port.h +++ b/chromium/mojo/edk/system/ports/port.h @@ -5,13 +5,13 @@ #ifndef MOJO_EDK_SYSTEM_PORTS_PORT_H_ #define MOJO_EDK_SYSTEM_PORTS_PORT_H_ +#include <memory> #include <queue> #include <utility> #include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/system/ports/message_queue.h" #include "mojo/edk/system/ports/user_data.h" @@ -37,7 +37,7 @@ class Port : public base::RefCountedThreadSafe<Port> { uint64_t next_sequence_num_to_send; uint64_t last_sequence_num_to_receive; MessageQueue message_queue; - scoped_ptr<std::pair<NodeName, ScopedMessage>> send_on_proxy_removal; + std::unique_ptr<std::pair<NodeName, ScopedMessage>> send_on_proxy_removal; scoped_refptr<UserData> user_data; bool remove_proxy_on_last_message; bool peer_closed; diff --git a/chromium/mojo/edk/system/ports/ports_unittest.cc b/chromium/mojo/edk/system/ports/ports_unittest.cc index 1bdca3ff8cb..1098e8e2942 100644 --- a/chromium/mojo/edk/system/ports/ports_unittest.cc +++ b/chromium/mojo/edk/system/ports/ports_unittest.cc @@ -11,6 +11,7 @@ #include <sstream> #include "base/logging.h" +#include "base/rand_util.h" #include "mojo/edk/system/ports/node.h" #include "mojo/edk/system/ports/node_delegate.h" #include "testing/gtest/include/gtest/gtest.h" @@ -73,12 +74,12 @@ struct Task { Task(NodeName node_name, ScopedMessage message) : node_name(node_name), message(std::move(message)), - priority(rand()) { + priority(base::RandUint64()) { } NodeName node_name; ScopedMessage message; - int32_t priority; + uint64_t priority; }; struct TaskComparator { @@ -122,7 +123,7 @@ int SendStringMessage(Node* node, const PortRef& port, const std::string& s) { size_t size = s.size() + 1; ScopedMessage message = TestMessage::NewUserMessage(size, 0); memcpy(message->mutable_payload_bytes(), s.data(), size); - return node->SendMessage(port, &message); + return node->SendMessage(port, std::move(message)); } int SendStringMessageWithPort(Node* node, @@ -133,7 +134,7 @@ int SendStringMessageWithPort(Node* node, ScopedMessage message = TestMessage::NewUserMessage(size, 1); memcpy(message->mutable_payload_bytes(), s.data(), size); message->mutable_ports()[0] = sent_port_name; - return node->SendMessage(port ,&message); + return node->SendMessage(port, std::move(message)); } int SendStringMessageWithPort(Node* node, @@ -719,31 +720,16 @@ TEST_F(PortsTest, SendFailure) { EXPECT_EQ(ERROR_PORT_CANNOT_SEND_PEER, SendStringMessageWithPort(&node0, A, "nope", B)); + // B should be closed immediately. + EXPECT_EQ(ERROR_PORT_UNKNOWN, node0.GetPort(B.name(), &B)); + PumpTasks(); // There should have been no messages accepted. ScopedMessage message; EXPECT_FALSE(node0_delegate.GetSavedMessage(&message)); - // Both A and B should still work. - - EXPECT_EQ(OK, SendStringMessage(&node0, A, "hi")); - EXPECT_EQ(OK, SendStringMessage(&node0, B, "hey")); - - PumpTasks(); - - ASSERT_TRUE(node0_delegate.GetSavedMessage(&message)); - EXPECT_EQ(0, strcmp("hi", ToString(message))); - ClosePortsInMessage(&node0, message.get()); - - ASSERT_TRUE(node0_delegate.GetSavedMessage(&message)); - EXPECT_EQ(0, strcmp("hey", ToString(message))); - ClosePortsInMessage(&node0, message.get()); - - PumpTasks(); - EXPECT_EQ(OK, node0.ClosePort(A)); - EXPECT_EQ(OK, node0.ClosePort(B)); PumpTasks(); @@ -1304,7 +1290,6 @@ TEST_F(PortsTest, MergePortsWithMovedPeers) { EXPECT_TRUE(node1.CanShutdownCleanly(false)); } - TEST_F(PortsTest, MergePortsFailsGracefully) { // This tests that the system remains in a well-defined state if something // goes wrong during port merge. diff --git a/chromium/mojo/edk/system/ports_message.cc b/chromium/mojo/edk/system/ports_message.cc index 91fe3f3bc35..5f3e8c01251 100644 --- a/chromium/mojo/edk/system/ports_message.cc +++ b/chromium/mojo/edk/system/ports_message.cc @@ -4,16 +4,18 @@ #include "mojo/edk/system/ports_message.h" +#include "base/memory/ptr_util.h" #include "mojo/edk/system/node_channel.h" namespace mojo { namespace edk { // static -scoped_ptr<PortsMessage> PortsMessage::NewUserMessage(size_t num_payload_bytes, - size_t num_ports, - size_t num_handles) { - return make_scoped_ptr( +std::unique_ptr<PortsMessage> PortsMessage::NewUserMessage( + size_t num_payload_bytes, + size_t num_ports, + size_t num_handles) { + return base::WrapUnique( new PortsMessage(num_payload_bytes, num_ports, num_handles)); } diff --git a/chromium/mojo/edk/system/ports_message.h b/chromium/mojo/edk/system/ports_message.h index 8e3036e0002..e2e2e836926 100644 --- a/chromium/mojo/edk/system/ports_message.h +++ b/chromium/mojo/edk/system/ports_message.h @@ -5,9 +5,9 @@ #ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_H__ #define MOJO_EDK_SYSTEM_PORTS_MESSAGE_H__ +#include <memory> #include <utility> -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/ports/message.h" @@ -19,9 +19,9 @@ class NodeController; class PortsMessage : public ports::Message { public: - static scoped_ptr<PortsMessage> NewUserMessage(size_t num_payload_bytes, - size_t num_ports, - size_t num_handles); + static std::unique_ptr<PortsMessage> NewUserMessage(size_t num_payload_bytes, + size_t num_ports, + size_t num_handles); ~PortsMessage() override; diff --git a/chromium/mojo/edk/system/remote_message_pipe_bootstrap.cc b/chromium/mojo/edk/system/remote_message_pipe_bootstrap.cc index eb38674cac4..d376cca5838 100644 --- a/chromium/mojo/edk/system/remote_message_pipe_bootstrap.cc +++ b/chromium/mojo/edk/system/remote_message_pipe_bootstrap.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/ports/name.h" diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc index d531989c103..df391050a2a 100644 --- a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc @@ -8,10 +8,10 @@ #include <stdint.h> #include <limits> +#include <memory> #include <utility> #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/node_controller.h" @@ -218,7 +218,7 @@ MojoResult SharedBufferDispatcher::MapBuffer( uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr<PlatformSharedBufferMapping>* mapping) { + std::unique_ptr<PlatformSharedBufferMapping>* mapping) { if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) return MOJO_RESULT_INVALID_ARGUMENT; if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) @@ -276,7 +276,7 @@ bool SharedBufferDispatcher::BeginTransit() { base::AutoLock lock(lock_); if (in_transit_) return false; - in_transit_ = shared_buffer_ != nullptr; + in_transit_ = static_cast<bool>(shared_buffer_); return in_transit_; } diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.h b/chromium/mojo/edk/system/shared_buffer_dispatcher.h index ffc07ff11e4..1648dd274b1 100644 --- a/chromium/mojo/edk/system/shared_buffer_dispatcher.h +++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.h @@ -77,7 +77,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher { uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr<PlatformSharedBufferMapping>* mapping) override; + std::unique_ptr<PlatformSharedBufferMapping>* mapping) override; void StartSerialize(uint32_t* num_bytes, uint32_t* num_ports, uint32_t* num_platform_handles) override; diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index 6e26bf9f1bd..c95bdc3b704 100644 --- a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -119,7 +119,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); // Make a couple of mappings. - scoped_ptr<PlatformSharedBufferMapping> mapping1; + std::unique_ptr<PlatformSharedBufferMapping> mapping1; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); ASSERT_TRUE(mapping1); @@ -128,7 +128,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { // Write something. static_cast<char*>(mapping1->GetBase())[50] = 'x'; - scoped_ptr<PlatformSharedBufferMapping> mapping2; + std::unique_ptr<PlatformSharedBufferMapping> mapping2; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); ASSERT_TRUE(mapping2); @@ -156,7 +156,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) { EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); // Make a couple of mappings. - scoped_ptr<PlatformSharedBufferMapping> mapping1; + std::unique_ptr<PlatformSharedBufferMapping> mapping1; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); ASSERT_TRUE(mapping1); @@ -165,7 +165,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) { // Write something. static_cast<char*>(mapping1->GetBase())[50] = 'x'; - scoped_ptr<PlatformSharedBufferMapping> mapping2; + std::unique_ptr<PlatformSharedBufferMapping> mapping2; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); ASSERT_TRUE(mapping2); @@ -188,7 +188,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { nullptr, 100, &dispatcher1)); // Map and write something. - scoped_ptr<PlatformSharedBufferMapping> mapping; + std::unique_ptr<PlatformSharedBufferMapping> mapping; EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); static_cast<char*>(mapping->GetBase())[0] = 'x'; @@ -230,7 +230,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { ASSERT_TRUE(dispatcher2); EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); { - scoped_ptr<PlatformSharedBufferMapping> mapping; + std::unique_ptr<PlatformSharedBufferMapping> mapping; EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, 0, &mapping)); } EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); @@ -291,7 +291,7 @@ TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { SharedBufferDispatcher::kDefaultCreateOptions, nullptr, 100, &dispatcher)); - scoped_ptr<PlatformSharedBufferMapping> mapping; + std::unique_ptr<PlatformSharedBufferMapping> mapping; EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); EXPECT_FALSE(mapping); diff --git a/chromium/mojo/edk/system/shared_buffer_unittest.cc b/chromium/mojo/edk/system/shared_buffer_unittest.cc index 9451ae865b3..3a728728a57 100644 --- a/chromium/mojo/edk/system/shared_buffer_unittest.cc +++ b/chromium/mojo/edk/system/shared_buffer_unittest.cc @@ -63,13 +63,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CopyToBufferClient, SharedBufferTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassSharedBufferCrossProcess DISABLED_PassSharedBufferCrossProcess -#else -#define MAYBE_PassSharedBufferCrossProcess PassSharedBufferCrossProcess -#endif -TEST_F(SharedBufferTest, MAYBE_PassSharedBufferCrossProcess) { +TEST_F(SharedBufferTest, PassSharedBufferCrossProcess) { const std::string message = "hello"; MojoHandle b = CreateBuffer(message.size()); @@ -93,13 +87,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateBufferClient, SharedBufferTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassSharedBufferFromChild DISABLED_PassSharedBufferFromChild -#else -#define MAYBE_PassSharedBufferFromChild PassSharedBufferFromChild -#endif -TEST_F(SharedBufferTest, MAYBE_PassSharedBufferFromChild) { +TEST_F(SharedBufferTest, PassSharedBufferFromChild) { const std::string message = "hello"; MojoHandle b; RUN_CHILD_ON_PIPE(CreateBufferClient, h) @@ -126,7 +114,6 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBuffer, SharedBufferTest, h) { WriteMessageWithHandles(other_child, "", &dupe, 1); EXPECT_EQ("quit", ReadMessage(h)); - WriteMessage(h, "ok"); } DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBuffer, SharedBufferTest, h) { @@ -143,17 +130,9 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBuffer, SharedBufferTest, h) { WriteToBuffer(b, 0, message); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); EXPECT_EQ("quit", ReadMessage(h)); - WriteMessage(h, "ok"); } -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassSharedBufferFromChildToChild \ - DISABLED_PassSharedBufferFromChildToChild -#else -#define MAYBE_PassSharedBufferFromChildToChild PassSharedBufferFromChildToChild -#endif -TEST_F(SharedBufferTest, MAYBE_PassSharedBufferFromChildToChild) { +TEST_F(SharedBufferTest, PassSharedBufferFromChildToChild) { const std::string message = "hello"; MojoHandle p0, p1; CreateMessagePipe(&p0, &p1); @@ -171,10 +150,8 @@ TEST_F(SharedBufferTest, MAYBE_PassSharedBufferFromChildToChild) { ReadMessageWithHandles(h0, &b, 1); WriteMessage(h1, "quit"); - EXPECT_EQ("ok", ReadMessage(h1)); END_CHILD() WriteMessage(h0, "quit"); - EXPECT_EQ("ok", ReadMessage(h0)); END_CHILD() // The second child should have written this message. @@ -197,8 +174,6 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBufferParent, SharedBufferTest, EXPECT_EQ("quit", ReadMessage(parent)); WriteMessage(child, "quit"); - EXPECT_EQ("ok", ReadMessage(child)); - WriteMessage(parent, "ok"); END_CHILD() } @@ -212,8 +187,6 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBufferParent, SharedBufferTest, EXPECT_EQ("quit", ReadMessage(parent)); WriteMessage(child, "quit"); - EXPECT_EQ("ok", ReadMessage(child)); - WriteMessage(parent, "ok"); END_CHILD() } @@ -245,10 +218,8 @@ TEST_F(SharedBufferTest, MAYBE_PassHandleBetweenCousins) { ReadMessageWithHandles(child1, &b, 1); WriteMessage(child2, "quit"); - EXPECT_EQ("ok", ReadMessage(child2)); END_CHILD() WriteMessage(child1, "quit"); - EXPECT_EQ("ok", ReadMessage(child1)); END_CHILD() // The second grandchild should have written this message. @@ -312,10 +283,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassReadOnlyBuffer, WriteMessage(h, "ok"); } -#if defined(OS_ANDROID) || (defined(OS_POSIX) && !defined(OS_MACOSX)) +#if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. -// Non-OSX posix uses a sync broker to create shared memory. Creating read-only -// duplicates in child processes is not currently supported via the sync broker. #define MAYBE_CreateAndPassFromChildReadOnlyBuffer \ DISABLED_CreateAndPassFromChildReadOnlyBuffer #else diff --git a/chromium/mojo/edk/system/wait_set_dispatcher.h b/chromium/mojo/edk/system/wait_set_dispatcher.h index 5bf457ff451..619a1beaa2a 100644 --- a/chromium/mojo/edk/system/wait_set_dispatcher.h +++ b/chromium/mojo/edk/system/wait_set_dispatcher.h @@ -8,11 +8,11 @@ #include <stdint.h> #include <deque> +#include <memory> #include <unordered_map> #include <utility> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/dispatcher.h" @@ -92,7 +92,7 @@ class MOJO_SYSTEM_IMPL_EXPORT WaitSetDispatcher : public Dispatcher { AwakableList awakable_list_; // Waiter used to wait on dispatchers. - scoped_ptr<Waiter> waiter_; + std::unique_ptr<Waiter> waiter_; DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcher); }; diff --git a/chromium/mojo/edk/system/wait_set_dispatcher_unittest.cc b/chromium/mojo/edk/system/wait_set_dispatcher_unittest.cc index 2a42be16452..42ac86548d6 100644 --- a/chromium/mojo/edk/system/wait_set_dispatcher_unittest.cc +++ b/chromium/mojo/edk/system/wait_set_dispatcher_unittest.cc @@ -13,6 +13,7 @@ #include "base/memory/ref_counted.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" +#include "mojo/edk/system/message_for_transit.h" #include "mojo/edk/system/message_pipe_dispatcher.h" #include "mojo/edk/system/request_context.h" #include "mojo/edk/system/test_utils.h" @@ -74,6 +75,35 @@ class WaitSetDispatcherTest : public ::testing::Test { dispatchers_to_close_.push_back(dispatcher); } + void WriteMessage(MessagePipeDispatcher* dispatcher, + const void* bytes, + size_t num_bytes) { + Core* core = mojo::edk::internal::g_core; + MojoMessageHandle msg; + ASSERT_EQ(MOJO_RESULT_OK, + core->AllocMessage(static_cast<uint32_t>(num_bytes), nullptr, 0, + MOJO_ALLOC_MESSAGE_FLAG_NONE, &msg)); + void* buffer; + ASSERT_EQ(MOJO_RESULT_OK, core->GetMessageBuffer(msg, &buffer)); + memcpy(buffer, bytes, num_bytes); + + std::unique_ptr<MessageForTransit> message( + reinterpret_cast<MessageForTransit*>(msg)); + ASSERT_EQ(MOJO_RESULT_OK, + dispatcher->WriteMessage(std::move(message), + MOJO_WRITE_MESSAGE_FLAG_NONE)); + } + + void ReadMessage(MessagePipeDispatcher* dispatcher, + void* bytes, + uint32_t* num_bytes) { + std::unique_ptr<MessageForTransit> message; + ASSERT_EQ(MOJO_RESULT_OK, + dispatcher->ReadMessage(&message, num_bytes, nullptr, 0, + MOJO_READ_MESSAGE_FLAG_NONE, false)); + memcpy(bytes, message->bytes(), *num_bytes); + } + protected: scoped_refptr<MessagePipeDispatcher> dispatcher0_; scoped_refptr<MessagePipeDispatcher> dispatcher1_; @@ -140,9 +170,7 @@ TEST_F(WaitSetDispatcherTest, Basic) { // Write to |dispatcher1_|, which should make |dispatcher0_| readable. char buffer[] = "abcd"; w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(buffer, sizeof(buffer), nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + WriteMessage(dispatcher1_.get(), buffer, sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); woken_dispatcher = nullptr; context = 0; @@ -187,9 +215,7 @@ TEST_F(WaitSetDispatcherTest, HandleWithoutRemoving) { // Write to |dispatcher1_|, which should make |dispatcher0_| readable. char buffer[] = "abcd"; w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(buffer, sizeof(buffer), nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + WriteMessage(dispatcher1_.get(), buffer, sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); woken_dispatcher = nullptr; context = 0; @@ -201,9 +227,7 @@ TEST_F(WaitSetDispatcherTest, HandleWithoutRemoving) { // Read from |dispatcher0_| which should change it's state to non-readable. char read_buffer[sizeof(buffer) + 5]; uint32_t num_bytes = sizeof(read_buffer); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher0_->ReadMessage(read_buffer, &num_bytes, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); + ReadMessage(dispatcher0_.get(), read_buffer, &num_bytes); EXPECT_EQ(sizeof(buffer), num_bytes); // No dispatchers are ready. @@ -212,7 +236,7 @@ TEST_F(WaitSetDispatcherTest, HandleWithoutRemoving) { context = 0; EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(nullptr, woken_dispatcher); + EXPECT_FALSE(woken_dispatcher); EXPECT_EQ(0u, context); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); } @@ -314,9 +338,7 @@ TEST_F(WaitSetDispatcherTest, MultipleReady) { // Write to |dispatcher1_|, which should make |dispatcher0_| readable. char buffer[] = "abcd"; w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(buffer, sizeof(buffer), nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + WriteMessage(dispatcher1_.get(), buffer, sizeof(buffer)); { Waiter mp_w; mp_w.Init(); diff --git a/chromium/mojo/gles2/command_buffer_client_impl.cc b/chromium/mojo/gles2/command_buffer_client_impl.cc index 14f0569ce14..1d78f850f5f 100644 --- a/chromium/mojo/gles2/command_buffer_client_impl.cc +++ b/chromium/mojo/gles2/command_buffer_client_impl.cc @@ -16,6 +16,7 @@ #include "components/mus/gles2/command_buffer_type_conversions.h" #include "components/mus/gles2/mojo_buffer_backing.h" #include "components/mus/gles2/mojo_gpu_memory_buffer.h" +#include "gpu/command_buffer/client/gpu_control_client.h" #include "gpu/command_buffer/common/command_buffer_id.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "gpu/command_buffer/common/sync_token.h" @@ -61,15 +62,11 @@ void InitializeCallback(mus::mojom::CommandBufferInitializeResultPtr* output, } // namespace -CommandBufferDelegate::~CommandBufferDelegate() {} - -void CommandBufferDelegate::ContextLost() {} - CommandBufferClientImpl::CommandBufferClientImpl( - CommandBufferDelegate* delegate, const std::vector<int32_t>& attribs, mojo::ScopedMessagePipeHandle command_buffer_handle) - : delegate_(delegate), + : gpu_control_client_(nullptr), + destroyed_(false), attribs_(attribs), client_binding_(this), command_buffer_id_(), @@ -193,7 +190,7 @@ scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer( command_buffer_->RegisterTransferBuffer(*id, std::move(duped), static_cast<uint32_t>(size)); - scoped_ptr<gpu::BufferBacking> backing( + std::unique_ptr<gpu::BufferBacking> backing( new mus::MojoBufferBacking(std::move(handle), memory, size)); scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(std::move(backing))); return buffer; @@ -203,6 +200,10 @@ void CommandBufferClientImpl::DestroyTransferBuffer(int32_t id) { command_buffer_->DestroyTransferBuffer(id); } +void CommandBufferClientImpl::SetGpuControlClient(gpu::GpuControlClient* c) { + gpu_control_client_ = c; +} + gpu::Capabilities CommandBufferClientImpl::GetCapabilities() { return capabilities_; } @@ -268,10 +269,11 @@ int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage( size_t height, unsigned internalformat, unsigned usage) { - scoped_ptr<gfx::GpuMemoryBuffer> buffer(mus::MojoGpuMemoryBufferImpl::Create( - gfx::Size(static_cast<int>(width), static_cast<int>(height)), - gpu::DefaultBufferFormatForImageFormat(internalformat), - gfx::BufferUsage::SCANOUT)); + std::unique_ptr<gfx::GpuMemoryBuffer> buffer( + mus::MojoGpuMemoryBufferImpl::Create( + gfx::Size(static_cast<int>(width), static_cast<int>(height)), + gpu::DefaultBufferFormatForImageFormat(internalformat), + gfx::BufferUsage::SCANOUT)); if (!buffer) return -1; @@ -285,10 +287,14 @@ void CommandBufferClientImpl::SignalQuery(uint32_t query, } void CommandBufferClientImpl::Destroyed(int32_t lost_reason, int32_t error) { + if (destroyed_) + return; last_state_.context_lost_reason = static_cast<gpu::error::ContextLostReason>(lost_reason); last_state_.error = static_cast<gpu::error::Error>(error); - delegate_->ContextLost(); + if (gpu_control_client_) + gpu_control_client_->OnGpuControlLostContext(); + destroyed_ = true; } void CommandBufferClientImpl::SignalAck(uint32_t id) { @@ -331,11 +337,6 @@ void CommandBufferClientImpl::MakeProgressAndUpdateState() { void CommandBufferClientImpl::SetLock(base::Lock* lock) { } -bool CommandBufferClientImpl::IsGpuChannelLost() { - // This is only possible for out-of-process command buffers. - return false; -} - void CommandBufferClientImpl::EnsureWorkVisible() { // This is only relevant for out-of-process command buffers. } diff --git a/chromium/mojo/gles2/command_buffer_client_impl.h b/chromium/mojo/gles2/command_buffer_client_impl.h index 995ff1c9511..45bcf402a0c 100644 --- a/chromium/mojo/gles2/command_buffer_client_impl.h +++ b/chromium/mojo/gles2/command_buffer_client_impl.h @@ -9,10 +9,10 @@ #include <stdint.h> #include <map> +#include <memory> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "components/mus/public/interfaces/command_buffer.mojom.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" @@ -27,25 +27,18 @@ class RunLoop; namespace gles2 { class CommandBufferClientImpl; -class CommandBufferDelegate { - public: - virtual ~CommandBufferDelegate(); - virtual void ContextLost(); -}; - class CommandBufferClientImpl : public mus::mojom::CommandBufferClient, public gpu::CommandBuffer, public gpu::GpuControl { public: explicit CommandBufferClientImpl( - CommandBufferDelegate* delegate, const std::vector<int32_t>& attribs, mojo::ScopedMessagePipeHandle command_buffer_handle); ~CommandBufferClientImpl() override; + bool Initialize(); // CommandBuffer implementation: - bool Initialize() override; State GetLastState() override; int32_t GetLastToken() override; void Flush(int32_t put_offset) override; @@ -58,6 +51,7 @@ class CommandBufferClientImpl void DestroyTransferBuffer(int32_t id) override; // gpu::GpuControl implementation: + void SetGpuControlClient(gpu::GpuControlClient*) override; gpu::Capabilities GetCapabilities() override; int32_t CreateImage(ClientBuffer buffer, size_t width, @@ -70,7 +64,6 @@ class CommandBufferClientImpl unsigned usage) override; void SignalQuery(uint32_t query, const base::Closure& callback) override; void SetLock(base::Lock*) override; - bool IsGpuChannelLost() override; void EnsureWorkVisible() override; gpu::CommandBufferNamespace GetNamespaceID() const override; gpu::CommandBufferId GetCommandBufferID() const override; @@ -96,7 +89,8 @@ class CommandBufferClientImpl gpu::CommandBufferSharedState* shared_state() const { return shared_state_; } - CommandBufferDelegate* delegate_; + gpu::GpuControlClient* gpu_control_client_; + bool destroyed_; std::vector<int32_t> attribs_; mojo::Binding<mus::mojom::CommandBufferClient> client_binding_; mus::mojom::CommandBufferPtr command_buffer_; diff --git a/chromium/mojo/gles2/gles2_context.cc b/chromium/mojo/gles2/gles2_context.cc index 90ba14e8c95..8159407b87f 100644 --- a/chromium/mojo/gles2/gles2_context.cc +++ b/chromium/mojo/gles2/gles2_context.cc @@ -11,24 +11,18 @@ #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "mojo/public/c/gles2/gles2.h" #include "mojo/public/cpp/system/core.h" namespace gles2 { -namespace { -const size_t kDefaultCommandBufferSize = 1024 * 1024; -const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024; -const size_t kDefaultMinTransferBufferSize = 1 * 256 * 1024; -const size_t kDefaultMaxTransferBufferSize = 16 * 1024 * 1024; -} - GLES2Context::GLES2Context(const std::vector<int32_t>& attribs, mojo::ScopedMessagePipeHandle command_buffer_handle, MojoGLES2ContextLost lost_callback, void* closure) - : command_buffer_(this, attribs, std::move(command_buffer_handle)), + : command_buffer_(attribs, std::move(command_buffer_handle)), lost_callback_(lost_callback), closure_(closure) {} @@ -37,8 +31,10 @@ GLES2Context::~GLES2Context() {} bool GLES2Context::Initialize() { if (!command_buffer_.Initialize()) return false; + + constexpr gpu::SharedMemoryLimits default_limits; gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(&command_buffer_)); - if (!gles2_helper_->Initialize(kDefaultCommandBufferSize)) + if (!gles2_helper_->Initialize(default_limits.command_buffer_size)) return false; gles2_helper_->SetAutomaticFlushes(false); transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get())); @@ -57,12 +53,18 @@ bool GLES2Context::Initialize() { lose_context_when_out_of_memory, support_client_side_arrays, &command_buffer_)); - return implementation_->Initialize(kDefaultStartTransferBufferSize, - kDefaultMinTransferBufferSize, - kDefaultMaxTransferBufferSize, - gpu::gles2::GLES2Implementation::kNoLimit); + if (!implementation_->Initialize(default_limits.start_transfer_buffer_size, + default_limits.min_transfer_buffer_size, + default_limits.max_transfer_buffer_size, + default_limits.mapped_memory_reclaim_limit)) + return false; + implementation_->SetLostContextCallback( + base::Bind(&GLES2Context::OnLostContext, base::Unretained(this))); + return true; } -void GLES2Context::ContextLost() { lost_callback_(closure_); } +void GLES2Context::OnLostContext() { + lost_callback_(closure_); +} } // namespace gles2 diff --git a/chromium/mojo/gles2/gles2_context.h b/chromium/mojo/gles2/gles2_context.h index e5dac202253..618d4bdfe45 100644 --- a/chromium/mojo/gles2/gles2_context.h +++ b/chromium/mojo/gles2/gles2_context.h @@ -7,10 +7,10 @@ #include <stdint.h> +#include <memory> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "mojo/gles2/command_buffer_client_impl.h" #include "mojo/public/c/gles2/gles2.h" @@ -27,14 +27,13 @@ class GLES2Implementation; namespace gles2 { -class GLES2Context : public CommandBufferDelegate, - public MojoGLES2ContextPrivate { +class GLES2Context : public MojoGLES2ContextPrivate { public: explicit GLES2Context(const std::vector<int32_t>& attribs, mojo::ScopedMessagePipeHandle command_buffer_handle, MojoGLES2ContextLost lost_callback, void* closure); - ~GLES2Context() override; + virtual ~GLES2Context(); bool Initialize(); gpu::gles2::GLES2Interface* interface() const { @@ -43,12 +42,12 @@ class GLES2Context : public CommandBufferDelegate, gpu::ContextSupport* context_support() const { return implementation_.get(); } private: - void ContextLost() override; + void OnLostContext(); CommandBufferClientImpl command_buffer_; - scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_; - scoped_ptr<gpu::TransferBuffer> transfer_buffer_; - scoped_ptr<gpu::gles2::GLES2Implementation> implementation_; + std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_; + std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; + std::unique_ptr<gpu::gles2::GLES2Implementation> implementation_; MojoGLES2ContextLost lost_callback_; void* closure_; diff --git a/chromium/mojo/gles2/gles2_impl.cc b/chromium/mojo/gles2/gles2_impl.cc index c1875f41b7b..4cab046f312 100644 --- a/chromium/mojo/gles2/gles2_impl.cc +++ b/chromium/mojo/gles2/gles2_impl.cc @@ -42,7 +42,7 @@ MojoGLES2Context MojoGLES2CreateContext(MojoHandle handle, } } attribs.push_back(kNone); - scoped_ptr<GLES2Context> client(new GLES2Context( + std::unique_ptr<GLES2Context> client(new GLES2Context( attribs, std::move(scoped_handle), lost_callback, closure)); if (!client->Initialize()) client.reset(); diff --git a/chromium/mojo/gpu/mojo_gles2_impl_autogen.cc b/chromium/mojo/gpu/mojo_gles2_impl_autogen.cc index 2e0c661eec8..2dd194949d5 100644 --- a/chromium/mojo/gpu/mojo_gles2_impl_autogen.cc +++ b/chromium/mojo/gpu/mojo_gles2_impl_autogen.cc @@ -1576,37 +1576,6 @@ void MojoGLES2Impl::BindUniformLocationCHROMIUM(GLuint program, MojoGLES2MakeCurrent(context_); glBindUniformLocationCHROMIUM(program, location, name); } -void MojoGLES2Impl::GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) { - MojoGLES2MakeCurrent(context_); - glGenValuebuffersCHROMIUM(n, buffers); -} -void MojoGLES2Impl::DeleteValuebuffersCHROMIUM(GLsizei n, - const GLuint* valuebuffers) { - MojoGLES2MakeCurrent(context_); - glDeleteValuebuffersCHROMIUM(n, valuebuffers); -} -GLboolean MojoGLES2Impl::IsValuebufferCHROMIUM(GLuint valuebuffer) { - MojoGLES2MakeCurrent(context_); - return glIsValuebufferCHROMIUM(valuebuffer); -} -void MojoGLES2Impl::BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) { - MojoGLES2MakeCurrent(context_); - glBindValuebufferCHROMIUM(target, valuebuffer); -} -void MojoGLES2Impl::SubscribeValueCHROMIUM(GLenum target, GLenum subscription) { - MojoGLES2MakeCurrent(context_); - glSubscribeValueCHROMIUM(target, subscription); -} -void MojoGLES2Impl::PopulateSubscribedValuesCHROMIUM(GLenum target) { - MojoGLES2MakeCurrent(context_); - glPopulateSubscribedValuesCHROMIUM(target); -} -void MojoGLES2Impl::UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) { - MojoGLES2MakeCurrent(context_); - glUniformValuebufferCHROMIUM(location, target, subscription); -} void MojoGLES2Impl::BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { MojoGLES2MakeCurrent(context_); glBindTexImage2DCHROMIUM(target, imageId); @@ -1690,12 +1659,13 @@ void MojoGLES2Impl::ScheduleCALayerCHROMIUM(GLuint contents_texture_id, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) { + const GLfloat* transform, + GLuint filter) { MojoGLES2MakeCurrent(context_); glScheduleCALayerCHROMIUM(contents_texture_id, contents_rect, opacity, background_color, edge_aa_mask, bounds_rect, is_clipped, clip_rect, sorting_context_id, - transform); + transform, filter); } void MojoGLES2Impl::CommitOverlayPlanesCHROMIUM() { MojoGLES2MakeCurrent(context_); diff --git a/chromium/mojo/gpu/mojo_gles2_impl_autogen.h b/chromium/mojo/gpu/mojo_gles2_impl_autogen.h index bedb8e09ad4..0d6b05c8717 100644 --- a/chromium/mojo/gpu/mojo_gles2_impl_autogen.h +++ b/chromium/mojo/gpu/mojo_gles2_impl_autogen.h @@ -13,6 +13,8 @@ #ifndef MOJO_GPU_MOJO_GLES2_IMPL_AUTOGEN_H_ #define MOJO_GPU_MOJO_GLES2_IMPL_AUTOGEN_H_ +#include <memory> + #include "gpu/command_buffer/client/gles2_interface.h" #include "mojo/public/c/gles2/gles2.h" @@ -732,16 +734,6 @@ class MojoGLES2Impl : public gpu::gles2::GLES2Interface { void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; - void GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) override; - void DeleteValuebuffersCHROMIUM(GLsizei n, - const GLuint* valuebuffers) override; - GLboolean IsValuebufferCHROMIUM(GLuint valuebuffer) override; - void BindValuebufferCHROMIUM(GLenum target, GLuint valuebuffer) override; - void SubscribeValueCHROMIUM(GLenum target, GLenum subscription) override; - void PopulateSubscribedValuesCHROMIUM(GLenum target) override; - void UniformValuebufferCHROMIUM(GLint location, - GLenum target, - GLenum subscription) override; void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, @@ -779,7 +771,8 @@ class MojoGLES2Impl : public gpu::gles2::GLES2Interface { GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform) override; + const GLfloat* transform, + GLuint filter) override; void CommitOverlayPlanesCHROMIUM() override; void SwapInterval(GLint interval) override; void FlushDriverCachesCHROMIUM() override; diff --git a/chromium/mojo/message_pump/handle_watcher.cc b/chromium/mojo/message_pump/handle_watcher.cc index 7c01ead1604..9bdbb2a0d99 100644 --- a/chromium/mojo/message_pump/handle_watcher.cc +++ b/chromium/mojo/message_pump/handle_watcher.cc @@ -19,8 +19,8 @@ #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" -#include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/message_pump/message_pump_mojo_handler.h" diff --git a/chromium/mojo/message_pump/handle_watcher.h b/chromium/mojo/message_pump/handle_watcher.h index 18211ca81ee..10056b143cb 100644 --- a/chromium/mojo/message_pump/handle_watcher.h +++ b/chromium/mojo/message_pump/handle_watcher.h @@ -5,9 +5,10 @@ #ifndef MOJO_MESSAGE_PUMP_HANDLE_WATCHER_H_ #define MOJO_MESSAGE_PUMP_HANDLE_WATCHER_H_ +#include <memory> + #include "base/callback_forward.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "mojo/message_pump/mojo_message_pump_export.h" #include "mojo/public/cpp/system/core.h" @@ -53,7 +54,7 @@ class MOJO_MESSAGE_PUMP_EXPORT HandleWatcher { class SecondaryThreadWatchingState; // If non-NULL Start() has been invoked. - scoped_ptr<StateBase> state_; + std::unique_ptr<StateBase> state_; DISALLOW_COPY_AND_ASSIGN(HandleWatcher); }; diff --git a/chromium/mojo/message_pump/handle_watcher_perftest.cc b/chromium/mojo/message_pump/handle_watcher_perftest.cc index 19f78101661..96c8495c020 100644 --- a/chromium/mojo/message_pump/handle_watcher_perftest.cc +++ b/chromium/mojo/message_pump/handle_watcher_perftest.cc @@ -28,8 +28,8 @@ enum MessageLoopConfig { MESSAGE_LOOP_CONFIG_MOJO = 1 }; -scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { - scoped_ptr<base::MessageLoop> loop; +std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { + std::unique_ptr<base::MessageLoop> loop; if (config == MESSAGE_LOOP_CONFIG_DEFAULT) loop.reset(new base::MessageLoop()); else @@ -78,7 +78,7 @@ class HandleWatcherPerftest : public testing::TestWithParam<MessageLoopConfig> { } private: - scoped_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<base::MessageLoop> message_loop_; DISALLOW_COPY_AND_ASSIGN(HandleWatcherPerftest); }; @@ -117,7 +117,7 @@ TEST_P(HandleWatcherPerftest, StartAllThenStop_1000Handles) { // Create separately from the start/stop loops to avoid affecting the // benchmark. for (uint64_t i = 0; i < kHandles; i++) { - scoped_ptr<TestData> test_data(new TestData); + std::unique_ptr<TestData> test_data(new TestData); ASSERT_TRUE(test_data->pipe.handle0.is_valid()); data_vector.push_back(std::move(test_data)); } @@ -176,7 +176,7 @@ TEST_P(HandleWatcherPerftest, StartAndSignal_1000Waiting) { }; ScopedVector<TestData> data_vector; for (uint64_t i = 0; i < kWaitingHandles; i++) { - scoped_ptr<TestData> test_data(new TestData); + std::unique_ptr<TestData> test_data(new TestData); ASSERT_TRUE(test_data->pipe.handle0.is_valid()); test_data->watcher.Start( test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, diff --git a/chromium/mojo/message_pump/handle_watcher_unittest.cc b/chromium/mojo/message_pump/handle_watcher_unittest.cc index c076587d691..fd1f49b3f9f 100644 --- a/chromium/mojo/message_pump/handle_watcher_unittest.cc +++ b/chromium/mojo/message_pump/handle_watcher_unittest.cc @@ -4,13 +4,13 @@ #include "mojo/message_pump/handle_watcher.h" +#include <memory> #include <string> #include "base/at_exit.h" #include "base/auto_reset.h" #include "base/bind.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/run_loop.h" #include "base/test/simple_test_tick_clock.h" @@ -50,8 +50,8 @@ void DeleteWatcherAndForwardResult( next_callback.Run(result); } -scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { - scoped_ptr<base::MessageLoop> loop; +std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { + std::unique_ptr<base::MessageLoop> loop; if (config == MESSAGE_LOOP_CONFIG_DEFAULT) loop.reset(new base::MessageLoop()); else @@ -147,8 +147,8 @@ class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> { base::SimpleTestTickClock tick_clock_; private: - scoped_ptr<base::ShadowingAtExitManager> at_exit_; - scoped_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<base::ShadowingAtExitManager> at_exit_; + std::unique_ptr<base::MessageLoop> message_loop_; DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); }; @@ -430,7 +430,7 @@ void RunStressTest(int count, callback_helper.RunUntilGotCallback(); EXPECT_TRUE(callback_helper.got_callback()); } else { - scoped_ptr<TestData> test_data(new TestData); + std::unique_ptr<TestData> test_data(new TestData); ASSERT_TRUE(test_data->pipe.handle0.is_valid()); test_data->watcher.Start(test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, @@ -467,7 +467,7 @@ TEST(HandleWatcherCleanEnvironmentTest, StressTest) { // Starts the threads first and then post the task in hopes of having more // threads running at once. for (int i = 0; i < kThreadCount; ++i) { - scoped_ptr<base::Thread> thread(new base::Thread("test thread")); + std::unique_ptr<base::Thread> thread(new base::Thread("test thread")); if (i % 2) { base::Thread::Options thread_options; thread_options.message_pump_factory = diff --git a/chromium/mojo/message_pump/message_pump_mojo.cc b/chromium/mojo/message_pump/message_pump_mojo.cc index e1f9c9604f1..bbf8ce3afe9 100644 --- a/chromium/mojo/message_pump/message_pump_mojo.cc +++ b/chromium/mojo/message_pump/message_pump_mojo.cc @@ -78,8 +78,8 @@ MessagePumpMojo::~MessagePumpMojo() { } // static -scoped_ptr<base::MessagePump> MessagePumpMojo::Create() { - return scoped_ptr<MessagePump>(new MessagePumpMojo()); +std::unique_ptr<base::MessagePump> MessagePumpMojo::Create() { + return std::unique_ptr<MessagePump>(new MessagePumpMojo()); } // static diff --git a/chromium/mojo/message_pump/message_pump_mojo.h b/chromium/mojo/message_pump/message_pump_mojo.h index 5b772d18fb3..ef2f55a7f72 100644 --- a/chromium/mojo/message_pump/message_pump_mojo.h +++ b/chromium/mojo/message_pump/message_pump_mojo.h @@ -8,11 +8,11 @@ #include <stdint.h> #include <functional> +#include <memory> #include <set> #include <unordered_map> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_pump.h" #include "base/observer_list.h" #include "base/synchronization/lock.h" @@ -45,7 +45,7 @@ class MOJO_MESSAGE_PUMP_EXPORT MessagePumpMojo : public base::MessagePump { // Static factory function (for using with |base::Thread::Options|, wrapped // using |base::Bind()|). - static scoped_ptr<base::MessagePump> Create(); + static std::unique_ptr<base::MessagePump> Create(); // Returns the MessagePumpMojo instance of the current thread, if it exists. static MessagePumpMojo* current(); diff --git a/chromium/mojo/message_pump/message_pump_mojo_unittest.cc b/chromium/mojo/message_pump/message_pump_mojo_unittest.cc index 805b14120b6..1abb27cfe96 100644 --- a/chromium/mojo/message_pump/message_pump_mojo_unittest.cc +++ b/chromium/mojo/message_pump/message_pump_mojo_unittest.cc @@ -15,8 +15,8 @@ namespace mojo { namespace common { namespace test { -scoped_ptr<base::MessagePump> CreateMojoMessagePump() { - return scoped_ptr<base::MessagePump>(new MessagePumpMojo()); +std::unique_ptr<base::MessagePump> CreateMojoMessagePump() { + return std::unique_ptr<base::MessagePump>(new MessagePumpMojo()); } RUN_MESSAGE_LOOP_TESTS(Mojo, &CreateMojoMessagePump); diff --git a/chromium/mojo/mojo_base.gyp b/chromium/mojo/mojo_base.gyp index b13343b63cf..65039c6f342 100644 --- a/chromium/mojo/mojo_base.gyp +++ b/chromium/mojo/mojo_base.gyp @@ -59,6 +59,23 @@ ], }, { + # GN version: //mojo/common:common_custom_types + 'target_name': 'mojo_common_custom_types_mojom', + 'type': 'none', + 'variables': { + 'mojom_files': [ + 'common/common_custom_types.mojom', + ], + 'mojom_typemaps': [ + 'common/common_custom_types.typemap', + ], + }, + 'dependencies': [ + '../ipc/ipc.gyp:ipc', + ], + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + { # GN version: //mojo/common:url_type_converters 'target_name': 'mojo_url_type_converters', 'type': 'static_library', @@ -95,6 +112,23 @@ ], }, { + # GN version: //mojo/common:test_common_custom_types + 'target_name': 'mojo_test_common_custom_types', + 'type': 'static_library', + 'variables': { + 'mojom_typemaps': [ + 'common/common_custom_types.typemap', + ], + }, + 'sources': [ + 'common/test_common_custom_types.mojom', + ], + 'dependencies': [ + 'mojo_common_custom_types_mojom', + ], + 'includes': [ 'mojom_bindings_generator.gypi' ], + }, + { # GN version: //mojo/common:mojo_common_unittests 'target_name': 'mojo_common_unittests', 'type': 'executable', @@ -104,88 +138,19 @@ '../base/base.gyp:base_message_loop_tests', '../testing/gtest.gyp:gtest', '../url/url.gyp:url_lib', + 'mojo_common_custom_types_mojom', 'mojo_common_lib', + 'mojo_test_common_custom_types', 'mojo_edk.gyp:mojo_system_impl', 'mojo_edk.gyp:mojo_common_test_support', 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_message_pump_lib', 'mojo_public.gyp:mojo_public_test_utils', 'mojo_url_type_converters', ], 'sources': [ + 'common/common_custom_types_unittest.cc', 'common/common_type_converters_unittest.cc', - 'message_pump/handle_watcher_unittest.cc', - 'message_pump/message_pump_mojo_unittest.cc', - ], - }, - { - 'target_name': 'mojo_application_bindings_mojom', - 'type': 'none', - 'variables': { - 'mojom_files': [ - 'services/catalog/public/interfaces/catalog.mojom', - 'services/catalog/public/interfaces/resolver.mojom', - 'shell/public/interfaces/capabilities.mojom', - 'shell/public/interfaces/connector.mojom', - 'shell/public/interfaces/interface_provider.mojom', - 'shell/public/interfaces/shell.mojom', - 'shell/public/interfaces/shell_client.mojom', - 'shell/public/interfaces/shell_client_factory.mojom', - 'shell/public/interfaces/shell_resolver.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - }, - { - # GN version: //mojo/shell/public/cpp - 'target_name': 'mojo_application_base', - 'type': 'static_library', - 'sources': [ - 'shell/public/cpp/application_runner.h', - 'shell/public/cpp/capabilities.h', - 'shell/public/cpp/connect.h', - 'shell/public/cpp/connection.h', - 'shell/public/cpp/connector.h', - 'shell/public/cpp/identity.h', - 'shell/public/cpp/initialize_base_and_icu.cc', - 'shell/public/cpp/initialize_base_and_icu.h', - 'shell/public/cpp/interface_binder.h', - 'shell/public/cpp/interface_factory.h', - 'shell/public/cpp/interface_factory_impl.h', - 'shell/public/cpp/interface_registry.h', - 'shell/public/cpp/lib/application_runner.cc', - 'shell/public/cpp/lib/capabilities.cc', - 'shell/public/cpp/lib/connection_impl.cc', - 'shell/public/cpp/lib/connection_impl.h', - 'shell/public/cpp/lib/connector_impl.cc', - 'shell/public/cpp/lib/connector_impl.h', - 'shell/public/cpp/lib/identity.cc', - 'shell/public/cpp/lib/interface_factory_binder.h', - 'shell/public/cpp/lib/interface_registry.cc', - 'shell/public/cpp/lib/message_loop_ref.cc', - 'shell/public/cpp/lib/names.cc', - 'shell/public/cpp/lib/shell_client.cc', - 'shell/public/cpp/lib/shell_connection.cc', - 'shell/public/cpp/message_loop_ref.h', - 'shell/public/cpp/names.h', - 'shell/public/cpp/shell.h', - 'shell/public/cpp/shell_client.h', - 'shell/public/cpp/shell_connection.h', - ], - 'dependencies': [ - '../base/base.gyp:base_i18n', - 'mojo_application_bindings', - 'mojo_public.gyp:mojo_message_pump_lib', - ], - }, - { - # GN version: //mojo/public/interfaces/application:application - 'target_name': 'mojo_application_bindings', - 'type': 'static_library', - 'dependencies': [ - 'mojo_application_bindings_mojom', - 'mojo_public.gyp:mojo_cpp_bindings', ], }, { @@ -201,60 +166,6 @@ 'test/test_utils_win.cc', ], }, - { - # GN version: //mojo/shell/public/cpp/tests - 'target_name': 'mojo_public_application_unittests', - 'type': 'executable', - 'dependencies': [ - '../base/base.gyp:base', - '../testing/gtest.gyp:gtest', - 'mojo_application_base', - 'mojo_edk.gyp:mojo_run_all_unittests', - ], - 'sources': [ - 'shell/public/cpp/tests/interface_registry_unittest.cc', - ], - }, - { - # Technically, these should be in the mojo_services.gyp, but this causes - # a cycle since the ios generator can't have gyp files refer to each - # other, even if the targets don't form a cycle. - # - # GN version: //mojo/services/tracing:lib - 'target_name': 'tracing_service', - 'type': 'static_library', - 'dependencies': [ - 'mojo_services.gyp:tracing_service_bindings_lib', - 'mojo_base.gyp:mojo_application_bindings', - 'mojo_edk.gyp:mojo_system_impl', - ], - 'sources': [ - 'services/tracing/trace_data_sink.cc', - 'services/tracing/trace_data_sink.h', - 'services/tracing/trace_recorder_impl.cc', - 'services/tracing/trace_recorder_impl.h', - 'services/tracing/tracing_app.cc', - 'services/tracing/tracing_app.h', - ], - }, - { - # GN version: //mojo/services/public/cpp - 'target_name': 'tracing_service_lib', - 'type': 'static_library', - 'dependencies': [ - 'mojo_services.gyp:tracing_service_bindings_lib', - 'mojo_base.gyp:mojo_application_bindings', - 'mojo_edk.gyp:mojo_system_impl', - ], - 'sources': [ - 'services/tracing/public/cpp/switches.cc', - 'services/tracing/public/cpp/switches.h', - 'services/tracing/public/cpp/tracing_impl.cc', - 'services/tracing/public/cpp/tracing_impl.h', - 'services/tracing/public/cpp/trace_provider_impl.cc', - 'services/tracing/public/cpp/trace_provider_impl.h', - ], - }, ], 'conditions': [ ['OS=="android"', { diff --git a/chromium/mojo/mojo_common_unittests.isolate b/chromium/mojo/mojo_common_unittests.isolate index 8fe9d31f728..a72311cd59e 100644 --- a/chromium/mojo/mojo_common_unittests.isolate +++ b/chromium/mojo/mojo_common_unittests.isolate @@ -19,26 +19,5 @@ ], }, }], - ['OS=="win"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/mojo_public_test_support.dll', - ], - }, - }], - ['OS=="linux"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/lib/libmojo_public_test_support.so', - ], - }, - }], - ['OS=="mac"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/libmojo_public_test_support.dylib', - ], - }, - }], ], } diff --git a/chromium/mojo/mojo_edk.gyp b/chromium/mojo/mojo_edk.gyp index db57fc58c13..b0002a599e7 100644 --- a/chromium/mojo/mojo_edk.gyp +++ b/chromium/mojo/mojo_edk.gyp @@ -18,6 +18,35 @@ }, 'targets': [ { + # GN version: //mojo/edk/system/ports + 'target_name': 'mojo_system_ports', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + '../crypto/crypto.gyp:crypto', + ], + 'sources': [ + 'edk/system/ports/event.cc', + 'edk/system/ports/event.h', + 'edk/system/ports/message.cc', + 'edk/system/ports/message.h', + 'edk/system/ports/message_queue.cc', + 'edk/system/ports/message_queue.h', + 'edk/system/ports/name.cc', + 'edk/system/ports/name.h', + 'edk/system/ports/node.cc', + 'edk/system/ports/node.h', + 'edk/system/ports/node_delegate.h', + 'edk/system/ports/port.cc', + 'edk/system/ports/port.h', + 'edk/system/ports/port_ref.cc', + 'edk/system/ports/user_data.h', + 'edk/system/ports_message.cc', + 'edk/system/ports_message.h', + ], + }, + { # GN version: //mojo/edk/system 'target_name': 'mojo_system_impl', 'type': '<(component)', @@ -26,6 +55,7 @@ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../crypto/crypto.gyp:crypto', 'mojo_public.gyp:mojo_system_headers', + 'mojo_system_ports', ], 'defines': [ 'MOJO_SYSTEM_IMPL_IMPLEMENTATION', @@ -58,6 +88,7 @@ 'edk/system/awakable_list.h', 'edk/system/async_waiter.cc', 'edk/system/async_waiter.h', + 'edk/system/atomic_flag.h', 'edk/system/broker.h', 'edk/system/broker_host.h', 'edk/system/broker_host_posix.cc', @@ -83,6 +114,8 @@ 'edk/system/handle_table.h', 'edk/system/mapping_table.cc', 'edk/system/mapping_table.h', + 'edk/system/message_for_transit.cc', + 'edk/system/message_for_transit.h', 'edk/system/message_pipe_dispatcher.cc', 'edk/system/message_pipe_dispatcher.h', 'edk/system/node_channel.cc', @@ -92,24 +125,6 @@ 'edk/system/options_validation.h', 'edk/system/platform_handle_dispatcher.cc', 'edk/system/platform_handle_dispatcher.h', - 'edk/system/ports/event.cc', - 'edk/system/ports/event.h', - 'edk/system/ports/hash_functions.h', - 'edk/system/ports/message.cc', - 'edk/system/ports/message.h', - 'edk/system/ports/message_queue.cc', - 'edk/system/ports/message_queue.h', - 'edk/system/ports/name.cc', - 'edk/system/ports/name.h', - 'edk/system/ports/node.cc', - 'edk/system/ports/node.h', - 'edk/system/ports/node_delegate.h', - 'edk/system/ports/port.cc', - 'edk/system/ports/port.h', - 'edk/system/ports/port_ref.cc', - 'edk/system/ports/user_data.h', - 'edk/system/ports_message.cc', - 'edk/system/ports_message.h', 'edk/system/remote_message_pipe_bootstrap.cc', 'edk/system/remote_message_pipe_bootstrap.h', 'edk/system/request_context.cc', @@ -161,8 +176,7 @@ 'dependencies': [ '../base/base.gyp:base', '../gin/gin.gyp:gin', - '../v8/tools/gyp/v8.gyp:v8', - 'mojo_public.gyp:mojo_message_pump_lib', + '../v8/src/v8.gyp:v8', ], 'export_dependent_settings': [ '../base/base.gyp:base', diff --git a/chromium/mojo/mojo_edk_tests.gyp b/chromium/mojo/mojo_edk_tests.gyp index bf7dfd026e4..6e09379f0eb 100644 --- a/chromium/mojo/mojo_edk_tests.gyp +++ b/chromium/mojo/mojo_edk_tests.gyp @@ -27,19 +27,6 @@ ], }, { - # GN version: //mojo/edk/system/ports:mojo_system_ports_unittests - 'target_name': 'mojo_system_ports_unittests', - 'type': 'executable', - 'dependencies': [ - '../testing/gtest.gyp:gtest', - '../testing/gtest.gyp:gtest_main', - 'mojo_edk.gyp:mojo_system_impl', - ], - 'sources': [ - 'edk/system/ports/ports_unittest.cc', - ], - }, - { # GN version: //mojo/edk/test:mojo_public_bindings_unittests 'target_name': 'mojo_public_bindings_unittests', 'type': 'executable', @@ -47,20 +34,18 @@ '../testing/gtest.gyp:gtest', 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_message_pump_lib', 'mojo_public.gyp:mojo_public_bindings_test_utils', 'mojo_public.gyp:mojo_public_test_associated_interfaces', 'mojo_public.gyp:mojo_public_test_interfaces', 'mojo_public.gyp:mojo_public_test_interfaces_blink', - 'mojo_public.gyp:mojo_public_test_interfaces_chromium', 'mojo_public.gyp:mojo_public_test_interfaces_struct_traits', 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_public_test_variant', ], 'sources': [ 'public/cpp/bindings/tests/array_common_test.h', 'public/cpp/bindings/tests/array_unittest.cc', 'public/cpp/bindings/tests/associated_interface_unittest.cc', + 'public/cpp/bindings/tests/bind_task_runner_unittest.cc', 'public/cpp/bindings/tests/binding_callback_unittest.cc', 'public/cpp/bindings/tests/binding_unittest.cc', 'public/cpp/bindings/tests/bounds_checker_unittest.cc', @@ -73,7 +58,6 @@ 'public/cpp/bindings/tests/equals_unittest.cc', 'public/cpp/bindings/tests/handle_passing_unittest.cc', 'public/cpp/bindings/tests/interface_ptr_unittest.cc', - 'public/cpp/bindings/tests/macros_unittest.cc', 'public/cpp/bindings/tests/map_unittest.cc', 'public/cpp/bindings/tests/message_queue.cc', 'public/cpp/bindings/tests/message_queue.h', @@ -107,6 +91,23 @@ 'public/cpp/bindings/tests/validation_unittest.cc', 'public/cpp/bindings/tests/variant_test_util.h', ], + 'conditions': [ + ['OS=="ios"', { + 'dependencies!': [ + 'mojo_public.gyp:mojo_public_test_interfaces_blink', + ], + 'sources!': [ + 'public/cpp/bindings/tests/pickle_unittest.cc', + 'public/cpp/bindings/tests/pickled_struct_blink.cc', + 'public/cpp/bindings/tests/pickled_struct_blink.h', + 'public/cpp/bindings/tests/pickled_struct_chromium.cc', + 'public/cpp/bindings/tests/pickled_struct_chromium.h', + 'public/cpp/bindings/tests/rect_blink.h', + 'public/cpp/bindings/tests/rect_blink_traits.h', + 'public/cpp/bindings/tests/struct_traits_unittest.cc', + ], + }], + ], }, { # GN version: //mojo/public/cpp/bindings/tests:for_blink_tests @@ -138,7 +139,6 @@ 'mojo_base.gyp:mojo_common_lib', 'mojo_edk.gyp:mojo_run_all_perftests', 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_message_pump_lib', 'mojo_public.gyp:mojo_public_bindings_test_utils', 'mojo_public.gyp:mojo_public_test_interfaces', 'mojo_public.gyp:mojo_public_test_utils', @@ -180,13 +180,14 @@ { # GN version: //mojo/edk/system:mojo_system_unittests 'target_name': 'mojo_system_unittests', - 'type': 'executable', + 'type': '<(gtest_target_type)', 'dependencies': [ '../base/base.gyp:base', '../testing/gtest.gyp:gtest', 'mojo_edk.gyp:mojo_common_test_support', 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_edk.gyp:mojo_system_impl', + 'mojo_edk.gyp:mojo_system_ports', ], 'sources': [ 'edk/embedder/embedder_unittest.cc', @@ -200,6 +201,7 @@ 'edk/system/multiprocess_message_pipe_unittest.cc', 'edk/system/options_validation_unittest.cc', 'edk/system/platform_handle_dispatcher_unittest.cc', + 'edk/system/ports/ports_unittest.cc', 'edk/system/shared_buffer_dispatcher_unittest.cc', 'edk/system/shared_buffer_unittest.cc', 'edk/system/test_utils.cc', @@ -216,6 +218,11 @@ 'edk/system/multiprocess_message_pipe_unittest.cc', ], }], + ['OS == "android"', { + 'dependencies': [ + '../testing/android/native_test.gyp:native_test_native_code', + ], + }], ], }, { @@ -311,6 +318,60 @@ 'mojo_public_system_unittests.isolate', ], }, + { + 'target_name': 'mojo_js_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_js_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_js_unittests.isolate', + ], + }, + { + 'target_name': 'mojo_js_integration_tests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_js_integration_tests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_js_integration_tests.isolate', + ], + }, + { + 'target_name': 'mojo_system_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_system_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_system_unittests.isolate', + ], + }, + ], + }], + ['OS == "android"', { + 'targets': [ + { + 'target_name': 'mojo_system_unittests_apk', + 'type': 'none', + 'dependencies': [ + 'mojo_system_unittests', + ], + 'variables': { + 'test_suite_name': 'mojo_system_unittests', + }, + 'includes': [ '../build/apk_test.gypi' ], + }, ], }], ], diff --git a/chromium/mojo/mojo_js_integration_tests.isolate b/chromium/mojo/mojo_js_integration_tests.isolate new file mode 100644 index 00000000000..2ce03457d9e --- /dev/null +++ b/chromium/mojo/mojo_js_integration_tests.isolate @@ -0,0 +1,49 @@ +# Copyright 2016 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. +{ + 'includes': [ + '../base/base.isolate', + '../gin/v8.isolate', + '../third_party/icu/icu.isolate', + ], + 'conditions': [ + ['OS=="win" or OS=="mac" or OS=="linux"', { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/mojo_js_integration_tests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + ], + 'files': [ + '../gin/test/expect.js', + '../mojo/edk/js/tests/', + '../mojo/public/js/', + '../testing/test_env.py', + '<(PRODUCT_DIR)/mojo_js_integration_tests<(EXECUTABLE_SUFFIX)', + '<(PRODUCT_DIR)/gen/mojo/common/common_custom_types.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/edk/js/tests/js_to_cpp.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/no_module.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/ping_service.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/rect.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/regression_tests.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_factory.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import2.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/scoping.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_constants.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_native_types.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js', + ], + }, + }], + ], +} diff --git a/chromium/mojo/mojo_js_unittests.isolate b/chromium/mojo/mojo_js_unittests.isolate index c6283884b53..81bae0b9a86 100644 --- a/chromium/mojo/mojo_js_unittests.isolate +++ b/chromium/mojo/mojo_js_unittests.isolate @@ -3,6 +3,8 @@ # found in the LICENSE file. { 'includes': [ + '../base/base.isolate', + '../gin/v8.isolate', '../third_party/icu/icu.isolate', ], 'conditions': [ @@ -17,30 +19,26 @@ 'files': [ '../gin/test/expect.js', '../testing/test_env.py', - '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/', - 'bindings/js/', - 'public/js/bindings/', - ], - }, - }], - ['OS=="win"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/mojo_public_test_support.dll', - ], - }, - }], - ['OS=="linux"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/lib/libmojo_public_test_support.so', - ], - }, - }], - ['OS=="mac"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/libmojo_public_test_support.dylib', + 'public/interfaces/bindings/tests/data/validation/', + 'public/js/', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/no_module.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/ping_service.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/rect.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/regression_tests.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_factory.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import2.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/scoping.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_constants.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_native_types.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js', + '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js', ], }, }], diff --git a/chromium/mojo/mojo_public.gyp b/chromium/mojo/mojo_public.gyp index 054fe4de595..a9a13715f2d 100644 --- a/chromium/mojo/mojo_public.gyp +++ b/chromium/mojo/mojo_public.gyp @@ -27,10 +27,7 @@ 'public/interfaces/bindings/tests/serialization_test_structs.mojom', 'public/interfaces/bindings/tests/test_constants.mojom', 'public/interfaces/bindings/tests/test_native_types.mojom', - 'public/interfaces/bindings/tests/test_structs.mojom', 'public/interfaces/bindings/tests/test_sync_methods.mojom', - 'public/interfaces/bindings/tests/test_unions.mojom', - 'public/interfaces/bindings/tests/validation_test_interfaces.mojom', ] }, 'targets': [ @@ -103,6 +100,7 @@ 'public/cpp/system/data_pipe.h', 'public/cpp/system/functions.h', 'public/cpp/system/handle.h', + 'public/cpp/system/message.h', 'public/cpp/system/message_pipe.h', 'public/cpp/system/watcher.cc', 'public/cpp/system/watcher.h', @@ -121,6 +119,9 @@ ], 'sources': [ 'public/cpp/bindings/array.h', + 'public/cpp/bindings/array_traits.h', + 'public/cpp/bindings/array_traits_standard.h', + 'public/cpp/bindings/array_traits_stl.h', 'public/cpp/bindings/associated_binding.h', 'public/cpp/bindings/associated_group.h', 'public/cpp/bindings/associated_interface_ptr.h', @@ -135,13 +136,10 @@ 'public/cpp/bindings/lib/array_internal.cc', 'public/cpp/bindings/lib/array_internal.h', 'public/cpp/bindings/lib/array_serialization.h', - 'public/cpp/bindings/lib/array_serialization_traits.h', 'public/cpp/bindings/lib/associated_group.cc', 'public/cpp/bindings/lib/associated_interface_ptr_state.h', 'public/cpp/bindings/lib/binding_state.h', 'public/cpp/bindings/lib/bindings_internal.h', - 'public/cpp/bindings/lib/bindings_serialization.cc', - 'public/cpp/bindings/lib/bindings_serialization.h', 'public/cpp/bindings/lib/bounds_checker.cc', 'public/cpp/bindings/lib/bounds_checker.h', 'public/cpp/bindings/lib/buffer.h', @@ -155,17 +153,18 @@ 'public/cpp/bindings/lib/filter_chain.cc', 'public/cpp/bindings/lib/filter_chain.h', 'public/cpp/bindings/lib/fixed_buffer.cc', - 'public/cpp/bindings/lib/interface_id.h', 'public/cpp/bindings/lib/fixed_buffer.h', 'public/cpp/bindings/lib/interface_endpoint_client.cc', 'public/cpp/bindings/lib/interface_endpoint_client.h', 'public/cpp/bindings/lib/interface_endpoint_controller.h', + 'public/cpp/bindings/lib/interface_id.h', 'public/cpp/bindings/lib/interface_ptr_state.h', - 'public/cpp/bindings/lib/macros.h', 'public/cpp/bindings/lib/map_data_internal.h', 'public/cpp/bindings/lib/map_internal.h', 'public/cpp/bindings/lib/map_serialization.h', 'public/cpp/bindings/lib/message.cc', + 'public/cpp/bindings/lib/message_buffer.cc', + 'public/cpp/bindings/lib/message_buffer.h', 'public/cpp/bindings/lib/message_builder.cc', 'public/cpp/bindings/lib/message_builder.h', 'public/cpp/bindings/lib/message_filter.cc', @@ -174,9 +173,12 @@ 'public/cpp/bindings/lib/message_internal.h', 'public/cpp/bindings/lib/multiplex_router.cc', 'public/cpp/bindings/lib/multiplex_router.h', + 'public/cpp/bindings/lib/native_struct.cc', + 'public/cpp/bindings/lib/native_struct_data.cc', + 'public/cpp/bindings/lib/native_struct_data.h', + 'public/cpp/bindings/lib/native_struct_serialization.cc', + 'public/cpp/bindings/lib/native_struct_serialization.h', 'public/cpp/bindings/lib/no_interface.cc', - 'public/cpp/bindings/lib/pickle_buffer.cc', - 'public/cpp/bindings/lib/pickle_buffer.h', 'public/cpp/bindings/lib/pipe_control_message_handler.cc', 'public/cpp/bindings/lib/pipe_control_message_handler.h', 'public/cpp/bindings/lib/pipe_control_message_handler_delegate.h', @@ -185,13 +187,17 @@ 'public/cpp/bindings/lib/router.cc', 'public/cpp/bindings/lib/router.h', 'public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc', - 'public/cpp/bindings/lib/scoped_interface_endpoint_handle.h', - 'public/cpp/bindings/lib/serialization_forward.h', 'public/cpp/bindings/lib/serialization.h', + 'public/cpp/bindings/lib/serialization_context.cc', + 'public/cpp/bindings/lib/serialization_context.h', + 'public/cpp/bindings/lib/serialization_forward.h', + 'public/cpp/bindings/lib/serialization_forward.h', + 'public/cpp/bindings/lib/serialization_util.cc', + 'public/cpp/bindings/lib/serialization_util.h', 'public/cpp/bindings/lib/shared_data.h', 'public/cpp/bindings/lib/shared_ptr.h', - 'public/cpp/bindings/lib/string_serialization.cc', 'public/cpp/bindings/lib/string_serialization.h', + 'public/cpp/bindings/lib/string_traits_string16.cc', 'public/cpp/bindings/lib/sync_handle_registry.cc', 'public/cpp/bindings/lib/sync_handle_registry.h', 'public/cpp/bindings/lib/sync_handle_watcher.cc', @@ -202,15 +208,20 @@ 'public/cpp/bindings/lib/validation_util.cc', 'public/cpp/bindings/lib/validation_util.h', 'public/cpp/bindings/lib/value_traits.h', - # Include the .h but not the .cc file. The .h file is used by - # serialization_forward.h. - 'public/cpp/bindings/lib/wtf_string_serialization.h', 'public/cpp/bindings/message.h', 'public/cpp/bindings/message_filter.h', + 'public/cpp/bindings/native_struct.h', 'public/cpp/bindings/no_interface.h', + 'public/cpp/bindings/scoped_interface_endpoint_handle.h', 'public/cpp/bindings/stl_converters.h', 'public/cpp/bindings/string.h', + 'public/cpp/bindings/string_traits.h', + 'public/cpp/bindings/string_traits_standard.h', + 'public/cpp/bindings/string_traits_stl.h', + 'public/cpp/bindings/string_traits_string16.h', + 'public/cpp/bindings/string_traits_string_piece.h', 'public/cpp/bindings/strong_binding.h', + 'public/cpp/bindings/struct_ptr.h', 'public/cpp/bindings/type_converter.h', # This comes from the mojo_interface_bindings_cpp_sources dependency. '>@(mojom_generated_sources)', @@ -229,10 +240,11 @@ '..' ], 'sources': [ - 'public/cpp/bindings/lib/wtf_array_serialization.h', + 'public/cpp/bindings/array_traits_wtf.h', + 'public/cpp/bindings/array_traits_wtf_vector.h', + 'public/cpp/bindings/lib/string_traits_wtf.cc', 'public/cpp/bindings/lib/wtf_serialization.h', - 'public/cpp/bindings/lib/wtf_string_serialization.cc', - 'public/cpp/bindings/lib/wtf_string_serialization.h', + 'public/cpp/bindings/string_traits_wtf.h', 'public/cpp/bindings/wtf_array.h', ], 'dependencies': [ @@ -319,9 +331,7 @@ { # GN version: //mojo/public/c/test_support 'target_name': 'mojo_public_test_support', - 'defines': [ - 'MOJO_TEST_SUPPORT_IMPLEMENTATION', - ], + 'type': 'static_library', 'include_dirs': [ '..', ], @@ -332,24 +342,10 @@ }, 'sources': [ 'public/c/test_support/test_support.h', - 'public/c/test_support/test_support_export.h', # TODO(vtl): Convert this to thunks http://crbug.com/386799 'public/tests/test_support_private.cc', 'public/tests/test_support_private.h', ], - 'conditions': [ - ['OS=="ios"', { - 'type': 'static_library', - }, { - 'type': 'shared_library', - }], - ['OS=="mac"', { - 'xcode_settings': { - # Make it a run-path dependent library. - 'DYLIB_INSTALL_NAME_BASE': '@loader_path', - }, - }], - ], }, { # GN version: //mojo/public/cpp/test_support:test_utils @@ -382,7 +378,16 @@ 'target_name': 'mojo_public_test_interfaces_mojom', 'type': 'none', 'variables': { - 'mojom_files': '<(mojo_public_test_interfaces_mojom_files)', + 'mojom_files': [ + 'public/interfaces/bindings/tests/test_structs.mojom', + 'public/interfaces/bindings/tests/test_unions.mojom', + 'public/interfaces/bindings/tests/validation_test_interfaces.mojom', + '<@(mojo_public_test_interfaces_mojom_files)', + ], + 'mojom_typemaps': [ + 'public/cpp/bindings/tests/rect_chromium.typemap', + 'public/cpp/bindings/tests/test_native_types_chromium.typemap', + ], }, 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], }, @@ -390,12 +395,13 @@ 'target_name': 'mojo_public_test_interfaces_struct_traits', 'type': 'static_library', 'variables': { - 'mojom_extra_generator_args': [ - '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/struct_with_traits.typemap', + 'mojom_typemaps': [ + 'public/cpp/bindings/tests/struct_with_traits.typemap', ], }, 'sources': [ 'public/interfaces/bindings/tests/struct_with_traits.mojom', + 'public/cpp/bindings/tests/struct_with_traits_impl_traits.cc', ], 'includes': [ 'mojom_bindings_generator.gypi' ], }, @@ -403,31 +409,14 @@ 'target_name': 'mojo_public_test_interfaces_mojom_blink', 'type': 'none', 'variables': { - 'mojom_variant': 'blink', - 'mojom_extra_generator_args': [ - '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/blink_test.typemap', - ], - 'mojom_files': '<(mojo_public_test_interfaces_mojom_files)', - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom', - ], - }, - { - 'target_name': 'mojo_public_test_interfaces_mojom_chromium', - 'type': 'none', - 'variables': { - 'mojom_variant': 'chromium', - 'mojom_extra_generator_args': [ - '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/chromium_test.typemap', + 'for_blink': 'true', + 'mojom_typemaps': [ + 'public/cpp/bindings/tests/rect_blink.typemap', + 'public/cpp/bindings/tests/test_native_types_blink.typemap', ], 'mojom_files': '<(mojo_public_test_interfaces_mojom_files)', }, 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom', - ], }, { # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces @@ -436,6 +425,9 @@ 'export_dependent_settings': [ 'mojo_cpp_bindings', ], + 'sources': [ + 'public/cpp/bindings/tests/pickled_struct_chromium.cc', + ], 'dependencies': [ 'mojo_public_test_interfaces_mojom', 'mojo_cpp_bindings', @@ -446,22 +438,14 @@ 'target_name': 'mojo_public_test_interfaces_blink', 'type': 'static_library', 'export_dependent_settings': [ - 'mojo_cpp_bindings', - ], - 'dependencies': [ 'mojo_public_test_interfaces_mojom_blink', 'mojo_cpp_bindings', ], - }, - { - # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_chromium - 'target_name': 'mojo_public_test_interfaces_chromium', - 'type': 'static_library', - 'export_dependent_settings': [ - 'mojo_cpp_bindings', + 'sources': [ + 'public/cpp/bindings/tests/pickled_struct_blink.cc', ], 'dependencies': [ - 'mojo_public_test_interfaces_mojom_chromium', + 'mojo_public_test_interfaces_mojom_blink', 'mojo_cpp_bindings', ], }, @@ -503,7 +487,6 @@ 'target_name': 'mojo_public_test_wtf_types_blink', 'type': 'static_library', 'variables': { - 'mojom_variant': 'blink', 'for_blink': 'true', }, 'sources': [ @@ -511,18 +494,6 @@ ], 'includes': [ 'mojom_bindings_generator.gypi' ], }, - { - 'target_name': 'mojo_public_test_variant', - 'type': 'static_library', - 'variables': { - 'mojom_variant': 'test_variant', - }, - 'sources': [ - 'public/interfaces/bindings/tests/test_variant_import.mojom', - 'public/interfaces/bindings/tests/test_variant.mojom', - ], - 'includes': [ 'mojom_bindings_generator.gypi' ], - }, ], 'conditions': [ ['OS == "android"', { diff --git a/chromium/mojo/mojo_public_bindings_unittests.isolate b/chromium/mojo/mojo_public_bindings_unittests.isolate index 4c1ffaaa616..846bf78b6d2 100644 --- a/chromium/mojo/mojo_public_bindings_unittests.isolate +++ b/chromium/mojo/mojo_public_bindings_unittests.isolate @@ -16,27 +16,7 @@ ], 'files': [ '../testing/test_env.py', - ], - }, - }], - ['OS=="win"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/mojo_public_test_support.dll', - ], - }, - }], - ['OS=="linux"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/lib/libmojo_public_test_support.so', - ], - }, - }], - ['OS=="mac"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/libmojo_public_test_support.dylib', + 'public/interfaces/bindings/tests/data/validation/', ], }, }], diff --git a/chromium/mojo/mojo_public_system_unittests.isolate b/chromium/mojo/mojo_public_system_unittests.isolate index 73b8c0052fc..f761bf77cd8 100644 --- a/chromium/mojo/mojo_public_system_unittests.isolate +++ b/chromium/mojo/mojo_public_system_unittests.isolate @@ -19,26 +19,5 @@ ], }, }], - ['OS=="win"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/mojo_public_test_support.dll', - ], - }, - }], - ['OS=="linux"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/lib/libmojo_public_test_support.so', - ], - }, - }], - ['OS=="mac"', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/libmojo_public_test_support.dylib', - ], - }, - }], ], } diff --git a/chromium/mojo/mojo_services.gyp b/chromium/mojo/mojo_services.gyp deleted file mode 100644 index 2ac03d0b88b..00000000000 --- a/chromium/mojo/mojo_services.gyp +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'tracing_service_bindings_mojom', - 'type': 'none', - 'variables': { - 'mojom_files': [ - 'services/tracing/public/interfaces/tracing.mojom', - ], - 'mojom_include_path': '<(DEPTH)/mojo/services', - }, - 'includes': [ - 'mojom_bindings_generator_explicit.gypi', - ], - }, - { - # GN version: //mojo/services/tracing/public/interfaces - 'target_name': 'tracing_service_bindings_lib', - 'type': 'static_library', - 'dependencies': [ - 'tracing_service_bindings_mojom', - ], - }, - ], -} diff --git a/chromium/mojo/mojo_shell.gyp b/chromium/mojo/mojo_shell.gyp deleted file mode 100644 index 1decb57f820..00000000000 --- a/chromium/mojo/mojo_shell.gyp +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [{ - 'target_name': 'mojo_shell_lib', - 'type': 'static_library', - 'sources': [ - 'services/catalog/catalog.cc', - 'services/catalog/catalog.h', - 'services/catalog/entry.cc', - 'services/catalog/entry.h', - 'services/catalog/factory.cc', - 'services/catalog/factory.h', - 'services/catalog/store.cc', - 'services/catalog/store.h', - 'services/catalog/types.h', - 'shell/loader.h', - 'shell/connect_params.cc', - 'shell/connect_params.h', - 'shell/connect_util.cc', - 'shell/connect_util.h', - 'shell/native_runner.h', - 'shell/native_runner_delegate.h', - 'shell/shell.cc', - 'shell/shell.h', - 'shell/switches.cc', - 'shell/switches.cc', - 'util/filename_util.cc', - 'util/filename_util.h', - ], - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters', - '<(DEPTH)/net/net.gyp:net', - '<(DEPTH)/url/url.gyp:url_lib', - ], - 'export_dependent_settings': [ - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - ], - }, { - 'target_name': 'mojo_shell_unittests', - 'type': 'executable', - 'sources': [ - 'shell/tests/loader_unittest.cc', - ], - 'dependencies': [ - 'mojo_shell_lib', - 'mojo_shell_test_bindings', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters', - '<(DEPTH)/mojo/mojo_edk.gyp:mojo_run_all_unittests', - '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(DEPTH)/url/url.gyp:url_lib', - ] - }, { - 'target_name': 'mojo_shell_test_bindings', - 'type': 'static_library', - 'variables': { - 'mojom_files': [ - 'shell/tests/test.mojom', - ], - }, - 'includes': [ - 'mojom_bindings_generator_explicit.gypi', - ], - }, { - 'target_name': 'mojo_runner_common_lib', - 'type': 'static_library', - 'sources': [ - 'shell/runner/common/client_util.cc', - 'shell/runner/common/client_util.h', - 'shell/runner/common/switches.cc', - 'shell/runner/common/switches.h', - ], - 'include_dirs': [ - '..', - ], - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl', - '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', - '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_system', - ], - 'export_dependent_settings': [ - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - ], - }, { - 'target_name': 'mojo_runner_host_lib', - 'type': 'static_library', - 'sources': [ - 'shell/runner/host/child_process.cc', - 'shell/runner/host/child_process.h', - 'shell/runner/host/child_process_base.cc', - 'shell/runner/host/child_process_base.h', - 'shell/runner/host/child_process_host.cc', - 'shell/runner/host/child_process_host.h', - 'shell/runner/host/in_process_native_runner.cc', - 'shell/runner/host/in_process_native_runner.h', - 'shell/runner/host/out_of_process_native_runner.cc', - 'shell/runner/host/out_of_process_native_runner.h', - 'shell/runner/host/native_application_support.cc', - 'shell/runner/host/native_application_support.h', - 'shell/runner/init.cc', - 'shell/runner/init.h', - ], - 'dependencies': [ - 'mojo_runner_common_lib', - 'mojo_shell_lib', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:base_i18n', - '<(DEPTH)/base/base.gyp:base_static', - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl', - '<(DEPTH)/mojo/mojo_platform_handle.gyp:platform_handle', - '<(DEPTH)/mojo/mojo_public.gyp:mojo_message_pump_lib', - ], - 'export_dependent_settings': [ - '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - ], - 'conditions': [ - ['OS=="linux"', { - 'sources': [ - 'shell/runner/host/linux_sandbox.cc', - 'shell/runner/host/linux_sandbox.h', - ], - 'dependencies': [ - '<(DEPTH)/sandbox/sandbox.gyp:sandbox', - '<(DEPTH)/sandbox/sandbox.gyp:sandbox_services', - '<(DEPTH)/sandbox/sandbox.gyp:seccomp_bpf', - '<(DEPTH)/sandbox/sandbox.gyp:seccomp_bpf_helpers', - ], - }], - ['OS=="mac"', { - 'sources': [ - 'shell/runner/host/mach_broker.cc', - 'shell/runner/host/mach_broker.h', - ], - }], - ], - }, { - # GN version: //mojo/services/catalog:manifest - 'target_name': 'mojo_catalog_manifest', - 'type': 'none', - 'variables': { - 'application_type': 'mojo', - 'application_name': 'catalog', - 'source_manifest': '<(DEPTH)/mojo/services/catalog/manifest.json', - }, - 'includes': [ - '../mojo/public/mojo_application_manifest.gypi', - ], - 'hard_dependency': 1, - }], -} diff --git a/chromium/mojo/mojo_system_unittests.isolate b/chromium/mojo/mojo_system_unittests.isolate new file mode 100644 index 00000000000..ef3cbb929a8 --- /dev/null +++ b/chromium/mojo/mojo_system_unittests.isolate @@ -0,0 +1,23 @@ +# 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. +{ + 'includes': [ + '../base/base.isolate', + ], + 'conditions': [ + ['OS=="win" or OS=="mac" or OS=="linux"', { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/mojo_system_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + ], + 'files': [ + '../testing/test_env.py', + ], + }, + }], + ], +} diff --git a/chromium/mojo/mojo_test_apk.isolate b/chromium/mojo/mojo_test_apk.isolate new file mode 100644 index 00000000000..e08c1be9141 --- /dev/null +++ b/chromium/mojo/mojo_test_apk.isolate @@ -0,0 +1,11 @@ +# Copyright 2016 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. + +{ + 'variables': { + 'files': [ + '<(DEPTH)/mojo/public/interfaces/bindings/tests/data/validation/', + ], + }, +} diff --git a/chromium/mojo/mojom_bindings_generator.gypi b/chromium/mojo/mojom_bindings_generator.gypi index bcf98b229e9..dea11695dd1 100644 --- a/chromium/mojo/mojom_bindings_generator.gypi +++ b/chromium/mojo/mojom_bindings_generator.gypi @@ -8,43 +8,41 @@ ], 'variables': { 'variables': { - 'mojom_typemap_dependencies%': [], - 'mojom_typemaps%': [], - 'mojom_variant%': 'none', - 'for_blink%': 'false', + 'variables': { + 'for_blink%': 'false', + }, + 'for_blink%': '<(for_blink)', + 'conditions': [ + ['for_blink=="true"', { + 'mojom_output_languages%': 'c++', + 'mojom_variant%': 'blink', + 'mojom_generator_wtf_arg%': [ + '--for_blink', + ], + 'wtf_dependencies%': [ + '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support', + '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf', + ], + }, { + 'mojom_output_languages%': 'c++,javascript,java', + 'mojom_variant%': 'none', + 'mojom_generator_wtf_arg%': [], + 'wtf_dependencies%': [], + }], + ], }, - 'mojom_typemap_dependencies%': ['<@(mojom_typemap_dependencies)'], - 'mojom_typemaps%': ['<@(mojom_typemaps)'], - 'mojom_variant%': '<(mojom_variant)', 'for_blink%': '<(for_blink)', + 'mojom_variant%': '<(mojom_variant)', + 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)', + 'wtf_dependencies%': '<(wtf_dependencies)', + 'mojom_output_languages%': '<(mojom_output_languages)', + 'mojom_typemaps%': [], 'mojom_base_output_dir': '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))', 'mojom_generated_outputs': [ '<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_list_outputs.py --basedir <(mojom_base_output_dir) --variant <(mojom_variant) <@(_sources))', ], - 'mojom_generator_typemap_args': [ - '<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_get_generator_typemap_args.py <@(mojom_typemaps))', - ], - 'mojom_extra_generator_args%': [], - 'conditions': [ - ['mojom_variant=="none"', { - 'mojom_output_languages%': 'c++,javascript,java', - }, { - 'mojom_output_languages%': 'c++', - }], - ['for_blink=="true"', { - 'mojom_generator_wtf_arg%': [ - '--for_blink', - ], - 'wtf_dependencies%': [ - '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support', - '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf', - ], - }, { - 'mojom_generator_wtf_arg%': [], - 'wtf_dependencies%': [], - }], - ], + 'generated_typemap_file': '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(_target_name)_type_mappings', }, 'actions': [ { @@ -62,7 +60,23 @@ ], 'inputs': [ '<@(_sources)' ], 'outputs': [ '<(stamp_filename)' ], - } + }, + { + 'variables': { + 'output': '<(generated_typemap_file)', + }, + 'action_name': '<(_target_name)_type_mappings', + 'action': [ + 'python', '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py', + '--output', + '<(output)', + '<!@(python <(DEPTH)/mojo/public/tools/bindings/format_typemap_generator_args.py <@(mojom_typemaps))', + ], + 'inputs':[ + '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py', + ], + 'outputs': [ '<(output)' ], + }, ], 'rules': [ { @@ -78,8 +92,8 @@ }, 'inputs': [ '<@(mojom_bindings_generator_sources)', - '<@(mojom_typemaps)', '<(stamp_filename)', + '<(generated_typemap_file)', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/cpp_templates.zip', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/java_templates.zip', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/js_templates.zip', @@ -110,8 +124,8 @@ '--java_output_directory=<(java_out_dir)', '--variant', '<(mojom_variant)', '-g', '<(mojom_output_languages)', - '<@(mojom_generator_typemap_args)', - '<@(mojom_extra_generator_args)', + '--typemap', + '<(generated_typemap_file)', '<@(mojom_generator_wtf_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', @@ -124,11 +138,9 @@ '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation', '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates', - '<@(mojom_typemap_dependencies)', '<@(wtf_dependencies)', ], 'export_dependent_settings': [ - '<@(mojom_typemap_dependencies)', '<@(wtf_dependencies)', ], 'include_dirs': [ diff --git a/chromium/mojo/mojom_bindings_generator_explicit.gypi b/chromium/mojo/mojom_bindings_generator_explicit.gypi index e3bb2e84552..06e831040ae 100644 --- a/chromium/mojo/mojom_bindings_generator_explicit.gypi +++ b/chromium/mojo/mojom_bindings_generator_explicit.gypi @@ -8,38 +8,43 @@ ], 'variables': { 'variables': { - 'mojom_variant%': 'none', + 'variables': { + 'for_blink%': 'false', + }, 'for_blink%': 'false', + 'conditions': [ + ['for_blink=="true"', { + 'mojom_output_languages%': 'c++', + 'mojom_variant%': 'blink', + 'mojom_generator_wtf_arg%': [ + '--for_blink', + ], + 'wtf_dependencies%': [ + '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support', + '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf', + ], + }, { + 'mojom_output_languages%': 'c++,javascript,java', + 'mojom_variant%': 'none', + 'mojom_generator_wtf_arg%': [], + 'wtf_dependencies%': [], + }], + ], }, - 'mojom_variant%': '<(mojom_variant)', 'for_blink%': '<(for_blink)', + 'mojom_variant%': '<(mojom_variant)', + 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)', + 'wtf_dependencies%': '<(wtf_dependencies)', + 'mojom_output_languages%': '<(mojom_output_languages)', + 'mojom_typemaps%': [], 'mojom_base_output_dir': '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))', 'mojom_generated_outputs': [ '<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_list_outputs.py --basedir <(mojom_base_output_dir) --variant <(mojom_variant) <@(mojom_files))', ], + 'generated_typemap_file': '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(_target_name)_type_mappings', 'mojom_include_path%': '<(DEPTH)', - 'mojom_extra_generator_args%': [], 'require_interface_bindings%': 1, - 'conditions': [ - ['mojom_variant=="none"', { - 'mojom_output_languages%': 'c++,javascript,java', - }, { - 'mojom_output_languages%': 'c++', - }], - ['for_blink=="true"', { - 'mojom_generator_wtf_arg%': [ - '--for_blink', - ], - 'wtf_dependencies%': [ - '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support', - '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf', - ], - }, { - 'mojom_generator_wtf_arg%': [], - 'wtf_dependencies%': [], - }], - ], }, # Given mojom files as inputs, generate sources. These sources will be # exported to another target (via dependent_settings) to be compiled. This @@ -65,6 +70,22 @@ 'outputs': [ '<(stamp_filename)' ], }, { + 'variables': { + 'output': '<(generated_typemap_file)', + }, + 'action_name': '<(_target_name)_type_mappings', + 'action': [ + 'python', '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py', + '--output', + '<(output)', + '<!@(python <(DEPTH)/mojo/public/tools/bindings/format_typemap_generator_args.py <@(mojom_typemaps))', + ], + 'inputs':[ + '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py', + ], + 'outputs': [ '<(output)' ], + }, + { 'action_name': '<(_target_name)_mojom_bindings_generator', 'variables': { 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src', @@ -79,6 +100,7 @@ '<@(mojom_bindings_generator_sources)', '<@(mojom_files)', '<(stamp_filename)', + '<(generated_typemap_file)', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/cpp_templates.zip', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/java_templates.zip', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/js_templates.zip', @@ -96,7 +118,8 @@ '--java_output_directory=<(java_out_dir)', '--variant', '<(mojom_variant)', '-g', '<(mojom_output_languages)', - '<@(mojom_extra_generator_args)', + '--typemap', + '<(generated_typemap_file)', '<@(mojom_generator_wtf_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', diff --git a/chromium/mojo/public/OWNERS b/chromium/mojo/public/OWNERS deleted file mode 100644 index 557fed88780..00000000000 --- a/chromium/mojo/public/OWNERS +++ /dev/null @@ -1 +0,0 @@ -yzshen@chromium.org diff --git a/chromium/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h b/chromium/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h index 5eebe552374..363a77197b1 100644 --- a/chromium/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h +++ b/chromium/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h @@ -262,31 +262,6 @@ VISIT_GL_CALL(BindUniformLocationCHROMIUM, void, (GLuint program, GLint location, const char* name), (program, location, name)) -VISIT_GL_CALL(GenValuebuffersCHROMIUM, - void, - (GLsizei n, GLuint* buffers), - (n, buffers)) -VISIT_GL_CALL(DeleteValuebuffersCHROMIUM, - void, - (GLsizei n, const GLuint* valuebuffers), - (n, valuebuffers)) -VISIT_GL_CALL(IsValuebufferCHROMIUM, - GLboolean, - (GLuint valuebuffer), - (valuebuffer)) -VISIT_GL_CALL(BindValuebufferCHROMIUM, - void, - (GLenum target, GLuint valuebuffer), - (target, valuebuffer)) -VISIT_GL_CALL(SubscribeValueCHROMIUM, - void, - (GLenum target, GLenum subscription), - (target, subscription)) -VISIT_GL_CALL(PopulateSubscribedValuesCHROMIUM, void, (GLenum target), (target)) -VISIT_GL_CALL(UniformValuebufferCHROMIUM, - void, - (GLint location, GLenum target, GLenum subscription), - (location, target, subscription)) VISIT_GL_CALL(BindTexImage2DCHROMIUM, void, (GLenum target, GLint imageId), @@ -365,7 +340,8 @@ VISIT_GL_CALL(ScheduleCALayerCHROMIUM, GLboolean is_clipped, const GLfloat* clip_rect, GLint sorting_context_id, - const GLfloat* transform), + const GLfloat* transform, + GLuint filter), (contents_texture_id, contents_rect, opacity, @@ -375,7 +351,8 @@ VISIT_GL_CALL(ScheduleCALayerCHROMIUM, is_clipped, clip_rect, sorting_context_id, - transform)) + transform, + filter)) VISIT_GL_CALL(CommitOverlayPlanesCHROMIUM, void, (), ()) VISIT_GL_CALL(SwapInterval, void, (GLint interval), (interval)) VISIT_GL_CALL(FlushDriverCachesCHROMIUM, void, (), ()) diff --git a/chromium/mojo/public/c/system/message_pipe.h b/chromium/mojo/public/c/system/message_pipe.h index 8c5c215eafa..d41e107a992 100644 --- a/chromium/mojo/public/c/system/message_pipe.h +++ b/chromium/mojo/public/c/system/message_pipe.h @@ -15,6 +15,18 @@ #include "mojo/public/c/system/system_export.h" #include "mojo/public/c/system/types.h" +// |MojoMessageHandle|: Used to refer to message objects created by +// |MojoAllocMessage()| and transferred by |MojoWriteMessageNew()| or +// |MojoReadMessageNew()|. + +typedef uintptr_t MojoMessageHandle; + +#ifdef __cplusplus +const MojoMessageHandle MOJO_MESSAGE_HANDLE_INVALID = 0; +#else +#define MOJO_MESSAGE_HANDLE_INVALID ((MojoMessageHandle)0) +#endif + // |MojoCreateMessagePipeOptions|: Used to specify creation parameters for a // message pipe to |MojoCreateMessagePipe()|. // |uint32_t struct_size|: Set to the size of the @@ -23,23 +35,15 @@ // |MojoCreateMessagePipeOptionsFlags flags|: Used to specify different modes // of operation. // |MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode. -// |MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE|: The message pipe -// can be sent over another pipe after it's been read, written or -// waited. This mode makes message pipes use more resources (one OS -// pipe each), so only specify if this functionality is required. typedef uint32_t MojoCreateMessagePipeOptionsFlags; #ifdef __cplusplus const MojoCreateMessagePipeOptionsFlags MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE = 0; -const MojoCreateMessagePipeOptionsFlags - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE = 1; #else #define MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE \ ((MojoCreateMessagePipeOptionsFlags)0) -#define MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE \ - ((MojoCreateMessagePipeOptionsFlags)1) #endif MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); @@ -79,6 +83,18 @@ const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0; #define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags)1 << 0) #endif +// |MojoAllocMessageFlags|: Used to specify different options for +// |MojoAllocMessage()|. +// |MOJO_ALLOC_MESSAGE_FLAG_NONE| - No flags; default mode. + +typedef uint32_t MojoAllocMessageFlags; + +#ifdef __cplusplus +const MojoAllocMessageFlags MOJO_ALLOC_MESSAGE_FLAG_NONE = 0; +#else +#define MOJO_ALLOC_MESSAGE_FLAG_NONE ((MojoAllocMessageFlags)0) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -113,7 +129,7 @@ MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe( // |num_bytes| must be zero. If there are no attached handles, |handles| may be // null, in which case |num_handles| must be zero. // -// If handles are attached, on success the handles will no longer be valid (the +// If handles are attached, the handles will no longer be valid (on success the // receiver will receive equivalent, but logically different, handles). Handles // to be sent should not be in simultaneous use (e.g., on another thread). // @@ -142,6 +158,17 @@ MOJO_SYSTEM_EXPORT MojoResult uint32_t num_handles, MojoWriteMessageFlags flags); +// Writes a message to the message pipe endpoint given by |message_pipe_handle|. +// +// |message|: A message object allocated by |MojoAllocMessage()|. Ownership of +// the message is passed into Mojo. +// +// Returns results corresponding to |MojoWriteMessage()| above. +MOJO_SYSTEM_EXPORT MojoResult + MojoWriteMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags); + // Reads the next message from a message pipe, or indicates the size of the // message if it cannot fit in the provided buffers. The message will be read // in its entirety or not at all; if it is not, it will remain enqueued unless @@ -181,6 +208,30 @@ MOJO_SYSTEM_EXPORT MojoResult uint32_t* num_handles, // Optional in/out. MojoReadMessageFlags flags); +// Reads the next message from a message pipe and returns a message containing +// the message bytes. The returned message must eventually be freed using +// |MojoFreeMessage()|. +// +// Message payload can be accessed using |MojoGetMessageBuffer()|. +// +// |message_pipe_handle|, |num_bytes|, |handles|, |num_handles|, and |flags| +// correspond to their use in |MojoReadMessage()| above, with the +// exception that |num_bytes| is only an output argument. +// |message| must be non-null unless |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| is +// set in flags. +// +// Return values correspond to the return values for |MojoReadMessage()| above. +// On success (MOJO_RESULT_OK), |*message| will contain a handle to a message +// object which may be passed to |MojoGetMessageBuffer()|. The caller owns the +// message object and is responsible for freeing it via |MojoFreeMessage()|. +MOJO_SYSTEM_EXPORT MojoResult + MojoReadMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle* message, // Optional out. + uint32_t* num_bytes, // Optional out. + MojoHandle* handles, // Optional out. + uint32_t* num_handles, // Optional in/out. + MojoReadMessageFlags flags); + // Fuses two message pipe endpoints together. Given two pipes: // // A <-> B and C <-> D @@ -205,6 +256,62 @@ MOJO_SYSTEM_EXPORT MojoResult MOJO_SYSTEM_EXPORT MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1); +// Allocates a new message whose ownership may be passed to +// |MojoWriteMessageNew()|. Use |MojoGetMessageBuffer()| to retrieve the address +// of the mutable message payload. +// +// |num_bytes|: The size of the message payload in bytes. +// |handles|: An array of handles to transfer in the message. This takes +// ownership of and invalidates all contained handles. Must be null if and +// only if |num_handles| is 0. +// |num_handles|: The number of handles contained in |handles|. +// |flags|: Must be |MOJO_CREATE_MESSAGE_FLAG_NONE|. +// |message|: The address of a handle to be filled with the allocated message's +// handle. Must be non-null. +// +// Returns: +// |MOJO_RESULT_OK| if the message was successfully allocated. In this case +// |*message| will be populated with a handle to an allocated message +// with a buffer large enough to hold |num_bytes| contiguous bytes. +// |MOJO_RESULT_INVALID_ARGUMENT| if one or more handles in |handles| was +// invalid, or |handles| was null with a non-zero |num_handles|. +// |MOJO_RESULT_RESOURCE_EXHAUSTED| if allocation failed because either +// |num_bytes| or |num_handles| exceeds an implementation-defined maximum. +// |MOJO_RESULT_BUSY| if one or more handles in |handles| cannot be sent at +// the time of this call. +// +// Only upon successful message allocation will all handles in |handles| be +// transferred into the message and invalidated. +MOJO_SYSTEM_EXPORT MojoResult +MojoAllocMessage(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message); // Out + +// Frees a message allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. +// +// |message|: The message to free. This must correspond to a message previously +// allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. Note that if +// the message has already been passed to |MojoWriteMessageNew()| it should +// NOT also be freed with this API. +// +// Returns: +// |MOJO_RESULT_OK| if |message| was valid and has been freed. +// |MOJO_RESULT_INVALID_ARGUMENT| if |message| was not a valid message. +MOJO_SYSTEM_EXPORT MojoResult MojoFreeMessage(MojoMessageHandle message); + +// Retrieves the address of mutable message bytes for a message allocated by +// either |MojoAllocMessage()| or |MojoReadMessageNew()|. +// +// Returns: +// |MOJO_RESULT_OK| if |message| is a valid message object. |*buffer| will +// be updated to point to mutable message bytes. +// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object. +// +// NOTE: A returned buffer address is always guaranteed to be 8-byte aligned. +MOJO_SYSTEM_EXPORT MojoResult MojoGetMessageBuffer(MojoMessageHandle message, + void** buffer); // Out #ifdef __cplusplus } // extern "C" diff --git a/chromium/mojo/public/c/test_support/BUILD.gn b/chromium/mojo/public/c/test_support/BUILD.gn index 592e80a63bd..75d9c13d346 100644 --- a/chromium/mojo/public/c/test_support/BUILD.gn +++ b/chromium/mojo/public/c/test_support/BUILD.gn @@ -2,24 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# GYP version: mojo/public/mojo_public.gyp:mojo_test_support -shared_library("test_support") { +# GYP version: mojo/mojo_public.gyp:mojo_test_support +static_library("test_support") { output_name = "mojo_public_test_support" - defines = [ "MOJO_TEST_SUPPORT_IMPLEMENTATION" ] - sources = [ "test_support.h", - "test_support_export.h", # TODO(vtl): Convert this to thunks http://crbug.com/386799 "../../tests/test_support_private.cc", "../../tests/test_support_private.h", ] - - if (is_mac) { - # TODO(GYP) - # # Make it a run-path dependent library. - # 'DYLIB_INSTALL_NAME_BASE': '@loader_path', - } } diff --git a/chromium/mojo/public/c/test_support/test_support.h b/chromium/mojo/public/c/test_support/test_support.h index 73a2eefac2e..8e50441d68c 100644 --- a/chromium/mojo/public/c/test_support/test_support.h +++ b/chromium/mojo/public/c/test_support/test_support.h @@ -9,8 +9,6 @@ #include <stdio.h> -#include "mojo/public/c/test_support/test_support_export.h" - #ifdef __cplusplus extern "C" { #endif @@ -21,14 +19,14 @@ extern "C" { // When the perf data is visualized by the performance dashboard, data with // different |sub_test_name|s (but the same |test_name|) are depicted as // different traces on the same chart. -MOJO_TEST_SUPPORT_EXPORT void MojoTestSupportLogPerfResult( +void MojoTestSupportLogPerfResult( const char* test_name, const char* sub_test_name, double value, const char* units); // Opens a "/"-delimited file path relative to the source root. -MOJO_TEST_SUPPORT_EXPORT FILE* MojoTestSupportOpenSourceRootRelativeFile( +FILE* MojoTestSupportOpenSourceRootRelativeFile( const char* source_root_relative_path); // Enumerates a "/"-delimited directory path relative to the source root. @@ -44,7 +42,6 @@ MOJO_TEST_SUPPORT_EXPORT FILE* MojoTestSupportOpenSourceRootRelativeFile( // ... // rv[N] = NULL; // -MOJO_TEST_SUPPORT_EXPORT char** MojoTestSupportEnumerateSourceRootRelativeDirectory( const char* source_root_relative_path); diff --git a/chromium/mojo/public/c/test_support/test_support_export.h b/chromium/mojo/public/c/test_support/test_support_export.h deleted file mode 100644 index e22a9e30144..00000000000 --- a/chromium/mojo/public/c/test_support/test_support_export.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_ -#define MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_ - -#if defined(WIN32) - -#if defined(MOJO_TEST_SUPPORT_IMPLEMENTATION) -#define MOJO_TEST_SUPPORT_EXPORT __declspec(dllexport) -#else -#define MOJO_TEST_SUPPORT_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_TEST_SUPPORT_IMPLEMENTATION) -#define MOJO_TEST_SUPPORT_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_TEST_SUPPORT_EXPORT -#endif - -#endif // defined(WIN32) - -#endif // MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_ diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn index c8d2883d0c7..c66853cf8e5 100644 --- a/chromium/mojo/public/cpp/bindings/BUILD.gn +++ b/chromium/mojo/public/cpp/bindings/BUILD.gn @@ -5,6 +5,9 @@ source_set("bindings") { sources = [ "array.h", + "array_traits.h", + "array_traits_standard.h", + "array_traits_stl.h", "associated_binding.h", "associated_group.h", "associated_interface_ptr.h", @@ -19,13 +22,10 @@ source_set("bindings") { "lib/array_internal.cc", "lib/array_internal.h", "lib/array_serialization.h", - "lib/array_serialization_traits.h", "lib/associated_group.cc", "lib/associated_interface_ptr_state.h", "lib/binding_state.h", "lib/bindings_internal.h", - "lib/bindings_serialization.cc", - "lib/bindings_serialization.h", "lib/bounds_checker.cc", "lib/bounds_checker.h", "lib/buffer.h", @@ -44,11 +44,12 @@ source_set("bindings") { "lib/interface_endpoint_controller.h", "lib/interface_id.h", "lib/interface_ptr_state.h", - "lib/macros.h", "lib/map_data_internal.h", "lib/map_internal.h", "lib/map_serialization.h", "lib/message.cc", + "lib/message_buffer.cc", + "lib/message_buffer.h", "lib/message_builder.cc", "lib/message_builder.h", "lib/message_filter.cc", @@ -57,9 +58,12 @@ source_set("bindings") { "lib/message_internal.h", "lib/multiplex_router.cc", "lib/multiplex_router.h", + "lib/native_struct.cc", + "lib/native_struct_data.cc", + "lib/native_struct_data.h", + "lib/native_struct_serialization.cc", + "lib/native_struct_serialization.h", "lib/no_interface.cc", - "lib/pickle_buffer.cc", - "lib/pickle_buffer.h", "lib/pipe_control_message_handler.cc", "lib/pipe_control_message_handler.h", "lib/pipe_control_message_handler_delegate.h", @@ -68,11 +72,14 @@ source_set("bindings") { "lib/router.cc", "lib/router.h", "lib/scoped_interface_endpoint_handle.cc", - "lib/scoped_interface_endpoint_handle.h", "lib/serialization.h", + "lib/serialization_context.cc", + "lib/serialization_context.h", "lib/serialization_forward.h", - "lib/string_serialization.cc", + "lib/serialization_util.cc", + "lib/serialization_util.h", "lib/string_serialization.h", + "lib/string_traits_string16.cc", "lib/sync_handle_registry.cc", "lib/sync_handle_registry.h", "lib/sync_handle_watcher.cc", @@ -84,24 +91,27 @@ source_set("bindings") { "lib/validation_util.cc", "lib/validation_util.h", "lib/value_traits.h", - - # Include the .h but not the .cc file. The .h file is used by - # serialization_forward.h. - "lib/wtf_string_serialization.h", "map.h", "message.h", "message_filter.h", + "native_struct.h", "no_interface.h", + "scoped_interface_endpoint_handle.h", "stl_converters.h", "string.h", + "string_traits.h", + "string_traits_standard.h", + "string_traits_stl.h", + "string_traits_string16.h", + "string_traits_string_piece.h", "strong_binding.h", "struct_ptr.h", - "struct_traits.h", "type_converter.h", ] public_deps = [ ":callback", + ":struct_traits", "//base", "//ipc:param_traits", "//mojo/public/cpp/system", @@ -128,12 +138,19 @@ source_set("callback") { ] } +source_set("struct_traits") { + sources = [ + "struct_traits.h", + ] +} + source_set("wtf_support") { sources = [ - "lib/wtf_array_serialization.h", + "array_traits_wtf.h", + "array_traits_wtf_vector.h", + "lib/string_traits_wtf.cc", "lib/wtf_serialization.h", - "lib/wtf_string_serialization.cc", - "lib/wtf_string_serialization.h", + "string_traits_wtf.h", "wtf_array.h", ] diff --git a/chromium/mojo/public/cpp/bindings/array.h b/chromium/mojo/public/cpp/bindings/array.h index e9bd6838412..d94feb0768c 100644 --- a/chromium/mojo/public/cpp/bindings/array.h +++ b/chromium/mojo/public/cpp/bindings/array.h @@ -30,10 +30,10 @@ class Array { public: using ConstRefType = typename std::vector<T>::const_reference; using RefType = typename std::vector<T>::reference; - using ElementType = T; - using Data_ = - internal::Array_Data<typename internal::WrapperTraits<T>::DataType>; + using Element = T; + using Data_ = internal::Array_Data< + typename internal::GetDataTypeAsArrayElement<T>::Data>; using iterator = typename std::vector<T>::iterator; using const_iterator = typename std::vector<T>::const_iterator; diff --git a/chromium/mojo/public/cpp/bindings/array_traits.h b/chromium/mojo/public/cpp/bindings/array_traits.h new file mode 100644 index 00000000000..c9512fbfd51 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/array_traits.h @@ -0,0 +1,41 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ + +namespace mojo { + +// This must be specialized for any type |T| to be serialized/deserialized as +// a mojom array. +// +// Usually you would like to do a partial specialization for an array/vector +// template. Imagine you want to specialize it for CustomArray<>, you need to +// implement: +// +// template <typename T> +// struct ArrayTraits<CustomArray<T>> { +// using Element = T; +// +// // These two methods are optional. Please see comments in struct_traits.h +// static bool IsNull(const CustomArray<T>& input); +// static void SetToNull(CustomArray<T>* output); +// +// static size_t GetSize(const CustomArray<T>& input); +// +// static T* GetData(CustomArray<T>& input); +// static const T* GetData(const CustomArray<T>& input); +// +// static T& GetAt(CustomArray<T>& input, size_t index); +// static const T& GetAt(const CustomArray<T>& input, size_t index); +// +// static void Resize(CustomArray<T>& input, size_t size); +// }; +// +template <typename T> +struct ArrayTraits; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/bindings/array_traits_standard.h b/chromium/mojo/public/cpp/bindings/array_traits_standard.h new file mode 100644 index 00000000000..7ee4bd2661a --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/array_traits_standard.h @@ -0,0 +1,40 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STANDARD_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STANDARD_H_ + +#include "mojo/public/cpp/bindings/array.h" +#include "mojo/public/cpp/bindings/array_traits.h" + +namespace mojo { + +template <typename T> +struct ArrayTraits<Array<T>> { + using Element = T; + + static bool IsNull(const Array<T>& input) { return input.is_null(); } + static void SetToNull(Array<T>* output) { *output = nullptr; } + + static size_t GetSize(const Array<T>& input) { return input.size(); } + + static T* GetData(Array<T>& input) { return &input.front(); } + + static const T* GetData(const Array<T>& input) { return &input.front(); } + + static typename Array<T>::RefType GetAt(Array<T>& input, size_t index) { + return input[index]; + } + + static typename Array<T>::ConstRefType GetAt(const Array<T>& input, + size_t index) { + return input[index]; + } + + static void Resize(Array<T>& input, size_t size) { input.resize(size); } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STANDARD_H_ diff --git a/chromium/mojo/public/cpp/bindings/array_traits_stl.h b/chromium/mojo/public/cpp/bindings/array_traits_stl.h new file mode 100644 index 00000000000..f78ae2f84cb --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/array_traits_stl.h @@ -0,0 +1,50 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ + +#include <vector> + +#include "mojo/public/cpp/bindings/array_traits.h" + +namespace mojo { + +template <typename T> +struct ArrayTraits<std::vector<T>> { + using Element = T; + + static bool IsNull(const std::vector<T>& input) { + // std::vector<> is always converted to non-null mojom array. + return false; + } + + static void SetToNull(std::vector<T>* output) { + // std::vector<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const std::vector<T>& input) { return input.size(); } + + static T* GetData(std::vector<T>& input) { return input.data(); } + + static const T* GetData(const std::vector<T>& input) { return input.data(); } + + static typename std::vector<T>::reference GetAt(std::vector<T>& input, + size_t index) { + return input[index]; + } + + static typename std::vector<T>::const_reference GetAt( + const std::vector<T>& input, + size_t index) { + return input[index]; + } + + static void Resize(std::vector<T>& input, size_t size) { input.resize(size); } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ diff --git a/chromium/mojo/public/cpp/bindings/array_traits_wtf.h b/chromium/mojo/public/cpp/bindings/array_traits_wtf.h new file mode 100644 index 00000000000..71f1da1116a --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/array_traits_wtf.h @@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_ + +#include "mojo/public/cpp/bindings/array_traits.h" +#include "mojo/public/cpp/bindings/wtf_array.h" + +namespace mojo { + +template <typename U> +struct ArrayTraits<WTFArray<U>> { + using Element = U; + + static bool IsNull(const WTFArray<U>& input) { return input.is_null(); } + static void SetToNull(WTFArray<U>* output) { *output = nullptr; } + + static size_t GetSize(const WTFArray<U>& input) { return input.size(); } + + static U* GetData(WTFArray<U>& input) { return &input.front(); } + + static const U* GetData(const WTFArray<U>& input) { return &input.front(); } + + static U& GetAt(WTFArray<U>& input, size_t index) { return input[index]; } + + static const U& GetAt(const WTFArray<U>& input, size_t index) { + return input[index]; + } + + static void Resize(WTFArray<U>& input, size_t size) { input.resize(size); } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_ diff --git a/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h b/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h new file mode 100644 index 00000000000..9b3755ad4f1 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h @@ -0,0 +1,44 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ + +#include "mojo/public/cpp/bindings/array_traits.h" +#include "third_party/WebKit/Source/wtf/Vector.h" + +namespace mojo { + +template <typename U> +struct ArrayTraits<WTF::Vector<U>> { + using Element = U; + + static bool IsNull(const WTF::Vector<U>& input) { + // WTF::Vector<> is always converted to non-null mojom array. + return false; + } + + static void SetToNull(WTF::Vector<U>* output) { + // WTF::Vector<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const WTF::Vector<U>& input) { return input.size(); } + + static U* GetData(WTF::Vector<U>& input) { return input.data(); } + + static const U* GetData(const WTF::Vector<U>& input) { return input.data(); } + + static U& GetAt(WTF::Vector<U>& input, size_t index) { return input[index]; } + + static const U& GetAt(const WTF::Vector<U>& input, size_t index) { + return input[index]; + } + + static void Resize(WTF::Vector<U>& input, size_t size) { input.resize(size); } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ diff --git a/chromium/mojo/public/cpp/bindings/associated_binding.h b/chromium/mojo/public/cpp/bindings/associated_binding.h index a7263635fef..2d4e3392230 100644 --- a/chromium/mojo/public/cpp/bindings/associated_binding.h +++ b/chromium/mojo/public/cpp/bindings/associated_binding.h @@ -5,21 +5,33 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ +#include <memory> #include <utility> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_interface_request.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { // Represents the implementation side of an associated interface. It is similar // to Binding, except that it doesn't own a message pipe handle. +// +// When you bind this class to a request, optionally you can specify a +// base::SingleThreadTaskRunner. This task runner must belong to the same +// thread. It will be used to dispatch incoming method calls and connection +// error notification. It is useful when you attach multiple task runners to a +// single thread for the purposes of task scheduling. Please note that incoming +// synchrounous method calls may not be run from this task runner, when they +// reenter outgoing synchrounous calls on the same thread. template <typename Interface> class AssociatedBinding { public: @@ -37,17 +49,21 @@ class AssociatedBinding { // pointer. |impl| must outlive this object. AssociatedBinding(Interface* impl, AssociatedInterfacePtrInfo<Interface>* ptr_info, - AssociatedGroup* associated_group) + AssociatedGroup* associated_group, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) : AssociatedBinding(impl) { - Bind(ptr_info, associated_group); + Bind(ptr_info, associated_group, std::move(runner)); } // Constructs a completed associated binding of |impl|. |impl| must outlive // the binding. AssociatedBinding(Interface* impl, - AssociatedInterfaceRequest<Interface> request) + AssociatedInterfaceRequest<Interface> request, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) : AssociatedBinding(impl) { - Bind(std::move(request)); + Bind(std::move(request), std::move(runner)); } ~AssociatedBinding() {} @@ -57,17 +73,20 @@ class AssociatedBinding { // message pipe endpoint referred to by |associated_group| to setup the // corresponding asssociated interface pointer. void Bind(AssociatedInterfacePtrInfo<Interface>* ptr_info, - AssociatedGroup* associated_group) { + AssociatedGroup* associated_group, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { AssociatedInterfaceRequest<Interface> request; associated_group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_PTR, ptr_info, &request); - Bind(std::move(request)); + Bind(std::move(request), std::move(runner)); } // Sets up this object as the implementation side of an associated interface. - void Bind(AssociatedInterfaceRequest<Interface> request) { - internal::ScopedInterfaceEndpointHandle handle = - internal::AssociatedInterfaceRequestHelper::PassHandle(&request); + void Bind(AssociatedInterfaceRequest<Interface> request, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { + ScopedInterfaceEndpointHandle handle = request.PassHandle(); DCHECK(handle.is_local()) << "The AssociatedInterfaceRequest is supposed to be used at the " @@ -80,8 +99,8 @@ class AssociatedBinding { endpoint_client_.reset(new internal::InterfaceEndpointClient( std::move(handle), &stub_, - make_scoped_ptr(new typename Interface::RequestValidator_()), - Interface::HasSyncMethods_)); + base::WrapUnique(new typename Interface::RequestValidator_()), + Interface::HasSyncMethods_, std::move(runner))); endpoint_client_->set_connection_error_handler( [this]() { connection_error_handler_.Run(); }); @@ -103,8 +122,7 @@ class AssociatedBinding { DCHECK(endpoint_client_); AssociatedInterfaceRequest<Interface> request; - internal::AssociatedInterfaceRequestHelper::SetHandle( - &request, endpoint_client_->PassHandle()); + request.Bind(endpoint_client_->PassHandle()); endpoint_client_.reset(); connection_error_handler_.reset(); @@ -135,7 +153,7 @@ class AssociatedBinding { } private: - scoped_ptr<internal::InterfaceEndpointClient> endpoint_client_; + std::unique_ptr<internal::InterfaceEndpointClient> endpoint_client_; typename Interface::Stub_ stub_; Interface* impl_; diff --git a/chromium/mojo/public/cpp/bindings/associated_group.h b/chromium/mojo/public/cpp/bindings/associated_group.h index ea3b5a16265..5f7a39632a4 100644 --- a/chromium/mojo/public/cpp/bindings/associated_group.h +++ b/chromium/mojo/public/cpp/bindings/associated_group.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" #include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { @@ -50,8 +50,8 @@ class AssociatedGroup { AssociatedInterfaceConfig config, AssociatedInterfacePtrInfo<T>* ptr_info, AssociatedInterfaceRequest<T>* request) { - internal::ScopedInterfaceEndpointHandle local; - internal::ScopedInterfaceEndpointHandle remote; + ScopedInterfaceEndpointHandle local; + ScopedInterfaceEndpointHandle remote; CreateEndpointHandlePair(&local, &remote); if (!local.is_valid() || !remote.is_valid()) { @@ -61,21 +61,19 @@ class AssociatedGroup { } if (config == WILL_PASS_PTR) { - internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info, - std::move(remote)); + ptr_info->set_handle(std::move(remote)); + // The implementation is local, therefore set the version according to // the interface definition that this code is built against. ptr_info->set_version(T::Version_); - internal::AssociatedInterfaceRequestHelper::SetHandle(request, - std::move(local)); + request->Bind(std::move(local)); } else { - internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info, - std::move(local)); + ptr_info->set_handle(std::move(local)); + // The implementation is remote, we don't know about its actual version // yet. ptr_info->set_version(0u); - internal::AssociatedInterfaceRequestHelper::SetHandle(request, - std::move(remote)); + request->Bind(std::move(remote)); } } @@ -83,8 +81,8 @@ class AssociatedGroup { friend class internal::MultiplexRouter; void CreateEndpointHandlePair( - internal::ScopedInterfaceEndpointHandle* local_endpoint, - internal::ScopedInterfaceEndpointHandle* remote_endpoint); + ScopedInterfaceEndpointHandle* local_endpoint, + ScopedInterfaceEndpointHandle* remote_endpoint); scoped_refptr<internal::MultiplexRouter> router_; }; diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h index 48caad654e3..c4435ee599b 100644 --- a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h +++ b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h @@ -10,6 +10,9 @@ #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" #include "mojo/public/cpp/bindings/associated_interface_request.h" @@ -52,20 +55,26 @@ class AssociatedInterfacePtr { // Calling with an invalid |info| has the same effect as reset(). In this // case, the AssociatedInterfacePtr is not considered as bound. // + // |runner| must belong to the same thread. It will be used to dispatch all + // callbacks and connection error notification. It is useful when you attach + // multiple task runners to a single thread for the purposes of task + // scheduling. + // // NOTE: Please see the comments of // AssociatedGroup.CreateAssociatedInterface() about when you can use this // object to make calls. - void Bind(AssociatedInterfacePtrInfo<Interface> info) { + void Bind(AssociatedInterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { reset(); - bool is_local = - internal::AssociatedInterfacePtrInfoHelper::GetHandle(&info).is_local(); + bool is_local = info.handle().is_local(); DCHECK(is_local) << "The AssociatedInterfacePtrInfo is supposed to be used " "at the other side of the message pipe."; if (info.is_valid() && is_local) - internal_state_.Bind(std::move(info)); + internal_state_.Bind(std::move(info), std::move(runner)); } bool is_bound() const { return internal_state_.is_bound(); } @@ -181,13 +190,15 @@ class AssociatedInterfacePtr { template <typename Interface> AssociatedInterfaceRequest<Interface> GetProxy( AssociatedInterfacePtr<Interface>* ptr, - AssociatedGroup* group) { + AssociatedGroup* group, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { AssociatedInterfaceRequest<Interface> request; AssociatedInterfacePtrInfo<Interface> ptr_info; group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_REQUEST, &ptr_info, &request); - ptr->Bind(std::move(ptr_info)); + ptr->Bind(std::move(ptr_info), std::move(runner)); return request; } diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_ptr_info.h b/chromium/mojo/public/cpp/bindings/associated_interface_ptr_info.h index 8340eeade62..a393bcea1d7 100644 --- a/chromium/mojo/public/cpp/bindings/associated_interface_ptr_info.h +++ b/chromium/mojo/public/cpp/bindings/associated_interface_ptr_info.h @@ -9,14 +9,10 @@ #include <utility> #include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { -namespace internal { -class AssociatedInterfacePtrInfoHelper; -} - // AssociatedInterfacePtrInfo stores necessary information to construct an // associated interface pointer. It is similar to InterfacePtrInfo except that // it doesn't own a message pipe handle. @@ -32,6 +28,10 @@ class AssociatedInterfacePtrInfo { other.version_ = 0u; } + AssociatedInterfacePtrInfo(ScopedInterfaceEndpointHandle handle, + uint32_t version) + : handle_(std::move(handle)), version_(version) {} + ~AssociatedInterfacePtrInfo() {} AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) { @@ -46,43 +46,22 @@ class AssociatedInterfacePtrInfo { bool is_valid() const { return handle_.is_valid(); } + ScopedInterfaceEndpointHandle PassHandle() { + return std::move(handle_); + } + const ScopedInterfaceEndpointHandle& handle() const { return handle_; } + void set_handle(ScopedInterfaceEndpointHandle handle) { + handle_ = std::move(handle); + } + uint32_t version() const { return version_; } void set_version(uint32_t version) { version_ = version; } private: - friend class internal::AssociatedInterfacePtrInfoHelper; - - internal::ScopedInterfaceEndpointHandle handle_; + ScopedInterfaceEndpointHandle handle_; uint32_t version_; }; -namespace internal { - -// With this helper, AssociatedInterfacePtrInfo doesn't have to expose any -// operations related to ScopedInterfaceEndpointHandle, which is an internal -// class. -class AssociatedInterfacePtrInfoHelper { - public: - template <typename Interface> - static ScopedInterfaceEndpointHandle PassHandle( - AssociatedInterfacePtrInfo<Interface>* info) { - return std::move(info->handle_); - } - - template <typename Interface> - static const ScopedInterfaceEndpointHandle& GetHandle( - AssociatedInterfacePtrInfo<Interface>* info) { - return info->handle_; - } - - template <typename Interface> - static void SetHandle(AssociatedInterfacePtrInfo<Interface>* info, - ScopedInterfaceEndpointHandle handle) { - info->handle_ = std::move(handle); - } -}; - -} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_request.h b/chromium/mojo/public/cpp/bindings/associated_interface_request.h index 36cbe3eb48c..a7a7f662166 100644 --- a/chromium/mojo/public/cpp/bindings/associated_interface_request.h +++ b/chromium/mojo/public/cpp/bindings/associated_interface_request.h @@ -8,14 +8,10 @@ #include <utility> #include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { -namespace internal { -class AssociatedInterfaceRequestHelper; -} - // AssociatedInterfaceRequest represents an associated interface request. It is // similar to InterfaceRequest except that it doesn't own a message pipe handle. template <typename Interface> @@ -51,39 +47,30 @@ class AssociatedInterfaceRequest { // handle. bool is_pending() const { return handle_.is_valid(); } - private: - friend class internal::AssociatedInterfaceRequestHelper; - - internal::ScopedInterfaceEndpointHandle handle_; -}; - -namespace internal { - -// With this helper, AssociatedInterfaceRequest doesn't have to expose any -// operations related to ScopedInterfaceEndpointHandle, which is an internal -// class. -class AssociatedInterfaceRequestHelper { - public: - template <typename Interface> - static ScopedInterfaceEndpointHandle PassHandle( - AssociatedInterfaceRequest<Interface>* request) { - return std::move(request->handle_); + void Bind(ScopedInterfaceEndpointHandle handle) { + handle_ = std::move(handle); } - template <typename Interface> - static const ScopedInterfaceEndpointHandle& GetHandle( - AssociatedInterfaceRequest<Interface>* request) { - return request->handle_; + ScopedInterfaceEndpointHandle PassHandle() { + return std::move(handle_); } - template <typename Interface> - static void SetHandle(AssociatedInterfaceRequest<Interface>* request, - ScopedInterfaceEndpointHandle handle) { - request->handle_ = std::move(handle); - } + const ScopedInterfaceEndpointHandle& handle() const { return handle_; } + + private: + ScopedInterfaceEndpointHandle handle_; }; -} // namespace internal +// Makes an AssociatedInterfaceRequest bound to the specified associated +// endpoint. +template <typename Interface> +AssociatedInterfaceRequest<Interface> MakeAssociatedRequest( + ScopedInterfaceEndpointHandle handle) { + AssociatedInterfaceRequest<Interface> request; + request.Bind(std::move(handle)); + return request; +} + } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ diff --git a/chromium/mojo/public/cpp/bindings/binding.h b/chromium/mojo/public/cpp/bindings/binding.h index 68dd32239c4..84b4f90d62d 100644 --- a/chromium/mojo/public/cpp/bindings/binding.h +++ b/chromium/mojo/public/cpp/bindings/binding.h @@ -8,6 +8,9 @@ #include <utility> #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/cpp/bindings/interface_ptr_info.h" @@ -52,6 +55,14 @@ class AssociatedGroup; // class must be from the thread that bound it. The interface implementation's // methods will be called from the thread that bound this. If a Binding is not // bound to a message pipe, it may be bound or destroyed on any thread. +// +// When you bind this class to a message pipe, optionally you can specify a +// base::SingleThreadTaskRunner. This task runner must belong to the same +// thread. It will be used to dispatch incoming method calls and connection +// error notification. It is useful when you attach multiple task runners to a +// single thread for the purposes of task scheduling. Please note that incoming +// synchrounous method calls may not be run from this task runner, when they +// reenter outgoing synchrounous calls on the same thread. template <typename Interface> class Binding { public: @@ -62,8 +73,12 @@ class Binding { // Constructs a completed binding of message pipe |handle| to implementation // |impl|. Does not take ownership of |impl|, which must outlive the binding. - Binding(Interface* impl, ScopedMessagePipeHandle handle) : Binding(impl) { - Bind(std::move(handle)); + Binding(Interface* impl, + ScopedMessagePipeHandle handle, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) + : Binding(impl) { + Bind(std::move(handle), std::move(runner)); } // Constructs a completed binding of |impl| to a new message pipe, passing the @@ -71,16 +86,23 @@ class Binding { // pass |ptr| on to the client of the service. Does not take ownership of any // of the parameters. |impl| must outlive the binding. |ptr| only needs to // last until the constructor returns. - Binding(Interface* impl, InterfacePtr<Interface>* ptr) : Binding(impl) { - Bind(ptr); + Binding(Interface* impl, + InterfacePtr<Interface>* ptr, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) + : Binding(impl) { + Bind(ptr, std::move(runner)); } // Constructs a completed binding of |impl| to the message pipe endpoint in // |request|, taking ownership of the endpoint. Does not take ownership of // |impl|, which must outlive the binding. - Binding(Interface* impl, InterfaceRequest<Interface> request) + Binding(Interface* impl, + InterfaceRequest<Interface> request, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) : Binding(impl) { - Bind(request.PassMessagePipe()); + Bind(request.PassMessagePipe(), std::move(runner)); } // Tears down the binding, closing the message pipe and leaving the interface @@ -89,17 +111,21 @@ class Binding { // Returns an InterfacePtr bound to one end of a pipe whose other end is // bound to |this|. - InterfacePtr<Interface> CreateInterfacePtrAndBind() { + InterfacePtr<Interface> CreateInterfacePtrAndBind( + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { InterfacePtr<Interface> interface_ptr; - Bind(&interface_ptr); + Bind(&interface_ptr, std::move(runner)); return interface_ptr; } // Completes a binding that was constructed with only an interface // implementation. Takes ownership of |handle| and binds it to the previously // specified implementation. - void Bind(ScopedMessagePipeHandle handle) { - internal_state_.Bind(std::move(handle)); + void Bind(ScopedMessagePipeHandle handle, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { + internal_state_.Bind(std::move(handle), std::move(runner)); } // Completes a binding that was constructed with only an interface @@ -107,18 +133,23 @@ class Binding { // previously specified implementation, and passing the other to |ptr|, which // takes ownership of it. The caller is expected to pass |ptr| on to the // eventual client of the service. Does not take ownership of |ptr|. - void Bind(InterfacePtr<Interface>* ptr) { + void Bind(InterfacePtr<Interface>* ptr, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { MessagePipe pipe; ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), - Interface::Version_)); - Bind(std::move(pipe.handle1)); + Interface::Version_), + runner); + Bind(std::move(pipe.handle1), std::move(runner)); } // Completes a binding that was constructed with only an interface // implementation by removing the message pipe endpoint from |request| and // binding it to the previously specified implementation. - void Bind(InterfaceRequest<Interface> request) { - Bind(request.PassMessagePipe()); + void Bind(InterfaceRequest<Interface> request, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { + Bind(request.PassMessagePipe(), std::move(runner)); } // Whether there are any associated interfaces running on the pipe currently. diff --git a/chromium/mojo/public/cpp/bindings/callback.h b/chromium/mojo/public/cpp/bindings/callback.h index 91f37d03fef..c5e328927f4 100644 --- a/chromium/mojo/public/cpp/bindings/callback.h +++ b/chromium/mojo/public/cpp/bindings/callback.h @@ -5,11 +5,11 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_ #define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_ +#include <memory> #include <type_traits> #include <utility> #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/public/cpp/bindings/lib/callback_internal.h" #include "mojo/public/cpp/bindings/lib/template_util.h" @@ -143,7 +143,7 @@ class Callback<void(Args...)> { struct RunnableHolder : public base::RefCountedThreadSafe<RunnableHolder> { explicit RunnableHolder(Runnable* runnable) : runnable(runnable) {} - scoped_ptr<Runnable> runnable; + std::unique_ptr<Runnable> runnable; private: friend class base::RefCountedThreadSafe<RunnableHolder>; diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr.h b/chromium/mojo/public/cpp/bindings/interface_ptr.h index 9b005eee815..e427dc4668d 100644 --- a/chromium/mojo/public/cpp/bindings/interface_ptr.h +++ b/chromium/mojo/public/cpp/bindings/interface_ptr.h @@ -10,6 +10,9 @@ #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/interface_ptr_info.h" #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h" @@ -68,10 +71,17 @@ class InterfacePtr { // Calling with an invalid |info| (containing an invalid message pipe handle) // has the same effect as reset(). In this case, the InterfacePtr is not // considered as bound. - void Bind(InterfacePtrInfo<Interface> info) { + // + // |runner| must belong to the same thread. It will be used to dispatch all + // callbacks and connection error notification. It is useful when you attach + // multiple task runners to a single thread for the purposes of task + // scheduling. + void Bind(InterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { reset(); if (info.is_valid()) - internal_state_.Bind(std::move(info)); + internal_state_.Bind(std::move(info), std::move(runner)); } // Returns whether or not this InterfacePtr is bound to a message pipe. @@ -208,10 +218,13 @@ class InterfacePtr { // If |info| is valid (containing a valid message pipe handle), returns an // InterfacePtr bound to it. Otherwise, returns an unbound InterfacePtr. template <typename Interface> -InterfacePtr<Interface> MakeProxy(InterfacePtrInfo<Interface> info) { +InterfacePtr<Interface> MakeProxy( + InterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { InterfacePtr<Interface> ptr; if (info.is_valid()) - ptr.Bind(std::move(info)); + ptr.Bind(std::move(info), std::move(runner)); return std::move(ptr); } diff --git a/chromium/mojo/public/cpp/bindings/interface_request.h b/chromium/mojo/public/cpp/bindings/interface_request.h index 807cd5dc94c..3d6b27c0a0e 100644 --- a/chromium/mojo/public/cpp/bindings/interface_request.h +++ b/chromium/mojo/public/cpp/bindings/interface_request.h @@ -7,6 +7,8 @@ #include <utility> +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/interface_ptr.h" namespace mojo { @@ -111,9 +113,13 @@ InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) { // CreateSource(std::move(source_request)); // Create implementation locally. // template <typename Interface> -InterfaceRequest<Interface> GetProxy(InterfacePtr<Interface>* ptr) { +InterfaceRequest<Interface> GetProxy( + InterfacePtr<Interface>* ptr, + scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()) { MessagePipe pipe; - ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u)); + ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u), + std::move(runner)); return MakeRequest<Interface>(std::move(pipe.handle1)); } diff --git a/chromium/mojo/public/cpp/bindings/lib/TODO b/chromium/mojo/public/cpp/bindings/lib/TODO deleted file mode 100644 index ea4ce81a2f4..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/TODO +++ /dev/null @@ -1,4 +0,0 @@ -TODOs: - - Optimize Buffer classes? - - Add compile-time asserts to verify object packing and padding. - - Investigate making arrays of objects not be arrays of pointers. diff --git a/chromium/mojo/public/cpp/bindings/lib/array_internal.cc b/chromium/mojo/public/cpp/bindings/lib/array_internal.cc index 542ab3d71e9..dd24eac4702 100644 --- a/chromium/mojo/public/cpp/bindings/lib/array_internal.cc +++ b/chromium/mojo/public/cpp/bindings/lib/array_internal.cc @@ -55,23 +55,5 @@ ArrayDataTraits<bool>::BitRef::operator bool() const { return (*storage_ & mask_) != 0; } -// static -void ArraySerializationHelper<Handle, true, false>::EncodePointersAndHandles( - const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { - for (uint32_t i = 0; i < header->num_elements; ++i) - EncodeHandle(&elements[i], handles); -} - -// static -void ArraySerializationHelper<Handle, true, false>::DecodePointersAndHandles( - const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { - for (uint32_t i = 0; i < header->num_elements; ++i) - DecodeHandle(&elements[i], handles); -} - } // namespace internal } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/array_internal.h b/chromium/mojo/public/cpp/bindings/lib/array_internal.h index d01484e2a1c..00ae00b7011 100644 --- a/chromium/mojo/public/cpp/bindings/lib/array_internal.h +++ b/chromium/mojo/public/cpp/bindings/lib/array_internal.h @@ -14,10 +14,10 @@ #include "base/logging.h" #include "mojo/public/c/system/macros.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/bounds_checker.h" #include "mojo/public/cpp/bindings/lib/buffer.h" #include "mojo/public/cpp/bindings/lib/map_data_internal.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" @@ -60,7 +60,7 @@ struct ArrayDataTraits { template <typename P> struct ArrayDataTraits<P*> { - typedef StructPointer<P> StorageType; + typedef Pointer<P> StorageType; typedef P*& Ref; typedef P* const& ConstRef; @@ -79,27 +79,6 @@ struct ArrayDataTraits<P*> { } }; -template <typename T> -struct ArrayDataTraits<Array_Data<T>*> { - typedef ArrayPointer<T> StorageType; - typedef Array_Data<T>*& Ref; - typedef Array_Data<T>* const& ConstRef; - - static const uint32_t kMaxNumElements = - (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); - - static uint32_t GetStorageSize(uint32_t num_elements) { - DCHECK(num_elements <= kMaxNumElements); - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; - } - static Ref ToRef(StorageType* storage, size_t offset) { - return storage[offset].ptr; - } - static ConstRef ToConstRef(const StorageType* storage, size_t offset) { - return storage[offset].ptr; - } -}; - // Specialization of Arrays for bools, optimized for space. It has the // following differences from a generalized Array: // * Each element takes up a single bit of memory. @@ -149,20 +128,18 @@ struct ArrayDataTraits<bool> { // of unions are inlined so they are not pointers, but comparing with primitives // they require more work for serialization/validation. -template <typename T, bool is_handle, bool is_union> +template <typename T, bool is_union> struct ArraySerializationHelper; template <typename T> -struct ArraySerializationHelper<T, false, false> { +struct ArraySerializationHelper<T, false> { typedef typename ArrayDataTraits<T>::StorageType ElementType; - static void EncodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) {} + static void EncodePointers(const ArrayHeader* header, + ElementType* elements) {} - static void DecodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) {} + static void DecodePointers(const ArrayHeader* header, + ElementType* elements) {} static bool ValidateElements(const ArrayHeader* header, const ElementType* elements, @@ -173,43 +150,27 @@ struct ArraySerializationHelper<T, false, false> { DCHECK(!validate_params->element_validate_params) << "Primitive type should not have array validate params"; - return ValidateCaller<ElementType>::Run(header, elements); - } - - private: - template <typename U, bool is_enum = IsEnumDataType<U>::value> - struct ValidateCaller {}; - - template <typename U> - struct ValidateCaller<U, false> { - static bool Run(const ArrayHeader* header, const ElementType* elements) { + if (!validate_params->validate_enum_func) return true; - } - }; - template <typename U> - struct ValidateCaller<U, true> { - static bool Run(const ArrayHeader* header, const ElementType* elements) { - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!ValidateEnum(elements[i])) - return false; - } - return true; + // Enum validation. + for (uint32_t i = 0; i < header->num_elements; ++i) { + if (!validate_params->validate_enum_func(elements[i])) + return false; } - }; + return true; + } }; template <> -struct ArraySerializationHelper<Handle, true, false> { - typedef ArrayDataTraits<Handle>::StorageType ElementType; +struct ArraySerializationHelper<Handle_Data, false> { + typedef ArrayDataTraits<Handle_Data>::StorageType ElementType; - static void EncodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles); + static void EncodePointers(const ArrayHeader* header, + ElementType* elements) {} - static void DecodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles); + static void DecodePointers(const ArrayHeader* header, + ElementType* elements) {} static bool ValidateElements(const ArrayHeader* header, const ElementType* elements, @@ -219,8 +180,7 @@ struct ArraySerializationHelper<Handle, true, false> { << "Handle type should not have array validate params"; for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && - elements[i].value() == kEncodedInvalidHandleValue) { + if (!validate_params->element_is_nullable && !elements[i].is_valid()) { ReportValidationError( VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, MakeMessageWithArrayIndex( @@ -238,49 +198,18 @@ struct ArraySerializationHelper<Handle, true, false> { } }; -template <typename H> -struct ArraySerializationHelper<H, true, false> { - typedef typename ArrayDataTraits<H>::StorageType ElementType; - - static void EncodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { - ArraySerializationHelper<Handle, true, false>::EncodePointersAndHandles( - header, elements, handles); - } - - static void DecodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { - ArraySerializationHelper<Handle, true, false>::DecodePointersAndHandles( - header, elements, handles); - } - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - BoundsChecker* bounds_checker, - const ArrayValidateParams* validate_params) { - return ArraySerializationHelper<Handle, true, false>::ValidateElements( - header, elements, bounds_checker, validate_params); - } -}; - template <typename P> -struct ArraySerializationHelper<P*, false, false> { +struct ArraySerializationHelper<P*, false> { typedef typename ArrayDataTraits<P*>::StorageType ElementType; - static void EncodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { + static void EncodePointers(const ArrayHeader* header, ElementType* elements) { for (uint32_t i = 0; i < header->num_elements; ++i) - Encode(&elements[i], handles); + Encode(&elements[i]); } - static void DecodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { + static void DecodePointers(const ArrayHeader* header, ElementType* elements) { for (uint32_t i = 0; i < header->num_elements; ++i) - Decode(&elements[i], handles); + Decode(&elements[i]); } static bool ValidateElements(const ArrayHeader* header, @@ -343,21 +272,17 @@ struct ArraySerializationHelper<P*, false, false> { }; template <typename U> -struct ArraySerializationHelper<U, false, true> { +struct ArraySerializationHelper<U, true> { typedef typename ArrayDataTraits<U>::StorageType ElementType; - static void EncodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { + static void EncodePointers(const ArrayHeader* header, ElementType* elements) { for (uint32_t i = 0; i < header->num_elements; ++i) - elements[i].EncodePointersAndHandles(handles); + elements[i].EncodePointers(); } - static void DecodePointersAndHandles(const ArrayHeader* header, - ElementType* elements, - std::vector<Handle>* handles) { + static void DecodePointers(const ArrayHeader* header, ElementType* elements) { for (uint32_t i = 0; i < header->num_elements; ++i) - elements[i].DecodePointersAndHandles(handles); + elements[i].DecodePointers(); } static bool ValidateElements(const ArrayHeader* header, @@ -383,14 +308,12 @@ struct ArraySerializationHelper<U, false, true> { template <typename T> class Array_Data { public: - typedef ArrayDataTraits<T> Traits; - typedef typename Traits::StorageType StorageType; - typedef typename Traits::Ref Ref; - typedef typename Traits::ConstRef ConstRef; - typedef ArraySerializationHelper<T, - IsHandle<T>::value, - IsUnionDataType<T>::value> - Helper; + using Traits = ArrayDataTraits<T>; + using StorageType = typename Traits::StorageType; + using Ref = typename Traits::Ref; + using ConstRef = typename Traits::ConstRef; + using Helper = ArraySerializationHelper<T, IsUnionDataType<T>::value>; + using Element = T; // Returns null if |num_elements| or the corresponding storage size cannot be // stored in uint32_t. @@ -465,13 +388,8 @@ class Array_Data { reinterpret_cast<const char*>(this) + sizeof(*this)); } - void EncodePointersAndHandles(std::vector<Handle>* handles) { - Helper::EncodePointersAndHandles(&header_, storage(), handles); - } - - void DecodePointersAndHandles(std::vector<Handle>* handles) { - Helper::DecodePointersAndHandles(&header_, storage(), handles); - } + void EncodePointers() { Helper::EncodePointers(&header_, storage()); } + void DecodePointers() { Helper::DecodePointers(&header_, storage()); } private: Array_Data(uint32_t num_bytes, uint32_t num_elements) { diff --git a/chromium/mojo/public/cpp/bindings/lib/array_serialization.h b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h index d5a59af2c19..3b4033b4fdf 100644 --- a/chromium/mojo/public/cpp/bindings/lib/array_serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h @@ -6,38 +6,397 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ #include <stddef.h> +#include <string.h> // For |memcpy()|. +#include <limits> +#include <type_traits> +#include <utility> +#include <vector> + +#include "base/logging.h" #include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/bindings/lib/array_serialization_traits.h" +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/serialization_forward.h" +#include "mojo/public/cpp/bindings/lib/template_util.h" +#include "mojo/public/cpp/bindings/lib/validation_errors.h" + +namespace WTF { +class String; +} namespace mojo { +namespace internal { -template <typename E> -inline size_t GetSerializedSize_(const Array<E>& input, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<Array<E>>::GetSerializedSize(input, - context); -} +enum class ArraySerializerType { + BOOLEAN, + // Except boolean. + POD, + HANDLE, + // String, array, map and struct. + POINTER, + UNION +}; -template <typename E, typename F> -inline void SerializeArray_( - Array<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<Array<E>>::template Serialize<F>( - std::move(input), buf, output, validate_params, context); -} +template <typename T> +struct GetArraySerializerType { + static const ArraySerializerType value = + IsUnionDataType<T>::value + ? ArraySerializerType::UNION + : (std::is_pointer<T>::value + ? ArraySerializerType::POINTER + : (IsHandle<T>::value ? ArraySerializerType::HANDLE + : (std::is_same<T, bool>::value + ? ArraySerializerType::BOOLEAN + : ArraySerializerType::POD))); +}; -template <typename E, typename F> -inline bool Deserialize_(internal::Array_Data<F>* input, - Array<E>* output, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<Array<E>>::template Deserialize<F>( - input, output, context); -} +template <typename MojomType, + typename MaybeConstUserType, + ArraySerializerType type = + GetArraySerializerType<typename MojomType::Data_::Element>::value> +struct ArraySerializer; + +// Handles serialization and deserialization of arrays of pod types. +template <typename MojomType, typename MaybeConstUserType> +struct ArraySerializer<MojomType, + MaybeConstUserType, + ArraySerializerType::POD> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Data = typename MojomType::Data_; + using DataElement = typename Data::Element; + using Element = typename MojomType::Element; + using Traits = ArrayTraits<UserType>; + + static_assert(sizeof(Element) == sizeof(DataElement), + "Incorrect array serializer"); + static_assert(std::is_same<Element, typename Traits::Element>::value, + "Incorrect array serializer"); + + static size_t GetSerializedSize(MaybeConstUserType& input, + SerializationContext* context) { + return sizeof(Data) + Align(Traits::GetSize(input) * sizeof(DataElement)); + } + + static void SerializeElements(MaybeConstUserType& input, + Buffer* buf, + Data* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + DCHECK(!validate_params->element_is_nullable) + << "Primitive type should be non-nullable"; + DCHECK(!validate_params->element_validate_params) + << "Primitive type should not have array validate params"; + + if (Traits::GetSize(input)) { + memcpy(output->storage(), Traits::GetData(input), + Traits::GetSize(input) * sizeof(DataElement)); + } + } + + static bool DeserializeElements(Data* input, + UserType* output, + SerializationContext* context) { + Traits::Resize(*output, input->size()); + if (input->size()) { + memcpy(Traits::GetData(*output), input->storage(), + input->size() * sizeof(DataElement)); + } + return true; + } +}; + +// Serializes and deserializes arrays of bools. +template <typename MojomType, typename MaybeConstUserType> +struct ArraySerializer<MojomType, + MaybeConstUserType, + ArraySerializerType::BOOLEAN> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Traits = ArrayTraits<UserType>; + using Data = typename MojomType::Data_; + + static_assert(std::is_same<bool, typename UserType::Element>::value, + "Incorrect array serializer"); + + static size_t GetSerializedSize(MaybeConstUserType& input, + SerializationContext* context) { + return sizeof(Data) + Align((Traits::GetSize(input) + 7) / 8); + } + + static void SerializeElements(MaybeConstUserType& input, + Buffer* buf, + Data* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + DCHECK(!validate_params->element_is_nullable) + << "Primitive type should be non-nullable"; + DCHECK(!validate_params->element_validate_params) + << "Primitive type should not have array validate params"; + + // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? + size_t size = Traits::GetSize(input); + for (size_t i = 0; i < size; ++i) + output->at(i) = Traits::GetAt(input, i); + } + static bool DeserializeElements(Data* input, + UserType* output, + SerializationContext* context) { + Traits::Resize(*output, input->size()); + // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? + for (size_t i = 0; i < input->size(); ++i) + Traits::GetAt(*output, i) = input->at(i); + return true; + } +}; + +// Serializes and deserializes arrays of handles. +template <typename MojomType, typename MaybeConstUserType> +struct ArraySerializer<MojomType, + MaybeConstUserType, + ArraySerializerType::HANDLE> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Data = typename MojomType::Data_; + using Element = typename MojomType::Element; + using Traits = ArrayTraits<UserType>; + + static_assert(std::is_same<Element, typename Traits::Element>::value, + "Incorrect array serializer"); + + static size_t GetSerializedSize(MaybeConstUserType& input, + SerializationContext* context) { + return sizeof(Data) + + Align(Traits::GetSize(input) * sizeof(typename Data::Element)); + } + + static void SerializeElements(MaybeConstUserType& input, + Buffer* buf, + Data* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + DCHECK(!validate_params->element_validate_params) + << "Handle type should not have array validate params"; + + size_t size = Traits::GetSize(input); + for (size_t i = 0; i < size; ++i) { + // Transfer ownership of the handle. + output->at(i) = + context->handles.AddHandle(Traits::GetAt(input, i).release()); + MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( + !validate_params->element_is_nullable && !output->at(i).is_valid(), + VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, + MakeMessageWithArrayIndex( + "invalid handle in array expecting valid handles", size, i)); + } + } + static bool DeserializeElements(Data* input, + UserType* output, + SerializationContext* context) { + using HandleType = typename Element::RawHandleType; + Traits::Resize(*output, input->size()); + for (size_t i = 0; i < input->size(); ++i) { + Traits::GetAt(*output, i) = MakeScopedHandle( + HandleType(context->handles.TakeHandle(input->at(i)).value())); + } + return true; + } +}; + +// This template must only apply to pointer mojo entity (strings, structs, +// arrays and maps). +template <typename MojomType, typename MaybeConstUserType> +struct ArraySerializer<MojomType, + MaybeConstUserType, + ArraySerializerType::POINTER> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Data = typename MojomType::Data_; + using DataElement = typename Data::Element; + using Element = typename MojomType::Element; + using Traits = ArrayTraits<UserType>; + + static size_t GetSerializedSize(MaybeConstUserType& input, + SerializationContext* context) { + size_t element_count = Traits::GetSize(input); + size_t size = + sizeof(Data) + + element_count * + sizeof(Pointer<typename std::remove_pointer<DataElement>::type>); + for (size_t i = 0; i < element_count; ++i) + size += PrepareToSerialize<Element>(Traits::GetAt(input, i), context); + return size; + } + + static void SerializeElements(MaybeConstUserType& input, + Buffer* buf, + Data* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + size_t size = Traits::GetSize(input); + for (size_t i = 0; i < size; ++i) { + DataElement element; + SerializeCaller<Element>::Run(Traits::GetAt(input, i), buf, &element, + validate_params->element_validate_params, + context); + output->at(i) = element; + MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( + !validate_params->element_is_nullable && !element, + VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, + MakeMessageWithArrayIndex("null in array expecting valid pointers", + size, i)); + } + } + static bool DeserializeElements(Data* input, + UserType* output, + SerializationContext* context) { + bool success = true; + Traits::Resize(*output, input->size()); + for (size_t i = 0; i < input->size(); ++i) { + // Note that we rely on complete deserialization taking place in order to + // transfer ownership of all encoded handles. Therefore we don't + // short-circuit on failure here. + if (!Deserialize<Element>(input->at(i), &Traits::GetAt(*output, i), + context)) { + success = false; + } + } + return success; + } + + private: + template <typename T, + bool is_array_or_map = IsSpecializationOf<Array, T>::value || + IsSpecializationOf<Map, T>::value> + struct SerializeCaller { + template <typename InputElementType> + static void Run(InputElementType&& input, + Buffer* buf, + DataElement* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + Serialize<T>(std::forward<InputElementType>(input), buf, output, context); + } + }; + + template <typename T> + struct SerializeCaller<T, true> { + template <typename InputElementType> + static void Run(InputElementType&& input, + Buffer* buf, + DataElement* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + Serialize<T>(std::forward<InputElementType>(input), buf, output, + validate_params, context); + } + }; +}; + +// Handles serialization and deserialization of arrays of unions. +template <typename MojomType, typename MaybeConstUserType> +struct ArraySerializer<MojomType, + MaybeConstUserType, + ArraySerializerType::UNION> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Data = typename MojomType::Data_; + using Element = typename MojomType::Element; + using Traits = ArrayTraits<UserType>; + + static_assert(std::is_same<typename MojomType::Element, + typename Traits::Element>::value, + "Incorrect array serializer"); + + static size_t GetSerializedSize(MaybeConstUserType& input, + SerializationContext* context) { + size_t element_count = Traits::GetSize(input); + size_t size = sizeof(Data); + for (size_t i = 0; i < element_count; ++i) { + // Call with |inlined| set to false, so that it will account for both the + // data in the union and the space in the array used to hold the union. + size += + PrepareToSerialize<Element>(Traits::GetAt(input, i), false, context); + } + return size; + } + + static void SerializeElements(MaybeConstUserType& input, + Buffer* buf, + Data* output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + size_t size = Traits::GetSize(input); + for (size_t i = 0; i < size; ++i) { + typename Data::Element* result = output->storage() + i; + Serialize<Element>(Traits::GetAt(input, i), buf, &result, true, context); + MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( + !validate_params->element_is_nullable && output->at(i).is_null(), + VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, + MakeMessageWithArrayIndex("null in array expecting valid unions", + size, i)); + } + } + + static bool DeserializeElements(Data* input, + UserType* output, + SerializationContext* context) { + bool success = true; + Traits::Resize(*output, input->size()); + for (size_t i = 0; i < input->size(); ++i) { + // Note that we rely on complete deserialization taking place in order to + // transfer ownership of all encoded handles. Therefore we don't + // short-circuit on failure here. + if (!Deserialize<Element>(&input->at(i), &Traits::GetAt(*output, i), + context)) { + success = false; + } + } + return success; + } +}; + +template <typename Element, typename MaybeConstUserType> +struct Serializer<Array<Element>, MaybeConstUserType> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Impl = ArraySerializer<Array<Element>, MaybeConstUserType>; + using Traits = ArrayTraits<UserType>; + using Data = typename Array<Element>::Data_; + + static size_t PrepareToSerialize(MaybeConstUserType& input, + SerializationContext* context) { + if (CallIsNullIfExists<Traits>(input)) + return 0; + return Impl::GetSerializedSize(input, context); + } + + static void Serialize(MaybeConstUserType& input, + Buffer* buf, + Data** output, + const ArrayValidateParams* validate_params, + SerializationContext* context) { + if (!CallIsNullIfExists<Traits>(input)) { + MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( + validate_params->expected_num_elements != 0 && + Traits::GetSize(input) != validate_params->expected_num_elements, + internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, + internal::MakeMessageWithExpectedArraySize( + "fixed-size array has wrong number of elements", + Traits::GetSize(input), validate_params->expected_num_elements)); + Data* result = Data::New(Traits::GetSize(input), buf); + if (result) + Impl::SerializeElements(input, buf, result, validate_params, context); + *output = result; + } else { + *output = nullptr; + } + } + + static bool Deserialize(Data* input, + UserType* output, + SerializationContext* context) { + if (!input) + return CallSetToNullIfExists<Traits>(output); + return Impl::DeserializeElements(input, output, context); + } +}; +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/array_serialization_traits.h b/chromium/mojo/public/cpp/bindings/lib/array_serialization_traits.h deleted file mode 100644 index 17817e01951..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/array_serialization_traits.h +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_TRAITS_H_ - -#include <stddef.h> -#include <string.h> // For |memcpy()|. - -#include <limits> -#include <type_traits> -#include <utility> -#include <vector> - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" - -namespace WTF { -class String; -} - -namespace mojo { -namespace internal { - -template <typename ArrayType, - typename ElementType, - typename ElementDataType, - bool is_union = IsUnionDataType< - typename RemovePointer<ElementDataType>::type>::value> -struct ArraySerializer; - -// Handles serialization and deserialization of arrays of pod types. -template <typename ArrayType, typename E, typename F> -struct ArraySerializer<ArrayType, E, F, false> { - static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer"); - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); - } - - static void SerializeElements(ArrayType input, - Buffer* buf, - Array_Data<F>* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - if (input.size()) - memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); - } - static bool DeserializeElements(Array_Data<F>* input, - ArrayType* output, - SerializationContext* context) { - ArrayType result(input->size()); - if (input->size()) - memcpy(&result.front(), input->storage(), input->size() * sizeof(E)); - output->Swap(&result); - return true; - } -}; - -// Serializes and deserializes arrays of bools. -template <typename ArrayType> -struct ArraySerializer<ArrayType, bool, bool, false> { - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); - } - - static void SerializeElements(ArrayType input, - Buffer* buf, - Array_Data<bool>* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? - for (size_t i = 0; i < input.size(); ++i) - output->at(i) = input[i]; - } - static bool DeserializeElements(Array_Data<bool>* input, - ArrayType* output, - SerializationContext* context) { - ArrayType result(input->size()); - // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? - for (size_t i = 0; i < input->size(); ++i) - result.at(i) = input->at(i); - output->Swap(&result); - return true; - } -}; - -// Serializes and deserializes arrays of handles. -template <typename ArrayType, typename H> -struct ArraySerializer<ArrayType, ScopedHandleBase<H>, H, false> { - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); - } - - static void SerializeElements(ArrayType input, - Buffer* buf, - Array_Data<H>* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_validate_params) - << "Handle type should not have array validate params"; - - for (size_t i = 0; i < input.size(); ++i) { - output->at(i) = input[i].release(); // Transfer ownership of the handle. - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && !output->at(i).is_valid(), - VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - MakeMessageWithArrayIndex( - "invalid handle in array expecting valid handles", input.size(), - i)); - } - } - static bool DeserializeElements(Array_Data<H>* input, - ArrayType* output, - SerializationContext* context) { - ArrayType result(input->size()); - for (size_t i = 0; i < input->size(); ++i) - result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); - output->Swap(&result); - return true; - } -}; - -// This template must only apply to pointer mojo entity (strings, structs, -// arrays and maps). This is done by ensuring that WrapperTraits<S>::DataType is -// a pointer. -template <typename ArrayType, typename S> -struct ArraySerializer< - ArrayType, - S, - typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value, - typename WrapperTraits<S>::DataType>::type, - false> { - typedef - typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data; - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - size_t size = sizeof(Array_Data<S_Data*>) + - input.size() * sizeof(StructPointer<S_Data>); - for (size_t i = 0; i < input.size(); ++i) - size += GetSerializedSize_(input[i], context); - return size; - } - - static void SerializeElements(ArrayType input, - Buffer* buf, - Array_Data<S_Data*>* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - for (size_t i = 0; i < input.size(); ++i) { - S_Data* element; - SerializeCaller<S>::Run(std::move(input[i]), buf, &element, - validate_params->element_validate_params, - context); - output->at(i) = element; - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && !element, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid pointers", - input.size(), i)); - } - } - static bool DeserializeElements(Array_Data<S_Data*>* input, - ArrayType* output, - SerializationContext* context) { - bool success = true; - ArrayType result(input->size()); - for (size_t i = 0; i < input->size(); ++i) { - // Note that we rely on complete deserialization taking place in order to - // transfer ownership of all encoded handles. Therefore we don't - // short-circuit on failure here. - if (!Deserialize_(input->at(i), &result[i], context)) - success = false; - } - output->Swap(&result); - return success; - } - - private: - template <typename T, - bool is_array = IsSpecializationOf<Array, T>::value || - IsSpecializationOf<WTFArray, T>::value, - bool is_string = std::is_same<T, String>::value || - std::is_same<T, WTF::String>::value> - struct SerializeCaller { - static void Run(T input, - Buffer* buf, - typename WrapperTraits<T>::DataType* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params) - << "Struct type should not have array validate params"; - - Serialize_(std::move(input), buf, output, context); - } - }; - - template <typename T> - struct SerializeCaller<T, true, false> { - static void Run(T input, - Buffer* buf, - typename T::Data_** output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - SerializeArray_(std::move(input), buf, output, validate_params, context); - } - }; - - template <typename T, typename U> - struct SerializeCaller<Map<T, U>, false, false> { - static void Run(Map<T, U> input, - Buffer* buf, - typename Map<T, U>::Data_** output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - SerializeMap_(std::move(input), buf, output, validate_params, context); - } - }; - - template <typename T> - struct SerializeCaller<T, false, true> { - static void Run(const T& input, - Buffer* buf, - String_Data** output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(validate_params && !validate_params->element_validate_params && - !validate_params->element_is_nullable && - validate_params->expected_num_elements == 0) - << "String type has unexpected array validate params"; - - Serialize_(input, buf, output, context); - } - }; -}; - -// Handles serialization and deserialization of arrays of unions. -template <typename ArrayType, typename U, typename U_Data> -struct ArraySerializer<ArrayType, U, U_Data, true> { - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - 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, context); - } - return size; - } - - static void SerializeElements(ArrayType input, - Buffer* buf, - Array_Data<U_Data>* output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - for (size_t i = 0; i < input.size(); ++i) { - U_Data* result = output->storage() + i; - SerializeUnion_(std::move(input[i]), buf, &result, true, context); - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && output->at(i).is_null(), - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid unions", - input.size(), i)); - } - } - - static bool DeserializeElements(Array_Data<U_Data>* input, - ArrayType* output, - SerializationContext* context) { - bool success = true; - ArrayType result(input->size()); - for (size_t i = 0; i < input->size(); ++i) { - // Note that we rely on complete deserialization taking place in order to - // transfer ownership of all encoded handles. Therefore we don't - // short-circuit on failure here. - if (!Deserialize_(&input->at(i), &result[i], context)) - success = false; - } - output->Swap(&result); - return success; - } -}; - -// Another layer of abstraction to switch between standard mojom type -// serializers and native-only serializers. -template <typename ArrayType, - bool use_native = - ShouldUseNativeSerializer<typename ArrayType::ElementType>::value> -struct ArraySerializationStrategy; - -// Serialization strategy for standard mojom types. This branches further -// by choosing an ArraySerializer specialization from above. -template <typename ArrayType> -struct ArraySerializationStrategy<ArrayType, false> { - template <class DataType> - using Serializer = - ArraySerializer<ArrayType, typename ArrayType::ElementType, DataType>; - - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - DCHECK(input); - return Serializer<typename WrapperTraits< - typename ArrayType::ElementType>::DataType>::GetSerializedSize(input, - context); - } - - template <typename F> - static void Serialize(ArrayType input, - Buffer* buf, - Array_Data<F>** output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - DCHECK(input); - Array_Data<F>* result = Array_Data<F>::New(input.size(), buf); - if (result) { - Serializer<F>::SerializeElements(std::move(input), buf, result, - validate_params, context); - } - *output = result; - } - - template <typename F> - static bool Deserialize(Array_Data<F>* input, - ArrayType* output, - SerializationContext* context) { - DCHECK(input); - return Serializer<F>::DeserializeElements(input, output, context); - } -}; - -// Serialization for arrays of native-only types, which are opaquely serialized -// as arrays of uint8_t arrays. -template <typename ArrayType> -struct ArraySerializationStrategy<ArrayType, true> { - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - DCHECK(input); - DCHECK_LE(input.size(), std::numeric_limits<uint32_t>::max()); - size_t size = ArrayDataTraits<Array_Data<uint8_t>*>::GetStorageSize( - static_cast<uint32_t>(input.size())); - for (size_t i = 0; i < input.size(); ++i) { - size_t element_size = GetSerializedSizeNative_(input[i], context); - DCHECK_LT(element_size, std::numeric_limits<uint32_t>::max()); - size += ArrayDataTraits<uint8_t>::GetStorageSize( - static_cast<uint32_t>(element_size)); - } - return size; - } - - template <typename F> - static void Serialize(ArrayType input, - Buffer* buf, - Array_Data<F>** output, - const ArrayValidateParams* validate_params, - SerializationContext* context) { - static_assert( - std::is_same<F, Array_Data<uint8_t>*>::value, - "Native-only type array must serialize to array of byte arrays."); - DCHECK(input); - DCHECK(validate_params); - // TODO(rockot): We may want to support nullable (i.e. scoped_ptr<T>) - // elements here. - DCHECK(!validate_params->element_is_nullable); - Array_Data<Array_Data<uint8_t>*>* result = - Array_Data<Array_Data<uint8_t>*>::New(input.size(), buf); - for (size_t i = 0; i < input.size(); ++i) - SerializeNative_(input[i], buf, &result->at(i), context); - *output = result; - } - - template <typename F> - static bool Deserialize(Array_Data<F>* input, - ArrayType* output, - SerializationContext* context) { - static_assert( - std::is_same<F, Array_Data<uint8_t>*>::value, - "Native-only type array must deserialize from array of byte arrays."); - DCHECK(input); - - ArrayType result(input->size()); - bool success = true; - for (size_t i = 0; i < input->size(); ++i) { - // We don't short-circuit on failure since we can't know what the native - // type's ParamTraits' expectations are. - if (!DeserializeNative_(input->at(i), &result[i], context)) - success = false; - } - output->Swap(&result); - return success; - } -}; - -template <typename ArrayType> -struct ArraySerializationImpl { - using Strategy = ArraySerializationStrategy<ArrayType>; - - static size_t GetSerializedSize(const ArrayType& input, - SerializationContext* context) { - if (!input) - return 0; - return Strategy::GetSerializedSize(input, context); - } - - template <typename F> - static void Serialize(ArrayType input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params, - SerializationContext* context) { - if (input) { - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - validate_params->expected_num_elements != 0 && - input.size() != validate_params->expected_num_elements, - internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - internal::MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", input.size(), - validate_params->expected_num_elements)); - Strategy::template Serialize<F>(std::move(input), buf, output, - validate_params, context); - } else { - *output = nullptr; - } - } - - template <typename F> - static bool Deserialize(internal::Array_Data<F>* input, - ArrayType* output, - internal::SerializationContext* context) { - if (input) - return Strategy::template Deserialize<F>(input, output, context); - *output = nullptr; - return true; - } -}; - -} // namespace internal - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/associated_group.cc b/chromium/mojo/public/cpp/bindings/lib/associated_group.cc index 0bdf809d1ed..c3bde6f1b47 100644 --- a/chromium/mojo/public/cpp/bindings/lib/associated_group.cc +++ b/chromium/mojo/public/cpp/bindings/lib/associated_group.cc @@ -24,8 +24,8 @@ AssociatedGroup& AssociatedGroup::operator=(const AssociatedGroup& other) { } void AssociatedGroup::CreateEndpointHandlePair( - internal::ScopedInterfaceEndpointHandle* local_endpoint, - internal::ScopedInterfaceEndpointHandle* remote_endpoint) { + ScopedInterfaceEndpointHandle* local_endpoint, + ScopedInterfaceEndpointHandle* remote_endpoint) { if (!router_) return; diff --git a/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h index 6f5f830d629..e214335a9ea 100644 --- a/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h +++ b/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h @@ -6,11 +6,15 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ #include <stdint.h> + #include <algorithm> // For |std::swap()|. +#include <memory> #include <utility> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" #include "mojo/public/cpp/bindings/callback.h" @@ -18,7 +22,7 @@ #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" #include "mojo/public/cpp/bindings/lib/interface_id.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/message_pipe.h" namespace mojo { @@ -77,7 +81,8 @@ class AssociatedInterfacePtrState { swap(other->version_, version_); } - void Bind(AssociatedInterfacePtrInfo<Interface> info) { + void Bind(AssociatedInterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner) { DCHECK(!endpoint_client_); DCHECK(!proxy_); DCHECK_EQ(0u, version_); @@ -85,8 +90,9 @@ class AssociatedInterfacePtrState { version_ = info.version(); endpoint_client_.reset(new InterfaceEndpointClient( - AssociatedInterfacePtrInfoHelper::PassHandle(&info), nullptr, - make_scoped_ptr(new typename Interface::ResponseValidator_()), false)); + info.PassHandle(), nullptr, + base::WrapUnique(new typename Interface::ResponseValidator_()), false, + std::move(runner))); proxy_.reset(new Proxy(endpoint_client_.get())); proxy_->serialization_context()->router = endpoint_client_->router(); } @@ -97,11 +103,7 @@ class AssociatedInterfacePtrState { ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); endpoint_client_.reset(); proxy_.reset(); - - AssociatedInterfacePtrInfo<Interface> result; - result.set_version(version_); - AssociatedInterfacePtrInfoHelper::SetHandle(&result, std::move(handle)); - return result; + return AssociatedInterfacePtrInfo<Interface>(std::move(handle), version_); } bool is_bound() const { return !!endpoint_client_; } @@ -127,8 +129,8 @@ class AssociatedInterfacePtrState { private: using Proxy = typename Interface::Proxy_; - scoped_ptr<InterfaceEndpointClient> endpoint_client_; - scoped_ptr<Proxy> proxy_; + std::unique_ptr<InterfaceEndpointClient> endpoint_client_; + std::unique_ptr<Proxy> proxy_; uint32_t version_; diff --git a/chromium/mojo/public/cpp/bindings/lib/binding_state.h b/chromium/mojo/public/cpp/bindings/lib/binding_state.h index b3588da724e..77a59f5d0ed 100644 --- a/chromium/mojo/public/cpp/bindings/lib/binding_state.h +++ b/chromium/mojo/public/cpp/bindings/lib/binding_state.h @@ -5,12 +5,14 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ +#include <memory> #include <utility> #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/interface_ptr.h" @@ -22,7 +24,7 @@ #include "mojo/public/cpp/bindings/lib/message_header_validator.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" #include "mojo/public/cpp/bindings/lib/router.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/core.h" namespace mojo { @@ -47,14 +49,16 @@ class BindingState<Interface, false> { Close(); } - void Bind(ScopedMessagePipeHandle handle) { + void Bind(ScopedMessagePipeHandle handle, + scoped_refptr<base::SingleThreadTaskRunner> runner) { DCHECK(!router_); internal::FilterChain filters; filters.Append<internal::MessageHeaderValidator>(); filters.Append<typename Interface::RequestValidator_>(); - router_ = new internal::Router(std::move(handle), std::move(filters), - Interface::HasSyncMethods_); + router_ = + new internal::Router(std::move(handle), std::move(filters), + Interface::HasSyncMethods_, std::move(runner)); router_->set_incoming_receiver(&stub_); router_->set_connection_error_handler( [this]() { connection_error_handler_.Run(); }); @@ -141,16 +145,17 @@ class BindingState<Interface, true> { Close(); } - void Bind(ScopedMessagePipeHandle handle) { + void Bind(ScopedMessagePipeHandle handle, + scoped_refptr<base::SingleThreadTaskRunner> runner) { DCHECK(!router_); - router_ = new internal::MultiplexRouter(false, std::move(handle)); + router_ = new internal::MultiplexRouter(false, std::move(handle), runner); stub_.serialization_context()->router = router_; endpoint_client_.reset(new internal::InterfaceEndpointClient( router_->CreateLocalEndpointHandle(internal::kMasterInterfaceId), - &stub_, make_scoped_ptr(new typename Interface::RequestValidator_()), - Interface::HasSyncMethods_)); + &stub_, base::WrapUnique(new typename Interface::RequestValidator_()), + Interface::HasSyncMethods_, std::move(runner))); endpoint_client_->set_connection_error_handler( [this]() { connection_error_handler_.Run(); }); @@ -217,7 +222,7 @@ class BindingState<Interface, true> { private: scoped_refptr<internal::MultiplexRouter> router_; - scoped_ptr<internal::InterfaceEndpointClient> endpoint_client_; + std::unique_ptr<internal::InterfaceEndpointClient> endpoint_client_; typename Interface::Stub_ stub_; Interface* impl_; diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h index 8d320823139..f38c7645eb9 100644 --- a/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h @@ -25,6 +25,14 @@ class InlinedStructPtr; namespace internal { +// Please note that this is a different value than |mojo::kInvalidHandleValue|, +// which is the "decoded" invalid handle. +const uint32_t kEncodedInvalidHandleValue = static_cast<uint32_t>(-1); + +// A serialized union always takes 16 bytes: +// 4-byte size + 4-byte tag + 8-byte payload. +const uint32_t kUnionDataSize = 16; + template <typename T> class Array_Data; @@ -45,32 +53,24 @@ struct ArrayHeader { static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)"); template <typename T> -union StructPointer { +union Pointer { uint64_t offset; T* ptr; }; -static_assert(sizeof(StructPointer<char>) == 8, "Bad_sizeof(StructPointer)"); +static_assert(sizeof(Pointer<char>) == 8, "Bad_sizeof(Pointer)"); -template <typename T> -union ArrayPointer { - uint64_t offset; - Array_Data<T>* ptr; -}; -static_assert(sizeof(ArrayPointer<char>) == 8, "Bad_sizeof(ArrayPointer)"); - -using StringPointer = ArrayPointer<char>; -static_assert(sizeof(StringPointer) == 8, "Bad_sizeof(StringPointer)"); +struct Handle_Data { + Handle_Data() = default; + explicit Handle_Data(uint32_t value) : value(value) {} + bool is_valid() const { return value != kEncodedInvalidHandleValue; } -template <typename T> -union UnionPointer { - uint64_t offset; - T* ptr; + uint32_t value; }; -static_assert(sizeof(UnionPointer<char>) == 8, "Bad_sizeof(UnionPointer)"); +static_assert(sizeof(Handle_Data) == 4, "Bad_sizeof(Handle_Data)"); struct Interface_Data { - MessagePipeHandle handle; + Handle_Data handle; uint32_t version; }; static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)"); @@ -101,30 +101,19 @@ T FetchAndReset(T* ptr) { template <typename H> struct IsHandle { - enum { value = IsBaseOf<Handle, H>::value }; + enum { value = 0 }; }; -template <typename T> -struct IsUnionDataType { - private: - template <typename U> - static YesType Test(const typename U::MojomUnionDataType*); - - template <typename U> - static NoType Test(...); - - EnsureTypeIsComplete<T> check_t_; - - public: - static const bool value = - sizeof(Test<T>(0)) == sizeof(YesType) && !IsConst<T>::value; +template <> +struct IsHandle<Handle_Data> { + enum { value = 1 }; }; template <typename T> -struct IsEnumDataType { +struct IsUnionDataType { private: template <typename U> - static YesType Test(const typename U::MojomEnumDataType*); + static YesType Test(const typename U::MojomUnionDataType*); template <typename U> static NoType Test(...); @@ -136,38 +125,48 @@ struct IsEnumDataType { sizeof(Test<T>(0)) == sizeof(YesType) && !IsConst<T>::value; }; -template <typename T, bool move_only = IsMoveOnlyType<T>::value> -struct WrapperTraits; +template <typename MojomType, bool move_only = IsMoveOnlyType<MojomType>::value> +struct GetDataTypeAsArrayElement; template <typename T> -struct WrapperTraits<T, false> { - typedef T DataType; +struct GetDataTypeAsArrayElement<T, false> { + using Data = + typename std::conditional<std::is_enum<T>::value, int32_t, T>::type; }; template <typename H> -struct WrapperTraits<ScopedHandleBase<H>, true> { - typedef H DataType; +struct GetDataTypeAsArrayElement<ScopedHandleBase<H>, true> { + using Data = Handle_Data; }; template <typename S> -struct WrapperTraits<StructPtr<S>, true> { - typedef typename S::Data_* DataType; +struct GetDataTypeAsArrayElement<StructPtr<S>, true> { + using Data = + typename std::conditional<IsUnionDataType<typename S::Data_>::value, + typename S::Data_, + typename S::Data_*>::type; }; template <typename S> -struct WrapperTraits<InlinedStructPtr<S>, true> { - typedef typename S::Data_* DataType; +struct GetDataTypeAsArrayElement<InlinedStructPtr<S>, true> { + using Data = + typename std::conditional<IsUnionDataType<typename S::Data_>::value, + typename S::Data_, + typename S::Data_*>::type; }; template <typename S> -struct WrapperTraits<S, true> { - typedef typename S::Data_* DataType; +struct GetDataTypeAsArrayElement<S, true> { + using Data = + typename std::conditional<IsUnionDataType<typename S::Data_>::value, + typename S::Data_, + typename S::Data_*>::type; }; template <> -struct WrapperTraits<String, false> { - typedef String_Data* DataType; +struct GetDataTypeAsArrayElement<String, false> { + using Data = String_Data*; }; template <> -struct WrapperTraits<WTF::String, false> { - typedef String_Data* DataType; +struct GetDataTypeAsArrayElement<WTF::String, false> { + using Data = String_Data*; }; } // namespace internal diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc deleted file mode 100644 index 48c52ddab5a..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/logging.h" - -namespace mojo { -namespace internal { - -namespace { - -const size_t kAlignment = 8; - -template <typename T> -T AlignImpl(T t) { - return t + (kAlignment - (t % kAlignment)) % kAlignment; -} - -} // namespace - -size_t Align(size_t size) { - return AlignImpl(size); -} - -char* AlignPointer(char* ptr) { - return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr))); -} - -bool IsAligned(const void* ptr) { - return !(reinterpret_cast<uintptr_t>(ptr) % kAlignment); -} - -void EncodePointer(const void* ptr, uint64_t* offset) { - if (!ptr) { - *offset = 0; - return; - } - - const char* p_obj = reinterpret_cast<const char*>(ptr); - const char* p_slot = reinterpret_cast<const char*>(offset); - DCHECK(p_obj > p_slot); - - *offset = static_cast<uint64_t>(p_obj - p_slot); -} - -const void* DecodePointerRaw(const uint64_t* offset) { - if (!*offset) - return nullptr; - return reinterpret_cast<const char*>(offset) + *offset; -} - -void EncodeHandle(Handle* handle, std::vector<Handle>* handles) { - if (handle->is_valid()) { - handles->push_back(*handle); - handle->set_value(static_cast<MojoHandle>(handles->size() - 1)); - } else { - handle->set_value(kEncodedInvalidHandleValue); - } -} - -void EncodeHandle(Interface_Data* data, std::vector<Handle>* handles) { - EncodeHandle(&data->handle, handles); -} - -void EncodeHandle(MojoHandle* handle, std::vector<Handle>* handles) { - EncodeHandle(reinterpret_cast<Handle*>(handle), handles); -} - -void DecodeHandle(Handle* handle, std::vector<Handle>* handles) { - if (handle->value() == kEncodedInvalidHandleValue) { - *handle = Handle(); - return; - } - DCHECK(handle->value() < handles->size()); - // Just leave holes in the vector so we don't screw up other indices. - *handle = FetchAndReset(&handles->at(handle->value())); -} - -void DecodeHandle(Interface_Data* data, std::vector<Handle>* handles) { - DecodeHandle(&data->handle, handles); -} - -void DecodeHandle(MojoHandle* handle, std::vector<Handle>* handles) { - DecodeHandle(reinterpret_cast<Handle*>(handle), handles); -} - -SerializationContext::SerializationContext() {} - -SerializationContext::SerializationContext( - scoped_refptr<MultiplexRouter> in_router) - : router(std::move(in_router)) {} - -SerializationContext::~SerializationContext() {} - -} // namespace internal -} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h deleted file mode 100644 index 7a10b1cb753..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace internal { - -class MultiplexRouter; - -// Please note that this is a different value than |mojo::kInvalidHandleValue|, -// which is the "decoded" invalid handle. -const MojoHandle kEncodedInvalidHandleValue = static_cast<MojoHandle>(-1); - -size_t Align(size_t size); -char* AlignPointer(char* ptr); - -bool IsAligned(const void* ptr); - -// Pointers are encoded as relative offsets. The offsets are relative to the -// address of where the offset value is stored, such that the pointer may be -// recovered with the expression: -// -// ptr = reinterpret_cast<char*>(offset) + *offset -// -// A null pointer is encoded as an offset value of 0. -// -void EncodePointer(const void* ptr, uint64_t* offset); -// Note: This function doesn't validate the encoded pointer value. -const void* DecodePointerRaw(const uint64_t* offset); - -// Note: This function doesn't validate the encoded pointer value. -template <typename T> -inline void DecodePointer(const uint64_t* offset, T** ptr) { - *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset))); -} - -// Handles are encoded as indices into a vector of handles. These functions -// manipulate the value of |handle|, mapping it to and from an index. - -void EncodeHandle(Handle* handle, std::vector<Handle>* handles); -void EncodeHandle(Interface_Data* data, std::vector<Handle>* handles); -void EncodeHandle(MojoHandle* handle, std::vector<Handle>* handles); -// Note: The following three functions don't validate the encoded handle value. -void DecodeHandle(Handle* handle, std::vector<Handle>* handles); -void DecodeHandle(Interface_Data* data, std::vector<Handle>* handles); -void DecodeHandle(MojoHandle* handle, std::vector<Handle>* handles); - -// The following 2 functions are used to encode/decode all objects (structs and -// arrays) in a consistent manner. - -template <typename T> -inline void Encode(T* obj, std::vector<Handle>* handles) { - if (obj->ptr) - obj->ptr->EncodePointersAndHandles(handles); - EncodePointer(obj->ptr, &obj->offset); -} - -// Note: This function doesn't validate the encoded pointer and handle values. -template <typename T> -inline void Decode(T* obj, std::vector<Handle>* handles) { - DecodePointer(&obj->offset, &obj->ptr); - if (obj->ptr) - obj->ptr->DecodePointersAndHandles(handles); -} - -template <typename T> -inline void InterfacePointerToData(InterfacePtr<T> input, - Interface_Data* output) { - InterfacePtrInfo<T> info = input.PassInterface(); - output->handle = info.PassHandle().release(); - output->version = info.version(); -} - -template <typename T> -inline void InterfaceDataToPointer(Interface_Data* input, - InterfacePtr<T>* output) { - output->Bind(InterfacePtrInfo<T>( - MakeScopedHandle(FetchAndReset(&input->handle)), input->version)); -} - -template <typename T> -inline void AssociatedInterfacePtrInfoToData( - AssociatedInterfacePtrInfo<T> input, - AssociatedInterface_Data* output) { - output->version = input.version(); - output->interface_id = - AssociatedInterfacePtrInfoHelper::PassHandle(&input).release(); -} - -template <typename T> -inline void AssociatedInterfaceDataToPtrInfo( - AssociatedInterface_Data* input, - AssociatedInterfacePtrInfo<T>* output, - MultiplexRouter* router) { - AssociatedInterfacePtrInfoHelper::SetHandle( - output, - router->CreateLocalEndpointHandle(FetchAndReset(&input->interface_id))); - output->set_version(input->version); -} - -class WTFStringContext { - public: - virtual ~WTFStringContext() {} -}; - -// Context information for serialization/deserialization routines. -struct SerializationContext { - SerializationContext(); - explicit SerializationContext(scoped_refptr<MultiplexRouter> in_router); - - ~SerializationContext(); - - // Used to serialize/deserialize associated interface pointers and requests. - scoped_refptr<MultiplexRouter> router; - - scoped_ptr<WTFStringContext> wtf_string_context; -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc index 64314ec21d2..49416d1116c 100644 --- a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc +++ b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc @@ -8,7 +8,7 @@ #include <stdint.h> #include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/system/handle.h" namespace mojo { @@ -50,8 +50,8 @@ bool BoundsChecker::ClaimMemory(const void* position, uint32_t num_bytes) { return true; } -bool BoundsChecker::ClaimHandle(const Handle& encoded_handle) { - uint32_t index = encoded_handle.value(); +bool BoundsChecker::ClaimHandle(const Handle_Data& encoded_handle) { + uint32_t index = encoded_handle.value; if (index == kEncodedInvalidHandleValue) return true; diff --git a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h index aac3b665c94..d59a68aa034 100644 --- a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h +++ b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h @@ -9,6 +9,7 @@ #include <stdint.h> #include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" namespace mojo { @@ -38,7 +39,7 @@ class BoundsChecker { // - |encoded_handle|'s value is |kEncodedInvalidHandleValue|. // - the handle is contained inside the valid range of handle indices. In this // case, the valid range is shinked to begin right after the claimed handle. - bool ClaimHandle(const Handle& encoded_handle); + bool ClaimHandle(const Handle_Data& encoded_handle); // Returns true if the specified range is not empty, and the range is // contained inside the valid memory range. diff --git a/chromium/mojo/public/cpp/bindings/lib/buffer.h b/chromium/mojo/public/cpp/bindings/lib/buffer.h index 98bbce0e6ae..c3b570e7767 100644 --- a/chromium/mojo/public/cpp/bindings/lib/buffer.h +++ b/chromium/mojo/public/cpp/bindings/lib/buffer.h @@ -10,18 +10,12 @@ namespace mojo { namespace internal { -class PickleBuffer; - // Buffer provides a way to allocate memory. Allocations are 8-byte aligned and // zero-initialized. Allocations remain valid for the lifetime of the Buffer. class Buffer { public: virtual ~Buffer() {} virtual void* Allocate(size_t num_bytes) = 0; - - // TODO(rockot): Remove this. It's a hack to get a PickleBuffer in - // Serialize_ calls without having to update every call site. - virtual PickleBuffer* AsPickleBuffer() = 0; }; } // namespace internal diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc index 70f9fd78b2a..9f1037ceae8 100644 --- a/chromium/mojo/public/cpp/bindings/lib/connector.cc +++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc @@ -8,10 +8,10 @@ #include <utility> #include "base/bind.h" +#include "base/location.h" #include "base/logging.h" #include "base/macros.h" #include "base/synchronization/lock.h" -#include "base/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/lib/sync_handle_watcher.h" namespace mojo { @@ -45,9 +45,12 @@ class MayAutoLock { // ---------------------------------------------------------------------------- Connector::Connector(ScopedMessagePipeHandle message_pipe, - ConnectorConfig config) + ConnectorConfig config, + scoped_refptr<base::SingleThreadTaskRunner> runner) : message_pipe_(std::move(message_pipe)), incoming_receiver_(nullptr), + task_runner_(std::move(runner)), + handle_watcher_(task_runner_), error_(false), drop_writes_(false), enforce_errors_from_incoming_receiver_(true), @@ -147,21 +150,11 @@ bool Connector::Accept(Message* message) { return true; MojoResult rv = - WriteMessageRaw(message_pipe_.get(), - message->data(), - message->data_num_bytes(), - message->mutable_handles()->empty() - ? nullptr - : reinterpret_cast<const MojoHandle*>( - &message->mutable_handles()->front()), - static_cast<uint32_t>(message->mutable_handles()->size()), + WriteMessageNew(message_pipe_.get(), message->TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE); switch (rv) { case MOJO_RESULT_OK: - // The handles were successfully transferred, so we don't need the message - // to track their lifetime any longer. - message->mutable_handles()->clear(); break; case MOJO_RESULT_FAILED_PRECONDITION: // There's no point in continuing to write to this pipe since the other @@ -249,7 +242,7 @@ void Connector::WaitToReadMore() { if (rv != MOJO_RESULT_OK) { // If the watch failed because the handle is invalid or its conditions can // no longer be met, we signal the error asynchronously to avoid reentry. - base::ThreadTaskRunnerHandle::Get()->PostTask( + task_runner_->PostTask( FROM_HERE, base::Bind(&Connector::OnWatcherHandleReady, weak_self_, rv)); } diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.h b/chromium/mojo/public/cpp/bindings/lib/connector.h index f61c18fb897..243159ef32f 100644 --- a/chromium/mojo/public/cpp/bindings/lib/connector.h +++ b/chromium/mojo/public/cpp/bindings/lib/connector.h @@ -5,9 +5,11 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_ +#include <memory> + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/lib/sync_handle_watcher.h" @@ -42,7 +44,9 @@ class Connector : public MessageReceiver { }; // The Connector takes ownership of |message_pipe|. - Connector(ScopedMessagePipeHandle message_pipe, ConnectorConfig config); + Connector(ScopedMessagePipeHandle message_pipe, + ConnectorConfig config, + scoped_refptr<base::SingleThreadTaskRunner> runner); ~Connector() override; // Sets the receiver to handle messages read from the message pipe. The @@ -139,6 +143,10 @@ class Connector : public MessageReceiver { return sync_handle_watcher_callback_count_ > 0; } + base::SingleThreadTaskRunner* task_runner() const { + return task_runner_.get(); + } + private: // Callback of mojo::Watcher. void OnWatcherHandleReady(MojoResult result); @@ -170,6 +178,7 @@ class Connector : public MessageReceiver { ScopedMessagePipeHandle message_pipe_; MessageReceiver* incoming_receiver_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; Watcher handle_watcher_; bool error_; @@ -180,9 +189,9 @@ class Connector : public MessageReceiver { // If sending messages is allowed from multiple threads, |lock_| is used to // protect modifications to |message_pipe_| and |drop_writes_|. - scoped_ptr<base::Lock> lock_; + std::unique_ptr<base::Lock> lock_; - scoped_ptr<SyncHandleWatcher> sync_watcher_; + std::unique_ptr<SyncHandleWatcher> sync_watcher_; bool allow_woken_up_by_others_; // If non-zero, currently the control flow is inside the sync handle watcher // callback. diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc index 1316b6d7d5c..1bcd87daf9e 100644 --- a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" namespace mojo { @@ -55,14 +56,14 @@ bool ControlMessageHandler::Run(Message* message, response_params_ptr->query_version_result = QueryVersionResult::New(); response_params_ptr->query_version_result->version = interface_version_; - size_t size = GetSerializedSize_(response_params_ptr, nullptr); + size_t size = PrepareToSerialize<RunResponseMessageParamsPtr>( + response_params_ptr, &context_); ResponseMessageBuilder builder(kRunMessageId, size, message->request_id()); RunResponseMessageParams_Data* response_params = nullptr; - Serialize_(std::move(response_params_ptr), builder.buffer(), &response_params, - nullptr); - response_params->EncodePointersAndHandles( - builder.message()->mutable_handles()); + Serialize<RunResponseMessageParamsPtr>(response_params_ptr, builder.buffer(), + &response_params, &context_); + response_params->EncodePointers(); bool ok = responder->Accept(builder.message()); ALLOW_UNUSED_LOCAL(ok); delete responder; @@ -74,10 +75,10 @@ bool ControlMessageHandler::RunOrClosePipe(Message* message) { RunOrClosePipeMessageParams_Data* params = reinterpret_cast<RunOrClosePipeMessageParams_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); + params->DecodePointers(); RunOrClosePipeMessageParamsPtr params_ptr; - Deserialize_(params, ¶ms_ptr, nullptr); + Deserialize<RunOrClosePipeMessageParamsPtr>(params, ¶ms_ptr, &context_); return interface_version_ >= params_ptr->require_version->version; } diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h index 27acde8cbdf..13b5aa6214e 100644 --- a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h +++ b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h @@ -8,6 +8,7 @@ #include <stdint.h> #include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/serialization_context.h" #include "mojo/public/cpp/bindings/message.h" namespace mojo { @@ -32,6 +33,7 @@ class ControlMessageHandler : public MessageReceiverWithResponderStatus { bool RunOrClosePipe(Message* message); uint32_t interface_version_; + SerializationContext context_; DISALLOW_COPY_AND_ASSIGN(ControlMessageHandler); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc index 620806502c2..6189e6973e7 100644 --- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc @@ -10,6 +10,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" @@ -35,10 +36,11 @@ bool RunResponseForwardToCallback::Accept(Message* message) { RunResponseMessageParams_Data* params = reinterpret_cast<RunResponseMessageParams_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); + params->DecodePointers(); RunResponseMessageParamsPtr params_ptr; - Deserialize_(params, ¶ms_ptr, nullptr); + SerializationContext context; + Deserialize<RunResponseMessageParamsPtr>(params, ¶ms_ptr, &context); callback_.Run(std::move(params_ptr->query_version_result)); return true; @@ -46,36 +48,41 @@ bool RunResponseForwardToCallback::Accept(Message* message) { void SendRunMessage(MessageReceiverWithResponder* receiver, QueryVersionPtr query_version, - const RunCallback& callback) { + const RunCallback& callback, + SerializationContext* context) { RunMessageParamsPtr params_ptr(RunMessageParams::New()); params_ptr->reserved0 = 16u; params_ptr->reserved1 = 0u; params_ptr->query_version = std::move(query_version); - size_t size = GetSerializedSize_(params_ptr, nullptr); + size_t size = PrepareToSerialize<RunMessageParamsPtr>(params_ptr, context); RequestMessageBuilder builder(kRunMessageId, size); RunMessageParams_Data* params = nullptr; - Serialize_(std::move(params_ptr), builder.buffer(), ¶ms, nullptr); - params->EncodePointersAndHandles(builder.message()->mutable_handles()); + Serialize<RunMessageParamsPtr>(params_ptr, builder.buffer(), ¶ms, + context); + params->EncodePointers(); MessageReceiver* responder = new RunResponseForwardToCallback(callback); if (!receiver->AcceptWithResponder(builder.message(), responder)) delete responder; } void SendRunOrClosePipeMessage(MessageReceiverWithResponder* receiver, - RequireVersionPtr require_version) { + RequireVersionPtr require_version, + SerializationContext* context) { RunOrClosePipeMessageParamsPtr params_ptr(RunOrClosePipeMessageParams::New()); params_ptr->reserved0 = 16u; params_ptr->reserved1 = 0u; params_ptr->require_version = std::move(require_version); - size_t size = GetSerializedSize_(params_ptr, nullptr); + size_t size = + PrepareToSerialize<RunOrClosePipeMessageParamsPtr>(params_ptr, context); MessageBuilder builder(kRunOrClosePipeMessageId, size); RunOrClosePipeMessageParams_Data* params = nullptr; - Serialize_(std::move(params_ptr), builder.buffer(), ¶ms, nullptr); - params->EncodePointersAndHandles(builder.message()->mutable_handles()); + Serialize<RunOrClosePipeMessageParamsPtr>(params_ptr, builder.buffer(), + ¶ms, context); + params->EncodePointers(); bool ok = receiver->Accept(builder.message()); ALLOW_UNUSED_LOCAL(ok); } @@ -91,13 +98,13 @@ void ControlMessageProxy::QueryVersion( auto run_callback = [callback](QueryVersionResultPtr query_version_result) { callback.Run(query_version_result->version); }; - SendRunMessage(receiver_, QueryVersion::New(), run_callback); + SendRunMessage(receiver_, QueryVersion::New(), run_callback, &context_); } void ControlMessageProxy::RequireVersion(uint32_t version) { RequireVersionPtr require_version(RequireVersion::New()); require_version->version = version; - SendRunOrClosePipeMessage(receiver_, std::move(require_version)); + SendRunOrClosePipeMessage(receiver_, std::move(require_version), &context_); } } // namespace internal diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h index 33aaf82a9f3..ce20fc8415f 100644 --- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h +++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h @@ -9,6 +9,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/serialization_context.h" namespace mojo { @@ -28,6 +29,7 @@ class ControlMessageProxy { protected: // Not owned. MessageReceiverWithResponder* receiver_; + SerializationContext context_; DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc index 9653345532e..50b8a21c56b 100644 --- a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc +++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc @@ -10,7 +10,7 @@ #include <algorithm> #include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" namespace mojo { namespace internal { @@ -39,8 +39,6 @@ void* FixedBuffer::Allocate(size_t delta) { return result; } -PickleBuffer* FixedBuffer::AsPickleBuffer() { return nullptr; } - FixedBufferForTesting::FixedBufferForTesting(size_t size) { size_ = internal::Align(size); // Use calloc here to ensure all message memory is zero'd out. diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h index d087c3b36a5..9a5704b4bfa 100644 --- a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h +++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h @@ -51,8 +51,6 @@ class FixedBuffer : public Buffer { // memory is zero-filled. void* Allocate(size_t num_bytes) override; - PickleBuffer* AsPickleBuffer() override; - protected: char* ptr_; size_t cursor_; diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc index 574d627888a..9e32c5af239 100644 --- a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc @@ -5,15 +5,15 @@ #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" #include <stdint.h> + #include <utility> #include "base/bind.h" #include "base/location.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" -#include "base/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/lib/interface_endpoint_controller.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" @@ -38,18 +38,24 @@ void DCheckIfInvalid(const base::WeakPtr<InterfaceEndpointClient>& client, class ResponderThunk : public MessageReceiverWithStatus { public: explicit ResponderThunk( - const base::WeakPtr<InterfaceEndpointClient>& endpoint_client) - : endpoint_client_(endpoint_client), accept_was_invoked_(false), - task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + const base::WeakPtr<InterfaceEndpointClient>& endpoint_client, + scoped_refptr<base::SingleThreadTaskRunner> runner) + : endpoint_client_(endpoint_client), + accept_was_invoked_(false), + task_runner_(std::move(runner)) {} ~ResponderThunk() override { if (!accept_was_invoked_) { // The Mojo application handled a message that was expecting a response // but did not send a response. + // We raise an error to signal the calling application that an error + // condition occurred. Without this the calling application would have no + // way of knowing it should stop waiting for a response. if (task_runner_->RunsTasksOnCurrentThread()) { + // Please note that even if this code is run from a different task + // runner on the same thread as |task_runner_|, it is okay to directly + // call InterfaceEndpointClient::RaiseError(), because it will raise + // error from the correct task runner asynchronously. if (endpoint_client_) { - // We raise an error to signal the calling application that an error - // condition occurred. Without this the calling application would have - // no way of knowing it should stop waiting for a response. endpoint_client_->RaiseError(); } } else { @@ -126,14 +132,16 @@ bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept( InterfaceEndpointClient::InterfaceEndpointClient( ScopedInterfaceEndpointHandle handle, MessageReceiverWithResponderStatus* receiver, - scoped_ptr<MessageFilter> payload_validator, - bool expect_sync_requests) + std::unique_ptr<MessageFilter> payload_validator, + bool expect_sync_requests, + scoped_refptr<base::SingleThreadTaskRunner> runner) : handle_(std::move(handle)), incoming_receiver_(receiver), payload_validator_(std::move(payload_validator)), thunk_(this), next_request_id_(1), encountered_error_(false), + task_runner_(std::move(runner)), weak_ptr_factory_(this) { DCHECK(handle_.is_valid()); DCHECK(handle_.is_local()); @@ -142,7 +150,8 @@ InterfaceEndpointClient::InterfaceEndpointClient( // directly is a little awkward. payload_validator_->set_sink(&thunk_); - controller_ = handle_.router()->AttachEndpointClient(handle_, this); + controller_ = + handle_.router()->AttachEndpointClient(handle_, this, task_runner_); if (expect_sync_requests) controller_->AllowWokenUpBySyncWatchOnSameThread(); } @@ -210,19 +219,20 @@ bool InterfaceEndpointClient::AcceptWithResponder(Message* message, message->set_request_id(request_id); + bool is_sync = message->has_flag(kMessageIsSync); if (!controller_->SendMessage(message)) return false; - if (!message->has_flag(kMessageIsSync)) { + if (!is_sync) { // We assume ownership of |responder|. - async_responders_[request_id] = make_scoped_ptr(responder); + async_responders_[request_id] = base::WrapUnique(responder); return true; } bool response_received = false; - scoped_ptr<MessageReceiver> sync_responder(responder); + std::unique_ptr<MessageReceiver> sync_responder(responder); sync_responses_.insert(std::make_pair( - request_id, make_scoped_ptr(new SyncResponseInfo(&response_received)))); + request_id, base::WrapUnique(new SyncResponseInfo(&response_received)))); base::WeakPtr<InterfaceEndpointClient> weak_self = weak_ptr_factory_.GetWeakPtr(); @@ -233,7 +243,7 @@ bool InterfaceEndpointClient::AcceptWithResponder(Message* message, auto iter = sync_responses_.find(request_id); DCHECK_EQ(&response_received, iter->second->response_received); if (response_received) { - scoped_ptr<Message> response = std::move(iter->second->response); + std::unique_ptr<Message> response = std::move(iter->second->response); ignore_result(sync_responder->Accept(response.get())); } sync_responses_.erase(iter); @@ -266,7 +276,7 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) { return false; MessageReceiverWithStatus* responder = - new ResponderThunk(weak_ptr_factory_.GetWeakPtr()); + new ResponderThunk(weak_ptr_factory_.GetWeakPtr(), task_runner_); bool ok = incoming_receiver_->AcceptWithResponder(message, responder); if (!ok) delete responder; @@ -287,7 +297,7 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) { auto it = async_responders_.find(request_id); if (it == async_responders_.end()) return false; - scoped_ptr<MessageReceiver> responder = std::move(it->second); + std::unique_ptr<MessageReceiver> responder = std::move(it->second); async_responders_.erase(it); return responder->Accept(message); } else { diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.h b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.h index 2560cfc42dc..3f820db3c30 100644 --- a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.h +++ b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.h @@ -8,16 +8,18 @@ #include <stdint.h> #include <map> +#include <memory> #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/message_filter.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { @@ -37,8 +39,9 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder { // object. InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle, MessageReceiverWithResponderStatus* receiver, - scoped_ptr<MessageFilter> payload_validator, - bool expect_sync_requests); + std::unique_ptr<MessageFilter> payload_validator, + bool expect_sync_requests, + scoped_refptr<base::SingleThreadTaskRunner> runner); ~InterfaceEndpointClient() override; // Sets the error handler to receive notifications when an error is @@ -86,14 +89,15 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder { private: // Maps from the id of a response to the MessageReceiver that handles the // response. - using AsyncResponderMap = std::map<uint64_t, scoped_ptr<MessageReceiver>>; + using AsyncResponderMap = + std::map<uint64_t, std::unique_ptr<MessageReceiver>>; struct SyncResponseInfo { public: explicit SyncResponseInfo(bool* in_response_received); ~SyncResponseInfo(); - scoped_ptr<Message> response; + std::unique_ptr<Message> response; // Points to a stack-allocated variable. bool* response_received; @@ -102,7 +106,7 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder { DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo); }; - using SyncResponseMap = std::map<uint64_t, scoped_ptr<SyncResponseInfo>>; + using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>; // Used as the sink for |payload_validator_| and forwards messages to // HandleValidatedMessage(). @@ -123,11 +127,11 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder { bool HandleValidatedMessage(Message* message); ScopedInterfaceEndpointHandle handle_; - scoped_ptr<AssociatedGroup> associated_group_; + std::unique_ptr<AssociatedGroup> associated_group_; InterfaceEndpointController* controller_; MessageReceiverWithResponderStatus* const incoming_receiver_; - scoped_ptr<MessageFilter> payload_validator_; + std::unique_ptr<MessageFilter> payload_validator_; HandleIncomingMessageThunk thunk_; AsyncResponderMap async_responders_; @@ -138,6 +142,8 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder { Closure error_handler_; bool encountered_error_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::ThreadChecker thread_checker_; base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_; diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h index 3f7d938e2dd..8cda57d2bdf 100644 --- a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h +++ b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h @@ -6,13 +6,16 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ #include <stdint.h> + #include <algorithm> // For |std::swap()|. +#include <memory> #include <utility> #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/interface_ptr_info.h" @@ -23,7 +26,7 @@ #include "mojo/public/cpp/bindings/lib/message_header_validator.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" #include "mojo/public/cpp/bindings/lib/router.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace mojo { namespace internal { @@ -89,10 +92,12 @@ class InterfacePtrState<Interface, false> { swap(other->proxy_, proxy_); swap(other->router_, router_); handle_.swap(other->handle_); + runner_.swap(other->runner_); swap(other->version_, version_); } - void Bind(InterfacePtrInfo<Interface> info) { + void Bind(InterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner) { DCHECK(!proxy_); DCHECK(!router_); DCHECK(!handle_.is_valid()); @@ -101,6 +106,7 @@ class InterfacePtrState<Interface, false> { handle_ = info.PassHandle(); version_ = info.version(); + runner_ = std::move(runner); } bool HasAssociatedInterfaces() const { return false; } @@ -161,7 +167,8 @@ class InterfacePtrState<Interface, false> { filters.Append<MessageHeaderValidator>(); filters.Append<typename Interface::ResponseValidator_>(); - router_ = new Router(std::move(handle_), std::move(filters), false); + router_ = new Router(std::move(handle_), std::move(filters), false, + std::move(runner_)); proxy_ = new Proxy(router_); } @@ -173,6 +180,7 @@ class InterfacePtrState<Interface, false> { // message pipe handle is needed. |handle_| is valid between the Bind() call // and the initialization of |proxy_| and |router_|. ScopedMessagePipeHandle handle_; + scoped_refptr<base::SingleThreadTaskRunner> runner_; uint32_t version_; @@ -236,10 +244,12 @@ class InterfacePtrState<Interface, true> { swap(other->endpoint_client_, endpoint_client_); swap(other->proxy_, proxy_); handle_.swap(other->handle_); + runner_.swap(other->runner_); swap(other->version_, version_); } - void Bind(InterfacePtrInfo<Interface> info) { + void Bind(InterfacePtrInfo<Interface> info, + scoped_refptr<base::SingleThreadTaskRunner> runner) { DCHECK(!router_); DCHECK(!endpoint_client_); DCHECK(!proxy_); @@ -249,6 +259,7 @@ class InterfacePtrState<Interface, true> { handle_ = info.PassHandle(); version_ = info.version(); + runner_ = std::move(runner); } bool HasAssociatedInterfaces() const { @@ -313,23 +324,25 @@ class InterfacePtrState<Interface, true> { if (!handle_.is_valid()) return; - router_ = new MultiplexRouter(true, std::move(handle_)); + router_ = new MultiplexRouter(true, std::move(handle_), runner_); endpoint_client_.reset(new InterfaceEndpointClient( router_->CreateLocalEndpointHandle(kMasterInterfaceId), nullptr, - make_scoped_ptr(new typename Interface::ResponseValidator_()), false)); + base::WrapUnique(new typename Interface::ResponseValidator_()), false, + std::move(runner_))); proxy_.reset(new Proxy(endpoint_client_.get())); proxy_->serialization_context()->router = endpoint_client_->router(); } scoped_refptr<MultiplexRouter> router_; - scoped_ptr<InterfaceEndpointClient> endpoint_client_; - scoped_ptr<Proxy> proxy_; + std::unique_ptr<InterfaceEndpointClient> endpoint_client_; + std::unique_ptr<Proxy> proxy_; // |router_| (as well as other members above) is not initialized until // read/write with the message pipe handle is needed. |handle_| is valid // between the Bind() call and the initialization of |router_|. ScopedMessagePipeHandle handle_; + scoped_refptr<base::SingleThreadTaskRunner> runner_; uint32_t version_; diff --git a/chromium/mojo/public/cpp/bindings/lib/macros.h b/chromium/mojo/public/cpp/bindings/lib/macros.h deleted file mode 100644 index 62f4292c1ee..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/macros.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MACROS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MACROS_H_ - -// This file defines macros that are only used by generated bindings. - -// The C++ standard requires that static const members have an out-of-class -// definition (in a single compilation unit), but MSVC chokes on this (when -// language extensions, which are required, are enabled). (You're only likely to -// notice the need for a definition if you take the address of the member or, -// more commonly, pass it to a function that takes it as a reference argument -- -// probably an STL function.) This macro makes MSVC do the right thing. See -// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more -// information. This workaround does not appear to be necessary after VS2015. -// Use like: -// -// In the .h file: -// struct Foo { -// static const int kBar = 5; -// }; -// -// In the .cc file: -// MOJO_STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar; -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define MOJO_STATIC_CONST_MEMBER_DEFINITION __declspec(selectany) -#else -#define MOJO_STATIC_CONST_MEMBER_DEFINITION -#endif - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MACROS_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h b/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h index 8315dbc8e10..a5363617817 100644 --- a/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h +++ b/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h @@ -113,17 +113,17 @@ class Map_Data { StructHeader header_; - ArrayPointer<Key> keys; - ArrayPointer<Value> values; + Pointer<Array_Data<Key>> keys; + Pointer<Array_Data<Value>> values; - void EncodePointersAndHandles(std::vector<mojo::Handle>* handles) { - Encode(&keys, handles); - Encode(&values, handles); + void EncodePointers() { + Encode(&keys); + Encode(&values); } - void DecodePointersAndHandles(std::vector<mojo::Handle>* handles) { - Decode(&keys, handles); - Decode(&values, handles); + void DecodePointers() { + Decode(&keys); + Decode(&values); } private: diff --git a/chromium/mojo/public/cpp/bindings/lib/map_serialization.h b/chromium/mojo/public/cpp/bindings/lib/map_serialization.h index bca23796bba..56ef68d3162 100644 --- a/chromium/mojo/public/cpp/bindings/lib/map_serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/map_serialization.h @@ -5,191 +5,115 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ -#include <stddef.h> -#include <utility> - -#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/array.h" #include "mojo/public/cpp/bindings/lib/map_data_internal.h" -#include "mojo/public/cpp/bindings/lib/map_internal.h" #include "mojo/public/cpp/bindings/lib/serialization_forward.h" #include "mojo/public/cpp/bindings/map.h" namespace mojo { namespace internal { -template <typename MapType, - typename DataType, - bool value_is_move_only_type = IsMoveOnlyType<MapType>::value, - bool is_union = - IsUnionDataType<typename RemovePointer<DataType>::type>::value> -struct MapSerializer; - -template <typename MapType, typename DataType> -struct MapSerializer<MapType, DataType, false, false> { - static size_t GetBaseArraySize(size_t count) { - return Align(count * sizeof(DataType)); - } - static size_t GetItemSize(const MapType& item, - SerializationContext* context) { - return 0; - } -}; - -template <> -struct MapSerializer<bool, bool, false, false> { - static size_t GetBaseArraySize(size_t count) { - return Align((count + 7) / 8); - } - static size_t GetItemSize(bool item, SerializationContext* context) { - return 0; - } -}; - -template <typename H> -struct MapSerializer<ScopedHandleBase<H>, H, true, false> { - static size_t GetBaseArraySize(size_t count) { - return Align(count * sizeof(H)); - } - static size_t GetItemSize(const ScopedHandleBase<H>& item, - SerializationContext* context) { - return 0; - } -}; - -// 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 MapSerializer< - 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 GetBaseArraySize(size_t count) { - return count * sizeof(StructPointer<S_Data>); - } - static size_t GetItemSize(const S& item, SerializationContext* context) { - return GetSerializedSize_(item, context); - } -}; +template <typename Key, typename Value> +struct MapContext { + explicit MapContext(bool in_is_null) : is_null(in_is_null) {} -template <typename U, typename U_Data> -struct MapSerializer<U, U_Data*, true, true> { - static size_t GetBaseArraySize(size_t count) { - return count * sizeof(U_Data); - } - static size_t GetItemSize(const U& item, SerializationContext* context) { - return GetSerializedSize_(item, true, context); - } + bool is_null; + Array<Key> keys; + Array<Value> values; }; -template <> -struct MapSerializer<String, String_Data*, false, false> { - static size_t GetBaseArraySize(size_t count) { - return count * sizeof(StringPointer); +template <typename Key, typename Value, typename MaybeConstUserType> +struct Serializer<Map<Key, Value>, MaybeConstUserType> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using UserKey = typename UserType::Key; + using UserValue = typename UserType::Value; + using Data = typename Map<Key, Value>::Data_; + + static_assert(std::is_same<MaybeConstUserType, UserType>::value, + "Only support serialization of non-const Maps."); + static_assert(IsSpecializationOf<Map, UserType>::value, + "Custom mapping of mojom map is not supported yet."); + + static size_t PrepareToSerialize(UserType& input, + SerializationContext* context) { + auto map_context = new MapContext<UserKey, UserValue>(input.is_null()); + if (!context->custom_contexts) + context->custom_contexts.reset(new std::queue<void*>()); + context->custom_contexts->push(map_context); + + if (!input) + return 0; + + input.DecomposeMapTo(&map_context->keys, &map_context->values); + + size_t struct_overhead = sizeof(Data); + size_t keys_size = + internal::PrepareToSerialize<Array<Key>>(map_context->keys, context); + size_t values_size = internal::PrepareToSerialize<Array<Value>>( + map_context->values, context); + + return struct_overhead + keys_size + values_size; } - static size_t GetItemSize(const String& item, SerializationContext* context) { - return GetSerializedSize_(item, context); - } -}; - -} // namespace internal -// TODO(erg): This can't go away yet. We still need to calculate out the size -// of a struct header, and two arrays. -template <typename MapKey, typename MapValue> -inline size_t GetSerializedSize_(const Map<MapKey, MapValue>& input, - internal::SerializationContext* context) { - if (!input) - return 0; - typedef typename internal::WrapperTraits<MapKey>::DataType DataKey; - typedef typename internal::WrapperTraits<MapValue>::DataType DataValue; - - size_t count = input.size(); - size_t struct_overhead = sizeof(mojo::internal::Map_Data<DataKey, DataValue>); - size_t key_base_size = - sizeof(internal::ArrayHeader) + - internal::MapSerializer<MapKey, DataKey>::GetBaseArraySize(count); - size_t value_base_size = - sizeof(internal::ArrayHeader) + - internal::MapSerializer<MapValue, DataValue>::GetBaseArraySize(count); - - size_t key_data_size = 0; - size_t value_data_size = 0; - for (auto it = input.begin(); it != input.end(); ++it) { - key_data_size += internal::MapSerializer<MapKey, DataKey>::GetItemSize( - it->first, context); - value_data_size += - internal::MapSerializer<MapValue, DataValue>::GetItemSize(it->second, - context); - } + // We don't need an ArrayValidateParams instance for key validation since + // we can deduce it from the Key type. (which can only be primitive types or + // non-nullable strings.) + static void Serialize(UserType& input, + Buffer* buf, + Data** output, + const ArrayValidateParams* value_validate_params, + SerializationContext* context) { + std::unique_ptr<MapContext<UserKey, UserValue>> map_context( + static_cast<MapContext<UserKey, UserValue>*>( + context->custom_contexts->front())); + context->custom_contexts->pop(); + + if (map_context->is_null) { + *output = nullptr; + return; + } - return struct_overhead + key_base_size + key_data_size + value_base_size + - value_data_size; -} - -// We don't need an ArrayValidateParams instance for key validation since -// we can deduce it from the Key type. (which can only be primitive types or -// non-nullable strings.) -template <typename MapKey, - typename MapValue, - typename DataKey, - typename DataValue> -inline void SerializeMap_( - Map<MapKey, MapValue> input, - internal::Buffer* buf, - internal::Map_Data<DataKey, DataValue>** output, - const internal::ArrayValidateParams* value_validate_params, - internal::SerializationContext* context) { - if (input) { - internal::Map_Data<DataKey, DataValue>* result = - internal::Map_Data<DataKey, DataValue>::New(buf); + auto result = Data::New(buf); if (result) { - Array<MapKey> keys; - Array<MapValue> values; - input.DecomposeMapTo(&keys, &values); - const internal::ArrayValidateParams* key_validate_params = - internal::MapKeyValidateParamsFactory<DataKey>::Get(); - SerializeArray_(std::move(keys), buf, &result->keys.ptr, - key_validate_params, context); - SerializeArray_(std::move(values), buf, &result->values.ptr, - value_validate_params, context); + const ArrayValidateParams* key_validate_params = + MapKeyValidateParamsFactory< + typename GetDataTypeAsArrayElement<Key>::Data>::Get(); + internal::Serialize<Array<Key>>(map_context->keys, buf, &result->keys.ptr, + key_validate_params, context); + internal::Serialize<Array<Value>>(map_context->values, buf, + &result->values.ptr, + value_validate_params, context); } *output = result; - } else { - *output = nullptr; } -} - -template <typename MapKey, - typename MapValue, - typename DataKey, - typename DataValue> -inline bool Deserialize_(internal::Map_Data<DataKey, DataValue>* input, - Map<MapKey, MapValue>* output, - internal::SerializationContext* context) { - bool success = true; - if (input) { - Array<MapKey> keys; - Array<MapValue> values; - - // Note that we rely on complete deserialization taking place in order to - // transfer ownership of all encoded handles. Therefore we don't - // short-circuit on failure here. - if (!Deserialize_(input->keys.ptr, &keys, context)) - success = false; - if (!Deserialize_(input->values.ptr, &values, context)) - success = false; - - *output = Map<MapKey, MapValue>(std::move(keys), std::move(values)); - } else { - *output = nullptr; + + static bool Deserialize(Data* input, + UserType* output, + SerializationContext* context) { + bool success = true; + if (input) { + Array<UserKey> keys; + Array<UserValue> values; + + // Note that we rely on complete deserialization taking place in order to + // transfer ownership of all encoded handles. Therefore we don't + // short-circuit on failure here. + if (!internal::Deserialize<Array<Key>>(input->keys.ptr, &keys, context)) + success = false; + if (!internal::Deserialize<Array<Value>>(input->values.ptr, &values, + context)) { + success = false; + } + + *output = UserType(std::move(keys), std::move(values)); + } else { + *output = nullptr; + } + return success; } - return success; -} +}; +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc index e1e8f190df9..4274cc86cb1 100644 --- a/chromium/mojo/public/cpp/bindings/lib/message.cc +++ b/chromium/mojo/public/cpp/bindings/lib/message.cc @@ -9,6 +9,7 @@ #include <stdlib.h> #include <algorithm> +#include <utility> #include "base/logging.h" @@ -23,7 +24,15 @@ Message::~Message() { void Message::Initialize(size_t capacity, bool zero_initialized) { DCHECK(!buffer_); - buffer_.reset(new internal::PickleBuffer(capacity, zero_initialized)); + buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); +} + +void Message::InitializeFromMojoMessage(ScopedMessageHandle message, + uint32_t num_bytes, + std::vector<Handle>* handles) { + DCHECK(!buffer_); + buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); + handles_.swap(*handles); } void Message::MoveTo(Message* destination) { @@ -38,6 +47,37 @@ void Message::MoveTo(Message* destination) { buffer_.reset(); } +ScopedMessageHandle Message::TakeMojoMessage() { + if (handles_.empty()) // Fast path for the common case: No handles. + return buffer_->TakeMessage(); + + // Allocate a new message with space for the handles, then copy the buffer + // contents into it. + // + // TODO(rockot): We could avoid this copy by extending GetSerializedSize() + // behavior to collect handles. It's unoptimized for now because it's much + // more common to have messages with no handles. + ScopedMessageHandle new_message; + MojoResult rv = AllocMessage( + data_num_bytes(), + handles_.empty() ? nullptr + : reinterpret_cast<const MojoHandle*>(handles_.data()), + handles_.size(), + MOJO_ALLOC_MESSAGE_FLAG_NONE, + &new_message); + CHECK_EQ(rv, MOJO_RESULT_OK); + handles_.clear(); + + void* new_buffer = nullptr; + rv = GetMessageBuffer(new_message.get(), &new_buffer); + CHECK_EQ(rv, MOJO_RESULT_OK); + + memcpy(new_buffer, data(), data_num_bytes()); + buffer_.reset(); + + return new_message; +} + void Message::CloseHandles() { for (std::vector<Handle>::iterator it = handles_.begin(); it != handles_.end(); ++it) { @@ -49,28 +89,32 @@ void Message::CloseHandles() { MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { MojoResult rv; + std::vector<Handle> handles; + ScopedMessageHandle mojo_message; uint32_t num_bytes = 0, num_handles = 0; - rv = ReadMessageRaw(handle, - nullptr, + rv = ReadMessageNew(handle, + &mojo_message, &num_bytes, nullptr, &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) - return rv; - - message->Initialize(num_bytes, false /* zero_initialized */); + if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { + DCHECK_GT(num_handles, 0u); + handles.resize(num_handles); + rv = ReadMessageNew(handle, + &mojo_message, + &num_bytes, + reinterpret_cast<MojoHandle*>(handles.data()), + &num_handles, + MOJO_READ_MESSAGE_FLAG_NONE); + } - void* mutable_data = message->buffer()->Allocate(num_bytes); - message->mutable_handles()->resize(num_handles); + if (rv != MOJO_RESULT_OK) + return rv; - rv = ReadMessageRaw( - handle, mutable_data, &num_bytes, - message->mutable_handles()->empty() - ? nullptr - : reinterpret_cast<MojoHandle*>(message->mutable_handles()->data()), - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - return rv; + message->InitializeFromMojoMessage( + std::move(mojo_message), num_bytes, &handles); + return MOJO_RESULT_OK; } } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc new file mode 100644 index 00000000000..7a153647f8f --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc @@ -0,0 +1,65 @@ +// Copyright 2016 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/lib/message_buffer.h" + +#include <limits> + +#include "mojo/public/cpp/bindings/lib/serialization_util.h" + +namespace mojo { +namespace internal { + +MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) { + DCHECK_LE(capacity, std::numeric_limits<uint32_t>::max()); + data_num_bytes_ = static_cast<uint32_t>(capacity); + + MojoResult rv = AllocMessage(capacity, nullptr, 0, + MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_); + CHECK_EQ(rv, MOJO_RESULT_OK); + + if (capacity == 0) { + buffer_ = nullptr; + } else { + rv = GetMessageBuffer(message_.get(), &buffer_); + CHECK_EQ(rv, MOJO_RESULT_OK); + + if (zero_initialized) + memset(buffer_, 0, capacity); + } +} + +MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) { + message_ = std::move(message); + data_num_bytes_ = num_bytes; + + if (num_bytes == 0) { + buffer_ = nullptr; + } else { + MojoResult rv = GetMessageBuffer(message_.get(), &buffer_); + CHECK_EQ(rv, MOJO_RESULT_OK); + } +} + +MessageBuffer::~MessageBuffer() {} + +void* MessageBuffer::Allocate(size_t delta) { + delta = internal::Align(delta); + + DCHECK_LE(delta, static_cast<size_t>(data_num_bytes_)); + DCHECK_GT(bytes_claimed_ + static_cast<uint32_t>(delta), bytes_claimed_); + + uint32_t new_bytes_claimed = bytes_claimed_ + static_cast<uint32_t>(delta); + if (new_bytes_claimed > data_num_bytes_) { + NOTREACHED(); + return nullptr; + } + + char* start = static_cast<char*>(buffer_) + bytes_claimed_; + bytes_claimed_ = new_bytes_claimed; + return static_cast<void*>(start); +} + +} // namespace internal +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/message_buffer.h b/chromium/mojo/public/cpp/bindings/lib/message_buffer.h new file mode 100644 index 00000000000..47ffea01514 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/message_buffer.h @@ -0,0 +1,52 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <utility> + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/buffer.h" +#include "mojo/public/cpp/system/message.h" + +namespace mojo { +namespace internal { + +// A fixed-size Buffer implementation using a Mojo message object for storage. +class MessageBuffer : public Buffer { + public: + // Initializes this buffer to carry a fixed byte capacity and no handles. + MessageBuffer(size_t capacity, bool zero_initialized); + + // Initializes this buffer from an existing Mojo MessageHandle. + MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes); + + ~MessageBuffer() override; + + void* data() const { return buffer_; } + uint32_t data_num_bytes() const { return data_num_bytes_; } + + // Buffer: + void* Allocate(size_t delta) override; + + ScopedMessageHandle TakeMessage() { return std::move(message_); } + + private: + uint32_t data_num_bytes_ = 0; + ScopedMessageHandle message_; + void* buffer_; + + uint32_t bytes_claimed_ = 0; + + DISALLOW_COPY_AND_ASSIGN(MessageBuffer); +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/message_builder.cc b/chromium/mojo/public/cpp/bindings/lib/message_builder.cc index 428fa91fda1..4ffa1808cc9 100644 --- a/chromium/mojo/public/cpp/bindings/lib/message_builder.cc +++ b/chromium/mojo/public/cpp/bindings/lib/message_builder.cc @@ -7,7 +7,7 @@ #include <stddef.h> #include <stdint.h> -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/message.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc index 75d14467e5a..d081b0155ba 100644 --- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -64,12 +65,14 @@ class MultiplexRouter::InterfaceEndpoint InterfaceEndpointClient* client() const { return client_; } - void AttachClient(InterfaceEndpointClient* client) { + void AttachClient(InterfaceEndpointClient* client, + scoped_refptr<base::SingleThreadTaskRunner> runner) { router_->lock_.AssertAcquired(); DCHECK(!client_); DCHECK(!closed_); + DCHECK(runner->BelongsToCurrentThread()); - task_runner_ = base::MessageLoop::current()->task_runner(); + task_runner_ = std::move(runner); client_ = client; } @@ -241,7 +244,7 @@ class MultiplexRouter::InterfaceEndpoint // used exclusively on the client's thread. They may be accessed outside of // the router's lock. - scoped_ptr<SyncHandleWatcher> sync_watcher_; + std::unique_ptr<SyncHandleWatcher> sync_watcher_; DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); }; @@ -249,16 +252,17 @@ class MultiplexRouter::InterfaceEndpoint struct MultiplexRouter::Task { public: // Doesn't take ownership of |message| but takes its contents. - static scoped_ptr<Task> CreateMessageTask(Message* message) { + static std::unique_ptr<Task> CreateMessageTask(Message* message) { Task* task = new Task(MESSAGE); task->message.reset(new Message); message->MoveTo(task->message.get()); - return make_scoped_ptr(task); + return base::WrapUnique(task); } - static scoped_ptr<Task> CreateNotifyErrorTask(InterfaceEndpoint* endpoint) { + static std::unique_ptr<Task> CreateNotifyErrorTask( + InterfaceEndpoint* endpoint) { Task* task = new Task(NOTIFY_ERROR); task->endpoint_to_notify = endpoint; - return make_scoped_ptr(task); + return base::WrapUnique(task); } ~Task() {} @@ -266,7 +270,7 @@ struct MultiplexRouter::Task { bool IsMessageTask() const { return type == MESSAGE; } bool IsNotifyErrorTask() const { return type == NOTIFY_ERROR; } - scoped_ptr<Message> message; + std::unique_ptr<Message> message; scoped_refptr<InterfaceEndpoint> endpoint_to_notify; enum Type { MESSAGE, NOTIFY_ERROR }; @@ -276,13 +280,17 @@ struct MultiplexRouter::Task { explicit Task(Type in_type) : type(in_type) {} }; -MultiplexRouter::MultiplexRouter(bool set_interface_id_namesapce_bit, - ScopedMessagePipeHandle message_pipe) +MultiplexRouter::MultiplexRouter( + bool set_interface_id_namesapce_bit, + ScopedMessagePipeHandle message_pipe, + scoped_refptr<base::SingleThreadTaskRunner> runner) : RefCountedDeleteOnMessageLoop( base::MessageLoop::current()->task_runner()), set_interface_id_namespace_bit_(set_interface_id_namesapce_bit), header_validator_(this), - connector_(std::move(message_pipe), Connector::MULTI_THREADED_SEND), + connector_(std::move(message_pipe), + Connector::MULTI_THREADED_SEND, + std::move(runner)), control_message_handler_(this), control_message_proxy_(&connector_), next_interface_id_value_(1), @@ -384,12 +392,13 @@ void MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) { if (!IsMasterInterfaceId(id)) control_message_proxy_.NotifyPeerEndpointClosed(id); - ProcessTasks(NO_DIRECT_CLIENT_CALLS); + ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); } InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* client) { + InterfaceEndpointClient* client, + scoped_refptr<base::SingleThreadTaskRunner> runner) { const InterfaceId id = handle.id(); DCHECK(IsValidInterfaceId(id)); @@ -399,11 +408,11 @@ InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( DCHECK(ContainsKey(endpoints_, id)); InterfaceEndpoint* endpoint = endpoints_[id].get(); - endpoint->AttachClient(client); + endpoint->AttachClient(client, std::move(runner)); if (endpoint->peer_closed()) tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - ProcessTasks(NO_DIRECT_CLIENT_CALLS); + ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); return endpoint; } @@ -430,8 +439,8 @@ void MultiplexRouter::RaiseError() { } } -scoped_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() { - scoped_ptr<AssociatedGroup> group(new AssociatedGroup); +std::unique_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() { + std::unique_ptr<AssociatedGroup> group(new AssociatedGroup); group->router_ = this; return group; } @@ -482,7 +491,8 @@ bool MultiplexRouter::Accept(Message* message) { : ALLOW_DIRECT_CLIENT_CALLS; bool processed = - tasks_.empty() && ProcessIncomingMessage(message, client_call_behavior); + tasks_.empty() && ProcessIncomingMessage(message, client_call_behavior, + connector_.task_runner()); if (!processed) { // Either the task queue is not empty or we cannot process the message @@ -501,7 +511,7 @@ bool MultiplexRouter::Accept(Message* message) { // Processing the message may result in new tasks (for error notification) // being added to the queue. In this case, we have to attempt to process the // tasks. - ProcessTasks(client_call_behavior); + ProcessTasks(client_call_behavior, connector_.task_runner()); } // Always return true. If we see errors during message processing, we will @@ -564,17 +574,20 @@ void MultiplexRouter::OnPipeConnectionError() { ProcessTasks(connector_.during_sync_handle_watcher_callback() ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES - : ALLOW_DIRECT_CLIENT_CALLS); + : ALLOW_DIRECT_CLIENT_CALLS, + connector_.task_runner()); } -void MultiplexRouter::ProcessTasks(ClientCallBehavior client_call_behavior) { +void MultiplexRouter::ProcessTasks( + ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner) { lock_.AssertAcquired(); if (posted_to_process_tasks_) return; while (!tasks_.empty()) { - scoped_ptr<Task> task(std::move(tasks_.front())); + std::unique_ptr<Task> task(std::move(tasks_.front())); tasks_.pop_front(); InterfaceId id = kInvalidInterfaceId; @@ -589,8 +602,10 @@ void MultiplexRouter::ProcessTasks(ClientCallBehavior client_call_behavior) { bool processed = task->IsNotifyErrorTask() - ? ProcessNotifyErrorTask(task.get(), client_call_behavior) - : ProcessIncomingMessage(task->message.get(), client_call_behavior); + ? ProcessNotifyErrorTask(task.get(), client_call_behavior, + current_task_runner) + : ProcessIncomingMessage(task->message.get(), client_call_behavior, + current_task_runner); if (!processed) { tasks_.push_front(std::move(task)); @@ -620,11 +635,11 @@ bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) { iter->second.pop_front(); DCHECK(task->IsMessageTask()); - scoped_ptr<Message> message(std::move(task->message)); + std::unique_ptr<Message> message(std::move(task->message)); // Note: after this call, |task| and |iter| may be invalidated. bool processed = ProcessIncomingMessage( - message.get(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES); + message.get(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, nullptr); DCHECK(processed); iter = sync_message_tasks_.find(id); @@ -633,18 +648,22 @@ bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) { bool MultiplexRouter::ProcessNotifyErrorTask( Task* task, - ClientCallBehavior client_call_behavior) { + ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner) { + DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); lock_.AssertAcquired(); InterfaceEndpoint* endpoint = task->endpoint_to_notify.get(); if (!endpoint->client()) return true; - if (!endpoint->task_runner()->BelongsToCurrentThread() || - client_call_behavior != ALLOW_DIRECT_CLIENT_CALLS) { + if (client_call_behavior != ALLOW_DIRECT_CLIENT_CALLS || + endpoint->task_runner() != current_task_runner) { MaybePostToProcessTasks(endpoint->task_runner()); return false; } + DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + InterfaceEndpointClient* client = endpoint->client(); { // We must unlock before calling into |client| because it may call this @@ -660,7 +679,9 @@ bool MultiplexRouter::ProcessNotifyErrorTask( bool MultiplexRouter::ProcessIncomingMessage( Message* message, - ClientCallBehavior client_call_behavior) { + ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner) { + DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); lock_.AssertAcquired(); if (!message) { @@ -703,16 +724,22 @@ bool MultiplexRouter::ProcessIncomingMessage( return false; } - bool can_direct_call = - (client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS) || - (client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES && - message->has_flag(kMessageIsSync)); + bool can_direct_call; + if (message->has_flag(kMessageIsSync)) { + can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS && + endpoint->task_runner()->BelongsToCurrentThread(); + } else { + can_direct_call = client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS && + endpoint->task_runner() == current_task_runner; + } - if (!endpoint->task_runner()->BelongsToCurrentThread() || !can_direct_call) { + if (!can_direct_call) { MaybePostToProcessTasks(endpoint->task_runner()); return false; } + DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + InterfaceEndpointClient* client = endpoint->client(); bool result = false; { @@ -738,6 +765,7 @@ void MultiplexRouter::MaybePostToProcessTasks( return; posted_to_process_tasks_ = true; + posted_to_task_runner_ = task_runner; task_runner->PostTask( FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); } @@ -747,7 +775,9 @@ void MultiplexRouter::LockAndCallProcessTasks() { // always called using base::Bind(), which holds a ref. base::AutoLock locker(lock_); posted_to_process_tasks_ = false; - ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS); + scoped_refptr<base::SingleThreadTaskRunner> runner( + std::move(posted_to_task_runner_)); + ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS, runner.get()); } void MultiplexRouter::UpdateEndpointStateMayRemove( diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h index e9cd35b9c9b..c348c7d8954 100644 --- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h +++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h @@ -9,13 +9,14 @@ #include <deque> #include <map> +#include <memory> #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_delete_on_message_loop.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "mojo/public/cpp/bindings/callback.h" @@ -25,7 +26,7 @@ #include "mojo/public/cpp/bindings/lib/pipe_control_message_handler.h" #include "mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h" #include "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h" -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" namespace base { class SingleThreadTaskRunner; @@ -57,7 +58,8 @@ class MultiplexRouter // If |set_interface_id_namespace_bit| is true, the interface IDs generated by // this router will have the highest bit set. MultiplexRouter(bool set_interface_id_namespace_bit, - ScopedMessagePipeHandle message_pipe); + ScopedMessagePipeHandle message_pipe, + scoped_refptr<base::SingleThreadTaskRunner> runner); // --------------------------------------------------------------------------- // The following public methods are safe to call from any threads. @@ -84,7 +86,8 @@ class MultiplexRouter // DetachEndpointClient(). InterfaceEndpointController* AttachEndpointClient( const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* endpoint_client); + InterfaceEndpointClient* endpoint_client, + scoped_refptr<base::SingleThreadTaskRunner> runner); // Detaches the client attached to the specified endpoint. It must be called // on the same thread as the corresponding AttachEndpointClient() call. @@ -94,7 +97,7 @@ class MultiplexRouter // and notifies all interfaces running on this pipe. void RaiseError(); - scoped_ptr<AssociatedGroup> CreateAssociatedGroup(); + std::unique_ptr<AssociatedGroup> CreateAssociatedGroup(); static MultiplexRouter* GetRouter(AssociatedGroup* associated_group); @@ -181,11 +184,16 @@ class MultiplexRouter }; // Processes enqueued tasks (incoming messages and error notifications). + // |current_task_runner| is only used when |client_call_behavior| is + // ALLOW_DIRECT_CLIENT_CALLS to determine whether we are on the right task + // runner to make client calls for async messages or connection error + // notifications. // // Note: Because calling into InterfaceEndpointClient may lead to destruction // of this object, if direct calls are allowed, the caller needs to hold on to // a ref outside of |lock_| before calling this method. - void ProcessTasks(ClientCallBehavior client_call_behavior); + void ProcessTasks(ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner); // Processes the first queued sync message for the endpoint corresponding to // |id|; returns whether there are more sync messages for that endpoint in the @@ -196,10 +204,14 @@ class MultiplexRouter bool ProcessFirstSyncMessageForEndpoint(InterfaceId id); // Returns true to indicate that |task|/|message| has been processed. - bool ProcessNotifyErrorTask(Task* task, - ClientCallBehavior client_call_behavior); - bool ProcessIncomingMessage(Message* message, - ClientCallBehavior client_call_behavior); + bool ProcessNotifyErrorTask( + Task* task, + ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner); + bool ProcessIncomingMessage( + Message* message, + ClientCallBehavior client_call_behavior, + base::SingleThreadTaskRunner* current_task_runner); void MaybePostToProcessTasks(base::SingleThreadTaskRunner* task_runner); void LockAndCallProcessTasks(); @@ -232,11 +244,12 @@ class MultiplexRouter std::map<InterfaceId, scoped_refptr<InterfaceEndpoint>> endpoints_; uint32_t next_interface_id_value_; - std::deque<scoped_ptr<Task>> tasks_; + std::deque<std::unique_ptr<Task>> tasks_; // It refers to tasks in |tasks_| and doesn't own any of them. std::map<InterfaceId, std::deque<Task*>> sync_message_tasks_; bool posted_to_process_tasks_; + scoped_refptr<base::SingleThreadTaskRunner> posted_to_task_runner_; bool encountered_error_; diff --git a/chromium/mojo/public/cpp/bindings/lib/native_serialization.h b/chromium/mojo/public/cpp/bindings/lib/native_serialization.h deleted file mode 100644 index 835e072a8f3..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/native_serialization.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_SERIALIZATION_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "base/logging.h" -#include "base/pickle.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" -#include "mojo/public/cpp/bindings/lib/pickle_buffer.h" - -namespace mojo { -namespace internal { - -// Generated bindings for native-only types will specialize this to |true|. -// It can be used as a signal (by e.g. the Array serializer) for when to use -// SerializeNative_ with a type. -template <typename E> -struct ShouldUseNativeSerializer { static const bool value = false; }; - -template <typename T> -size_t GetSerializedSizeNative_(const T& value, SerializationContext* context) { - base::PickleSizer sizer; - IPC::ParamTraits<T>::GetSize(&sizer, value); - return Align(sizer.payload_size() + sizeof(ArrayHeader)); -} - -template <typename T> -void SerializeNative_(const T& value, - Buffer* buffer, - Array_Data<uint8_t>** out, - SerializationContext* context) { - PickleBuffer* pickler = buffer->AsPickleBuffer(); - DCHECK(pickler) << "Native types can only be used with PickleBuffers."; - - ArrayHeader* header = - reinterpret_cast<ArrayHeader*>(buffer->Allocate(sizeof(ArrayHeader))); - - // Remember where the Pickle started before writing. - base::Pickle* pickle = pickler->pickle(); - const char* data_start = pickle->end_of_payload(); - -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - const char* payload_base = pickle->payload(); - size_t size_before_write = pickle->payload_size(); -#endif - - IPC::ParamTraits<T>::Write(pickle, value); - -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - // Ensure the pickle buffer hasn't moved. - DCHECK_EQ(payload_base, pickle->payload()); - // Explicitly validate that the value returned by GetSize() always equals the - // number of bytes actually written by Write(). - DCHECK_GE(pickle->payload_size(), size_before_write); - size_t bytes_written = pickle->payload_size() - size_before_write; - DCHECK_EQ(Align(bytes_written + sizeof(ArrayHeader)), - GetSerializedSizeNative_(value, context)); -#endif - - // Fix up the ArrayHeader so that num_elements contains the length of the - // pickled data. - size_t pickled_size = pickle->end_of_payload() - data_start; - size_t total_size = pickled_size + sizeof(ArrayHeader); - DCHECK_LT(total_size, std::numeric_limits<uint32_t>::max()); - header->num_bytes = static_cast<uint32_t>(total_size); - header->num_elements = static_cast<uint32_t>(pickled_size); - - *out = reinterpret_cast<Array_Data<uint8_t>*>(header); -} - -template <typename T> -bool DeserializeNative_(Array_Data<uint8_t>* data, - T* out, - SerializationContext* context) { - if (!data) - return true; - - // Construct a temporary base::Pickle view over the array data. Note that - // the Array_Data is laid out like this: - // - // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] - // - // and base::Pickle expects to view data like this: - // - // [payload_size (4 bytes)] [header bytes ...] [payload...] - // - // Because ArrayHeader's num_bytes includes the length of the header and - // Pickle's payload_size does not, we need to adjust the stored value - // momentarily so Pickle can view the data. - ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data); - DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); - header->num_bytes -= sizeof(ArrayHeader); - - { - // Construct a view over the full Array_Data, including our hacked up - // header. Pickle will infer from this that the header is 8 bytes long, - // and the payload will contain all of the pickled bytes. - base::Pickle pickle_view(reinterpret_cast<const char*>(header), - header->num_bytes + sizeof(ArrayHeader)); - base::PickleIterator iter(pickle_view); - if (!IPC::ParamTraits<T>::Read(&pickle_view, &iter, out)) - return false; - } - - // Return the header to its original state. - header->num_bytes += sizeof(ArrayHeader); - - return true; -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct.cc b/chromium/mojo/public/cpp/bindings/lib/native_struct.cc new file mode 100644 index 00000000000..837b75a60e3 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/native_struct.cc @@ -0,0 +1,30 @@ +// Copyright 2016 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/native_struct.h" + +namespace mojo { + +// static +NativeStructPtr NativeStruct::New() { + NativeStructPtr rv; + internal::StructHelper<NativeStruct>::Initialize(&rv); + return rv; +} + +NativeStruct::NativeStruct() : data(nullptr) {} + +NativeStruct::~NativeStruct() {} + +NativeStructPtr NativeStruct::Clone() const { + NativeStructPtr rv(New()); + rv->data = data.Clone(); + return rv; +} + +bool NativeStruct::Equals(const NativeStruct& other) const { + return data.Equals(other.data); +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_data.cc b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.cc new file mode 100644 index 00000000000..1d6bf6f873f --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.cc @@ -0,0 +1,22 @@ +// Copyright 2016 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/lib/native_struct_data.h" + +#include "mojo/public/cpp/bindings/lib/bounds_checker.h" +#include "mojo/public/cpp/bindings/lib/buffer.h" + +namespace mojo { +namespace internal { + +// static +bool NativeStruct_Data::Validate(const void* data, + BoundsChecker* bounds_checker) { + const ArrayValidateParams data_validate_params(0, false, nullptr); + return Array_Data<uint8_t>::Validate(data, bounds_checker, + &data_validate_params); +} + +} // namespace internal +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h new file mode 100644 index 00000000000..0c2cccd1488 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h @@ -0,0 +1,41 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ + +#include <vector> + +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/system/handle.h" + +namespace mojo { +namespace internal { + +class BoundsChecker; +class Buffer; + +class NativeStruct_Data { + public: + static bool Validate(const void* data, BoundsChecker* bounds_checker); + + void EncodePointers() {} + void DecodePointers() {} + + // Unlike normal structs, the memory layout is exactly the same as an array + // of uint8_t. + Array_Data<uint8_t> data; + + private: + NativeStruct_Data() = delete; + ~NativeStruct_Data() = delete; +}; + +static_assert(sizeof(Array_Data<uint8_t>) == sizeof(NativeStruct_Data), + "Mismatched NativeStruct_Data and Array_Data<uint8_t> size"); + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc new file mode 100644 index 00000000000..fe65f147c61 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc @@ -0,0 +1,59 @@ +// Copyright 2016 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/lib/native_struct_serialization.h" + +#include "mojo/public/cpp/bindings/lib/serialization.h" + +namespace mojo { +namespace internal { + +// static +size_t UnmappedNativeStructSerializerImpl::PrepareToSerialize( + const NativeStructPtr& input, + SerializationContext* context) { + if (!input) + return 0; + return internal::PrepareToSerialize<Array<uint8_t>>(input->data, context); +} + +// static +void UnmappedNativeStructSerializerImpl::Serialize( + const NativeStructPtr& input, + Buffer* buffer, + NativeStruct_Data** output, + SerializationContext* context) { + if (!input) { + *output = nullptr; + return; + } + + Array_Data<uint8_t>* data = nullptr; + const ArrayValidateParams params(0, false, nullptr); + internal::Serialize<Array<uint8_t>>(input->data, buffer, &data, ¶ms, + context); + *output = reinterpret_cast<NativeStruct_Data*>(data); +} + +// static +bool UnmappedNativeStructSerializerImpl::Deserialize( + NativeStruct_Data* input, + NativeStructPtr* output, + SerializationContext* context) { + Array_Data<uint8_t>* data = reinterpret_cast<Array_Data<uint8_t>*>(input); + + NativeStructPtr result(NativeStruct::New()); + if (!internal::Deserialize<Array<uint8_t>>(data, &result->data, context)) { + output = nullptr; + return false; + } + if (!result->data) + *output = nullptr; + else + result.Swap(output); + return true; +} + +} // namespace internal +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h new file mode 100644 index 00000000000..09f3c883131 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h @@ -0,0 +1,132 @@ +// 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. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <limits> + +#include "base/logging.h" +#include "base/pickle.h" +#include "ipc/ipc_param_traits.h" +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/native_struct_data.h" +#include "mojo/public/cpp/bindings/lib/serialization_forward.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" +#include "mojo/public/cpp/bindings/native_struct.h" + +namespace mojo { +namespace internal { + +template <typename MaybeConstUserType> +struct NativeStructSerializerImpl { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Traits = IPC::ParamTraits<UserType>; + + static size_t PrepareToSerialize(MaybeConstUserType& value, + SerializationContext* context) { + base::PickleSizer sizer; + Traits::GetSize(&sizer, value); + return Align(sizer.payload_size() + sizeof(ArrayHeader)); + } + + static void Serialize(MaybeConstUserType& value, + Buffer* buffer, + NativeStruct_Data** out, + SerializationContext* context) { + base::Pickle pickle; + Traits::Write(&pickle, value); + +#if DCHECK_IS_ON() + base::PickleSizer sizer; + Traits::GetSize(&sizer, value); + DCHECK_EQ(sizer.payload_size(), pickle.payload_size()); +#endif + + size_t total_size = pickle.payload_size() + sizeof(ArrayHeader); + DCHECK_LT(total_size, std::numeric_limits<uint32_t>::max()); + + // Allocate a uint8 array, initialize its header, and copy the Pickle in. + ArrayHeader* header = + reinterpret_cast<ArrayHeader*>(buffer->Allocate(total_size)); + header->num_bytes = static_cast<uint32_t>(total_size); + header->num_elements = static_cast<uint32_t>(pickle.payload_size()); + memcpy(reinterpret_cast<char*>(header) + sizeof(ArrayHeader), + pickle.payload(), pickle.payload_size()); + + *out = reinterpret_cast<NativeStruct_Data*>(header); + } + + static bool Deserialize(NativeStruct_Data* data, + UserType* out, + SerializationContext* context) { + if (!data) + return true; + + // Construct a temporary base::Pickle view over the array data. Note that + // the Array_Data is laid out like this: + // + // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] + // + // and base::Pickle expects to view data like this: + // + // [payload_size (4 bytes)] [header bytes ...] [payload...] + // + // Because ArrayHeader's num_bytes includes the length of the header and + // Pickle's payload_size does not, we need to adjust the stored value + // momentarily so Pickle can view the data. + ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data); + DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); + header->num_bytes -= sizeof(ArrayHeader); + + { + // Construct a view over the full Array_Data, including our hacked up + // header. Pickle will infer from this that the header is 8 bytes long, + // and the payload will contain all of the pickled bytes. + base::Pickle pickle_view(reinterpret_cast<const char*>(header), + header->num_bytes + sizeof(ArrayHeader)); + base::PickleIterator iter(pickle_view); + if (!Traits::Read(&pickle_view, &iter, out)) + return false; + } + + // Return the header to its original state. + header->num_bytes += sizeof(ArrayHeader); + + return true; + } +}; + +struct UnmappedNativeStructSerializerImpl { + static size_t PrepareToSerialize(const NativeStructPtr& input, + SerializationContext* context); + static void Serialize(const NativeStructPtr& input, + Buffer* buffer, + NativeStruct_Data** output, + SerializationContext* context); + static bool Deserialize(NativeStruct_Data* input, + NativeStructPtr* output, + SerializationContext* context); +}; + +template <> +struct NativeStructSerializerImpl<NativeStructPtr> + : public UnmappedNativeStructSerializerImpl {}; + +template <> +struct NativeStructSerializerImpl<const NativeStructPtr> + : public UnmappedNativeStructSerializerImpl {}; + +template <typename MaybeConstUserType> +struct Serializer<NativeStructPtr, MaybeConstUserType> + : public NativeStructSerializerImpl<MaybeConstUserType> {}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.cc deleted file mode 100644 index ecd75dba69d..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/pickle_buffer.h" - -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/pickle.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" - -namespace mojo { -namespace internal { - -class PickleBuffer::Storage : public base::Pickle { - public: - explicit Storage(size_t num_bytes); - ~Storage() override {} - - size_t available_capacity() const { - return capacity_after_header() - payload_size(); - } - - void* GetData() { return static_cast<void*>(mutable_payload()); } - void* Claim(size_t num_bytes) { return ClaimBytes(num_bytes); } - - private: - // TODO(rockot): Stop wasting 8 bytes per buffer. - // - // We don't use Pickle's header at all, but its base header type consumes 4 - // bytes. We waste another 4 bytes to keep our actual buffer aligned to an - // 8-byte boundary. - // - // The reason we don't use base::Pickle's header is that it stores payload - // length in the first 4 bytes. Mojo Messages are packed like mojom structs, - // where the first 4 bytes are header size rather than payload size. - struct PaddedHeader : public base::Pickle::Header { - uint32_t padding; - }; - - static_assert(sizeof(PaddedHeader) % 8 == 0, - "PickleBuffer requires a Pickle header size with 8-byte alignment."); - - DISALLOW_COPY_AND_ASSIGN(Storage); -}; - -PickleBuffer::Storage::Storage(size_t num_bytes) - : base::Pickle(sizeof(PaddedHeader)) { - headerT<PaddedHeader>()->padding = 0; - Resize(num_bytes); -} - -PickleBuffer::PickleBuffer(size_t num_bytes, bool zero_initialized) - : storage_(new Storage(num_bytes)) { - if (zero_initialized) - memset(storage_->GetData(), 0, num_bytes); -} - -PickleBuffer::~PickleBuffer() { -} - -const void* PickleBuffer::data() const { return storage_->GetData(); } - -size_t PickleBuffer::data_num_bytes() const { return storage_->payload_size(); } - -base::Pickle* PickleBuffer::pickle() const { - return storage_.get(); -} - -void* PickleBuffer::Allocate(size_t num_bytes) { - DCHECK(storage_); - - // The last allocation may terminate in between 8-byte boundaries. Pad the - // front of this allocation if that's the case. - size_t padded_capacity = Align(storage_->payload_size()); - DCHECK_GE(padded_capacity, storage_->payload_size()); - - size_t padding_bytes = padded_capacity - storage_->payload_size(); - size_t allocation_size = padding_bytes + num_bytes; - const void* previous_data_location = storage_->GetData(); - if (storage_->available_capacity() < allocation_size) { - NOTREACHED() << - "Message buffers must be fully allocated before serialization."; - return nullptr; - } - char* p = static_cast<char*>(storage_->Claim(allocation_size)); - DCHECK_EQ(storage_->GetData(), previous_data_location); - return p + padding_bytes; -} - -PickleBuffer* PickleBuffer::AsPickleBuffer() { return this; } - -} // namespace internal -} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.h b/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.h deleted file mode 100644 index c940b38f786..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/pickle_buffer.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_PICKLE_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_PICKLE_BUFFER_H_ - -#include <stddef.h> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/pickle.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" - -namespace mojo { -namespace internal { - -// An implementation of Buffer which uses base::Pickle for its backing. Note -// that this does not use Pickle's header structure at all, instead storing -// the complete Message (including header) in the Pickle's payload. -class PickleBuffer : public Buffer { - public: - PickleBuffer(size_t num_bytes, bool zero_initialized); - ~PickleBuffer() override; - - const void* data() const; - - void* data() { - return const_cast<void*>(static_cast<const PickleBuffer*>(this)->data()); - } - - size_t data_num_bytes() const; - - base::Pickle* pickle() const; - - private: - class Storage; - - // Buffer implementation. Note that this cannot grow the Pickle's capacity and - // it is an error to Allocate() more bytes in total than have been - // pre-allocated using ReserveCapacity() or ReserveUninitializedCapacity(). - // - // This guarantees that the returned data is aligned on an 8-byte boundary. - void* Allocate(size_t num_bytes) override; - PickleBuffer* AsPickleBuffer() override; - - scoped_ptr<Storage> storage_; - - DISALLOW_COPY_AND_ASSIGN(PickleBuffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_PICKLE_BUFFER_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc index 6a5c224ed68..ae952c503f2 100644 --- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc +++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" #include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" @@ -51,10 +52,11 @@ bool PipeControlMessageHandler::RunOrClosePipe(Message* message) { reinterpret_cast< pipe_control::internal::RunOrClosePipeMessageParams_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); + params->DecodePointers(); pipe_control::RunOrClosePipeMessageParamsPtr params_ptr; - Deserialize_(params, ¶ms_ptr, nullptr); + Deserialize<pipe_control::RunOrClosePipeMessageParamsPtr>(params, ¶ms_ptr, + &context_); if (params_ptr->input->is_peer_associated_endpoint_closed_event()) { return delegate_->OnPeerAssociatedEndpointClosed( diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.h b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.h index 091e7c28758..c42d0bae3d1 100644 --- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.h +++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/interface_id.h" +#include "mojo/public/cpp/bindings/lib/serialization_context.h" #include "mojo/public/cpp/bindings/message.h" namespace mojo { @@ -38,6 +39,7 @@ class PipeControlMessageHandler : public MessageReceiver { bool RunOrClosePipe(Message* message); PipeControlMessageHandlerDelegate* const delegate_; + SerializationContext context_; DISALLOW_COPY_AND_ASSIGN(PipeControlMessageHandler); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc index 4ea0353e29f..492bc02d85a 100644 --- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc +++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" @@ -17,17 +18,21 @@ namespace internal { namespace { void SendRunOrClosePipeMessage(MessageReceiver* receiver, - pipe_control::RunOrClosePipeInputPtr input) { + pipe_control::RunOrClosePipeInputPtr input, + SerializationContext* context) { pipe_control::RunOrClosePipeMessageParamsPtr params_ptr( pipe_control::RunOrClosePipeMessageParams::New()); params_ptr->input = std::move(input); - size_t size = GetSerializedSize_(params_ptr, nullptr); + size_t size = + PrepareToSerialize<pipe_control::RunOrClosePipeMessageParamsPtr>( + params_ptr, context); MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId, size); pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr; - Serialize_(std::move(params_ptr), builder.buffer(), ¶ms, nullptr); - params->EncodePointersAndHandles(builder.message()->mutable_handles()); + Serialize<pipe_control::RunOrClosePipeMessageParamsPtr>( + params_ptr, builder.buffer(), ¶ms, context); + params->EncodePointers(); builder.message()->set_interface_id(kInvalidInterfaceId); bool ok = receiver->Accept(builder.message()); // This return value may be ignored as !ok implies the underlying message pipe @@ -49,7 +54,7 @@ void PipeControlMessageProxy::NotifyPeerEndpointClosed(InterfaceId id) { pipe_control::RunOrClosePipeInput::New()); input->set_peer_associated_endpoint_closed_event(std::move(event)); - SendRunOrClosePipeMessage(receiver_, std::move(input)); + SendRunOrClosePipeMessage(receiver_, std::move(input), &context_); } void PipeControlMessageProxy::NotifyEndpointClosedBeforeSent(InterfaceId id) { @@ -61,7 +66,7 @@ void PipeControlMessageProxy::NotifyEndpointClosedBeforeSent(InterfaceId id) { pipe_control::RunOrClosePipeInput::New()); input->set_associated_endpoint_closed_before_sent_event(std::move(event)); - SendRunOrClosePipeMessage(receiver_, std::move(input)); + SendRunOrClosePipeMessage(receiver_, std::move(input), &context_); } } // namespace internal diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h index 3804c4ce063..87a8d478c8a 100644 --- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h +++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/interface_id.h" +#include "mojo/public/cpp/bindings/lib/serialization_context.h" namespace mojo { @@ -26,6 +27,7 @@ class PipeControlMessageProxy { private: // Not owned. MessageReceiver* receiver_; + SerializationContext context_; DISALLOW_COPY_AND_ASSIGN(PipeControlMessageProxy); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/router.cc b/chromium/mojo/public/cpp/bindings/lib/router.cc index 9e93f0cfd62..da5f34b1df5 100644 --- a/chromium/mojo/public/cpp/bindings/lib/router.cc +++ b/chromium/mojo/public/cpp/bindings/lib/router.cc @@ -5,15 +5,14 @@ #include "mojo/public/cpp/bindings/lib/router.h" #include <stdint.h> + #include <utility> #include "base/bind.h" #include "base/location.h" #include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/memory/ptr_util.h" #include "base/stl_util.h" -#include "base/thread_task_runner_handle.h" namespace mojo { namespace internal { @@ -30,20 +29,25 @@ void DCheckIfInvalid(const base::WeakPtr<Router>& router, class ResponderThunk : public MessageReceiverWithStatus { public: - explicit ResponderThunk(const base::WeakPtr<Router>& router) - : router_(router), accept_was_invoked_(false), - task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + explicit ResponderThunk(const base::WeakPtr<Router>& router, + scoped_refptr<base::SingleThreadTaskRunner> runner) + : router_(router), + accept_was_invoked_(false), + task_runner_(std::move(runner)) {} ~ResponderThunk() override { if (!accept_was_invoked_) { // The Mojo application handled a message that was expecting a response // but did not send a response. + // We raise an error to signal the calling application that an error + // condition occurred. Without this the calling application would have no + // way of knowing it should stop waiting for a response. if (task_runner_->RunsTasksOnCurrentThread()) { - if (router_) { - // We raise an error to signal the calling application that an error - // condition occurred. Without this the calling application would have - // no way of knowing it should stop waiting for a response. + // Please note that even if this code is run from a different task + // runner on the same thread as |task_runner_|, it is okay to directly + // call Router::RaiseError(), because it will raise error from the + // correct task runner asynchronously. + if (router_) router_->RaiseError(); - } } else { task_runner_->PostTask(FROM_HERE, base::Bind(&Router::RaiseError, router_)); @@ -112,10 +116,13 @@ bool Router::HandleIncomingMessageThunk::Accept(Message* message) { Router::Router(ScopedMessagePipeHandle message_pipe, FilterChain filters, - bool expects_sync_requests) + bool expects_sync_requests, + scoped_refptr<base::SingleThreadTaskRunner> runner) : thunk_(this), filters_(std::move(filters)), - connector_(std::move(message_pipe), Connector::SINGLE_THREADED_SEND), + connector_(std::move(message_pipe), + Connector::SINGLE_THREADED_SEND, + std::move(runner)), incoming_receiver_(nullptr), next_request_id_(0), testing_mode_(false), @@ -146,20 +153,21 @@ bool Router::AcceptWithResponder(Message* message, MessageReceiver* responder) { if (request_id == 0) request_id = next_request_id_++; + bool is_sync = message->has_flag(kMessageIsSync); message->set_request_id(request_id); if (!connector_.Accept(message)) return false; - if (!message->has_flag(kMessageIsSync)) { + if (!is_sync) { // We assume ownership of |responder|. - async_responders_[request_id] = make_scoped_ptr(responder); + async_responders_[request_id] = base::WrapUnique(responder); return true; } bool response_received = false; - scoped_ptr<MessageReceiver> sync_responder(responder); + std::unique_ptr<MessageReceiver> sync_responder(responder); sync_responses_.insert(std::make_pair( - request_id, make_scoped_ptr(new SyncResponseInfo(&response_received)))); + request_id, base::WrapUnique(new SyncResponseInfo(&response_received)))); base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr(); connector_.SyncWatch(&response_received); @@ -169,7 +177,7 @@ bool Router::AcceptWithResponder(Message* message, MessageReceiver* responder) { auto iter = sync_responses_.find(request_id); DCHECK_EQ(&response_received, iter->second->response_received); if (response_received) { - scoped_ptr<Message> response = std::move(iter->second->response); + std::unique_ptr<Message> response = std::move(iter->second->response); ignore_result(sync_responder->Accept(response.get())); } sync_responses_.erase(iter); @@ -192,13 +200,13 @@ bool Router::HandleIncomingMessage(Message* message) { connector_.during_sync_handle_watcher_callback(); if (!message->has_flag(kMessageIsSync) && (during_sync_call || !pending_messages_.empty())) { - scoped_ptr<Message> pending_message(new Message); + std::unique_ptr<Message> pending_message(new Message); message->MoveTo(pending_message.get()); pending_messages_.push(std::move(pending_message)); if (!pending_task_for_messages_) { pending_task_for_messages_ = true; - base::MessageLoop::current()->PostTask( + connector_.task_runner()->PostTask( FROM_HERE, base::Bind(&Router::HandleQueuedMessages, weak_factory_.GetWeakPtr())); } @@ -215,7 +223,7 @@ void Router::HandleQueuedMessages() { base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr(); while (!pending_messages_.empty()) { - scoped_ptr<Message> message(std::move(pending_messages_.front())); + std::unique_ptr<Message> message(std::move(pending_messages_.front())); pending_messages_.pop(); bool result = HandleMessageInternal(message.get()); @@ -242,8 +250,8 @@ bool Router::HandleMessageInternal(Message* message) { if (!incoming_receiver_) return false; - MessageReceiverWithStatus* responder = - new ResponderThunk(weak_factory_.GetWeakPtr()); + MessageReceiverWithStatus* responder = new ResponderThunk( + weak_factory_.GetWeakPtr(), connector_.task_runner()); bool ok = incoming_receiver_->AcceptWithResponder(message, responder); if (!ok) delete responder; @@ -269,7 +277,7 @@ bool Router::HandleMessageInternal(Message* message) { DCHECK(testing_mode_); return false; } - scoped_ptr<MessageReceiver> responder = std::move(it->second); + std::unique_ptr<MessageReceiver> responder = std::move(it->second); async_responders_.erase(it); return responder->Accept(message); } else { @@ -294,7 +302,7 @@ void Router::OnConnectionError() { if (connector_.during_sync_handle_watcher_callback()) { // We don't want the error handler to reenter an ongoing sync call. - base::MessageLoop::current()->PostTask( + connector_.task_runner()->PostTask( FROM_HERE, base::Bind(&Router::OnConnectionError, weak_factory_.GetWeakPtr())); return; diff --git a/chromium/mojo/public/cpp/bindings/lib/router.h b/chromium/mojo/public/cpp/bindings/lib/router.h index 054bcc115a2..2f5e8e2a971 100644 --- a/chromium/mojo/public/cpp/bindings/lib/router.h +++ b/chromium/mojo/public/cpp/bindings/lib/router.h @@ -8,11 +8,13 @@ #include <stdint.h> #include <map> +#include <memory> #include <queue> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/lib/connector.h" @@ -27,7 +29,8 @@ class Router : public MessageReceiverWithResponder { public: Router(ScopedMessagePipeHandle message_pipe, FilterChain filters, - bool expects_sync_requests); + bool expects_sync_requests, + scoped_refptr<base::SingleThreadTaskRunner> runner); ~Router() override; // Sets the receiver to handle messages read from the message pipe that do @@ -113,14 +116,15 @@ class Router : public MessageReceiverWithResponder { private: // Maps from the id of a response to the MessageReceiver that handles the // response. - using AsyncResponderMap = std::map<uint64_t, scoped_ptr<MessageReceiver>>; + using AsyncResponderMap = + std::map<uint64_t, std::unique_ptr<MessageReceiver>>; struct SyncResponseInfo { public: explicit SyncResponseInfo(bool* in_response_received); ~SyncResponseInfo(); - scoped_ptr<Message> response; + std::unique_ptr<Message> response; // Points to a stack-allocated variable. bool* response_received; @@ -129,7 +133,7 @@ class Router : public MessageReceiverWithResponder { DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo); }; - using SyncResponseMap = std::map<uint64_t, scoped_ptr<SyncResponseInfo>>; + using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>; class HandleIncomingMessageThunk : public MessageReceiver { public: @@ -157,7 +161,7 @@ class Router : public MessageReceiverWithResponder { SyncResponseMap sync_responses_; uint64_t next_request_id_; bool testing_mode_; - std::queue<scoped_ptr<Message>> pending_messages_; + std::queue<std::unique_ptr<Message>> pending_messages_; // Whether a task has been posted to trigger processing of // |pending_messages_|. bool pending_task_for_messages_; diff --git a/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc index dfe4e234241..83db0d9533a 100644 --- a/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc +++ b/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc @@ -2,30 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "base/logging.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" namespace mojo { -namespace internal { ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle() - : ScopedInterfaceEndpointHandle(kInvalidInterfaceId, true, nullptr) {} + : ScopedInterfaceEndpointHandle(internal::kInvalidInterfaceId, true, + nullptr) {} ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( - InterfaceId id, + internal::InterfaceId id, bool is_local, - scoped_refptr<MultiplexRouter> router) + scoped_refptr<internal::MultiplexRouter> router) : id_(id), is_local_(is_local), router_(std::move(router)) { - DCHECK(!IsValidInterfaceId(id) || router_); + DCHECK(!internal::IsValidInterfaceId(id) || router_); } ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( ScopedInterfaceEndpointHandle&& other) : id_(other.id_), is_local_(other.is_local_) { router_.swap(other.router_); - other.id_ = kInvalidInterfaceId; + other.id_ = internal::kInvalidInterfaceId; } ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() { @@ -41,12 +41,12 @@ ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=( } void ScopedInterfaceEndpointHandle::reset() { - if (!IsValidInterfaceId(id_)) + if (!internal::IsValidInterfaceId(id_)) return; router_->CloseEndpointHandle(id_, is_local_); - id_ = kInvalidInterfaceId; + id_ = internal::kInvalidInterfaceId; is_local_ = true; router_ = nullptr; } @@ -58,15 +58,14 @@ void ScopedInterfaceEndpointHandle::swap(ScopedInterfaceEndpointHandle& other) { swap(other.router_, router_); } -InterfaceId ScopedInterfaceEndpointHandle::release() { - InterfaceId result = id_; +internal::InterfaceId ScopedInterfaceEndpointHandle::release() { + internal::InterfaceId result = id_; - id_ = kInvalidInterfaceId; + id_ = internal::kInvalidInterfaceId; is_local_ = true; router_ = nullptr; return result; } -} // namespace internal } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization.h b/chromium/mojo/public/cpp/bindings/lib/serialization.h index c3af9ffdfc7..b37cc2761e8 100644 --- a/chromium/mojo/public/cpp/bindings/lib/serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/serialization.h @@ -5,9 +5,15 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ +#include "mojo/public/cpp/bindings/array_traits_standard.h" +#include "mojo/public/cpp/bindings/array_traits_stl.h" #include "mojo/public/cpp/bindings/lib/array_serialization.h" #include "mojo/public/cpp/bindings/lib/map_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_serialization.h" +#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" #include "mojo/public/cpp/bindings/lib/string_serialization.h" +#include "mojo/public/cpp/bindings/string_traits_standard.h" +#include "mojo/public/cpp/bindings/string_traits_stl.h" +#include "mojo/public/cpp/bindings/string_traits_string16.h" +#include "mojo/public/cpp/bindings/string_traits_string_piece.h" #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_context.cc b/chromium/mojo/public/cpp/bindings/lib/serialization_context.cc new file mode 100644 index 00000000000..f0cf730f1a4 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/serialization_context.cc @@ -0,0 +1,62 @@ +// Copyright 2016 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/lib/serialization_context.h" + +#include <limits> + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" +#include "mojo/public/cpp/system/core.h" + +namespace mojo { +namespace internal { + +SerializedHandleVector::SerializedHandleVector() {} + +SerializedHandleVector::~SerializedHandleVector() { + for (auto handle : handles_) { + if (handle.is_valid()) { + MojoResult rv = MojoClose(handle.value()); + DCHECK_EQ(rv, MOJO_RESULT_OK); + } + } +} + +Handle_Data SerializedHandleVector::AddHandle(mojo::Handle handle) { + Handle_Data data; + if (!handle.is_valid()) { + data.value = kEncodedInvalidHandleValue; + } else { + DCHECK_LT(handles_.size(), std::numeric_limits<uint32_t>::max()); + data.value = static_cast<uint32_t>(handles_.size()); + handles_.push_back(handle); + } + return data; +} + +mojo::Handle SerializedHandleVector::TakeHandle( + const Handle_Data& encoded_handle) { + if (!encoded_handle.is_valid()) + return mojo::Handle(); + DCHECK_LT(encoded_handle.value, handles_.size()); + return FetchAndReset(&handles_[encoded_handle.value]); +} + +void SerializedHandleVector::Swap(std::vector<mojo::Handle>* other) { + handles_.swap(*other); +} + +SerializationContext::SerializationContext() {} + +SerializationContext::SerializationContext( + scoped_refptr<MultiplexRouter> in_router) + : router(std::move(in_router)) {} + +SerializationContext::~SerializationContext() { + DCHECK(!custom_contexts || custom_contexts->empty()); +} + +} // namespace internal +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_context.h b/chromium/mojo/public/cpp/bindings/lib/serialization_context.h new file mode 100644 index 00000000000..48d37cf713a --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/serialization_context.h @@ -0,0 +1,75 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ + +#include <stddef.h> + +#include <memory> +#include <queue> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/system/handle.h" + +namespace mojo { +namespace internal { + +class MultiplexRouter; + +// A container for handles during serialization/deserialization. +class SerializedHandleVector { + public: + SerializedHandleVector(); + ~SerializedHandleVector(); + + size_t size() const { return handles_.size(); } + + // Adds a handle to the handle list and returns its index for encoding. + Handle_Data AddHandle(mojo::Handle handle); + + // Takes a handle from the list of serialized handle data. + mojo::Handle TakeHandle(const Handle_Data& encoded_handle); + + // Takes a handle from the list of serialized handle data and returns it in + // |*out_handle| as a specific scoped handle type. + template <typename T> + ScopedHandleBase<T> TakeHandleAs(const Handle_Data& encoded_handle) { + return MakeScopedHandle(T(TakeHandle(encoded_handle).value())); + } + + // Swaps all owned handles out with another Handle vector. + void Swap(std::vector<mojo::Handle>* other); + + private: + // Handles are owned by this object. + std::vector<mojo::Handle> handles_; + + DISALLOW_COPY_AND_ASSIGN(SerializedHandleVector); +}; + +// Context information for serialization/deserialization routines. +struct SerializationContext { + SerializationContext(); + explicit SerializationContext(scoped_refptr<MultiplexRouter> in_router); + + ~SerializationContext(); + + // Used to serialize/deserialize associated interface pointers and requests. + scoped_refptr<MultiplexRouter> router; + + // Opaque context pointers returned by StringTraits::SetUpContext(). + std::unique_ptr<std::queue<void*>> custom_contexts; + + // Stashes handles encoded in a message by index. + SerializedHandleVector handles; +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h b/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h index b6050498d87..266b3a89757 100644 --- a/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h +++ b/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h @@ -5,10 +5,9 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ -#include <stddef.h> - -#include "mojo/public/cpp/bindings/lib/string_serialization.h" -#include "mojo/public/cpp/bindings/lib/wtf_string_serialization.h" +#include "mojo/public/cpp/bindings/array_traits.h" +#include "mojo/public/cpp/bindings/string_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" // This file is included by serialization implementation files to avoid circular // includes. @@ -16,118 +15,40 @@ // wtf_serialization.h if necessary). namespace mojo { - -template <typename T> -class Array; - -template <typename K, typename V> -class Map; - -template <typename T> -class WTFArray; - namespace internal { -template <typename T> -class Array_Data; - -class ArrayValidateParams; - -class Buffer; - -template <typename K, typename V> -class Map_Data; - -struct SerializationContext; - -template <typename T> -struct ShouldUseNativeSerializer; - -// ----------------------------------------------------------------------------- -// Forward declaration for native types. - -template <typename T> -size_t GetSerializedSizeNative_(const T& value, SerializationContext* context); - -template <typename T> -void SerializeNative_(const T& value, - Buffer* buffer, - Array_Data<uint8_t>** out, - SerializationContext* context); - -template <typename T> -bool DeserializeNative_(Array_Data<uint8_t>* data, - T* out, - SerializationContext* context); +template <typename MojomType, typename MaybeConstUserType> +struct Serializer; + +// PrepareToSerialize() must be matched by a Serialize() for the same input +// later. Moreover, within the same SerializationContext if PrepareToSerialize() +// is called for |input_1|, ..., |input_n|, Serialize() must be called for +// those objects in the exact same order. +template <typename MojomType, typename InputUserType, typename... Args> +size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { + return Serializer<MojomType, + typename std::remove_reference<InputUserType>::type>:: + PrepareToSerialize(std::forward<InputUserType>(input), + std::forward<Args>(args)...); +} + +template <typename MojomType, typename InputUserType, typename... Args> +void Serialize(InputUserType&& input, Args&&... args) { + Serializer<MojomType, typename std::remove_reference<InputUserType>::type>:: + Serialize(std::forward<InputUserType>(input), + std::forward<Args>(args)...); +} + +template <typename MojomType, + typename DataType, + typename InputUserType, + typename... Args> +bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { + return Serializer<MojomType, InputUserType>::Deserialize( + std::forward<DataType>(input), output, std::forward<Args>(args)...); +} } // namespace internal - -// ----------------------------------------------------------------------------- -// Forward declaration for Array. - -template <typename E> -inline size_t GetSerializedSize_(const Array<E>& input, - internal::SerializationContext* context); - -template <typename E, typename F> -inline void SerializeArray_( - Array<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params, - internal::SerializationContext* context); - -template <typename E, typename F> -inline bool Deserialize_(internal::Array_Data<F>* input, - Array<E>* output, - internal::SerializationContext* context); - -// ----------------------------------------------------------------------------- -// Forward declaration for WTFArray. - -template <typename E> -inline size_t GetSerializedSize_(const WTFArray<E>& input, - internal::SerializationContext* context); - -template <typename E, typename F> -inline void SerializeArray_( - WTFArray<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params, - internal::SerializationContext* context); - -template <typename E, typename F> -inline bool Deserialize_(internal::Array_Data<F>* input, - WTFArray<E>* output, - internal::SerializationContext* context); - -// ----------------------------------------------------------------------------- -// Forward declaration for Map. - -template <typename MapKey, typename MapValue> -inline size_t GetSerializedSize_(const Map<MapKey, MapValue>& input, - internal::SerializationContext* context); - -template <typename MapKey, - typename MapValue, - typename DataKey, - typename DataValue> -inline void SerializeMap_( - Map<MapKey, MapValue> input, - internal::Buffer* buf, - internal::Map_Data<DataKey, DataValue>** output, - const internal::ArrayValidateParams* value_validate_params, - internal::SerializationContext* context); - -template <typename MapKey, - typename MapValue, - typename DataKey, - typename DataValue> -inline bool Deserialize_(internal::Map_Data<DataKey, DataValue>* input, - Map<MapKey, MapValue>* output, - internal::SerializationContext* context); - } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc b/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc new file mode 100644 index 00000000000..d672243b779 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc @@ -0,0 +1,53 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/bindings/lib/serialization_util.h" + +namespace mojo { +namespace internal { + +namespace { + +const size_t kAlignment = 8; + +template <typename T> +T AlignImpl(T t) { + return t + (kAlignment - (t % kAlignment)) % kAlignment; +} + +} // namespace + +size_t Align(size_t size) { + return AlignImpl(size); +} + +char* AlignPointer(char* ptr) { + return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr))); +} + +bool IsAligned(const void* ptr) { + return !(reinterpret_cast<uintptr_t>(ptr) % kAlignment); +} + +void EncodePointer(const void* ptr, uint64_t* offset) { + if (!ptr) { + *offset = 0; + return; + } + + const char* p_obj = reinterpret_cast<const char*>(ptr); + const char* p_slot = reinterpret_cast<const char*>(offset); + DCHECK(p_obj > p_slot); + + *offset = static_cast<uint64_t>(p_obj - p_slot); +} + +const void* DecodePointerRaw(const uint64_t* offset) { + if (!*offset) + return nullptr; + return reinterpret_cast<const char*>(offset) + *offset; +} + +} // namespace internal +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_util.h b/chromium/mojo/public/cpp/bindings/lib/serialization_util.h new file mode 100644 index 00000000000..698e90d9628 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/serialization_util.h @@ -0,0 +1,233 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <queue> + +#include "base/logging.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/serialization_context.h" +#include "mojo/public/cpp/system/handle.h" + +namespace mojo { +namespace internal { + +class MultiplexRouter; + +size_t Align(size_t size); +char* AlignPointer(char* ptr); + +bool IsAligned(const void* ptr); + +// Pointers are encoded as relative offsets. The offsets are relative to the +// address of where the offset value is stored, such that the pointer may be +// recovered with the expression: +// +// ptr = reinterpret_cast<char*>(offset) + *offset +// +// A null pointer is encoded as an offset value of 0. +// +void EncodePointer(const void* ptr, uint64_t* offset); +// Note: This function doesn't validate the encoded pointer value. +const void* DecodePointerRaw(const uint64_t* offset); + +// Note: This function doesn't validate the encoded pointer value. +template <typename T> +inline void DecodePointer(const uint64_t* offset, T** ptr) { + *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset))); +} + +// The following 2 functions are used to encode/decode all objects (structs and +// arrays) in a consistent manner. + +template <typename T> +inline void Encode(T* obj) { + if (obj->ptr) + obj->ptr->EncodePointers(); + EncodePointer(obj->ptr, &obj->offset); +} + +// Note: This function doesn't validate the encoded pointer and handle values. +template <typename T> +inline void Decode(T* obj) { + DecodePointer(&obj->offset, &obj->ptr); + if (obj->ptr) + obj->ptr->DecodePointers(); +} + +template <typename T> +inline void AssociatedInterfacePtrInfoToData( + AssociatedInterfacePtrInfo<T> input, + AssociatedInterface_Data* output) { + output->version = input.version(); + output->interface_id = input.PassHandle().release(); +} + +template <typename T> +inline void AssociatedInterfaceDataToPtrInfo( + AssociatedInterface_Data* input, + AssociatedInterfacePtrInfo<T>* output, + MultiplexRouter* router) { + output->set_handle( + router->CreateLocalEndpointHandle(FetchAndReset(&input->interface_id))); + output->set_version(input->version); +} + +template <typename T> +inline void InterfacePointerToData(InterfacePtr<T> input, + Interface_Data* output, + SerializationContext* context) { + InterfacePtrInfo<T> info = input.PassInterface(); + output->handle = context->handles.AddHandle(info.PassHandle().release()); + output->version = info.version(); +} + +template <typename T> +inline void InterfaceDataToPointer(Interface_Data* input, + InterfacePtr<T>* output, + SerializationContext* context) { + output->Bind(InterfacePtrInfo<T>( + context->handles.TakeHandleAs<mojo::MessagePipeHandle>(input->handle), + input->version)); +} + +template <typename T> +struct HasIsNullMethod { + template <typename U> + static char Test(decltype(U::IsNull)*); + template <typename U> + static int Test(...); + static const bool value = sizeof(Test<T>(0)) == sizeof(char); + + private: + EnsureTypeIsComplete<T> check_t_; +}; + +template < + typename Traits, + typename UserType, + typename std::enable_if<HasIsNullMethod<Traits>::value>::type* = nullptr> +bool CallIsNullIfExists(const UserType& input) { + return Traits::IsNull(input); +} + +template < + typename Traits, + typename UserType, + typename std::enable_if<!HasIsNullMethod<Traits>::value>::type* = nullptr> +bool CallIsNullIfExists(const UserType& input) { + return false; +} +template <typename T> +struct HasSetToNullMethod { + template <typename U> + static char Test(decltype(U::SetToNull)*); + template <typename U> + static int Test(...); + static const bool value = sizeof(Test<T>(0)) == sizeof(char); + + private: + EnsureTypeIsComplete<T> check_t_; +}; + +template < + typename Traits, + typename UserType, + typename std::enable_if<HasSetToNullMethod<Traits>::value>::type* = nullptr> +bool CallSetToNullIfExists(UserType* output) { + Traits::SetToNull(output); + return true; +} + +template <typename Traits, + typename UserType, + typename std::enable_if<!HasSetToNullMethod<Traits>::value>::type* = + nullptr> +bool CallSetToNullIfExists(UserType* output) { + LOG(ERROR) << "A null value is received. But the Struct/Array/StringTraits " + << "class doesn't define a SetToNull() function and therefore is " + << "unable to deserialize the value."; + return false; +} + +template <typename T> +struct HasSetUpContextMethod { + template <typename U> + static char Test(decltype(U::SetUpContext)*); + template <typename U> + static int Test(...); + static const bool value = sizeof(Test<T>(0)) == sizeof(char); + + private: + EnsureTypeIsComplete<T> check_t_; +}; + +template <typename Traits, + bool has_context = HasSetUpContextMethod<Traits>::value> +struct CustomContextHelper; + +template <typename Traits> +struct CustomContextHelper<Traits, true> { + template <typename MaybeConstUserType> + static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { + void* custom_context = Traits::SetUpContext(input); + if (!context->custom_contexts) + context->custom_contexts.reset(new std::queue<void*>()); + context->custom_contexts->push(custom_context); + return custom_context; + } + + static void* GetNext(SerializationContext* context) { + void* custom_context = context->custom_contexts->front(); + context->custom_contexts->pop(); + return custom_context; + } + + template <typename MaybeConstUserType> + static void TearDown(MaybeConstUserType& input, void* custom_context) { + Traits::TearDownContext(input, custom_context); + } +}; + +template <typename Traits> +struct CustomContextHelper<Traits, false> { + template <typename MaybeConstUserType> + static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { + return nullptr; + } + + static void* GetNext(SerializationContext* context) { return nullptr; } + + template <typename MaybeConstUserType> + static void TearDown(MaybeConstUserType& input, void* custom_context) { + DCHECK(!custom_context); + } +}; + +template <typename ReturnType, typename ParamType, typename MaybeConstUserType> +ReturnType CallWithContext(ReturnType (*f)(ParamType, void*), + MaybeConstUserType& input, + void* context) { + return f(input, context); +} + +template <typename ReturnType, typename ParamType, typename MaybeConstUserType> +ReturnType CallWithContext(ReturnType (*f)(ParamType), + MaybeConstUserType& input, + void* context) { + return f(input); +} + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc deleted file mode 100644 index 6b9f741457c..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/string_serialization.h" - -#include <stddef.h> -#include <string.h> - -namespace mojo { - -size_t GetSerializedSize_(const String& input, - internal::SerializationContext* context) { - if (!input) - return 0; - return internal::Align(sizeof(internal::String_Data) + input.size()); -} - -void Serialize_(const String& input, - internal::Buffer* buf, - internal::String_Data** output, - internal::SerializationContext* context) { - if (input) { - internal::String_Data* result = - internal::String_Data::New(input.size(), buf); - if (result) - memcpy(result->storage(), input.data(), input.size()); - *output = result; - } else { - *output = nullptr; - } -} - -bool Deserialize_(internal::String_Data* input, - String* output, - internal::SerializationContext* context) { - if (input) { - String result(input->storage(), input->size()); - result.Swap(output); - } else { - *output = nullptr; - } - return true; -} - -} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/string_serialization.h b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h index a1ae951bdb2..5e65891ef5e 100644 --- a/chromium/mojo/public/cpp/bindings/lib/string_serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h @@ -6,22 +6,65 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ #include <stddef.h> +#include <string.h> #include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/serialization_forward.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/string.h" +#include "mojo/public/cpp/bindings/string_traits.h" namespace mojo { +namespace internal { -size_t GetSerializedSize_(const String& input, - internal::SerializationContext* context); -void Serialize_(const String& input, - internal::Buffer* buffer, - internal::String_Data** output, - internal::SerializationContext* context); -bool Deserialize_(internal::String_Data* input, - String* output, - internal::SerializationContext* context); +template <typename MaybeConstUserType> +struct Serializer<String, MaybeConstUserType> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Traits = StringTraits<UserType>; + static size_t PrepareToSerialize(MaybeConstUserType& input, + SerializationContext* context) { + if (CallIsNullIfExists<Traits>(input)) + return 0; + + void* custom_context = CustomContextHelper<Traits>::SetUp(input, context); + return Align(sizeof(String_Data) + + CallWithContext(Traits::GetSize, input, custom_context)); + } + + static void Serialize(MaybeConstUserType& input, + Buffer* buffer, + String_Data** output, + SerializationContext* context) { + if (CallIsNullIfExists<Traits>(input)) { + *output = nullptr; + return; + } + + void* custom_context = CustomContextHelper<Traits>::GetNext(context); + + String_Data* result = String_Data::New( + CallWithContext(Traits::GetSize, input, custom_context), buffer); + if (result) { + memcpy(result->storage(), + CallWithContext(Traits::GetData, input, custom_context), + CallWithContext(Traits::GetSize, input, custom_context)); + } + *output = result; + + CustomContextHelper<Traits>::TearDown(input, custom_context); + } + + static bool Deserialize(String_Data* input, + UserType* output, + SerializationContext* context) { + if (!input) + return CallSetToNullIfExists<Traits>(output); + return Traits::Read(StringDataView(input), output); + } +}; + +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc b/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc new file mode 100644 index 00000000000..95ff6ccf257 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc @@ -0,0 +1,42 @@ +// Copyright 2016 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/string_traits_string16.h" + +#include <string> + +#include "base/strings/utf_string_conversions.h" + +namespace mojo { + +// static +void* StringTraits<base::string16>::SetUpContext(const base::string16& input) { + return new std::string(base::UTF16ToUTF8(input)); +} + +// static +void StringTraits<base::string16>::TearDownContext(const base::string16& input, + void* context) { + delete static_cast<std::string*>(context); +} + +// static +size_t StringTraits<base::string16>::GetSize(const base::string16& input, + void* context) { + return static_cast<std::string*>(context)->size(); +} + +// static +const char* StringTraits<base::string16>::GetData(const base::string16& input, + void* context) { + return static_cast<std::string*>(context)->data(); +} + +// static +bool StringTraits<base::string16>::Read(StringDataView input, + base::string16* output) { + return base::UTF8ToUTF16(input.storage(), input.size(), output); +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc new file mode 100644 index 00000000000..19fa9074483 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc @@ -0,0 +1,85 @@ +// Copyright 2016 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/string_traits_wtf.h" + +#include <string.h> + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "third_party/WebKit/Source/wtf/text/StringUTF8Adaptor.h" + +namespace mojo { +namespace { + +struct UTF8AdaptorInfo { + explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) { +#if DCHECK_IS_ON() + original_size_in_bytes = static_cast<size_t>(input.sizeInBytes()); +#endif + } + + ~UTF8AdaptorInfo() {} + + WTF::StringUTF8Adaptor utf8_adaptor; + +#if DCHECK_IS_ON() + // For sanity check only. + size_t original_size_in_bytes; +#endif +}; + +UTF8AdaptorInfo* ToAdaptor(const WTF::String& input, void* context) { + UTF8AdaptorInfo* adaptor = static_cast<UTF8AdaptorInfo*>(context); + +#if DCHECK_IS_ON() + DCHECK_EQ(adaptor->original_size_in_bytes, + static_cast<size_t>(input.sizeInBytes())); +#endif + return adaptor; +} + +} // namespace + +// static +void StringTraits<WTF::String>::SetToNull(WTF::String* output) { + if (output->isNull()) + return; + + WTF::String result; + output->swap(result); +} + +// static +void* StringTraits<WTF::String>::SetUpContext(const WTF::String& input) { + return new UTF8AdaptorInfo(input); +} + +// static +void StringTraits<WTF::String>::TearDownContext(const WTF::String& input, + void* context) { + delete ToAdaptor(input, context); +} + +// static +size_t StringTraits<WTF::String>::GetSize(const WTF::String& input, + void* context) { + return ToAdaptor(input, context)->utf8_adaptor.length(); +} + +// static +const char* StringTraits<WTF::String>::GetData(const WTF::String& input, + void* context) { + return ToAdaptor(input, context)->utf8_adaptor.data(); +} + +// static +bool StringTraits<WTF::String>::Read(StringDataView input, + WTF::String* output) { + WTF::String result = WTF::String::fromUTF8(input.storage(), input.size()); + output->swap(result); + return true; +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc index 3d88ec96da7..e4b49557937 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc @@ -20,11 +20,12 @@ base::LazyInstance<base::ThreadLocalPointer<SyncHandleRegistry>> } // namespace // static -SyncHandleRegistry* SyncHandleRegistry::current() { - SyncHandleRegistry* result = g_current_sync_handle_watcher.Pointer()->Get(); +scoped_refptr<SyncHandleRegistry> SyncHandleRegistry::current() { + scoped_refptr<SyncHandleRegistry> result( + g_current_sync_handle_watcher.Pointer()->Get()); if (!result) { result = new SyncHandleRegistry(); - DCHECK_EQ(result, g_current_sync_handle_watcher.Pointer()->Get()); + DCHECK_EQ(result.get(), g_current_sync_handle_watcher.Pointer()->Get()); } return result; } @@ -66,10 +67,8 @@ bool SyncHandleRegistry::WatchAllHandles(const bool* should_stop[], MojoHandle ready_handle; MojoResult ready_handle_result; - // This object may be destroyed during a callback. So we have to preserve - // the boolean. - scoped_refptr<base::RefCountedData<bool>> destroyed = destroyed_; - while (!destroyed->data) { + scoped_refptr<SyncHandleRegistry> preserver(this); + while (true) { for (size_t i = 0; i < count; ++i) if (*should_stop[i]) return true; @@ -96,8 +95,7 @@ bool SyncHandleRegistry::WatchAllHandles(const bool* should_stop[], return false; } -SyncHandleRegistry::SyncHandleRegistry() - : destroyed_(new base::RefCountedData<bool>(false)) { +SyncHandleRegistry::SyncHandleRegistry() { MojoHandle handle; MojoResult result = MojoCreateWaitSet(&handle); CHECK_EQ(MOJO_RESULT_OK, result); @@ -106,24 +104,12 @@ SyncHandleRegistry::SyncHandleRegistry() DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); g_current_sync_handle_watcher.Pointer()->Set(this); - - base::MessageLoop::current()->AddDestructionObserver(this); } SyncHandleRegistry::~SyncHandleRegistry() { DCHECK(thread_checker_.CalledOnValidThread()); - destroyed_->data = true; g_current_sync_handle_watcher.Pointer()->Set(nullptr); } -void SyncHandleRegistry::WillDestroyCurrentMessageLoop() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); - - base::MessageLoop::current()->RemoveDestructionObserver(this); - - delete this; -} - } // namespace internal } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h index df927dbb543..d6b8c38e0ce 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h +++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h @@ -9,7 +9,7 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/memory/ref_counted.h" #include "base/threading/thread_checker.h" #include "mojo/public/cpp/system/core.h" @@ -20,10 +20,10 @@ namespace internal { // be watched together. // // This class is not thread safe. -class SyncHandleRegistry : public base::MessageLoop::DestructionObserver { +class SyncHandleRegistry : public base::RefCounted<SyncHandleRegistry> { public: // Returns a thread-local object. - static SyncHandleRegistry* current(); + static scoped_refptr<SyncHandleRegistry> current(); using HandleCallback = base::Callback<void(MojoResult)>; bool RegisterHandle(const Handle& handle, @@ -40,6 +40,8 @@ class SyncHandleRegistry : public base::MessageLoop::DestructionObserver { bool WatchAllHandles(const bool* should_stop[], size_t count); private: + friend class base::RefCounted<SyncHandleRegistry>; + struct HandleHasher { size_t operator()(const Handle& handle) const { return std::hash<uint32_t>()(static_cast<uint32_t>(handle.value())); @@ -48,17 +50,12 @@ class SyncHandleRegistry : public base::MessageLoop::DestructionObserver { using HandleMap = std::unordered_map<Handle, HandleCallback, HandleHasher>; SyncHandleRegistry(); - ~SyncHandleRegistry() override; - - // base::MessageLoop::DestructionObserver implementation: - void WillDestroyCurrentMessageLoop() override; + ~SyncHandleRegistry(); HandleMap handles_; ScopedHandle wait_set_handle_; - scoped_refptr<base::RefCountedData<bool>> destroyed_; - base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(SyncHandleRegistry); diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc b/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc index e259578634b..44092038e78 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc +++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc @@ -18,12 +18,13 @@ SyncHandleWatcher::SyncHandleWatcher( callback_(callback), registered_(false), register_request_count_(0), + registry_(SyncHandleRegistry::current()), destroyed_(new base::RefCountedData<bool>(false)) {} SyncHandleWatcher::~SyncHandleWatcher() { DCHECK(thread_checker_.CalledOnValidThread()); if (registered_) - SyncHandleRegistry::current()->UnregisterHandle(handle_); + registry_->UnregisterHandle(handle_); destroyed_->data = true; } @@ -45,8 +46,7 @@ bool SyncHandleWatcher::SyncWatch(const bool* should_stop) { // to preserve the boolean that WatchAllHandles uses. auto destroyed = destroyed_; const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = - SyncHandleRegistry::current()->WatchAllHandles(should_stop_array, 2); + bool result = registry_->WatchAllHandles(should_stop_array, 2); // This object has been destroyed. if (destroyed->data) @@ -59,8 +59,8 @@ bool SyncHandleWatcher::SyncWatch(const bool* should_stop) { void SyncHandleWatcher::IncrementRegisterCount() { register_request_count_++; if (!registered_) { - registered_ = SyncHandleRegistry::current()->RegisterHandle( - handle_, handle_signals_, callback_); + registered_ = + registry_->RegisterHandle(handle_, handle_signals_, callback_); } } @@ -69,7 +69,7 @@ void SyncHandleWatcher::DecrementRegisterCount() { register_request_count_--; if (register_request_count_ == 0 && registered_) { - SyncHandleRegistry::current()->UnregisterHandle(handle_); + registry_->UnregisterHandle(handle_); registered_ = false; } } diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.h b/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.h index 8d4fd5510a5..93d527bdc83 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.h +++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_watcher.h @@ -61,6 +61,8 @@ class SyncHandleWatcher { // If non-zero, |handle_| should be registered with SyncHandleRegistry. size_t register_request_count_; + scoped_refptr<SyncHandleRegistry> registry_; + scoped_refptr<base::RefCountedData<bool>> destroyed_; base::ThreadChecker thread_checker_; diff --git a/chromium/mojo/public/cpp/bindings/lib/validate_params.h b/chromium/mojo/public/cpp/bindings/lib/validate_params.h index 78c05892f4f..2509b6bb0a6 100644 --- a/chromium/mojo/public/cpp/bindings/lib/validate_params.h +++ b/chromium/mojo/public/cpp/bindings/lib/validate_params.h @@ -12,6 +12,8 @@ namespace mojo { namespace internal { +using ValidateEnumFunc = bool (*)(int32_t); + class ArrayValidateParams { public: // ArrayValidateParams takes ownership of |in_element_validate params|. @@ -20,15 +22,22 @@ class ArrayValidateParams { ArrayValidateParams* in_element_validate_params) : expected_num_elements(in_expected_num_elements), element_is_nullable(in_element_is_nullable), - element_validate_params(in_element_validate_params) {} + element_validate_params(in_element_validate_params), + validate_enum_func(nullptr) {} + + // Validates an array of enums. + ArrayValidateParams(uint32_t in_expected_num_elements, + ValidateEnumFunc in_validate_enum_func) + : expected_num_elements(in_expected_num_elements), + element_is_nullable(false), + element_validate_params(nullptr), + validate_enum_func(in_validate_enum_func) {} ~ArrayValidateParams() { if (element_validate_params) delete element_validate_params; } - // TODO(vtl): The members of this class shouldn't be public. - // If |expected_num_elements| is not 0, the array is expected to have exactly // that number of elements. uint32_t expected_num_elements; @@ -41,6 +50,9 @@ class ArrayValidateParams { // nullptr. In the case of maps, this is used to validate the value array. ArrayValidateParams* element_validate_params; + // Validation function for enum elements. + ValidateEnumFunc validate_enum_func; + private: DISALLOW_COPY_AND_ASSIGN(ArrayValidateParams); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_util.cc b/chromium/mojo/public/cpp/bindings/lib/validation_util.cc index 70dcb29c5e2..28d52884cdc 100644 --- a/chromium/mojo/public/cpp/bindings/lib/validation_util.cc +++ b/chromium/mojo/public/cpp/bindings/lib/validation_util.cc @@ -8,8 +8,8 @@ #include <limits> -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/message_internal.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" @@ -52,6 +52,26 @@ bool ValidateStructHeaderAndClaimMemory(const void* data, return true; } +bool ValidateUnionHeaderAndClaimMemory(const void* data, + bool inlined, + BoundsChecker* bounds_checker) { + if (!IsAligned(data)) { + ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); + return false; + } + + // 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, kUnionDataSize)) { + ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); + return false; + } + + return true; +} + bool ValidateMessageIsRequestWithoutResponse(const Message* message) { if (message->has_flag(kMessageIsResponse) || message->has_flag(kMessageExpectsResponse)) { @@ -101,8 +121,9 @@ bool ValidateControlResponse(const Message* message) { return false; } -bool ValidateHandleNonNullable(const Handle& input, const char* error_message) { - if (input.value() != kEncodedInvalidHandleValue) +bool ValidateHandleNonNullable(const Handle_Data& input, + const char* error_message) { + if (input.is_valid()) return true; ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, @@ -120,7 +141,7 @@ bool ValidateInterfaceIdNonNullable(InterfaceId input, return false; } -bool ValidateHandle(const Handle& input, BoundsChecker* bounds_checker) { +bool ValidateHandle(const Handle_Data& input, BoundsChecker* bounds_checker) { if (bounds_checker->ClaimHandle(input)) return true; diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_util.h b/chromium/mojo/public/cpp/bindings/lib/validation_util.h index 5314a362702..6189ffda40b 100644 --- a/chromium/mojo/public/cpp/bindings/lib/validation_util.h +++ b/chromium/mojo/public/cpp/bindings/lib/validation_util.h @@ -9,6 +9,7 @@ #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/bounds_checker.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" #include "mojo/public/cpp/bindings/message.h" @@ -30,6 +31,14 @@ bool ValidateEncodedPointer(const uint64_t* offset); bool ValidateStructHeaderAndClaimMemory(const void* data, BoundsChecker* bounds_checker); +// Validates that |data| contains a valid union header, in terms of alignment +// and size. If not inlined, it checks that the memory range +// [data, data + num_bytes) is not marked as occupied by other objects in +// |bounds_checker|. On success, the memory range is marked as occupied. +bool ValidateUnionHeaderAndClaimMemory(const void* data, + bool inlined, + BoundsChecker* bounds_checker); + // Validates that the message is a request which doesn't expect a response. bool ValidateMessageIsRequestWithoutResponse(const Message* message); // Validates that the message is a request expecting a response. @@ -73,13 +82,14 @@ bool ValidateInlinedUnionNonNullable(const T& input, return false; } -bool ValidateHandleNonNullable(const Handle& input, const char* error_message); +bool ValidateHandleNonNullable(const Handle_Data& input, + const char* error_message); bool ValidateInterfaceIdNonNullable(InterfaceId input, const char* error_message); template <typename T> -bool ValidateArray(const ArrayPointer<T>& input, +bool ValidateArray(const Pointer<Array_Data<T>>& input, BoundsChecker* bounds_checker, const ArrayValidateParams* validate_params) { if (!ValidateEncodedPointer(&input.offset)) { @@ -92,7 +102,7 @@ bool ValidateArray(const ArrayPointer<T>& input, } template <typename T> -bool ValidateMap(const StructPointer<T>& input, +bool ValidateMap(const Pointer<T>& input, BoundsChecker* bounds_checker, const ArrayValidateParams* value_validate_params) { if (!ValidateEncodedPointer(&input.offset)) { @@ -105,8 +115,7 @@ bool ValidateMap(const StructPointer<T>& input, } template <typename T> -bool ValidateStruct(const StructPointer<T>& input, - BoundsChecker* bounds_checker) { +bool ValidateStruct(const Pointer<T>& input, BoundsChecker* bounds_checker) { if (!ValidateEncodedPointer(&input.offset)) { ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); return false; @@ -120,25 +129,21 @@ bool ValidateInlinedUnion(const T& input, BoundsChecker* bounds_checker) { return T::Validate(&input, bounds_checker, true); } -bool ValidateHandle(const Handle& input, BoundsChecker* bounds_checker); - -bool ValidateAssociatedInterfaceId(InterfaceId input); - -// Checks whether the given enum value is valid. Please note that any value is -// valid for an extensible enum, although it may be from a newer version and -// thus unknown. template <typename T> -bool ValidateEnum(const T& input) { - if (T::kIsExtensible) - return true; - - if (T::IsKnownValue(input.value)) - return true; +bool ValidateNonInlinedUnion(const Pointer<T>& input, + BoundsChecker* bounds_checker) { + if (!ValidateEncodedPointer(&input.offset)) { + ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); + return false; + } - ReportValidationError(VALIDATION_ERROR_UNKNOWN_ENUM_VALUE); - return false; + return T::Validate(DecodePointerRaw(&input.offset), bounds_checker, false); } +bool ValidateHandle(const Handle_Data& input, BoundsChecker* bounds_checker); + +bool ValidateAssociatedInterfaceId(InterfaceId input); + } // namespace internal } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_array_serialization.h b/chromium/mojo/public/cpp/bindings/lib/wtf_array_serialization.h deleted file mode 100644 index 70edbf1fe6b..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_array_serialization.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_ARRAY_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_ARRAY_SERIALIZATION_H_ - -#include <stddef.h> - -#include "mojo/public/cpp/bindings/lib/array_serialization_traits.h" -#include "mojo/public/cpp/bindings/wtf_array.h" - -namespace mojo { - -template <typename E> -inline size_t GetSerializedSize_(const WTFArray<E>& input, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<WTFArray<E>>::GetSerializedSize( - input, context); -} - -template <typename E, typename F> -inline void SerializeArray_( - WTFArray<E> input, - internal::Buffer* buf, - internal::Array_Data<F>** output, - const internal::ArrayValidateParams* validate_params, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<WTFArray<E>>::template Serialize<F>( - std::move(input), buf, output, validate_params, context); -} - -template <typename E, typename F> -inline bool Deserialize_(internal::Array_Data<F>* input, - WTFArray<E>* output, - internal::SerializationContext* context) { - return internal::ArraySerializationImpl<WTFArray<E>>::template Deserialize<F>( - input, output, context); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_ARRAY_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h b/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h index 318d1522231..dbb3f9edbca 100644 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h @@ -5,7 +5,8 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ -#include "mojo/public/cpp/bindings/lib/wtf_array_serialization.h" -#include "mojo/public/cpp/bindings/lib/wtf_string_serialization.h" +#include "mojo/public/cpp/bindings/array_traits_wtf.h" +#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" +#include "mojo/public/cpp/bindings/string_traits_wtf.h" #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc deleted file mode 100644 index febd073ff5e..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2016 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/lib/wtf_string_serialization.h" - -#include <string.h> - -#include <queue> - -#include "base/logging.h" -#include "third_party/WebKit/Source/wtf/text/StringUTF8Adaptor.h" -#include "third_party/WebKit/Source/wtf/text/WTFString.h" - -namespace WTF { -namespace { - -struct UTF8AdaptorInfo { - explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) { -#if DCHECK_IS_ON() - original_size_in_bytes = static_cast<size_t>(input.sizeInBytes()); -#endif - } - - ~UTF8AdaptorInfo() {} - - WTF::StringUTF8Adaptor utf8_adaptor; - -#if DCHECK_IS_ON() - // For sanity check only. - size_t original_size_in_bytes; -#endif -}; - -class WTFStringContextImpl : public mojo::internal::WTFStringContext { - public: - WTFStringContextImpl() {} - ~WTFStringContextImpl() override {} - - std::queue<UTF8AdaptorInfo>& utf8_adaptors() { return utf8_adaptors_; } - - private: - // When serializing an object, we call GetSerializedSize_() recursively on - // all its elements/members to compute the total size, and then call - // Serialize*_() recursively in the same order to do the actual - // serialization. If some WTF::Strings need to be converted to UTF8, we don't - // want to do that twice. Therefore, we store a WTF::StringUTF8Adaptor for - // each in the first pass, and reuse it in the second pass. - std::queue<UTF8AdaptorInfo> utf8_adaptors_; - - DISALLOW_COPY_AND_ASSIGN(WTFStringContextImpl); -}; - -} // namespace - -size_t GetSerializedSize_(const WTF::String& input, - mojo::internal::SerializationContext* context) { - if (input.isNull()) - return 0; - - if (!context->wtf_string_context) - context->wtf_string_context.reset(new WTFStringContextImpl); - - auto& utf8_adaptors = - static_cast<WTFStringContextImpl*>(context->wtf_string_context.get()) - ->utf8_adaptors(); - - utf8_adaptors.emplace(input); - - return mojo::internal::Align(sizeof(mojo::internal::String_Data) + - utf8_adaptors.back().utf8_adaptor.length()); -} - -void Serialize_(const WTF::String& input, - mojo::internal::Buffer* buf, - mojo::internal::String_Data** output, - mojo::internal::SerializationContext* context) { - if (input.isNull()) { - *output = nullptr; - return; - } - - auto& utf8_adaptors = - static_cast<WTFStringContextImpl*>(context->wtf_string_context.get()) - ->utf8_adaptors(); - - DCHECK(!utf8_adaptors.empty()); -#if DCHECK_IS_ON() - DCHECK_EQ(utf8_adaptors.front().original_size_in_bytes, - static_cast<size_t>(input.sizeInBytes())); -#endif - - const WTF::StringUTF8Adaptor& adaptor = utf8_adaptors.front().utf8_adaptor; - - mojo::internal::String_Data* result = - mojo::internal::String_Data::New(adaptor.length(), buf); - if (result) - memcpy(result->storage(), adaptor.data(), adaptor.length()); - - utf8_adaptors.pop(); - - *output = result; -} - -bool Deserialize_(mojo::internal::String_Data* input, - WTF::String* output, - mojo::internal::SerializationContext* context) { - if (input) { - WTF::String result = WTF::String::fromUTF8(input->storage(), input->size()); - output->swap(result); - } else if (!output->isNull()) { - WTF::String result; - output->swap(result); - } - return true; -} - -} // namespace WTF diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.h b/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.h deleted file mode 100644 index a1102654dcd..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_string_serialization.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ - -#include <stddef.h> - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" - -namespace WTF { -class String; - -size_t GetSerializedSize_(const WTF::String& input, - mojo::internal::SerializationContext* context); -void Serialize_(const WTF::String& input, - mojo::internal::Buffer* buffer, - mojo::internal::String_Data** output, - mojo::internal::SerializationContext* context); -bool Deserialize_(mojo::internal::String_Data* input, - WTF::String* output, - mojo::internal::SerializationContext* context); - -} // namespace WTF - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ diff --git a/chromium/mojo/public/cpp/bindings/map.h b/chromium/mojo/public/cpp/bindings/map.h index 6d0d57d6793..f1cdd41ae7c 100644 --- a/chromium/mojo/public/cpp/bindings/map.h +++ b/chromium/mojo/public/cpp/bindings/map.h @@ -24,20 +24,23 @@ namespace mojo { // - There can only be one entry per unique key. // - Values of move-only types will be moved into the Map when they are added // using the insert() method. -template <typename Key, typename Value> +template <typename K, typename V> class Map { MOVE_ONLY_TYPE_FOR_CPP_03(Map); public: + using Key = K; + using Value = V; + // Map keys cannot be move only classes. static_assert(!internal::IsMoveOnlyType<Key>::value, "Map keys cannot be move only types."); using ConstIterator = typename std::map<Key, Value>::const_iterator; - using Data_ = - internal::Map_Data<typename internal::WrapperTraits<Key>::DataType, - typename internal::WrapperTraits<Value>::DataType>; + using Data_ = internal::Map_Data< + typename internal::GetDataTypeAsArrayElement<Key>::Data, + typename internal::GetDataTypeAsArrayElement<Value>::Data>; // Constructs an empty map. Map() : is_null_(false) {} diff --git a/chromium/mojo/public/cpp/bindings/message.h b/chromium/mojo/public/cpp/bindings/message.h index 51636693c71..d8eed2bfc3e 100644 --- a/chromium/mojo/public/cpp/bindings/message.h +++ b/chromium/mojo/public/cpp/bindings/message.h @@ -9,12 +9,13 @@ #include <stdint.h> #include <limits> +#include <memory> #include <vector> #include "base/logging.h" -#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/bindings/lib/message_buffer.h" #include "mojo/public/cpp/bindings/lib/message_internal.h" -#include "mojo/public/cpp/bindings/lib/pickle_buffer.h" +#include "mojo/public/cpp/system/message.h" namespace mojo { @@ -27,15 +28,18 @@ class Message { Message(); ~Message(); + // Initializes a Message with enough space for |capacity| bytes. void Initialize(size_t capacity, bool zero_initialized); + // Initializes a Message from an existing Mojo MessageHandle. + void InitializeFromMojoMessage(ScopedMessageHandle message, + uint32_t num_bytes, + std::vector<Handle>* handles); + // Transfers data and handles to |destination|. void MoveTo(Message* destination); - uint32_t data_num_bytes() const { - DCHECK(buffer_->data_num_bytes() <= std::numeric_limits<uint32_t>::max()); - return static_cast<uint32_t>(buffer_->data_num_bytes()); - } + uint32_t data_num_bytes() const { return buffer_->data_num_bytes(); } // Access the raw bytes of the message. const uint8_t* data() const { @@ -90,10 +94,15 @@ class Message { // Access the underlying Buffer interface. internal::Buffer* buffer() { return buffer_.get(); } + // Takes a scoped MessageHandle which may be passed to |WriteMessageNew()| for + // transmission. Note that this invalidates this Message object, taking + // ownership of its internal storage and any attached handles. + ScopedMessageHandle TakeMojoMessage(); + private: void CloseHandles(); - scoped_ptr<internal::PickleBuffer> buffer_; + std::unique_ptr<internal::MessageBuffer> buffer_; std::vector<Handle> handles_; DISALLOW_COPY_AND_ASSIGN(Message); @@ -122,7 +131,8 @@ class MessageReceiverWithResponder : public MessageReceiver { // |responder| and will delete it after calling |responder->Accept| or upon // its own destruction. // - // TODO(yzshen): consider changing |responder| to scoped_ptr<MessageReceiver>. + // TODO(yzshen): consider changing |responder| to + // std::unique_ptr<MessageReceiver>. virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder) WARN_UNUSED_RESULT = 0; }; @@ -160,7 +170,8 @@ class MessageReceiverWithResponderStatus : public MessageReceiver { // |responder| and will delete it after calling |responder->Accept| or upon // its own destruction. // - // TODO(yzshen): consider changing |responder| to scoped_ptr<MessageReceiver>. + // TODO(yzshen): consider changing |responder| to + // std::unique_ptr<MessageReceiver>. virtual bool AcceptWithResponder(Message* message, MessageReceiverWithStatus* responder) WARN_UNUSED_RESULT = 0; diff --git a/chromium/mojo/public/cpp/bindings/native_struct.h b/chromium/mojo/public/cpp/bindings/native_struct.h new file mode 100644 index 00000000000..882c970ce25 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/native_struct.h @@ -0,0 +1,47 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ + +#include "mojo/public/cpp/bindings/array.h" +#include "mojo/public/cpp/bindings/lib/native_struct_data.h" +#include "mojo/public/cpp/bindings/struct_ptr.h" +#include "mojo/public/cpp/bindings/type_converter.h" + +namespace mojo { + +class NativeStruct; +using NativeStructPtr = StructPtr<NativeStruct>; + +// Native-only structs correspond to "[Native] struct Foo;" definitions in +// mojom. +class NativeStruct { + public: + using Data_ = internal::NativeStruct_Data; + + static NativeStructPtr New(); + + template <typename U> + static NativeStructPtr From(const U& u) { + return TypeConverter<NativeStructPtr, U>::Convert(u); + } + + template <typename U> + U To() const { + return TypeConverter<U, NativeStruct>::Convert(*this); + } + + NativeStruct(); + ~NativeStruct(); + + NativeStructPtr Clone() const; + bool Equals(const NativeStruct& other) const; + + Array<uint8_t> data; +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h b/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h index cb941812071..d13676470f0 100644 --- a/chromium/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h +++ b/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ +#ifndef MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -11,9 +11,10 @@ #include "mojo/public/cpp/bindings/lib/interface_id.h" namespace mojo { -namespace internal { +namespace internal { class MultiplexRouter; +} // ScopedInterfaceEndpointHandle refers to one end of an interface, either the // implementation side or the client side. @@ -24,14 +25,6 @@ class ScopedInterfaceEndpointHandle { // Creates an invalid endpoint handle. ScopedInterfaceEndpointHandle(); - // This is supposed to be used by MultiplexRouter only. - // |id| is the corresponding interface ID. - // If |is_local| is false, this handle is meant to be passed over |router| to - // the remote side. - ScopedInterfaceEndpointHandle(InterfaceId id, - bool is_local, - scoped_refptr<MultiplexRouter> router); - ScopedInterfaceEndpointHandle(ScopedInterfaceEndpointHandle&& other); ~ScopedInterfaceEndpointHandle(); @@ -39,25 +32,39 @@ class ScopedInterfaceEndpointHandle { ScopedInterfaceEndpointHandle& operator=( ScopedInterfaceEndpointHandle&& other); - bool is_valid() const { return IsValidInterfaceId(id_); } + bool is_valid() const { return internal::IsValidInterfaceId(id_); } - InterfaceId id() const { return id_; } bool is_local() const { return is_local_; } - MultiplexRouter* router() const { return router_.get(); } void reset(); void swap(ScopedInterfaceEndpointHandle& other); + // DO NOT USE METHODS BELOW THIS LINE. These are for internal use and testing. + + internal::InterfaceId id() const { return id_; } + + internal::MultiplexRouter* router() const { return router_.get(); } + // Releases the handle without closing it. - InterfaceId release(); + internal::InterfaceId release(); private: - InterfaceId id_; + friend class internal::MultiplexRouter; + + // This is supposed to be used by MultiplexRouter only. + // |id| is the corresponding interface ID. + // If |is_local| is false, this handle is meant to be passed over |router| to + // the remote side. + ScopedInterfaceEndpointHandle( + internal::InterfaceId id, + bool is_local, + scoped_refptr<internal::MultiplexRouter> router); + + internal::InterfaceId id_; bool is_local_; - scoped_refptr<MultiplexRouter> router_; + scoped_refptr<internal::MultiplexRouter> router_; }; -} // namespace internal } // namespace mojo -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ +#endif // MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits.h b/chromium/mojo/public/cpp/bindings/string_traits.h new file mode 100644 index 00000000000..a6ade6fdf68 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits.h @@ -0,0 +1,69 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/lib/array_internal.h" + +namespace mojo { + +// Access to the contents of a serialized string. +class StringDataView { + public: + explicit StringDataView(internal::String_Data* data) : data_(data) { + DCHECK(data_); + } + + const char* storage() const { return data_->storage(); } + + size_t size() const { return data_->size(); } + + private: + internal::String_Data* data_; +}; + +// This must be specialized for any type |T| to be serialized/deserialized as +// a mojom string. +// +// Imagine you want to specialize it for CustomString, usually you need to +// implement: +// +// template <T> +// struct StringTraits<CustomString> { +// // These two methods are optional. Please see comments in struct_traits.h +// static bool IsNull(const CustomString& input); +// static void SetToNull(CustomString* output); +// +// static size_t GetSize(const CustomString& input); +// static const char* GetData(const CustomString& input); +// +// static bool Read(StringDataView input, CustomString* output); +// }; +// +// In some cases, you may need to do conversion before you can return the size +// and data as 8-bit characters for serialization. (For example, CustomString is +// UTF-16 string). In that case, you can add two optional methods: +// +// static void* SetUpContext(const CustomString& input); +// static void TearDownContext(const CustomString& input, void* context); +// +// And then you append a second parameter, void* context, to GetSize() and +// GetData(): +// +// static size_t GetSize(const CustomString& input, void* context); +// static const char* GetData(const CustomString& input, void* context); +// +// If a CustomString instance is not null, the serialization code will call +// SetUpContext() at the beginning, and pass the resulting context pointer to +// GetSize()/GetData(). After serialization is done, it calls TearDownContext() +// so that you can do any necessary cleanup. +// +template <typename T> +struct StringTraits; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_standard.h b/chromium/mojo/public/cpp/bindings/string_traits_standard.h new file mode 100644 index 00000000000..9b78d2473ec --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits_standard.h @@ -0,0 +1,31 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STANDARD_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STANDARD_H_ + +#include "mojo/public/cpp/bindings/string.h" +#include "mojo/public/cpp/bindings/string_traits.h" + +namespace mojo { + +template <> +struct StringTraits<String> { + static bool IsNull(const String& input) { return input.is_null(); } + static void SetToNull(String* output) { *output = nullptr; } + + static size_t GetSize(const String& input) { return input.size(); } + + static const char* GetData(const String& input) { return input.data(); } + + static bool Read(StringDataView input, String* output) { + String result(input.storage(), input.size()); + result.Swap(output); + return true; + } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STANDARD_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_stl.h b/chromium/mojo/public/cpp/bindings/string_traits_stl.h new file mode 100644 index 00000000000..f6cc8ad098f --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits_stl.h @@ -0,0 +1,38 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ + +#include <string> + +#include "mojo/public/cpp/bindings/string_traits.h" + +namespace mojo { + +template <> +struct StringTraits<std::string> { + static bool IsNull(const std::string& input) { + // std::string is always converted to non-null mojom string. + return false; + } + + static void SetToNull(std::string* output) { + // std::string doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const std::string& input) { return input.size(); } + + static const char* GetData(const std::string& input) { return input.data(); } + + static bool Read(StringDataView input, std::string* output) { + output->assign(input.storage(), input.size()); + return true; + } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_string16.h b/chromium/mojo/public/cpp/bindings/string_traits_string16.h new file mode 100644 index 00000000000..5a089080bd0 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits_string16.h @@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ + +#include "base/strings/string16.h" +#include "mojo/public/cpp/bindings/string_traits.h" + +namespace mojo { + +template <> +struct StringTraits<base::string16> { + static bool IsNull(const base::string16& input) { + // base::string16 is always converted to non-null mojom string. + return false; + } + + static void SetToNull(base::string16* output) { + // Convert null to an "empty" base::string16. + output->clear(); + } + + static void* SetUpContext(const base::string16& input); + static void TearDownContext(const base::string16& input, void* context); + + static size_t GetSize(const base::string16& input, void* context); + static const char* GetData(const base::string16& input, void* context); + + static bool Read(StringDataView input, base::string16* output); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_string_piece.h b/chromium/mojo/public/cpp/bindings/string_traits_string_piece.h new file mode 100644 index 00000000000..af6be893ac0 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits_string_piece.h @@ -0,0 +1,43 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ + +#include "base/strings/string_piece.h" +#include "mojo/public/cpp/bindings/string_traits.h" + +namespace mojo { + +template <> +struct StringTraits<base::StringPiece> { + static bool IsNull(const base::StringPiece& input) { + // base::StringPiece is always converted to non-null mojom string. We could + // have let StringPiece containing a null data pointer map to null mojom + // string, but StringPiece::empty() returns true in this case. It seems + // confusing to mix the concept of empty and null strings, especially + // because they mean different things in mojom. + return false; + } + + static void SetToNull(base::StringPiece* output) { + // Convert null to an "empty" base::StringPiece. + output->set(nullptr, 0); + } + + static size_t GetSize(const base::StringPiece& input) { return input.size(); } + + static const char* GetData(const base::StringPiece& input) { + return input.data(); + } + + static bool Read(StringDataView input, base::StringPiece* output) { + output->set(input.storage(), input.size()); + return true; + } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_wtf.h b/chromium/mojo/public/cpp/bindings/string_traits_wtf.h new file mode 100644 index 00000000000..238c2eb1199 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/string_traits_wtf.h @@ -0,0 +1,31 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ + +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/string_traits.h" +#include "third_party/WebKit/Source/wtf/text/WTFString.h" + +namespace mojo { + +template <> +struct StringTraits<WTF::String> { + static bool IsNull(const WTF::String& input) { return input.isNull(); } + static void SetToNull(WTF::String* output); + + static void* SetUpContext(const WTF::String& input); + static void TearDownContext(const WTF::String& input, void* context); + + static size_t GetSize(const WTF::String& input, void* context); + + static const char* GetData(const WTF::String& input, void* context); + + static bool Read(StringDataView input, WTF::String* output); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ diff --git a/chromium/mojo/public/cpp/bindings/struct_traits.h b/chromium/mojo/public/cpp/bindings/struct_traits.h index fb7290b20ab..ee9a336ba18 100644 --- a/chromium/mojo/public/cpp/bindings/struct_traits.h +++ b/chromium/mojo/public/cpp/bindings/struct_traits.h @@ -10,22 +10,97 @@ namespace mojo { // This must be specialized for any type |T| to be serialized/deserialized as // a mojom struct of type |MojomType|. // -// Each specialization must implement a few things: -// +// Each specialization needs to implement a few things: // 1. Static getters for each field in the Mojom type. These should be // of the form: // -// static <return type> <field name>(const T&) +// static <return type> <field name>(const T& input); // // and should return a serializable form of the named field as extracted -// from the referenced |T| instance. +// from |input|. +// +// Serializable form of a field: +// Value or reference of the same type used in |MojomType|, or the +// following alternatives: +// - string: +// Value or reference of any type that has a StringTraits defined. +// Supported by default: base::StringPiece, std::string. +// +// - array: +// Value or reference of any type that has an ArrayTraits defined. +// Supported by default: std::vector, WTF::Vector (in blink). +// +// - struct: +// Value or reference of any type that has a StructTraits defined. +// +// 2. A static Read() method to set the contents of a |T| instance from a +// |MojomType|DataView (e.g., if |MojomType| is test::Example, the data +// view will be test::ExampleDataView). +// +// static bool Read(|MojomType|DataView data, T* output); +// +// The generated |MojomType|DataView type provides a convenient, +// inexpensive view of a serialized struct's field data. +// +// Returning false indicates invalid incoming data and causes the message +// pipe receiving it to be disconnected. Therefore, you can do custom +// validation for |T| in this method. +// +// 3. [Optional] A static IsNull() method indicating whether a given |T| +// instance is null: +// +// static bool IsNull(const T& input); +// +// If this method returns true, it is guaranteed that none of the getters +// (described in section 1) will be called for the same |input|. So you +// don't have to check whether |input| is null in those getters. +// +// If it is not defined, |T| instances are always considered non-null. +// +// [Optional] A static SetToNull() method to set the contents of a given +// |T| instance to null. +// +// static void SetToNull(T* output); +// +// When a null serialized struct is received, the deserialization code +// calls this method instead of Read(). +// +// NOTE: It is to set |*output|'s contents to a null state, not to set the +// |output| pointer itself to null. "Null state" means whatever state you +// think it makes sense to map a null serialized struct to. +// +// If it is not defined, null is not allowed to be converted to |T|. In +// that case, an incoming null value is considered invalid and causes the +// message pipe to be disconnected. +// +// EXAMPLE: +// +// Mojom definition: +// struct Bar {}; +// struct Foo { +// int32 f_integer; +// string f_string; +// array<string> f_string_array; +// Bar f_bar; +// }; // -// 2. A static Read method to initialize a new |T| from a MojomType::Reader: +// StructTraits for Foo: +// template <> +// struct StructTraits<Foo, CustomFoo> { +// // Optional methods dealing with null: +// static bool IsNull(const CustomFoo& input); +// static void SetToNull(CustomFoo* output); // -// static bool Read(MojomType::Reader r, T* out); +// // Field getters: +// static int32_t f_integer(const CustomFoo& input); +// static const std::string& f_string(const CustomFoo& input); +// static const std::vector<std::string>& f_string_array( +// const CustomFoo& input); +// // Assuming there is a StructTraits<Bar, CustomBar> defined. +// static const CustomBar& f_bar(const CustomFoo& input); // -// The generated MojomType::Reader type provides a convenient, inexpensive -// view of a serialized struct's field data. +// static bool Read(FooDataView data, CustomFoo* output); +// }; // template <typename MojomType, typename T> struct StructTraits; diff --git a/chromium/mojo/public/cpp/bindings/wtf_array.h b/chromium/mojo/public/cpp/bindings/wtf_array.h index b5d1a30c363..06c910d5996 100644 --- a/chromium/mojo/public/cpp/bindings/wtf_array.h +++ b/chromium/mojo/public/cpp/bindings/wtf_array.h @@ -29,9 +29,9 @@ class WTFArray { MOVE_ONLY_TYPE_FOR_CPP_03(WTFArray); public: - using Data_ = - internal::Array_Data<typename internal::WrapperTraits<T>::DataType>; - using ElementType = T; + using Data_ = internal::Array_Data< + typename internal::GetDataTypeAsArrayElement<T>::Data>; + using Element = T; // Constructs an empty array. WTFArray() : is_null_(false) {} diff --git a/chromium/mojo/public/cpp/system/BUILD.gn b/chromium/mojo/public/cpp/system/BUILD.gn index 0aef01df652..64869f3b577 100644 --- a/chromium/mojo/public/cpp/system/BUILD.gn +++ b/chromium/mojo/public/cpp/system/BUILD.gn @@ -9,6 +9,7 @@ source_set("system") { "data_pipe.h", "functions.h", "handle.h", + "message.h", "message_pipe.h", "watcher.cc", "watcher.h", diff --git a/chromium/mojo/public/cpp/system/handle.h b/chromium/mojo/public/cpp/system/handle.h index a0c162a85ea..f83a9226f18 100644 --- a/chromium/mojo/public/cpp/system/handle.h +++ b/chromium/mojo/public/cpp/system/handle.h @@ -75,6 +75,8 @@ class ScopedHandleBase { MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase); public: + using RawHandleType = HandleType; + ScopedHandleBase() {} explicit ScopedHandleBase(HandleType handle) : handle_(handle) {} ~ScopedHandleBase() { CloseIfNecessary(); } @@ -122,11 +124,8 @@ class ScopedHandleBase { private: void CloseIfNecessary() { - if (!handle_.is_valid()) - return; - MojoResult result = MojoClose(handle_.value()); - ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); + if (handle_.is_valid()) + handle_.Close(); } HandleType handle_; @@ -160,6 +159,13 @@ class Handle { MojoHandle* mutable_value() { return &value_; } void set_value(MojoHandle value) { value_ = value; } + void Close() { + DCHECK(is_valid()); + MojoResult result = MojoClose(value_); + ALLOW_UNUSED_LOCAL(result); + DCHECK_EQ(MOJO_RESULT_OK, result); + } + private: MojoHandle value_; diff --git a/chromium/mojo/shell/public/cpp/shell.h b/chromium/mojo/public/cpp/system/message.cc index 772d23f8f66..09d8d46e6dd 100644 --- a/chromium/mojo/shell/public/cpp/shell.h +++ b/chromium/mojo/public/cpp/system/message.cc @@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_SHELL_PUBLIC_CPP_SHELL_H_ -#define MOJO_SHELL_PUBLIC_CPP_SHELL_H_ - -#include "mojo/shell/public/cpp/connector.h" +#include "mojo/public/cpp/system/message.h" namespace mojo { -using Shell = Connector; +ScopedMessageHandle::~ScopedMessageHandle() { -} // namespace mojo +} -#endif // MOJO_SHELL_PUBLIC_CPP_SHELL_H_ +} // namespace mojo diff --git a/chromium/mojo/public/cpp/system/message.h b/chromium/mojo/public/cpp/system/message.h new file mode 100644 index 00000000000..f9002e4c51a --- /dev/null +++ b/chromium/mojo/public/cpp/system/message.h @@ -0,0 +1,76 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ +#define MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ + +#include <limits> + +#include "base/macros.h" +#include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/cpp/system/handle.h" + +namespace mojo { + +const MojoMessageHandle kInvalidMessageHandleValue = + MOJO_MESSAGE_HANDLE_INVALID; + +// Handle wrapper base class for a |MojoMessageHandle|. +class MessageHandle { + public: + MessageHandle() : value_(kInvalidMessageHandleValue) {} + explicit MessageHandle(MojoMessageHandle value) : value_(value) {} + ~MessageHandle() {} + + void swap(MessageHandle& other) { + MojoMessageHandle temp = value_; + value_ = other.value_; + other.value_ = temp; + } + + bool is_valid() const { return value_ != kInvalidMessageHandleValue; } + + const MojoMessageHandle& value() const { return value_; } + MojoMessageHandle* mutable_value() { return &value_; } + void set_value(MojoMessageHandle value) { value_ = value; } + + void Close() { + DCHECK(is_valid()); + MojoResult result = MojoFreeMessage(value_); + ALLOW_UNUSED_LOCAL(result); + DCHECK_EQ(MOJO_RESULT_OK, result); + } + + private: + MojoMessageHandle value_; +}; + +using ScopedMessageHandle = ScopedHandleBase<MessageHandle>; + +inline MojoResult AllocMessage(size_t num_bytes, + const MojoHandle* handles, + size_t num_handles, + MojoAllocMessageFlags flags, + ScopedMessageHandle* handle) { + DCHECK_LE(num_bytes, std::numeric_limits<uint32_t>::max()); + DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max()); + MojoMessageHandle raw_handle; + MojoResult rv = MojoAllocMessage(static_cast<uint32_t>(num_bytes), handles, + static_cast<uint32_t>(num_handles), flags, + &raw_handle); + if (rv != MOJO_RESULT_OK) + return rv; + + handle->reset(MessageHandle(raw_handle)); + return MOJO_RESULT_OK; +} + +inline MojoResult GetMessageBuffer(MessageHandle message, void** buffer) { + DCHECK(message.is_valid()); + return MojoGetMessageBuffer(message.value(), buffer); +} + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ diff --git a/chromium/mojo/public/cpp/system/message_pipe.h b/chromium/mojo/public/cpp/system/message_pipe.h index a56021d75d7..5ba9666e033 100644 --- a/chromium/mojo/public/cpp/system/message_pipe.h +++ b/chromium/mojo/public/cpp/system/message_pipe.h @@ -18,6 +18,7 @@ #include "base/logging.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/cpp/system/handle.h" +#include "mojo/public/cpp/system/message.h" namespace mojo { @@ -88,6 +89,33 @@ inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, message_pipe.value(), bytes, num_bytes, handles, num_handles, flags); } +// Writes to a message pipe. Takes ownership of |message| and any attached +// handles. +inline MojoResult WriteMessageNew(MessagePipeHandle message_pipe, + ScopedMessageHandle message, + MojoWriteMessageFlags flags) { + return MojoWriteMessageNew( + message_pipe.value(), message.release().value(), flags); +} + +// Reads from a message pipe. See |MojoReadMessageNew()| for complete +// documentation. +inline MojoResult ReadMessageNew(MessagePipeHandle message_pipe, + ScopedMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags) { + MojoMessageHandle raw_message; + MojoResult rv = MojoReadMessageNew(message_pipe.value(), &raw_message, + num_bytes, handles, num_handles, flags); + if (rv != MOJO_RESULT_OK) + return rv; + + message->reset(MessageHandle(raw_message)); + return MOJO_RESULT_OK; +} + // Fuses two message pipes together at the given handles. See // |MojoFuseMessagePipes()| for complete documentation. inline MojoResult FuseMessagePipes(ScopedMessagePipeHandle message_pipe0, diff --git a/chromium/mojo/public/cpp/system/watcher.cc b/chromium/mojo/public/cpp/system/watcher.cc index a3a00a9726d..10cf6341262 100644 --- a/chromium/mojo/public/cpp/system/watcher.cc +++ b/chromium/mojo/public/cpp/system/watcher.cc @@ -8,7 +8,6 @@ #include "base/location.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" -#include "base/thread_task_runner_handle.h" #include "mojo/public/c/system/functions.h" namespace mojo { @@ -28,8 +27,10 @@ class Watcher::MessageLoopObserver // base::MessageLoop::DestructionObserver: void WillDestroyCurrentMessageLoop() override { StopObservingIfNecessary(); - if (watcher_->IsWatching()) + if (watcher_->IsWatching()) { + // TODO(yzshen): Remove this notification. crbug.com/604762 watcher_->OnHandleReady(MOJO_RESULT_ABORTED); + } } void StopObservingIfNecessary() { @@ -45,9 +46,12 @@ class Watcher::MessageLoopObserver DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver); }; -Watcher::Watcher() - : task_runner_(base::ThreadTaskRunnerHandle::Get()), +Watcher::Watcher(scoped_refptr<base::SingleThreadTaskRunner> runner) + : task_runner_(std::move(runner)), + is_default_task_runner_(task_runner_ == + base::ThreadTaskRunnerHandle::Get()), weak_factory_(this) { + DCHECK(task_runner_->BelongsToCurrentThread()); weak_self_ = weak_factory_.GetWeakPtr(); } @@ -130,7 +134,11 @@ void Watcher::CallOnHandleReady(uintptr_t context, // Current HandleWatcher users have no need for it, so it's omitted here. Watcher* watcher = reinterpret_cast<Watcher*>(context); if ((flags & MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM) && - watcher->task_runner_->RunsTasksOnCurrentThread()) { + watcher->task_runner_->RunsTasksOnCurrentThread() && + watcher->is_default_task_runner_) { + // System notifications will trigger from the task runner passed to + // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the + // default task runner for the IO thread. watcher->OnHandleReady(result); } else { watcher->task_runner_->PostTask( diff --git a/chromium/mojo/public/cpp/system/watcher.h b/chromium/mojo/public/cpp/system/watcher.h index bc82391542c..34a61f8b0c8 100644 --- a/chromium/mojo/public/cpp/system/watcher.h +++ b/chromium/mojo/public/cpp/system/watcher.h @@ -5,13 +5,15 @@ #ifndef MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ #define MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ +#include <memory> + #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" +#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/handle.h" @@ -40,9 +42,8 @@ class Watcher { // Cancel() the watch in this case. using ReadyCallback = base::Callback<void(MojoResult result)>; - // TODO(rockot/yzshen): Support giving Watcher an explicit TaskRunner for - // more fine-grained control over dispatch behavior. - Watcher(); + explicit Watcher(scoped_refptr<base::SingleThreadTaskRunner> runner = + base::ThreadTaskRunnerHandle::Get()); // NOTE: This destructor automatically calls |Cancel()| if the Watcher is // still active. @@ -92,8 +93,11 @@ class Watcher { // The TaskRunner of this Watcher's owning thread. This field is safe to // access from any thread. const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + // Whether |task_runner_| is the same as base::ThreadTaskRunnerHandle::Get() + // for the thread. + const bool is_default_task_runner_; - scoped_ptr<MessageLoopObserver> message_loop_observer_; + std::unique_ptr<MessageLoopObserver> message_loop_observer_; // A persistent weak reference to this Watcher which can be passed to the // Dispatcher any time this object should be signalled. Safe to access (but diff --git a/chromium/mojo/public/js/BUILD.gn b/chromium/mojo/public/js/BUILD.gn index 4b86e6eb9a5..eda7e04d07e 100644 --- a/chromium/mojo/public/js/BUILD.gn +++ b/chromium/mojo/public/js/BUILD.gn @@ -8,3 +8,38 @@ source_set("js") { "constants.h", ] } + +group("bindings") { + data = [ + "bindings.js", + "buffer.js", + "codec.js", + "connection.js", + "connector.js", + "constants.cc", + "constants.h", + "core.js", + "router.js", + "support.js", + "threading.js", + "unicode.js", + "validator.js", + ] +} + +group("tests") { + testonly = true + + data = [ + "codec_unittests.js", + "core_unittests.js", + "struct_unittests.js", + "test/validation_test_input_parser.js", + "union_unittests.js", + "validation_unittests.js", + "//mojo/public/interfaces/bindings/tests/data/validation/", + ] + public_deps = [ + ":bindings", + ] +} diff --git a/chromium/mojo/public/js/bindings.js b/chromium/mojo/public/js/bindings.js index 44aa9f4e9fe..2fdcae39f30 100644 --- a/chromium/mojo/public/js/bindings.js +++ b/chromium/mojo/public/js/bindings.js @@ -31,17 +31,8 @@ define("mojo/public/js/bindings", [ throw new Error("no stub object"); } - function connectionHandle(connection) { - return connection && - connection.router && - connection.router.connector_ && - connection.router.connector_.handle_; - } - ProxyProperties.prototype.close = function() { - var handle = connectionHandle(this.connection); - if (handle) - core.close(handle); + this.connection.close(); } // Public stub class properties that are managed at runtime by the JS @@ -51,9 +42,7 @@ define("mojo/public/js/bindings", [ } StubProperties.prototype.close = function() { - var handle = connectionHandle(this.connection); - if (handle) - core.close(handle); + this.connection.close(); } // The base class for generated proxy classes. @@ -125,4 +114,4 @@ define("mojo/public/js/bindings", [ exports.StubBase = StubBase; exports.StubBindings = StubBindings; return exports; -});
\ No newline at end of file +}); diff --git a/chromium/mojo/public/js/connection.js b/chromium/mojo/public/js/connection.js index 62e8798fb2d..cdf99ce8c3d 100644 --- a/chromium/mojo/public/js/connection.js +++ b/chromium/mojo/public/js/connection.js @@ -25,6 +25,11 @@ define("mojo/public/js/connection", [ this.remote = remoteProxy; this.router_.setIncomingReceiver(localStub); + this.router_.setErrorHandler(function() { + if (StubBindings(this.local) && + StubBindings(this.local).connectionErrorHandler) + StubBindings(this.local).connectionErrorHandler(); + }.bind(this)); if (this.remote) this.remote.receiver_ = router; diff --git a/chromium/mojo/public/js/router.js b/chromium/mojo/public/js/router.js index dba3e3c85d4..e3db0a6a788 100644 --- a/chromium/mojo/public/js/router.js +++ b/chromium/mojo/public/js/router.js @@ -20,6 +20,7 @@ define("mojo/public/js/router", [ connectorFactory = Connector; this.connector_ = new connectorFactory(handle); this.incomingReceiver_ = null; + this.errorHandler_ = null; this.nextRequestID_ = 0; this.completers_ = new Map(); this.payloadValidators_ = []; @@ -72,6 +73,10 @@ define("mojo/public/js/router", [ this.payloadValidators_ = payloadValidators; }; + Router.prototype.setErrorHandler = function(handler) { + this.errorHandler_ = handler; + }; + Router.prototype.encounteredError = function() { return this.connector_.encounteredError(); }; @@ -118,6 +123,8 @@ define("mojo/public/js/router", [ this.completers_.forEach(function(value) { value.reject(result); }); + if (this.errorHandler_) + this.errorHandler_(); this.close(); }; diff --git a/chromium/mojo/public/mojo_application.gni b/chromium/mojo/public/mojo_application.gni index a18111196fc..1c090a88dd2 100644 --- a/chromium/mojo/public/mojo_application.gni +++ b/chromium/mojo/public/mojo_application.gni @@ -83,7 +83,7 @@ template("mojo_native_application") { if (!defined(invoker.avoid_runner_cycle) || !invoker.avoid_runner_cycle) { # Give the user an out; as some mojo services are depended on by the # runner. - data_deps += [ "//mojo/shell/standalone" ] + data_deps += [ "//services/shell/standalone" ] } if (defined(invoker.data_deps)) { data_deps += invoker.data_deps @@ -93,6 +93,7 @@ template("mojo_native_application") { deps = [ "//mojo/platform_handle:for_shared_library", "//mojo/public/c/system:for_shared_library", + "//services/shell/public/cpp:application_support", ] deps += mojo_deps diff --git a/chromium/mojo/public/mojo_application_manifest.gni b/chromium/mojo/public/mojo_application_manifest.gni index b66626b88bf..61844173058 100644 --- a/chromium/mojo/public/mojo_application_manifest.gni +++ b/chromium/mojo/public/mojo_application_manifest.gni @@ -107,11 +107,14 @@ template("mojo_application_manifest") { } } deps = [] + data_deps = [] if (defined(invoker.deps)) { deps += invoker.deps + data_deps += invoker.deps } if (defined(invoker.base_deps)) { deps += invoker.base_deps + data_deps += invoker.base_deps } } diff --git a/chromium/mojo/public/mojo_application_manifest.gypi b/chromium/mojo/public/mojo_application_manifest.gypi index bda86404707..9b89abb93fd 100644 --- a/chromium/mojo/public/mojo_application_manifest.gypi +++ b/chromium/mojo/public/mojo_application_manifest.gypi @@ -8,23 +8,30 @@ 'application_name%': '<(application_name)', 'application_type%': '<(application_type)', 'base_manifest%': 'none', + 'packaged_manifests%': [] }, 'application_type%': '<(application_type)', 'application_name%': '<(application_name)', 'base_manifest%': '<(base_manifest)', 'manifest_collator_script%': '<(DEPTH)/mojo/public/tools/manifest/manifest_collator.py', + 'packaged_manifests%': '<(packaged_manifests)', 'source_manifest%': '<(source_manifest)', 'conditions': [ ['application_type=="mojo"', { - 'output_manifest%': '<(PRODUCT_DIR)/<(application_name)/manifest.json', + 'output_manifest%': '<(PRODUCT_DIR)/Mojo Applications/<(application_name)/manifest.json', }, { 'output_manifest%': '<(PRODUCT_DIR)/<(application_name)_manifest.json', }], ['base_manifest!="none"', { - 'extra_args%': [ '--base-manifest=<(base_manifest)', ], + 'extra_args%': [ + '--base-manifest=<(base_manifest)', + '<@(packaged_manifests)', + ], }, { - 'extra_args%': [], + 'extra_args%': [ + '<@(packaged_manifests)', + ], }] ], }, diff --git a/chromium/mojo/public/platform/native/system_thunks.cc b/chromium/mojo/public/platform/native/system_thunks.cc index 72d879b5eaf..238ede3f7e1 100644 --- a/chromium/mojo/public/platform/native/system_thunks.cc +++ b/chromium/mojo/public/platform/native/system_thunks.cc @@ -205,6 +205,44 @@ MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { return g_thunks.FuseMessagePipes(handle0, handle1); } +MojoResult MojoWriteMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags) { + assert(g_thunks.WriteMessageNew); + return g_thunks.WriteMessageNew(message_pipe_handle, message, flags); +} + +MojoResult MojoReadMessageNew(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags) { + assert(g_thunks.ReadMessageNew); + return g_thunks.ReadMessageNew(message_pipe_handle, message, num_bytes, + handles, num_handles, flags); +} + +MojoResult MojoAllocMessage(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message) { + assert(g_thunks.AllocMessage); + return g_thunks.AllocMessage( + num_bytes, handles, num_handles, flags, message); +} + +MojoResult MojoFreeMessage(MojoMessageHandle message) { + assert(g_thunks.FreeMessage); + return g_thunks.FreeMessage(message); +} + +MojoResult MojoGetMessageBuffer(MojoMessageHandle message, void** buffer) { + assert(g_thunks.GetMessageBuffer); + return g_thunks.GetMessageBuffer(message, buffer); +} + extern "C" THUNK_EXPORT size_t MojoSetSystemThunks( const MojoSystemThunks* system_thunks) { if (system_thunks->size >= sizeof(g_thunks)) diff --git a/chromium/mojo/public/platform/native/system_thunks.h b/chromium/mojo/public/platform/native/system_thunks.h index 679043640fb..8bd4eca4d7e 100644 --- a/chromium/mojo/public/platform/native/system_thunks.h +++ b/chromium/mojo/public/platform/native/system_thunks.h @@ -120,6 +120,22 @@ struct MojoSystemThunks { uintptr_t context); MojoResult (*CancelWatch)(MojoHandle handle, uintptr_t context); MojoResult (*FuseMessagePipes)(MojoHandle handle0, MojoHandle handle1); + MojoResult (*WriteMessageNew)(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags); + MojoResult (*ReadMessageNew)(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles, + MojoReadMessageFlags flags); + MojoResult (*AllocMessage)(uint32_t num_bytes, + const MojoHandle* handles, + uint32_t num_handles, + MojoAllocMessageFlags flags, + MojoMessageHandle* message); + MojoResult (*FreeMessage)(MojoMessageHandle message); + MojoResult (*GetMessageBuffer)(MojoMessageHandle message, void** buffer); }; #pragma pack(pop) @@ -153,7 +169,12 @@ inline MojoSystemThunks MojoMakeSystemThunks() { MojoGetReadyHandles, MojoWatch, MojoCancelWatch, - MojoFuseMessagePipes}; + MojoFuseMessagePipes, + MojoWriteMessageNew, + MojoReadMessageNew, + MojoAllocMessage, + MojoFreeMessage, + MojoGetMessageBuffer}; return system_thunks; } #endif diff --git a/chromium/mojo/public/tools/bindings/BUILD.gn b/chromium/mojo/public/tools/bindings/BUILD.gn index 2dfa97637f0..ac6bfd4c215 100644 --- a/chromium/mojo/public/tools/bindings/BUILD.gn +++ b/chromium/mojo/public/tools/bindings/BUILD.gn @@ -18,6 +18,8 @@ action("precompile_templates") { "$mojom_generator_root/generators/cpp_templates/module-internal.h.tmpl", "$mojom_generator_root/generators/cpp_templates/module.cc.tmpl", "$mojom_generator_root/generators/cpp_templates/module.h.tmpl", + "$mojom_generator_root/generators/cpp_templates/struct_data_view_declaration.tmpl", + "$mojom_generator_root/generators/cpp_templates/struct_data_view_definition.tmpl", "$mojom_generator_root/generators/cpp_templates/struct_declaration.tmpl", "$mojom_generator_root/generators/cpp_templates/struct_definition.tmpl", "$mojom_generator_root/generators/cpp_templates/struct_macros.tmpl", diff --git a/chromium/mojo/public/tools/bindings/bindings.gyp b/chromium/mojo/public/tools/bindings/bindings.gyp index 6b28e78bd43..140c833b5ae 100644 --- a/chromium/mojo/public/tools/bindings/bindings.gyp +++ b/chromium/mojo/public/tools/bindings/bindings.gyp @@ -26,6 +26,8 @@ 'generators/cpp_templates/module.cc.tmpl', 'generators/cpp_templates/module.h.tmpl', 'generators/cpp_templates/module-internal.h.tmpl', + 'generators/cpp_templates/struct_data_view_declaration.tmpl', + 'generators/cpp_templates/struct_data_view_definition.tmpl', 'generators/cpp_templates/struct_declaration.tmpl', 'generators/cpp_templates/struct_definition.tmpl', 'generators/cpp_templates/struct_macros.tmpl', diff --git a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni new file mode 100644 index 00000000000..67541862617 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni @@ -0,0 +1,34 @@ +# Copyright 2016 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. + +variant = "blink" + +for_blink = true + +_typemap_imports = [ "//mojo/public/cpp/bindings/tests/blink_typemaps.gni" ] +_typemaps = [] + +foreach(typemap_import, _typemap_imports) { + _imported = read_file(typemap_import, "scope") + _typemaps += _imported.typemaps +} + +typemaps = [] +foreach(typemap, _typemaps) { + typemaps += [ read_file(typemap, "scope") ] +} + +blacklist = [ + # TODO(sammc): Remove the following once |for_blink| bindings support WTF + # maps. See https://crbug.com/583738. + "//components/mus/public/interfaces/clipboard.mojom", + "//components/mus/public/interfaces/window_manager.mojom", + "//components/mus/public/interfaces/window_tree.mojom", + "//extensions/common/api/mime_handler.mojom", + "//mojo/public/interfaces/bindings/tests/test_structs.mojom", + "//mojo/public/interfaces/bindings/tests/test_unions.mojom", + "//mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom", + "//services/catalog/public/interfaces/catalog.mojom", + "//services/shell/public/interfaces/capabilities.mojom", +] diff --git a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni new file mode 100644 index 00000000000..d2779901bce --- /dev/null +++ b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni @@ -0,0 +1,23 @@ +# Copyright 2016 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. + +_typemap_imports = [ + "//components/typemaps.gni", + "//gpu/ipc/common/typemaps.gni", + "//media/mojo/interfaces/typemaps.gni", + "//mojo/common/typemaps.gni", + "//mojo/public/cpp/bindings/tests/chromium_typemaps.gni", + "//url/mojo/typemaps.gni", +] +_typemaps = [] + +foreach(typemap_import, _typemap_imports) { + _imported = read_file(typemap_import, "scope") + _typemaps += _imported.typemaps +} + +typemaps = [] +foreach(typemap, _typemaps) { + typemaps += [ read_file(typemap, "scope") ] +} diff --git a/chromium/mojo/public/tools/bindings/format_typemap_generator_args.py b/chromium/mojo/public/tools/bindings/format_typemap_generator_args.py new file mode 100755 index 00000000000..5057d6cdaca --- /dev/null +++ b/chromium/mojo/public/tools/bindings/format_typemap_generator_args.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# Copyright 2016 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 sys + +# This utility converts mojom dependencies into their corresponding typemap +# paths and formats them to be consumed by generate_type_mappings.py. + + +def FormatTypemap(typemap_filename): + # A simple typemap is valid Python with a minor alteration. + with open(typemap_filename) as f: + typemap_content = f.read().replace('=\n', '=') + typemap = {} + exec typemap_content in typemap + + for header in typemap.get('public_headers', []): + yield 'public_headers=%s' % header + for header in typemap.get('traits_headers', []): + yield 'traits_headers=%s' % header + for header in typemap.get('type_mappings', []): + yield 'type_mappings=%s' % header + + +def main(): + typemaps = sys.argv[1:] + print ' '.join('--start-typemap %s' % ' '.join(FormatTypemap(typemap)) + for typemap in typemaps) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/mojo/public/tools/bindings/generate_type_mappings.py b/chromium/mojo/public/tools/bindings/generate_type_mappings.py new file mode 100755 index 00000000000..20d0c722938 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generate_type_mappings.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Generates a JSON typemap from its command-line arguments and dependencies. + +Each typemap should be specified in an command-line argument of the form +key=value, with an argument of "--start-typemap" preceding each typemap. + +For example, +generate_type_mappings.py --output=foo.typemap --start-typemap \\ + public_headers=foo.h traits_headers=foo_traits.h \\ + type_mappings=mojom.Foo=FooImpl + +generates a foo.typemap containing +{ + "c++": { + "mojom.Foo": { + "typename": "FooImpl", + "traits_headers": [ + "foo_traits.h" + ], + "public_headers": [ + "foo.h" + ] + } + } +} + +Then, +generate_type_mappings.py --dependency foo.typemap --output=bar.typemap \\ + --start-typemap public_headers=bar.h traits_headers=bar_traits.h \\ + type_mappings=mojom.Bar=BarImpl + +generates a bar.typemap containing +{ + "c++": { + "mojom.Bar": { + "typename": "BarImpl", + "traits_headers": [ + "bar_traits.h" + ], + "public_headers": [ + "bar.h" + ] + }, + "mojom.Foo": { + "typename": "FooImpl", + "traits_headers": [ + "foo_traits.h" + ], + "public_headers": [ + "foo.h" + ] + } + } +} +""" + +import argparse +import json +import os + + +def ReadTypemap(path): + with open(path) as f: + return json.load(f)['c++'] + + +def ParseTypemapArgs(args): + typemaps = [s for s in '\n'.join(args).split('--start-typemap\n') if s] + result = {} + for typemap in typemaps: + result.update(ParseTypemap(typemap)) + return result + + +def ParseTypemap(typemap): + values = {'type_mappings': [], 'public_headers': [], 'traits_headers': []} + for line in typemap.split('\n'): + if not line: + continue + key, _, value = line.partition('=') + values[key].append(value.lstrip('/')) + result = {} + for typename in values['type_mappings']: + mojom_type, _, native_type = typename.partition('=') + result[mojom_type] = { + 'typename': native_type, + 'public_headers': values['public_headers'], + 'traits_headers': values['traits_headers'], + } + return result + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument( + '--dependency', + type=str, + action='append', + default=[], + help=('A path to another JSON typemap to merge into the output. ' + 'This may be repeated to merge multiple typemaps.')) + parser.add_argument('--output', + type=str, + required=True, + help='The path to which to write the generated JSON.') + params, typemap_params = parser.parse_known_args() + typemaps = ParseTypemapArgs(typemap_params) + missing = [path for path in params.dependency if not os.path.exists(path)] + if missing: + raise IOError('Missing dependencies: %s' % ', '.join(missing)) + for path in params.dependency: + typemaps.update(ReadTypemap(path)) + with open(params.output, 'w') as f: + json.dump({'c++': typemaps}, f, indent=2) + + +if __name__ == '__main__': + main() diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl index 745ebf6bd18..a200a6297c9 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl @@ -16,9 +16,6 @@ enum class {{enum.name}} : int32_t { {%- macro enum_data_decl(enum) %} struct {{enum.name}}_Data { public: - // Used to identify Mojom Enum Data Classes. - typedef void MojomEnumDataType; - static bool const kIsExtensible = {% if enum.extensible %}true{% else %}false{% endif %}; static bool IsKnownValue(int32_t value) { @@ -31,7 +28,13 @@ struct {{enum.name}}_Data { return false; } - int32_t value; + static bool Validate(int32_t value) { + if (kIsExtensible || IsKnownValue(value)) + return true; + + ReportValidationError(mojo::internal::VALIDATION_ERROR_UNKNOWN_ENUM_VALUE); + return false; + } }; {%- endmacro %} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl index 76888c7908f..014e8d57e96 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl @@ -45,12 +45,9 @@ class {{interface.name}} { {%- for method in interface.methods %} {% if method.response_parameters != None %} {%- if method.sync %} - virtual bool {{method.name}}({{interface_macros.declare_sync_method_params("", method)}}) { - // Sync method. This signature is used by the client side; the service side - // should implement the signature with callback below. - NOTREACHED(); - return false; - } + // Sync method. This signature is used by the client side; the service side + // should implement the signature with callback below. + virtual bool {{method.name}}({{interface_macros.declare_sync_method_params("", method)}}); {%- endif %} using {{method.name}}Callback = {{interface_macros.declare_callback(method, for_blink)}}; diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index 8ed0f96ab97..aef7e9d3d78 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl @@ -5,12 +5,16 @@ {%- set proxy_name = interface.name ~ "Proxy" %} {%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %} -{%- macro alloc_params(struct, serialization_context) %} +{%- macro alloc_params(struct, params, message, serialization_context) %} + ({{params}})->DecodePointers(); + ({{serialization_context}})->handles.Swap(({{message}})->mutable_handles()); bool success = true; {%- for param in struct.packed.packed_fields_in_ordinal_order %} {{param.field.kind|cpp_wrapper_type}} p_{{param.field.name}}{}; {%- endfor %} - {{struct_macros.deserialize(struct, "params", "p_%s", serialization_context, "success")}} + {{struct.name}}DataView input_data_view({{params}}, + {{serialization_context}}); + {{struct_macros.deserialize(struct, "input_data_view", "p_%s", "success")}} if (!success) return false; {%- endmacro %} @@ -31,19 +35,32 @@ p_{{param.name}} {{struct_macros.serialize(struct, struct_display_name, input_pattern, "params", "builder.buffer()", serialization_context)}} - params->EncodePointersAndHandles(builder.message()->mutable_handles()); + ({{serialization_context}})->handles.Swap( + builder.message()->mutable_handles()); + params->EncodePointers(); + {%- endmacro %} {#--- Begin #} -MOJO_STATIC_CONST_MEMBER_DEFINITION const char {{class_name}}::Name_[] = "{{namespace_as_string}}::{{class_name}}"; -MOJO_STATIC_CONST_MEMBER_DEFINITION const uint32_t {{class_name}}::Version_; +const char {{class_name}}::Name_[] = "{{namespace_as_string}}::{{class_name}}"; +const uint32_t {{class_name}}::Version_; {#--- Constants #} {%- for constant in interface.constants %} {%- if constant.kind|is_integral_kind %} -MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}}; +const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}}; {%- else %} -MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}} = {{constant|constant_value}}; +const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}} = {{constant|constant_value}}; +{%- endif %} +{%- endfor %} + + +{%- for method in interface.methods %} +{%- if method.sync %} +bool {{class_name}}::{{method.name}}({{interface_macros.declare_sync_method_params("", method)}}) { + NOTREACHED(); + return false; +} {%- endif %} {%- endfor %} @@ -80,8 +97,8 @@ bool {{class_name}}_{{method.name}}_HandleSyncResponse::Accept( reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); - {{alloc_params(method.response_param_struct, "&serialization_context_")}} + {{alloc_params(method.response_param_struct, "params", "message", + "&serialization_context_")}} {%- for param in method.response_parameters %} {%- if param.kind|is_move_only_kind %} @@ -115,8 +132,8 @@ bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept( reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); - {{alloc_params(method.response_param_struct, "&serialization_context_")}} + {{alloc_params(method.response_param_struct, "params", "message", + "&serialization_context_")}} callback_.Run({{pass_params(method.response_parameters)}}); return true; } @@ -276,8 +293,8 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) { reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); - {{alloc_params(method.param_struct, "&serialization_context_")|indent(4)}} + {{alloc_params(method.param_struct, "params", "message", + "&serialization_context_")|indent(4)}} // A null |sink_| means no implementation was bound. assert(sink_); TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}"); @@ -306,8 +323,8 @@ bool {{class_name}}Stub::AcceptWithResponder( reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>( message->mutable_payload()); - params->DecodePointersAndHandles(message->mutable_handles()); - {{alloc_params(method.param_struct, "&serialization_context_")|indent(4)}} + {{alloc_params(method.param_struct, "params", "message", + "&serialization_context_")|indent(4)}} {{class_name}}::{{method.name}}Callback::Runnable* runnable = new {{class_name}}_{{method.name}}_ProxyToResponder( message->request_id(), diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl index 84a0a8b0971..c112a753d63 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl @@ -45,7 +45,11 @@ namespace {{variant}} { {#--- Wrapper forward declarations #} {% for struct in structs %} +{%- if struct|is_native_only_kind %} +using {{struct.name}} = mojo::NativeStruct; +{%- else %} class {{struct.name}}; +{%- endif %} {%- endfor %} {#--- Wrapper forward declarations for unions #} @@ -57,7 +61,11 @@ namespace internal { {#--- Internal forward declarations #} {% for struct in structs %} +{%- if struct|is_native_only_kind %} +using {{struct.name}}_Data = mojo::internal::NativeStruct_Data; +{%- else %} class {{struct.name}}_Data; +{%- endif %} {%- endfor %} {% for union in unions %} @@ -80,7 +88,9 @@ class {{union.name}}_Data; {#--- Struct class declarations #} {% for struct in structs %} -{% include "struct_declaration.tmpl" %} +{%- if not struct|is_native_only_kind %} +{% include "struct_declaration.tmpl" %} +{%- endif %} {%- endfor %} {#--- Interface class declarations. They are needed only when they contain diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index 9d40509435f..7d9870a2ba8 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl @@ -26,11 +26,10 @@ #include "base/logging.h" #include "base/trace_event/trace_event.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/bounds_checker.h" -#include "mojo/public/cpp/bindings/lib/macros.h" #include "mojo/public/cpp/bindings/lib/map_data_internal.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" @@ -85,7 +84,9 @@ const uint32_t {{method_name}} = {{method.ordinal}}; {#--- Struct definitions #} {% for struct in structs %} -{%- include "struct_definition.tmpl" %} +{%- if not struct|is_native_only_kind %} +{%- include "struct_definition.tmpl" %} +{%- endif %} {%- endfor %} {#--- Union definitions #} @@ -95,20 +96,41 @@ const uint32_t {{method_name}} = {{method.ordinal}}; } // namespace internal +namespace { + +{#--- Interface parameter data view definitions #} +{%- for interface in interfaces %} +{%- for method in interface.methods %} +{% set struct = method.param_struct %} +{% include "struct_data_view_declaration.tmpl" %} +{% include "struct_data_view_definition.tmpl" %} +{%- if method.response_parameters != None %} +{%- set struct = method.response_param_struct %} +{% include "struct_data_view_declaration.tmpl" %} +{% include "struct_data_view_definition.tmpl" %} +{%- endif %} +{%- endfor %} +{%- endfor %} + +} // namespace + {#--- Struct Constants #} {%- for struct in structs %} {%- for constant in struct.constants %} {%- if constant.kind|is_integral_kind %} -MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}}; +const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}}; {%- else %} -MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{constant|constant_value}}; +const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{constant|constant_value}}; {%- endif %} {%- endfor %} {%- endfor %} {#--- Struct builder definitions #} {%- for struct in structs %} -{%- include "wrapper_class_definition.tmpl" %} +{%- if not struct|is_native_only_kind %} +{%- include "wrapper_class_definition.tmpl" %} +{%- include "struct_data_view_definition.tmpl" %} +{%- endif %} {%- endfor %} {#--- Union builder definitions #} @@ -121,9 +143,20 @@ MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{struc {%- include "interface_definition.tmpl" %} {%- endfor %} -{#--- Struct Serialization Helpers #} -{%- for struct in structs %} -{%- include "struct_serialization_definition.tmpl" %} +{%- if variant %} +} // namespace {{variant}} +{%- endif %} +{%- for namespace in namespaces_as_array|reverse %} +} // namespace {{namespace}} +{%- endfor %} + +namespace mojo { + +{#--- Struct Serialization Helpers -#} +{% for struct in structs %} +{%- if not struct|is_native_only_kind %} +{% include "struct_serialization_definition.tmpl" %} +{%- endif %} {%- endfor %} {#--- Union Serialization Helpers #} @@ -131,12 +164,8 @@ MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{struc {%- include "union_serialization_definition.tmpl" %} {%- endfor %} -{%- if variant %} -} // namespace {{variant}} -{%- endif %} -{%- for namespace in namespaces_as_array|reverse %} -} // namespace {{namespace}} -{%- endfor %} +} // namespace mojo + #if defined(__clang__) #pragma clang diagnostic pop diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 3d0ce78dff7..a600f531f70 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -17,6 +17,8 @@ #include <stdint.h> #include <ostream> +#include <type_traits> +#include <utility> #include "base/strings/string_piece.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" @@ -30,6 +32,7 @@ #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/map.h" #include "mojo/public/cpp/bindings/message_filter.h" +#include "mojo/public/cpp/bindings/native_struct.h" #include "mojo/public/cpp/bindings/no_interface.h" #include "mojo/public/cpp/bindings/struct_ptr.h" #include "mojo/public/cpp/bindings/struct_traits.h" @@ -53,6 +56,26 @@ #include "{{header}}" {%- endfor %} +{#--- Struct Serialization Helpers -#} +{% for struct in structs %} +{%- if struct|is_native_only_kind and struct|is_typemapped_kind %} +{# This helps the array serializer understand how to serialize arrays of this + native-only type. #} + +namespace mojo { +namespace internal { + +template <> +struct GetDataTypeAsArrayElement<{{struct|cpp_wrapper_type}}> { + using Data = NativeStruct_Data*; +}; + +} // namespace internal +} // namespace mojo + +{%- endif %} +{%- endfor %} + {%- for namespace in namespaces_as_array %} namespace {{namespace}} { {%- endfor %} @@ -97,13 +120,18 @@ using {{interface.name}}AssociatedRequest = {#--- Struct Forward Declarations -#} {% for struct in structs %} +{%- if struct|is_native_only_kind %} +using {{struct.name}} = mojo::NativeStruct; +using {{struct.name}}Ptr = mojo::NativeStructPtr; +{%- else %} class {{struct.name}}; -class {{struct.name}}_Reader; -{% if struct|should_inline %} +class {{struct.name}}DataView; +{%- if struct|should_inline %} using {{struct.name}}Ptr = mojo::InlinedStructPtr<{{struct.name}}>; -{% else %} +{%- else %} using {{struct.name}}Ptr = mojo::StructPtr<{{struct.name}}>; -{% endif %} +{%- endif %} +{%- endif %} {% endfor %} {#--- Union Forward Declarations -#} @@ -152,32 +180,20 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr; {#--- Inlined structs #} {% for struct in structs %} -{% if struct|should_inline %} +{% if struct|should_inline and not struct|is_native_only_kind %} {% include "wrapper_class_declaration.tmpl" %} +{% include "struct_data_view_declaration.tmpl" %} {% endif %} {%- endfor %} {#--- Non-inlined structs #} {% for struct in structs %} -{% if not struct|should_inline %} +{% if not struct|should_inline and not struct|is_native_only_kind %} {% include "wrapper_class_declaration.tmpl" %} +{% include "struct_data_view_declaration.tmpl" %} {% endif %} {%- endfor %} -{#--- Struct Serialization Helpers -#} -{% if structs %} -{% for struct in structs %} -{% include "struct_serialization_declaration.tmpl" %} -{%- endfor %} -{%- endif %} - -{#--- Union Serialization Helpers -#} -{% if unions %} -{% for union in unions %} -{% include "union_serialization_declaration.tmpl" %} -{%- endfor %} -{%- endif %} - {%- for struct in structs %} {%- for enum in struct.enums %} {{enum_stream_operator(enum)}} @@ -199,4 +215,22 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr; } // namespace {{namespace}} {%- endfor %} +namespace mojo { + +{#--- Struct Serialization Helpers -#} +{% for struct in structs %} +{%- if not struct|is_native_only_kind %} +{% include "struct_serialization_declaration.tmpl" %} +{%- endif %} +{%- endfor %} + +{#--- Union Serialization Helpers -#} +{% if unions %} +{%- for union in unions %} +{% include "union_serialization_declaration.tmpl" %} +{%- endfor %} +{%- endif %} + +} // namespace mojo + #endif // {{header_guard}} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl new file mode 100644 index 00000000000..41c96d36f96 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl @@ -0,0 +1,35 @@ +class {{struct.name}}DataView { + public: + {{struct.name}}DataView( + internal::{{struct.name}}_Data* data, + mojo::internal::SerializationContext* context); + +{%- for pf in struct.packed.packed_fields_in_ordinal_order %} +{%- set kind = pf.field.kind -%} +{%- set name = pf.field.name -%} +{%- if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind %} + template <typename UserType> + bool Read{{name|under_to_camel}}(UserType* value) { +{%- if pf.min_version != 0 %} + auto pointer = data_->header_.version >= {{pf.min_version}} + ? data_->{{name}}.ptr : nullptr; +{%- else %} + auto pointer = data_->{{name}}.ptr; +{%- endif %} + return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>( + pointer, value, context_); + } +{%- elif kind|is_map_kind or kind|is_union_kind %} + bool Read{{name|under_to_camel}}({{kind|cpp_wrapper_type}}* value); +{%- elif kind|is_interface_kind or kind|is_any_handle_kind or + kind|is_associated_kind %} + {{kind|cpp_wrapper_type}} Take{{name|under_to_camel}}(); +{%- else %} + {{kind|cpp_wrapper_type}} {{name}}() const; +{%- endif %} +{%- endfor %} + private: + internal::{{struct.name}}_Data* data_; + mojo::internal::SerializationContext* context_; +}; + diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl new file mode 100644 index 00000000000..4fc70d414f7 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl @@ -0,0 +1,107 @@ +{{struct.name}}DataView::{{struct.name}}DataView( + internal::{{struct.name}}_Data* data, + mojo::internal::SerializationContext* context) + : data_(data), context_(context) { + DCHECK(data_); +} + +{%- for pf in struct.packed.packed_fields_in_ordinal_order %} +{%- set kind = pf.field.kind -%} +{%- set name = pf.field.name -%} +{%- if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind %} +{#- Does nothing. They are already defined in the class declaration. #} +{%- elif kind|is_map_kind %} +bool {{struct.name}}DataView::Read{{name|under_to_camel}}( + {{kind|cpp_wrapper_type}}* value) { +{%- if pf.min_version != 0 %} + auto pointer = data_->header_.version >= {{pf.min_version}} + ? data_->{{name}}.ptr : nullptr; +{%- else %} + auto pointer = data_->{{name}}.ptr; +{%- endif %} + return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>( + pointer, value, context_); +} + +{%- elif kind|is_union_kind %} +bool {{struct.name}}DataView::Read{{name|under_to_camel}}( + {{kind|cpp_wrapper_type}}* value) { +{%- if pf.min_version != 0 %} + auto pointer = data_->header_.version >= {{pf.min_version}} + ? &data_->{{name}} : nullptr; +{%- else %} + auto pointer = &data_->{{name}}; +{%- endif %} + return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>( + pointer, value, context_); +} + +{%- elif kind|is_interface_kind %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() { + {{kind|cpp_wrapper_type}} result; +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return result; +{%- endif %} + mojo::internal::InterfaceDataToPointer(&data_->{{name}}, &result, context_); + return result; +} + +{%- elif kind|is_interface_request_kind %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() { + {{kind|cpp_wrapper_type}} result; +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return result; +{%- endif %} + result.Bind(context_->handles.TakeHandleAs<mojo::MessagePipeHandle>( + data_->{{name}})); + return result; +} + +{%- elif kind|is_any_handle_kind %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() { +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return {{kind|cpp_wrapper_type}}(); +{%- endif %} + + return context_->handles.TakeHandleAs< + {{kind|cpp_wrapper_type}}::RawHandleType>(data_->{{name}}); +} + +{%- elif kind|is_associated_interface_kind %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() { + {{kind|cpp_wrapper_type}} result; +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return result; +{%- endif %} + mojo::internal::AssociatedInterfaceDataToPtrInfo(&data_->{{name}}, &result, + context_->router.get()); + return result; +} + +{%- elif kind|is_associated_interface_request_kind %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() { + {{kind|cpp_wrapper_type}} result; +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return result; +{%- endif %} + result.Bind(context_->router->CreateLocalEndpointHandle( + mojo::internal::FetchAndReset(&data_->{{name}}))); + return result; +} + +{%- else %} +{{kind|cpp_wrapper_type}} {{struct.name}}DataView::{{name}}() const { +{%- if pf.min_version != 0 %} + if (data_->header_.version < {{pf.min_version}}) + return {{kind|cpp_wrapper_type}}{}; +{%- endif %} + return static_cast<{{kind|cpp_wrapper_type}}>(data_->{{name}}); +} +{%- endif %} +{%- endfor %} + diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl index 8b3c4ce7aca..29c6d1a06e6 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl @@ -7,8 +7,8 @@ class {{class_name}} { static bool Validate(const void* data, mojo::internal::BoundsChecker* bounds_checker); - void EncodePointersAndHandles(std::vector<mojo::Handle>* handles); - void DecodePointersAndHandles(std::vector<mojo::Handle>* handles); + void EncodePointers(); + void DecodePointers(); {% from "enum_macros.tmpl" import enum_data_decl -%} {#--- Enums #} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl index e2e4831435e..1b4e5efa623 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl @@ -1,105 +1,6 @@ +{%- import "validation_macros.tmpl" as validation_macros %} {%- set class_name = struct.name ~ "_Data" %} -{#- Validates the specified struct field, which is supposed to be an object - (struct/array/string/map/union). - This macro is expanded by the Validate() method. #} -{%- macro _validate_object(struct, packed_field) %} -{%- set name = packed_field.field.name %} -{%- set kind = packed_field.field.kind %} -{%- if not kind|is_nullable_kind %} -{%- if kind|is_union_kind %} - if (!mojo::internal::ValidateInlinedUnionNonNullable( - object->{{name}}, "null {{name}} field in {{struct.name}} struct")) { - return false; - } -{%- else %} - if (!mojo::internal::ValidatePointerNonNullable( - object->{{name}}, "null {{name}} field in {{struct.name}} struct")) { - return false; - } -{%- endif %} -{%- endif %} -{%- if kind|is_array_kind or kind|is_string_kind or - kind|is_native_only_kind %} - const mojo::internal::ArrayValidateParams {{name}}_validate_params( - {{kind|get_array_validate_params_ctor_args|indent(6)}}); - if (!mojo::internal::ValidateArray(object->{{name}}, bounds_checker, - &{{name}}_validate_params)) { - return false; - } -{%- elif kind|is_map_kind %} - const mojo::internal::ArrayValidateParams {{name}}_validate_params( - {{kind.value_kind|get_map_validate_params_ctor_args|indent(6)}}); - if (!mojo::internal::ValidateMap(object->{{name}}, bounds_checker, - &{{name}}_validate_params)) { - return false; - } -{%- elif kind|is_struct_kind %} - if (!mojo::internal::ValidateStruct(object->{{name}}, bounds_checker)) - return false; -{%- elif kind|is_union_kind %} - if (!mojo::internal::ValidateInlinedUnion(object->{{name}}, bounds_checker)) { - return false; - } -{%- else %} -#error Not reached! -{%- endif %} -{%- endmacro %} - -{#- Validates the specified struct field, which is supposed to be a handle or - contain a handle (in the case of interfaces). - This macro is expanded by the Validate() method. #} -{%- macro _validate_handle(struct, packed_field) %} -{%- set name = packed_field.field.name %} -{%- set kind = packed_field.field.kind %} -{%- if kind|is_interface_kind %} - const mojo::Handle {{name}}_handle = object->{{name}}.handle; -{%- else %} - const mojo::Handle {{name}}_handle = object->{{name}}; -{%- endif %} -{%- if not kind|is_nullable_kind %} - if (!mojo::internal::ValidateHandleNonNullable( - {{name}}_handle, - "invalid {{name}} field in {{struct.name}} struct")) { - return false; - } -{%- endif %} - if (!mojo::internal::ValidateHandle({{name}}_handle, bounds_checker)) - return false; -{%- endmacro %} - -{#- Validates the specified struct field, which is supposed to be an associated - interface or an associated interface request. - This macro is expanded by the Validate() method. #} -{%- macro _validate_associated(struct, packed_field) %} -{%- set name = packed_field.field.name %} -{%- set kind = packed_field.field.kind %} -{%- if kind|is_associated_interface_kind %} - const mojo::internal::InterfaceId {{name}}_interface_id = - object->{{name}}.interface_id; -{%- else %} - const mojo::internal::InterfaceId {{name}}_interface_id = object->{{name}}; -{%- endif %} -{%- if not kind|is_nullable_kind %} - if (!mojo::internal::ValidateInterfaceIdNonNullable( - {{name}}_interface_id, - "invalid {{name}} field in {{struct.name}} struct")) { - return false; - } -{%- endif %} - if (!mojo::internal::ValidateAssociatedInterfaceId({{name}}_interface_id)) - return false; -{%- endmacro %} - -{#- Validates the specified struct field, which is supposed to be an enum. - This macro is expanded by the Validate() method. #} -{%- macro _validate_enum(struct, packed_field) %} -{%- set name = packed_field.field.name %} -{%- set kind = packed_field.field.kind %} - if (!mojo::internal::ValidateEnum(object->{{name}})) - return false; -{%- endmacro %} - // static {{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) { return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); @@ -162,39 +63,28 @@ bool {{class_name}}::Validate(const void* data, if (object->header_.version < {{packed_field.min_version}}) return true; {%- endif %} -{%- if kind|is_object_kind %} -{{_validate_object(struct, packed_field)}} -{%- elif kind|is_any_handle_kind or kind|is_interface_kind %} -{{_validate_handle(struct, packed_field)}} -{%- elif kind|is_associated_kind %} -{{_validate_associated(struct, packed_field)}} -{%- else %} -{{_validate_enum(struct, packed_field)}} -{%- endif %} +{%- set field_expr = "object->" ~ packed_field.field.name %} +{{validation_macros.validate_field(packed_field.field, field_expr, struct.name, true)}} {%- endif %} {%- endfor %} return true; } -void {{class_name}}::EncodePointersAndHandles( - std::vector<mojo::Handle>* handles) { +void {{class_name}}::EncodePointers() { CHECK(header_.version == {{struct.versions[-1].version}}); {%- for pf in struct.packed.packed_fields_in_ordinal_order %} {%- if pf.field.kind|is_union_kind %} - this->{{pf.field.name}}.EncodePointersAndHandles(handles); + this->{{pf.field.name}}.EncodePointers(); {%- elif pf.field.kind|is_object_kind %} - mojo::internal::Encode(&this->{{pf.field.name}}, handles); -{%- elif pf.field.kind|is_any_handle_kind or pf.field.kind|is_interface_kind %} - mojo::internal::EncodeHandle(&this->{{pf.field.name}}, handles); + mojo::internal::Encode(&this->{{pf.field.name}}); {%- endif %} {%- endfor %} } -void {{class_name}}::DecodePointersAndHandles( - std::vector<mojo::Handle>* handles) { - // NOTE: The memory backing |this| may has be smaller than |sizeof(*this)|, if - // the message comes from an older version. +void {{class_name}}::DecodePointers() { + // NOTE: The memory backing |this| may be smaller than |sizeof(*this)|, if the + // message comes from an older version. {#- Before decoding fields introduced at a certain version, we need to add a version check, which makes sure we skip further decoding if |this| is from an earlier version. |last_checked_version| records the last @@ -203,18 +93,16 @@ void {{class_name}}::DecodePointersAndHandles( {%- for pf in struct.packed.packed_fields_in_ordinal_order %} {%- set name = pf.field.name %} {%- set kind = pf.field.kind %} -{%- if kind|is_object_kind or kind|is_any_handle_kind or kind|is_interface_kind %} +{%- if kind|is_object_kind %} {%- if pf.min_version > last_checked_version %} {%- set last_checked_version = pf.min_version %} if (header_.version < {{pf.min_version}}) return; {%- endif %} {%- if kind|is_union_kind %} - this->{{name}}.DecodePointersAndHandles(handles); + this->{{name}}.DecodePointers(); {%- elif kind|is_object_kind %} - mojo::internal::Decode(&this->{{name}}, handles); -{%- else %} - mojo::internal::DecodeHandle(&this->{{name}}, handles); + mojo::internal::Decode(&this->{{name}}); {%- endif %} {%- endif %} {%- endfor %} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl index 2d32b593169..12898471bdb 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl @@ -6,28 +6,36 @@ placeholder, for example, "input->%s", "p_%s". The placeholder will be substituted with struct field names to refer to the input fields. |context| is the name of the serialization context. + |input_may_be_temp| indicates whether any input may be temporary obejcts. + We need to assign temporary objects to local variables before passing it to + Serializer, because it is illegal to pass temporary objects as non-const + references. This macro is expanded to compute seriailized size for both: - user-defined structs: the input is an instance of the corresponding struct wrapper class. - method parameters/response parameters: the input is a list of arguments. It declares |size| of type size_t to store the resulting size. #} -{%- macro get_serialized_size(struct, input_field_pattern, context) -%} - size_t size = sizeof(internal::{{struct.name}}_Data); +{%- macro get_serialized_size(struct, input_field_pattern, context, + input_may_be_temp=False) -%} + size_t size = sizeof({{struct|get_qualified_name_for_kind(internal=True)}}); {%- for pf in struct.packed.packed_fields_in_ordinal_order if pf.field.kind|is_object_kind %} {%- set name = pf.field.name -%} {%- set kind = pf.field.kind -%} -{%- if kind|is_native_only_kind and kind|is_typemapped_kind %} - size += mojo::internal::GetSerializedSizeNative_( - {{input_field_pattern|format(name)}}, {{context}}); -{%- elif kind|is_typemapped_kind %} - size += - {{kind|get_name_for_kind}}_SerializerTraits_<{{kind|cpp_wrapper_type}}> - ::GetSize({{input_field_pattern|format(name)}}); -{%- elif kind|is_union_kind %} - size += GetSerializedSize_({{input_field_pattern|format(name)}}, true, {{context}}); +{%- set original_input_field = input_field_pattern|format(name) %} +{%- set input_field = "in_%s"|format(name) if input_may_be_temp + else original_input_field %} +{%- if input_may_be_temp %} + decltype({{original_input_field}}) in_{{name}} = {{original_input_field}}; +{%- endif %} + +{%- set serializer_type = kind|unmapped_type_for_serializer %} +{%- if kind|is_union_kind %} + size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( + {{input_field}}, true, {{context}}); {%- else %} - size += GetSerializedSize_({{input_field_pattern|format(name)}}, {{context}}); + size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( + {{input_field}}, {{context}}); {%- endif %} {%- endfor %} {%- endmacro -%} @@ -42,44 +50,42 @@ |output| is the name of the output struct instance. |buffer| is the name of the Buffer instance used. |context| is the name of the serialization context. + |input_may_be_temp|: please see the comments of get_serialized_size. This macro is expanded to do serialization for both: - user-defined structs: the input is an instance of the corresponding struct wrapper class. - method parameters/response parameters: the input is a list of arguments. #} {%- macro serialize(struct, struct_display_name, input_field_pattern, output, - buffer, context) -%} - internal::{{struct.name}}_Data* {{output}} = - internal::{{struct.name}}_Data::New({{buffer}}); + buffer, context, input_may_be_temp=False) -%} + auto {{output}} = + {{struct|get_qualified_name_for_kind(internal=True)}}::New({{buffer}}); {%- for pf in struct.packed.packed_fields_in_ordinal_order %} {%- set input_field = input_field_pattern|format(pf.field.name) %} {%- set name = pf.field.name %} {%- set kind = pf.field.kind %} {%- if kind|is_object_kind %} -{%- if kind|is_array_kind or - (kind|is_native_only_kind and not kind|is_typemapped_kind) %} +{%- set serializer_type = kind|unmapped_type_for_serializer %} +{%- set original_input_field = input_field_pattern|format(name) %} +{%- set input_field = "in_%s"|format(name) if input_may_be_temp + else original_input_field %} +{%- if input_may_be_temp %} + decltype({{original_input_field}}) in_{{name}} = {{original_input_field}}; +{%- endif %} + +{%- if kind|is_array_kind or kind|is_map_kind %} const mojo::internal::ArrayValidateParams {{name}}_validate_params( {{kind|get_array_validate_params_ctor_args|indent(10)}}); - mojo::SerializeArray_(std::move({{input_field}}), {{buffer}}, - &{{output}}->{{name}}.ptr, &{{name}}_validate_params, {{context}}); -{%- elif kind|is_map_kind %} - const mojo::internal::ArrayValidateParams {{name}}_validate_params( - {{kind.value_kind|get_map_validate_params_ctor_args|indent(10)}}); - mojo::SerializeMap_(std::move({{input_field}}), {{buffer}}, - &{{output}}->{{name}}.ptr, &{{name}}_validate_params, {{context}}); -{%- elif kind|is_native_only_kind and kind|is_typemapped_kind %} - mojo::internal::SerializeNative_( - {{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, {{context}}); -{%- elif kind|is_typemapped_kind %} - {{kind|get_name_for_kind}}_SerializerTraits_<{{kind|cpp_wrapper_type}}> - ::Serialize({{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr); + mojo::internal::Serialize<{{serializer_type}}>( + {{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, + &{{name}}_validate_params, {{context}}); {%- elif kind|is_union_kind %} - internal::{{kind.name}}_Data* {{name}}_ptr = &{{output}}->{{name}}; - SerializeUnion_(std::move({{input_field}}), {{buffer}}, &{{name}}_ptr, true, - {{context}}); + auto {{name}}_ptr = &{{output}}->{{name}}; + mojo::internal::Serialize<{{serializer_type}}>( + {{input_field}}, {{buffer}}, &{{name}}_ptr, true, {{context}}); {%- else %} - Serialize_(std::move({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr, - {{context}}); + mojo::internal::Serialize<{{serializer_type}}>( + {{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, {{context}}); {%- endif %} {%- if not kind|is_nullable_kind %} MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( @@ -93,11 +99,14 @@ {%- endif %} {%- elif kind|is_any_handle_kind or kind|is_interface_kind %} {%- if kind|is_interface_kind %} - mojo::internal::InterfacePointerToData(std::move({{input_field}}), &{{output}}->{{name}}); + mojo::internal::InterfacePointerToData( + std::move({{input_field}}), &{{output}}->{{name}}, {{context}}); {%- elif kind|is_interface_request_kind %} - {{output}}->{{name}} = {{input_field}}.PassMessagePipe().release(); + {{output}}->{{name}} = ({{context}})->handles.AddHandle( + {{input_field}}.PassMessagePipe().release()); {%- else %} - {{output}}->{{name}} = {{input_field}}.release(); + {{output}}->{{name}} = + ({{context}})->handles.AddHandle({{input_field}}.release()); {%- endif %} {%- if not kind|is_nullable_kind %} MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( @@ -114,10 +123,10 @@ {%- if kind|is_associated_interface_kind %} mojo::internal::AssociatedInterfacePtrInfoToData(std::move({{input_field}}), &{{output}}->{{name}}); {%- else %} - {{output}}->{{name}} = mojo::internal::AssociatedInterfaceRequestHelper::PassHandle(&{{input_field}}).release(); + {{output}}->{{name}} = {{input_field}}.PassHandle().release(); {%- endif %} {%- elif kind|is_enum_kind %} - {{output}}->{{name}}.value = static_cast<int32_t>({{input_field}}); + {{output}}->{{name}} = static_cast<int32_t>({{input_field}}); {%- else %} {{output}}->{{name}} = {{input_field}}; {%- endif %} @@ -126,7 +135,8 @@ {# Deserializes the specified struct. |struct| is the struct definition. - |input| is the name of the input struct instance. + |input| is the name of the input struct data view. It is expected to be + non-null. |output_field_pattern| should be a pattern that contains one string placeholder, for example, "result->%s", "p_%s". The placeholder will be substituted with struct field names to refer to the output fields. @@ -137,60 +147,19 @@ struct wrapper class. - method parameters/response parameters: the output is a list of arguments. #} -{%- macro deserialize(struct, input, output_field_pattern, context, success) -%} - do { - // NOTE: The memory backing |{{input}}| may has be smaller than - // |sizeof(*{{input}})| if the message comes from an older version. -{#- Before deserialize fields introduced at a certain version, we need to add - a version check, which makes sure we skip further deserialization if - |input| is from an earlier version. |last_checked_version| records the - last version that we have added such version check. #} -{%- set last_checked_version = 0 %} +{%- macro deserialize(struct, input, output_field_pattern, success) -%} {%- for pf in struct.packed.packed_fields_in_ordinal_order %} {%- set output_field = output_field_pattern|format(pf.field.name) %} {%- set name = pf.field.name %} {%- set kind = pf.field.kind %} -{%- if pf.min_version > last_checked_version %} -{%- set last_checked_version = pf.min_version %} - if ({{input}}->header_.version < {{pf.min_version}}) - break; -{%- endif %} -{%- if kind|is_native_only_kind and kind|is_typemapped_kind %} - if (!DeserializeNative_( - {{input}}->{{name}}.ptr, &{{output_field}}, {{context}})) { - {{success}} = false; - } -{%- elif kind|is_typemapped_kind %} - if (!{{kind|get_name_for_kind}}_SerializerTraits_<{{kind|cpp_wrapper_type}}> - ::Deserialize( - {{input}}->{{name}}.ptr, &{{output_field}}, {{context}})) { - {{success}} = false; - } -{%- elif kind|is_object_kind %} -{%- if kind|is_union_kind %} - if (!Deserialize_(&{{input}}->{{name}}, &{{output_field}}, {{context}})) - {{success}} = false; -{%- else %} - if (!Deserialize_({{input}}->{{name}}.ptr, &{{output_field}}, {{context}})) - {{success}} = false; -{%- endif %} -{%- elif kind|is_interface_kind %} - mojo::internal::InterfaceDataToPointer(&{{input}}->{{name}}, &{{output_field}}); -{%- elif kind|is_interface_request_kind %} - {{output_field}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&{{input}}->{{name}}))); -{%- elif kind|is_any_handle_kind %} - {{output_field}}.reset(mojo::internal::FetchAndReset(&{{input}}->{{name}})); -{%- elif kind|is_associated_interface_kind %} - mojo::internal::AssociatedInterfaceDataToPtrInfo(&{{input}}->{{name}}, &{{output_field}}, ({{context}})->router.get()); -{%- elif kind|is_associated_interface_request_kind %} - mojo::internal::AssociatedInterfaceRequestHelper::SetHandle( - &{{output_field}}, - ({{context}})->router->CreateLocalEndpointHandle(mojo::internal::FetchAndReset(&{{input}}->{{name}}))); -{%- elif kind|is_enum_kind %} - {{output_field}} = static_cast<{{kind|cpp_wrapper_type}}>({{input}}->{{name}}.value); +{%- if kind|is_object_kind %} + if (!{{input}}.Read{{name|under_to_camel}}(&{{output_field}})) + {{success}} = false; +{%- elif kind|is_interface_kind or kind|is_any_handle_kind or + kind|is_associated_kind %} + {{output_field}} = {{input}}.Take{{name|under_to_camel}}(); {%- else %} - {{output_field}} = {{input}}->{{name}}; + {{output_field}} = {{input}}.{{name}}(); {%- endif %} {%- endfor %} - } while (false); {%- endmacro %} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl index 00390a8578b..8f72cf64d82 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl @@ -1,158 +1,76 @@ -size_t GetSerializedSize_(const {{struct.name}}Ptr& input, - mojo::internal::SerializationContext* context); -void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer, - internal::{{struct.name}}_Data** output, - mojo::internal::SerializationContext* context); -bool Deserialize_(internal::{{struct.name}}_Data* input, - {{struct.name}}Ptr* output, - mojo::internal::SerializationContext* context); - -{%- if struct|is_native_only_kind and struct|is_typemapped_kind %} -{# This helps the array serializer understand how to serialize arrays of this - native-only type. #} - -{%- for namespace in namespaces_as_array|reverse %} -} // namespace {{namespace}} -{%- endfor %} -{%- if variant %} -} // namespace {{variant}} -{%- endif %} - -namespace mojo { -namespace internal { +{%- import "struct_macros.tmpl" as struct_macros %} +{%- set mojom_type = struct|get_qualified_name_for_kind %} +{%- set data_type = struct|get_qualified_name_for_kind(internal=True) %} template <> -struct ShouldUseNativeSerializer<{{struct|cpp_wrapper_type}}> { - static const bool value = true; -}; - -template <> -struct WrapperTraits<{{struct|cpp_wrapper_type}}> { - using DataType = Array_Data<uint8_t>*; -}; - -} // namespace internal -} // namespace mojo - -{%- for namespace in namespaces_as_array %} -namespace {{namespace}} { -{%- endfor %} -{%- if variant %} -namespace {{variant}} { -{%- endif %} - -{%- endif %} - -{%- if not struct|is_native_only_kind %} - -{# NOTE: Generated Reader instances are intentionally cheap to copy and devoid - of heap allocations. They should stay this way. #} -class {{struct.name}}_Reader { - public: - {{struct.name}}_Reader(internal::{{struct.name}}_Data* data, - mojo::internal::SerializationContext* context); - -{%- for pf in struct.packed.packed_fields_in_ordinal_order %} -{%- set kind = pf.field.kind -%} -{%- set name = pf.field.name -%} -{%- if kind|is_nullable_kind %} - bool has_{{name}}() const; -{%- endif %} -{%- if kind|is_struct_kind and not kind|is_native_only_kind %} - {{kind|get_name_for_kind}}::Reader {{name}}() const; -{%- elif kind|is_string_kind %} - base::StringPiece {{name}}() const; -{%- elif kind|is_union_kind %} - // TODO(rockot): Support reading unions. ({{name}}() omitted) -{%- elif kind|is_object_kind %} - // TODO(rockot): Support reading other object kinds. ({{name}}() omitted) -{%- elif kind|is_any_handle_kind %} - // TODO(rockot): Support reading handles. ({{name}}() omitted) -{%- elif kind|is_interface_kind %} - // TODO(rockot): Support reading interfaces. ({{name}}() omitted) -{%- elif kind|is_interface_request_kind %} - // TODO(rockot): Support reading interface requests. ({{name}}() omitted) -{%- elif kind|is_associated_kind %} - // TODO(rockot): Support reading associated kinds. ({{name}}() omitted) -{%- elif kind|is_enum_kind %} - {{kind|cpp_result_type}} {{name}}() const { - return static_cast<{{kind|cpp_result_type}}>(data_->{{name}}.value); +struct StructTraits<{{mojom_type}}, {{mojom_type}}Ptr> { + static bool IsNull(const {{mojom_type}}Ptr& input) { return !input; } + static void SetToNull({{mojom_type}}Ptr* output) { output->reset(); } + +{%- for field in struct.fields %} +{%- set return_ref = field.kind|is_object_kind or + field.kind|is_any_handle_kind or + field.kind|is_interface_kind or + field.kind|is_associated_kind %} +{%- if return_ref %} + static decltype({{mojom_type}}::{{field.name}})& {{field.name}}( + {{mojom_type}}Ptr& input) { + return input->{{field.name}}; } -{%- else %} - {{kind|cpp_result_type}} {{name}}() const { return data_->{{name}}; } -{%- endif %} -{%- endfor %} + static const decltype({{mojom_type}}::{{field.name}})& {{field.name}}( + const {{mojom_type}}Ptr& input) { + return input->{{field.name}}; + } +{%- else %} + static decltype({{mojom_type}}::{{field.name}}) {{field.name}}( + const {{mojom_type}}Ptr& input) { + return input->{{field.name}}; + } +{%- endif %} +{%- endfor %} - private: - internal::{{struct.name}}_Data* data_; - mojo::internal::SerializationContext* context_; + static bool Read({{mojom_type}}DataView input, {{mojom_type}}Ptr* output); }; -template <typename NativeType> -struct {{struct.name}}_SerializerTraits_ { - static size_t GetSize(const NativeType& input) { - size_t size = sizeof(internal::{{struct.name}}_Data); -{%- for pf in struct.packed.packed_fields_in_ordinal_order %} - do { -{%- if pf.field.kind|is_nullable_kind %} - if (!mojo::StructTraits<{{struct.name}}, NativeType> - ::has_{{pf.field.name}}(input)) - break; -{%- endif %} -{%- if pf.field.kind|is_string_kind %} - size += mojo::internal::Align( - mojo::internal::String_Data::Traits::GetStorageSize( - static_cast<uint32_t>( - mojo::StructTraits<{{struct.name}}, NativeType> - ::{{pf.field.name}}(input).size()))); -{%- elif pf.field.kind|is_object_kind %} - NOTREACHED() << "Unsupported field type for StructTraits: " - << "{{pf.field.name}}"; -{%- endif %} - } while (false); -{%- endfor %} +namespace internal { + +template <typename MaybeConstUserType> +struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + using Traits = StructTraits<{{mojom_type}}, UserType>; + + static size_t PrepareToSerialize(MaybeConstUserType& input, + SerializationContext* context) { + if (CallIsNullIfExists<Traits>(input)) + return 0; + {{struct_macros.get_serialized_size(struct, "Traits::%s(input)", "context", + True)|indent(2)}} return size; } - static void Serialize(const NativeType& input, - mojo::internal::Buffer* buffer, - internal::{{struct.name}}_Data** output) { - internal::{{struct.name}}_Data* result = - internal::{{struct.name}}_Data::New(buffer); -{%- for pf in struct.packed.packed_fields_in_ordinal_order -%} -{%- set name = pf.field.name -%} -{%- set kind = pf.field.kind %} - do { -{%- if kind|is_nullable_kind %} - if (!mojo::StructTraits<{{struct.name}}, NativeType> - ::has_{{name}}(input)) - break; -{%- endif %} -{%- if kind|is_string_kind %} - base::StringPiece input_{{name}} = - mojo::StructTraits<{{struct.name}}, NativeType>::{{name}}(input); - result->{{name}}.ptr = - mojo::internal::String_Data::New(input_{{name}}.size(), buffer); - memcpy(result->{{name}}.ptr->storage(), input_{{name}}.data(), - input_{{name}}.size()); -{%- elif kind|is_object_kind %} - NOTREACHED() << "Unsupported field type for StructTraits: " - << "{{pf.field.name}}"; -{%- else %} - result->{{name}} = mojo::StructTraits<{{struct.name}}, NativeType> - ::{{name}}(input); -{%- endif %} - } while (false); -{%- endfor %} - *output = result; + static void Serialize(MaybeConstUserType& input, + Buffer* buffer, + {{data_type}}** output, + SerializationContext* context) { + if (!CallIsNullIfExists<Traits>(input)) { + {{struct_macros.serialize(struct, struct.name ~ " struct", + "Traits::%s(input)", "result", "buffer", + "context", True)|indent(4)}} + *output = result; + } else { + *output = nullptr; + } } - static bool Deserialize(internal::{{struct.name}}_Data* input, - NativeType* output, - mojo::internal::SerializationContext* context) { - return mojo::StructTraits<{{struct.name}}, NativeType>::Read( - {{struct.name}}_Reader(input, context), output); + static bool Deserialize({{data_type}}* input, + UserType* output, + SerializationContext* context) { + if (!input) + return CallSetToNullIfExists<Traits>(output); + + {{mojom_type}}DataView data_view(input, context); + return Traits::Read(data_view, output); } }; -{%- endif %} {# not variant #} +} // namespace internal diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl index 97c6521a748..7421abcd787 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl @@ -1,79 +1,14 @@ {%- import "struct_macros.tmpl" as struct_macros %} -size_t GetSerializedSize_(const {{struct.name}}Ptr& input, - mojo::internal::SerializationContext* context) { - if (!input) - return 0; - {{struct_macros.get_serialized_size(struct, "input->%s", "context")}} - return size; -} - -void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buf, - internal::{{struct.name}}_Data** output, - mojo::internal::SerializationContext* context) { - if (input) { - {{struct_macros.serialize(struct, struct.name ~ " struct", "input->%s", "result", "buf", "context")|indent(2)}} - *output = result; - } else { - *output = nullptr; - } -} +{%- set mojom_type = struct|get_qualified_name_for_kind %} -bool Deserialize_(internal::{{struct.name}}_Data* input, - {{struct.name}}Ptr* output, - mojo::internal::SerializationContext* context) { +// static +bool StructTraits<{{mojom_type}}, {{mojom_type}}Ptr>::Read( + {{mojom_type}}DataView input, + {{mojom_type}}Ptr* output) { bool success = true; - if (input) { - {{struct.name}}Ptr result({{struct.name}}::New()); - {{struct_macros.deserialize(struct, "input", "result->%s", "context", "success")|indent(2)}} - *output = std::move(result); - } else { - output->reset(); - } + {{mojom_type}}Ptr result({{mojom_type}}::New()); + {{struct_macros.deserialize(struct, "input", "result->%s", + "success")|indent(4)}} + *output = std::move(result); return success; } - -{%- if not struct|is_native_only_kind %} - -{{struct.name}}_Reader::{{struct.name}}_Reader( - internal::{{struct.name}}_Data* data, - mojo::internal::SerializationContext* context) - : data_(data), context_(context) { } - -{%- for pf in struct.packed.packed_fields_in_ordinal_order %} -{%- set name = pf.field.name -%} -{%- set kind = pf.field.kind %} -{%- if kind|is_nullable_kind %} -bool {{struct.name}}_Reader::has_{{name}}() const { -{%- if kind|is_union_kind %} - return !data_->{{name}}.is_null(); -{%- elif kind|is_object_kind %} - return data_->{{name}}.ptr != nullptr; -{%- elif kind|is_interface_kind %} - return data_->{{name}}.handle.is_valid(); -{%- elif kind|is_interface_request_kind %} - return data_->{{name}}.is_valid(); -{%- elif kind|is_associated_interface_kind %} - return data_->{{name}}.interface_id == mojo::internal::kInvalidInterfaceId; -{%- elif kind|is_associated_interface_request_kind %} - return data_->{{name}} == mojo::internal::kInvalidInterfaceId; -{%- elif kind|is_any_handle_kind %} - return data_->{{name}}.is_valid(); -{%- else %} - return !!data_->{{name}}; -{%- endif %} -} -{%- endif %} -{%- if kind|is_struct_kind and not kind|is_native_only_kind %} -{{kind|get_name_for_kind}}_Reader {{struct.name}}_Reader::{{name}}() const { - return {{kind|get_name_for_kind}}_Reader(data_->{{name}}.ptr, context_); -} -{%- elif kind|is_string_kind %} -base::StringPiece {{struct.name}}_Reader::{{name}}() const { - DCHECK(data_->{{name}}.ptr); - return base::StringPiece(data_->{{name}}.ptr->storage(), - data_->{{name}}.ptr->size()); -} -{%- endif %} -{%- endfor %} - -{%- endif %} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl index 8c0e89c0c27..059dbab1bd0 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl @@ -45,10 +45,8 @@ class {{class_name}} { {{enum_name}} tag; Union_ data; - void EncodePointersAndHandles(std::vector<mojo::Handle>* handles); - void DecodePointersAndHandles(std::vector<mojo::Handle>* handles); + void EncodePointers(); + void DecodePointers(); }; -static_assert(sizeof({{class_name}}) == 16, +static_assert(sizeof({{class_name}}) == mojo::internal::kUnionDataSize, "Bad sizeof({{class_name}})"); -static_assert(sizeof({{class_name}}::Union_) == 8, - "Bad sizeof({{class_name}}::Union_)"); diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl index 90d6152bd53..3621fe4d68f 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl @@ -11,30 +11,21 @@ bool {{class_name}}::Validate(const void* data, mojo::internal::BoundsChecker* bounds_checker, bool inlined) { - if (!data) { + if (!data) return true; - } - if (!mojo::internal::IsAligned(data)) { - ReportValidationError(mojo::internal::VALIDATION_ERROR_MISALIGNED_OBJECT); + if (!ValidateUnionHeaderAndClaimMemory(data, inlined, bounds_checker)) return false; - } - // 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; - } const {{class_name}}* object = static_cast<const {{class_name}}*>(data); ALLOW_UNUSED_LOCAL(object); switch (object->tag) { {% for field in union.fields %} case {{enum_name}}::{{field.name|upper}}: { - {{ validation_macros.validate_union_field(field, union)|indent(6) }} +{%- set field_expr = "object->data.f_" ~ field.name %} +{{validation_macros.validate_field(field, field_expr, union.name, false)|indent(4)}} + return true; } {%- endfor %} default: { @@ -55,19 +46,12 @@ void {{class_name}}::set_null() { {{class_name}}::{{class_name}}() { } -void {{class_name}}::EncodePointersAndHandles( - std::vector<mojo::Handle>* handles) { +void {{class_name}}::EncodePointers() { switch (tag) { {%- for field in union.fields %} case {{enum_name}}::{{field.name|upper}}: { {%- if field.kind|is_object_kind %} - mojo::internal::Encode(&data.f_{{field.name}}, handles); -{%- elif field.kind|is_any_handle_kind %} - mojo::internal::EncodeHandle(&data.f_{{field.name}}, handles); -{%- elif field.kind|is_interface_kind %} - mojo::internal::EncodeHandle( - reinterpret_cast<mojo::internal::Interface_Data*>( - &data.f_{{field.name}}), handles); + mojo::internal::Encode(&data.f_{{field.name}}); {%- endif %} return; } @@ -75,19 +59,12 @@ void {{class_name}}::EncodePointersAndHandles( } } -void {{class_name}}::DecodePointersAndHandles( - std::vector<mojo::Handle>* handles) { +void {{class_name}}::DecodePointers() { switch (tag) { {%- for field in union.fields %} case {{enum_name}}::{{field.name|upper}}: { {%- if field.kind|is_object_kind %} - mojo::internal::Decode(&data.f_{{field.name}}, handles); -{%- elif field.kind|is_any_handle_kind %} - mojo::internal::DecodeHandle(&data.f_{{field.name}}, handles); -{%- elif field.kind|is_interface_kind %} - mojo::internal::DecodeHandle( - reinterpret_cast<mojo::internal::Interface_Data*>( - &data.f_{{field.name}}), handles); + mojo::internal::Decode(&data.f_{{field.name}}); {%- endif %} return; } diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl index f2d6a2a7b67..bab90452272 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl @@ -1,11 +1,37 @@ -size_t GetSerializedSize_(const {{union.name}}Ptr& input, - bool inlined, - mojo::internal::SerializationContext* context); -void SerializeUnion_({{union.name}}Ptr input, - mojo::internal::Buffer* buffer, - internal::{{union.name}}_Data** output, - bool inlined, - mojo::internal::SerializationContext* context); -bool Deserialize_(internal::{{union.name}}_Data* input, - {{union.name}}Ptr* output, - mojo::internal::SerializationContext* context); +{%- set mojom_type = union|get_qualified_name_for_kind %} +{%- set data_type = union|get_qualified_name_for_kind(internal=True) %} + +namespace internal { + +template <typename MojomType> +struct UnionSerializerImpl; + +template <> +struct UnionSerializerImpl<{{mojom_type}}Ptr> { + static size_t PrepareToSerialize({{mojom_type}}Ptr& input, + bool inlined, + SerializationContext* context); + + static void Serialize({{mojom_type}}Ptr& input, + Buffer* buffer, + {{data_type}}** output, + bool inlined, + SerializationContext* context); + + static bool Deserialize({{data_type}}* input, + {{mojom_type}}Ptr* output, + SerializationContext* context); +}; + +template <typename MaybeConstUserType> +struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> + : public UnionSerializerImpl<{{mojom_type}}Ptr> { + using UserType = typename std::remove_const<MaybeConstUserType>::type; + + static_assert(std::is_same<MaybeConstUserType, UserType>::value, + "Only support serialization of non-const Unions."); + static_assert(std::is_same<UserType, {{mojom_type}}Ptr>::value, + "Custom mapping of mojom union is not supported."); +}; + +} // namespace internal diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl index a7bcc922c72..f3e0c777838 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl @@ -1,23 +1,30 @@ -size_t GetSerializedSize_(const {{union.name}}Ptr& input, - bool inlined, - mojo::internal::SerializationContext* context) { - size_t size = 0U; - if (!inlined) { - size += sizeof(internal::{{union.name}}_Data); - } +{%- set mojom_type = union|get_qualified_name_for_kind %} +{%- set data_type = union|get_qualified_name_for_kind(internal=True) %} + +namespace internal { + +// static +size_t UnionSerializerImpl<{{mojom_type}}Ptr>::PrepareToSerialize( + {{mojom_type}}Ptr& input, + bool inlined, + SerializationContext* context) { + size_t size = inlined ? 0 : sizeof({{data_type}}); if (!input) return size; - mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get()); + UnionAccessor<{{mojom_type}}> input_acc(input.get()); switch (input->which()) { {% for field in union.fields %} {% if field.kind|is_object_kind %} - case {{union.name}}::Tag::{{field.name|upper}}: +{%- set serializer_type = field.kind|unmapped_type_for_serializer %} + case {{mojom_type}}::Tag::{{field.name|upper}}: {% if field.kind|is_union_kind %} - size += GetSerializedSize_(*(input_acc.data()->{{field.name}}), false, context); + size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( + *(input_acc.data()->{{field.name}}), false, context); {% else %} - size += GetSerializedSize_(*(input_acc.data()->{{field.name}}), context); + size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( + *(input_acc.data()->{{field.name}}), context); {% endif %} break; {%- endif %} @@ -28,65 +35,56 @@ size_t GetSerializedSize_(const {{union.name}}Ptr& input, return size; } -void SerializeUnion_({{union.name}}Ptr input, - mojo::internal::Buffer* buf, - internal::{{union.name}}_Data** output, - bool inlined, - mojo::internal::SerializationContext* context) { - internal::{{union.name}}_Data* result = *output; +// static +void UnionSerializerImpl<{{mojom_type}}Ptr>::Serialize( + {{mojom_type}}Ptr& input, + Buffer* buf, + {{data_type}}** output, + bool inlined, + SerializationContext* context) { + {{data_type}}* result = *output; if (input) { - if (!inlined) { - result = internal::{{union.name}}_Data::New(buf); - } - mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get()); + if (!inlined) + result = {{data_type}}::New(buf); + UnionAccessor<{{mojom_type}}> input_acc(input.get()); // 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 %} - case {{union.name}}::Tag::{{field.name|upper}}: { + case {{mojom_type}}::Tag::{{field.name|upper}}: { {% if field.kind|is_object_kind %} -{% if field.kind|is_string_kind %} - Serialize_( - *(input_acc.data()->{{field.name}}), - buf, &result->data.f_{{field.name}}.ptr, context); -{% elif field.kind|is_struct_kind %} - Serialize_( - std::move(*(input_acc.data()->{{field.name}})), - buf, &result->data.f_{{field.name}}.ptr, context); -{% elif field.kind|is_union_kind %} - SerializeUnion_( - std::move(*(input_acc.data()->{{field.name}})), - buf, &result->data.f_{{field.name}}.ptr, false, context); -{% elif field.kind|is_array_kind %} - const mojo::internal::ArrayValidateParams {{field.name}}_validate_params( +{%- set serializer_type = field.kind|unmapped_type_for_serializer %} +{% if field.kind|is_union_kind %} + mojo::internal::Serialize<{{serializer_type}}>( + *(input_acc.data()->{{field.name}}), buf, + &result->data.f_{{field.name}}.ptr, false, context); +{% elif field.kind|is_array_kind or field.kind|is_map_kind %} + const ArrayValidateParams {{field.name}}_validate_params( {{field.kind|get_array_validate_params_ctor_args|indent(16)}}); - SerializeArray_( - std::move(*(input_acc.data()->{{field.name}})), - buf, &result->data.f_{{field.name}}.ptr, - &{{field.name}}_validate_params, context); -{% elif field.kind|is_map_kind %} - const mojo::internal::ArrayValidateParams {{field.name}}_validate_params( - {{field.kind.value_kind|get_map_validate_params_ctor_args|indent(16)}}); - SerializeMap_( - std::move(*(input_acc.data()->{{field.name}})), - buf, &result->data.f_{{field.name}}.ptr, - &{{field.name}}_validate_params, context); + mojo::internal::Serialize<{{serializer_type}}>( + *(input_acc.data()->{{field.name}}), buf, + &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params, + context); +{% else %} + mojo::internal::Serialize<{{serializer_type}}>( + *(input_acc.data()->{{field.name}}), buf, + &result->data.f_{{field.name}}.ptr, context); {%- endif %} {% elif field.kind|is_any_handle_kind %} - result->data.f_{{field.name}} = - input_acc.data()->{{field.name}}->release().value(); + result->data.f_{{field.name}} = context->handles.AddHandle( + input_acc.data()->{{field.name}}->release()); {% elif field.kind|is_interface_kind %} - mojo::internal::Interface_Data* {{field.name}} = - reinterpret_cast<mojo::internal::Interface_Data*>( - &result->data.f_{{field.name}}); - mojo::internal::InterfacePointerToData( - std::move(*input_acc.data()->{{field.name}}), {{field.name}}); + Interface_Data* {{field.name}} = reinterpret_cast<Interface_Data*>( + &result->data.f_{{field.name}}); + InterfacePointerToData(std::move(*input_acc.data()->{{field.name}}), + {{field.name}}, context); {%- elif field.kind|is_associated_kind %} // TODO(yzshen): add seralization logic for associated kinds. {% elif field.kind|is_enum_kind %} - result->data.f_{{field.name}}.value = static_cast<int32_t>(input_acc.data()->{{field.name}}); + result->data.f_{{field.name}} = + static_cast<int32_t>(input_acc.data()->{{field.name}}); {% else %} result->data.f_{{field.name}} = input_acc.data()->{{field.name}}; {%- endif %} @@ -102,36 +100,43 @@ void SerializeUnion_({{union.name}}Ptr input, *output = result; } -bool Deserialize_(internal::{{union.name}}_Data* input, - {{union.name}}Ptr* output, - mojo::internal::SerializationContext* context) { +// static +bool UnionSerializerImpl<{{mojom_type}}Ptr>::Deserialize( + {{data_type}}* input, + {{mojom_type}}Ptr* output, + SerializationContext* context) { bool success = true; if (input && !input->is_null()) { - {{union.name}}Ptr result({{union.name}}::New()); - mojo::internal::UnionAccessor<{{union.name}}> result_acc(result.get()); + {{mojom_type}}Ptr result({{mojom_type}}::New()); + UnionAccessor<{{mojom_type}}> result_acc(result.get()); switch (input->tag) { {% for field in union.fields %} - case {{union.name}}::Tag::{{field.name|upper}}: { + case {{mojom_type}}::Tag::{{field.name|upper}}: { {% if field.kind|is_object_kind %} - result_acc.SwitchActive({{union.name}}::Tag::{{field.name|upper}}); - if (!Deserialize_(input->data.f_{{field.name}}.ptr, result_acc.data()->{{field.name}}, context)) +{%- set serializer_type = field.kind|unmapped_type_for_serializer %} + result_acc.SwitchActive({{mojom_type}}::Tag::{{field.name|upper}}); + if (!mojo::internal::Deserialize<{{serializer_type}}>( + input->data.f_{{field.name}}.ptr, + result_acc.data()->{{field.name}}, context)) success = false; {% elif field.kind|is_any_handle_kind %} - {{field.kind|cpp_wrapper_type}}* {{field.name}} = - reinterpret_cast<{{field.kind|cpp_wrapper_type}}*>(&input->data.f_{{field.name}}); - result->set_{{field.name}}(std::move(*{{field.name}})); + {{field.kind|cpp_wrapper_type}} {{field.name}}; + {{field.name}} = context->handles.TakeHandleAs< + typename {{field.kind|cpp_wrapper_type}}::RawHandleType>( + input->data.f_{{field.name}}); + result->set_{{field.name}}(std::move({{field.name}})); {% elif field.kind|is_interface_kind %} - {{field.kind|cpp_wrapper_type}} {{field.name}}_out; - mojo::internal::Interface_Data* {{field.name}}_in = - reinterpret_cast<mojo::internal::Interface_Data*>( - &input->data.f_{{field.name}}); - mojo::internal::InterfaceDataToPointer( - {{field.name}}_in, &{{field.name}}_out); + {{field.kind|get_qualified_name_for_kind}}Ptr {{field.name}}_out; + Interface_Data* {{field.name}}_in = reinterpret_cast<Interface_Data*>( + &input->data.f_{{field.name}}); + InterfaceDataToPointer({{field.name}}_in, &{{field.name}}_out, context); result->set_{{field.name}}(std::move({{field.name}}_out)); {%- elif field.kind|is_associated_kind %} // TODO(yzshen): add deserialization logic for associated kinds. {% elif field.kind|is_enum_kind %} - result->set_{{field.name}}(static_cast<{{field.kind|cpp_wrapper_type}}>(input->data.f_{{field.name}}.value)); + result->set_{{field.name}}( + static_cast<{{field.kind|get_qualified_name_for_kind}}>( + input->data.f_{{field.name}})); {% else %} result->set_{{field.name}}(input->data.f_{{field.name}}); {%- endif %} @@ -145,3 +150,5 @@ bool Deserialize_(internal::{{union.name}}_Data* input, } return success; } + +} // namespace internal diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl index 99731fb5e0a..5dabf24d09a 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl @@ -1,74 +1,113 @@ -{%- macro validate_not_null_ptr(field_expr, field, object_name) %} -if (!{{field_expr}}->offset) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - "null {{field.name}} field in {{object_name}}"); - return false; -} -{%- endmacro %} - -{%- macro validate_encoded_ptr(field_expr) %} -if (!mojo::internal::ValidateEncodedPointer(&{{field_expr}}->offset)) { - ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER); - return false; -} -{%- endmacro %} - -{%- macro validate_array_or_string(field_expr, field) -%} -const mojo::internal::ArrayValidateParams {{field.name}}_validate_params( - {{field.kind|get_array_validate_params_ctor_args|indent(4)}}); -if (!{{field.kind|cpp_wrapper_type}}::Data_::Validate( - mojo::internal::DecodePointerRaw(&{{field_expr}}->offset), - bounds_checker, &{{field.name}}_validate_params)) { - return false; -} -{%- endmacro %} - -{%- macro validate_handle(field_expr, field, object_name) -%} - const mojo::Handle {{field.name}}_handle(object->data.f_{{field.name}}); - -{%- if not field.kind|is_nullable_kind %} - if ({{field.name}}_handle.value() == mojo::internal::kEncodedInvalidHandleValue) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - "invalid {{field.name}} field in {{object_name}}"); +{#- Validates the specified field, which is supposed to be an object + (struct/array/string/map/union). If it is a union, |union_is_inlined| + indicates whether the union is inlined. (Nested unions are not inlined.) + This macro is expanded by the Validate() method. #} +{%- macro validate_object(field, field_expr, object_name, union_is_inlined) %} +{%- set name = field.name %} +{%- set kind = field.kind %} +{%- if not kind|is_nullable_kind %} +{%- if kind|is_union_kind and union_is_inlined %} + if (!mojo::internal::ValidateInlinedUnionNonNullable( + {{field_expr}}, "null {{name}} field in {{object_name}}")) { + return false; + } +{%- else %} + if (!mojo::internal::ValidatePointerNonNullable( + {{field_expr}}, "null {{name}} field in {{object_name}}")) { return false; } +{%- endif %} {%- endif %} - if (!bounds_checker->ClaimHandle({{field.name}}_handle)) { - ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_HANDLE); +{%- if kind|is_array_kind or kind|is_string_kind %} + const mojo::internal::ArrayValidateParams {{name}}_validate_params( + {{kind|get_array_validate_params_ctor_args|indent(6)}}); + if (!mojo::internal::ValidateArray({{field_expr}}, bounds_checker, + &{{name}}_validate_params)) { return false; } -{%- endmacro -%} - -{%- macro validate_enum(field_expr, field) -%} -if (!mojo::internal::ValidateEnum(*{{field_expr}})) - return false; -{%- endmacro -%} - -{%- macro validate_union_field(field, union) %} -{%- set field_expr = "(reinterpret_cast<const " - ~ field.kind|cpp_union_field_type - ~ "*>(&object->data.f_" - ~ field.name - ~ "))" -%} -{%- if field.kind|is_object_kind -%} -{%- if not field.kind|is_nullable_kind -%} -{{ validate_not_null_ptr(field_expr, field, union.name) }} +{%- elif kind|is_map_kind %} + const mojo::internal::ArrayValidateParams {{name}}_validate_params( + {{kind.value_kind|get_map_validate_params_ctor_args|indent(6)}}); + if (!mojo::internal::ValidateMap({{field_expr}}, bounds_checker, + &{{name}}_validate_params)) { + return false; + } +{%- elif kind|is_struct_kind %} + if (!mojo::internal::ValidateStruct({{field_expr}}, bounds_checker)) + return false; +{%- elif kind|is_union_kind %} +{%- if union_is_inlined %} + if (!mojo::internal::ValidateInlinedUnion({{field_expr}}, bounds_checker)) + return false; +{%- else %} + if (!mojo::internal::ValidateNonInlinedUnion({{field_expr}}, bounds_checker)) + return false; {%- endif %} -{{ validate_encoded_ptr(field_expr) }} +{%- else %} +#error Not reached! {%- endif %} +{%- endmacro %} -{%- if field.kind|is_array_kind or field.kind|is_string_kind -%} -{{ validate_array_or_string(field_expr, field) }} +{#- Validates the specified field, which is supposed to be a handle or contain a + handle (in the case of interfaces). + This macro is expanded by the Validate() method. #} +{%- macro validate_handle(field, field_expr, object_name) %} +{%- set name = field.name %} +{%- set kind = field.kind %} +{%- if kind|is_interface_kind %} + const mojo::internal::Handle_Data {{name}}_handle = {{field_expr}}.handle; +{%- else %} + const mojo::internal::Handle_Data {{name}}_handle = {{field_expr}}; +{%- endif %} +{%- if not kind|is_nullable_kind %} + if (!mojo::internal::ValidateHandleNonNullable( + {{name}}_handle, + "invalid {{name}} field in {{object_name}}")) { + return false; + } {%- endif %} + if (!mojo::internal::ValidateHandle({{name}}_handle, bounds_checker)) + return false; +{%- endmacro %} -{%- if field.kind|is_any_handle_kind -%} -{{ validate_handle(field_expr, field, union.name) }} +{#- Validates the specified field, which is supposed to be an associated + interface or an associated interface request. + This macro is expanded by the Validate() method. #} +{%- macro validate_associated(field, field_expr, object_name) %} +{%- set name = field.name %} +{%- set kind = field.kind %} +{%- if kind|is_associated_interface_kind %} + const mojo::internal::InterfaceId {{name}}_interface_id = + {{field_expr}}.interface_id; +{%- else %} + const mojo::internal::InterfaceId {{name}}_interface_id = {{field_expr}}; +{%- endif %} +{%- if not kind|is_nullable_kind %} + if (!mojo::internal::ValidateInterfaceIdNonNullable( + {{name}}_interface_id, + "invalid {{name}} field in {{object_name}}")) { + return false; + } {%- endif %} + if (!mojo::internal::ValidateAssociatedInterfaceId({{name}}_interface_id)) + return false; +{%- endmacro %} -{%- if field.kind|is_enum_kind -%} -{{ validate_enum(field_expr, field) }} +{#- Validates the specified field, which is supposed to be an enum. + This macro is expanded by the Validate() method. #} +{%- macro validate_enum(field, field_expr) %} + if (!{{field.kind|get_qualified_name_for_kind(internal=True)}}::Validate({{field_expr}})) + return false; +{%- endmacro %} + +{%- macro validate_field(field, field_expr, object_name, union_is_inlined) %} +{%- if field.kind|is_object_kind -%} +{{validate_object(field, field_expr, object_name, union_is_inlined)}} +{%- elif field.kind|is_any_handle_kind or field.kind|is_interface_kind -%} +{{validate_handle(field, field_expr, object_name)}} +{%- elif field.kind|is_associated_kind %} +{{validate_associated(field, field_expr, object_name)}} +{%- elif field.kind|is_enum_kind %} +{{validate_enum(field, field_expr)}} {%- endif %} -return true; {%- endmacro %} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl index d0b9fd9cfe9..263bc9fff4c 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl @@ -1,11 +1,8 @@ {% from "enum_macros.tmpl" import enum_decl -%} -class {{struct.name}}_Reader; - class {{struct.name}} { public: using Data_ = internal::{{struct.name}}_Data; - using Reader = {{struct.name}}_Reader; {#--- Enums #} {%- for enum in struct.enums -%} @@ -39,7 +36,19 @@ class {{struct.name}} { {% if struct|is_cloneable_kind %} {{struct.name}}Ptr Clone() const; {%- endif %} - bool Equals(const {{struct.name}}& other) const; + // Equals() is a template so it is only instantiated if it is used. Thus, the + // bindings generator does not need to know whether typemapped native types + // support operator==. + template <typename T, + typename std::enable_if<std::is_same< + T, {{struct.name}}>::value>::type* = nullptr> + bool Equals(const T& other) const { + {%- for field in struct.fields %} + if (!mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(this->{{field.name}}, other.{{field.name}})) + return false; + {%- endfor %} + return true; + } {#--- Struct members #} {% for field in struct.fields %} @@ -48,3 +57,4 @@ class {{struct.name}} { {{type}} {{name}}; {%- endfor %} }; + diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl index 6f60a9a9b23..2bd7ceb337d 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl @@ -27,15 +27,3 @@ return rv; } {% endif %} - -bool {{struct.name}}::Equals(const {{struct.name}}& other) const { -{%- for field in struct.fields %} -{%- if not field.kind|supports_equality %} - NOTREACHED() << "Equality testing not supported for field {{field.name}}"; -{%- else %} - if (!mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(this->{{field.name}}, other.{{field.name}})) - return false; -{%- endif %} -{%- endfor %} - return true; -} diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl index 2c4593325cf..5cf9a6812df 100644 --- a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl @@ -122,6 +122,19 @@ if (decoder{{level+1}} == null) { {{variable}} = {{kind|java_type}}.decode(decoder{{level}}, {{offset}}); {% else %} {{variable}} = decoder{{level}}.{{kind|decode_method(offset, bit)}}; +{% if kind|is_array_kind and kind.kind|is_enum_kind %} +{% if kind|is_nullable_kind %} +if ({{variable}} != null) { +{% else %} +{ +{% endif %} + for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) { + {{kind.kind|java_class_for_enum}}.validate({{variable}}[i{{level}}]); + } +} +{% elif kind|is_enum_kind %} + {{kind|java_class_for_enum}}.validate({{variable}}); +{% endif %} {% endif %} {% endmacro %} diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl index a16c178e67e..814e3e28e61 100644 --- a/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl @@ -15,6 +15,25 @@ public {{ 'static ' if not top_level }}final class {{enum|name}} { public static final int {{field|name}} = {{enum_value(enum, field, loop.index0)}}; {% endfor %} + private static final boolean IS_EXTENSIBLE = {% if enum.extensible %}true{% else %}false{% endif %}; + + public static boolean isKnownValue(int value) { + switch (value) { +{%- for enum_field in enum.fields|groupby('numeric_value') %} + case {{enum_field[0]}}: +{%- endfor %} + return true; + } + return false; + } + + public static void validate(int value) { + if (IS_EXTENSIBLE || isKnownValue(value)) + return; + + throw new DeserializationException("Invalid enum value."); + } + private {{enum|name}}() {} } diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl index 6a23c66f281..1d67890452b 100644 --- a/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl @@ -11,3 +11,4 @@ package {{package}}; import org.chromium.base.annotations.SuppressFBWarnings; +import org.chromium.mojo.bindings.DeserializationException;
\ No newline at end of file diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index d5e3db1b3fc..daac7802b64 100644 --- a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py @@ -19,16 +19,6 @@ _kind_to_cpp_type = { mojom.INT32: "int32_t", mojom.UINT32: "uint32_t", mojom.FLOAT: "float", - mojom.HANDLE: "mojo::Handle", - mojom.DCPIPE: "mojo::DataPipeConsumerHandle", - mojom.DPPIPE: "mojo::DataPipeProducerHandle", - mojom.MSGPIPE: "mojo::MessagePipeHandle", - mojom.SHAREDBUFFER: "mojo::SharedBufferHandle", - mojom.NULLABLE_HANDLE: "mojo::Handle", - mojom.NULLABLE_DCPIPE: "mojo::DataPipeConsumerHandle", - mojom.NULLABLE_DPPIPE: "mojo::DataPipeProducerHandle", - mojom.NULLABLE_MSGPIPE: "mojo::MessagePipeHandle", - mojom.NULLABLE_SHAREDBUFFER: "mojo::SharedBufferHandle", mojom.INT64: "int64_t", mojom.UINT64: "uint64_t", mojom.DOUBLE: "double", @@ -82,8 +72,6 @@ class _NameFormatter(object): def _MapKindName(self, token, internal): if not internal: return token.name - if mojom.IsStructKind(token) and token.native_only: - return "mojo::Array_Data<uint8_t>" if (mojom.IsStructKind(token) or mojom.IsUnionKind(token) or mojom.IsInterfaceKind(token) or mojom.IsEnumKind(token)): return token.name + "_Data" @@ -156,21 +144,7 @@ def IsNativeOnlyKind(kind): def GetNativeTypeName(typemapped_kind): return _current_typemap[GetFullMojomNameForKind(typemapped_kind)]["typename"] -def DoesKindSupportEquality(kind): - if IsTypemappedKind(kind): - return False - if mojom.IsStructKind(kind) and kind.native_only: - return False - if mojom.IsArrayKind(kind): - return DoesKindSupportEquality(kind.kind) - if mojom.IsMapKind(kind): - return DoesKindSupportEquality(kind.value_kind) - return True - def GetCppType(kind): - if mojom.IsStructKind(kind) and kind.native_only: - # A native-only type is just a blob of bytes. - return "mojo::internal::Array_Data<uint8_t>*" if mojom.IsArrayKind(kind): return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind) if mojom.IsMapKind(kind): @@ -183,15 +157,17 @@ def GetCppType(kind): if mojom.IsInterfaceKind(kind): return "mojo::internal::Interface_Data" if mojom.IsInterfaceRequestKind(kind): - return "mojo::MessagePipeHandle" + return "mojo::internal::Handle_Data" if mojom.IsAssociatedInterfaceKind(kind): return "mojo::internal::AssociatedInterface_Data" if mojom.IsAssociatedInterfaceRequestKind(kind): return "mojo::internal::AssociatedInterfaceRequest_Data" if mojom.IsEnumKind(kind): - return GetNameForKind(kind, internal=True) + return "int32_t" if mojom.IsStringKind(kind): return "mojo::internal::String_Data*" + if mojom.IsAnyHandleKind(kind): + return "mojo::internal::Handle_Data" return _kind_to_cpp_type[kind] def GetCppPodType(kind): @@ -200,16 +176,8 @@ def GetCppPodType(kind): return _kind_to_cpp_type[kind] def GetCppArrayArgWrapperType(kind): - if mojom.IsStructKind(kind) and kind.native_only: - if IsTypemappedKind(kind): - return GetNativeTypeName(kind) - else: - # Without a relevant typemap to apply, a native-only struct can only be - # exposed as a blob of bytes. - return "mojo::Array<uint8_t>" if IsTypemappedKind(kind): - raise Exception( - "Cannot serialize containers of non-native typemapped structs yet!") + return GetNativeTypeName(kind) if mojom.IsEnumKind(kind): return GetNameForKind(kind) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): @@ -246,8 +214,6 @@ def GetCppArrayArgWrapperType(kind): def GetCppResultWrapperType(kind): if IsTypemappedKind(kind): return "const %s&" % GetNativeTypeName(kind) - if mojom.IsStructKind(kind) and kind.native_only: - return "mojo::Array<uint8_t>" if mojom.IsEnumKind(kind): return GetNameForKind(kind) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): @@ -289,8 +255,6 @@ def GetCppResultWrapperType(kind): def GetCppWrapperType(kind): if IsTypemappedKind(kind): return GetNativeTypeName(kind) - if mojom.IsStructKind(kind) and kind.native_only: - return "mojo::Array<uint8_t>" if mojom.IsEnumKind(kind): return GetNameForKind(kind) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): @@ -326,8 +290,6 @@ def GetCppWrapperType(kind): def GetCppConstWrapperType(kind): if IsTypemappedKind(kind): return "const %s&" % GetNativeTypeName(kind) - if mojom.IsStructKind(kind) and kind.native_only: - return "mojo::Array<uint8_t>" if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): return "%sPtr" % GetNameForKind(kind) if mojom.IsArrayKind(kind): @@ -363,40 +325,36 @@ def GetCppConstWrapperType(kind): return _kind_to_cpp_type[kind] def GetCppFieldType(kind): - if mojom.IsStructKind(kind) and kind.native_only: - return "mojo::internal::ArrayPointer<uint8_t>" if mojom.IsStructKind(kind): - return ("mojo::internal::StructPointer<%s>" % + return ("mojo::internal::Pointer<%s>" % GetNameForKind(kind, internal=True)) if mojom.IsUnionKind(kind): return "%s" % GetNameForKind(kind, internal=True) if mojom.IsArrayKind(kind): - return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind) + return ("mojo::internal::Pointer<mojo::internal::Array_Data<%s>>" % + GetCppType(kind.kind)) if mojom.IsMapKind(kind): - return ("mojo::internal::StructPointer<mojo::internal::Map_Data<%s, %s>>" % + return ("mojo::internal::Pointer<mojo::internal::Map_Data<%s, %s>>" % (GetCppType(kind.key_kind), GetCppType(kind.value_kind))) if mojom.IsInterfaceKind(kind): return "mojo::internal::Interface_Data" if mojom.IsInterfaceRequestKind(kind): - return "mojo::MessagePipeHandle" + return "mojo::internal::Handle_Data" if mojom.IsAssociatedInterfaceKind(kind): return "mojo::internal::AssociatedInterface_Data" if mojom.IsAssociatedInterfaceRequestKind(kind): return "mojo::internal::AssociatedInterfaceRequest_Data" if mojom.IsEnumKind(kind): - return GetNameForKind(kind, internal=True) + return "int32_t" if mojom.IsStringKind(kind): - return "mojo::internal::StringPointer" + return "mojo::internal::Pointer<mojo::internal::String_Data>" + if mojom.IsAnyHandleKind(kind): + return "mojo::internal::Handle_Data" return _kind_to_cpp_type[kind] def GetCppUnionFieldType(kind): - if mojom.IsAnyHandleKind(kind): - return "MojoHandle" - if mojom.IsInterfaceKind(kind): - return "uint64_t" if mojom.IsUnionKind(kind): - return ("mojo::internal::UnionPointer<%s>" % - GetNameForKind(kind, internal=True)) + return ("mojo::internal::Pointer<%s>" % GetNameForKind(kind, internal=True)) return GetCppFieldType(kind) def GetUnionGetterReturnType(kind): @@ -407,6 +365,41 @@ def GetUnionGetterReturnType(kind): return "%s&" % GetCppWrapperType(kind) return GetCppResultWrapperType(kind) +# TODO(yzshen): It is unfortunate that we have so many functions for returning +# types. Refactor them. +def GetUnmappedTypeForSerializer(kind): + if mojom.IsEnumKind(kind): + return GetQualifiedNameForKind(kind) + if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): + return "%sPtr" % GetQualifiedNameForKind(kind) + if mojom.IsArrayKind(kind): + return "mojo::Array<%s>" % GetUnmappedTypeForSerializer(kind.kind) + if mojom.IsMapKind(kind): + return "mojo::Map<%s, %s>" % ( + GetUnmappedTypeForSerializer(kind.key_kind), + GetUnmappedTypeForSerializer(kind.value_kind)) + if mojom.IsInterfaceKind(kind): + return "%sPtr" % GetQualifiedNameForKind(kind) + if mojom.IsInterfaceRequestKind(kind): + return "%sRequest" % GetQualifiedNameForKind(kind.kind) + if mojom.IsAssociatedInterfaceKind(kind): + return "%sAssociatedPtrInfo" % GetQualifiedNameForKind(kind.kind) + if mojom.IsAssociatedInterfaceRequestKind(kind): + return "%sAssociatedRequest" % GetQualifiedNameForKind(kind.kind) + if mojom.IsStringKind(kind): + return "mojo::String" + if mojom.IsGenericHandleKind(kind): + return "mojo::ScopedHandle" + if mojom.IsDataPipeConsumerKind(kind): + return "mojo::ScopedDataPipeConsumerHandle" + if mojom.IsDataPipeProducerKind(kind): + return "mojo::ScopedDataPipeProducerHandle" + if mojom.IsMessagePipeKind(kind): + return "mojo::ScopedMessagePipeHandle" + if mojom.IsSharedBufferKind(kind): + return "mojo::ScopedSharedBufferHandle" + return _kind_to_cpp_type[kind] + def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): return _NameFormatter(token, _variant).FormatForCpp() @@ -456,28 +449,36 @@ def ShouldInlineUnion(union): return not any(mojom.IsMoveOnlyKind(field.kind) for field in union.fields) def GetArrayValidateParamsCtorArgs(kind): - if mojom.IsStringKind(kind) or (mojom.IsStructKind(kind) and - kind.native_only): + if mojom.IsStringKind(kind): expected_num_elements = 0 element_is_nullable = False element_validate_params = "nullptr" + enum_validate_func = "nullptr" elif mojom.IsMapKind(kind): expected_num_elements = 0 element_is_nullable = mojom.IsNullableKind(kind.value_kind) element_validate_params = GetNewArrayValidateParams(kind.value_kind) + enum_validate_func = "nullptr" else: expected_num_elements = generator.ExpectedArraySize(kind) or 0 element_is_nullable = mojom.IsNullableKind(kind.kind) element_validate_params = GetNewArrayValidateParams(kind.kind) + if mojom.IsEnumKind(kind.kind): + enum_validate_func = ("%s::Validate" % + GetQualifiedNameForKind(kind.kind, internal=True)) + else: + enum_validate_func = "nullptr" - return "%d, %s, %s" % (expected_num_elements, - "true" if element_is_nullable else "false", - element_validate_params) + if enum_validate_func == "nullptr": + return "%d, %s, %s" % (expected_num_elements, + "true" if element_is_nullable else "false", + element_validate_params) + else: + return "%d, %s" % (expected_num_elements, enum_validate_func) def GetNewArrayValidateParams(kind): if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and - not mojom.IsStringKind(kind) and - not (mojom.IsStructKind(kind) and kind.native_only)): + not mojom.IsStringKind(kind)): return "nullptr" return "new mojo::internal::ArrayValidateParams(%s)" % ( @@ -499,7 +500,6 @@ class Generator(generator.Generator): "cpp_union_field_type": GetCppUnionFieldType, "cpp_pod_type": GetCppPodType, "cpp_result_type": GetCppResultWrapperType, - "cpp_type": GetCppType, "cpp_union_getter_return_type": GetUnionGetterReturnType, "cpp_wrapper_type": GetCppWrapperType, "default_value": DefaultValue, @@ -536,8 +536,8 @@ class Generator(generator.Generator): "passes_associated_kinds": mojom.PassesAssociatedKinds, "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE, "stylize_method": generator.StudlyCapsToCamel, - "supports_equality": DoesKindSupportEquality, "under_to_camel": generator.UnderToCamel, + "unmapped_type_for_serializer": GetUnmappedTypeForSerializer, } def GetExtraTraitsHeaders(self): diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py index 3104c13a510..481efbc3d1f 100644 --- a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py +++ b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py @@ -237,6 +237,10 @@ def GetNameForKind(context, kind): elements += _GetNameHierachy(kind) return '.'.join(elements) +@contextfilter +def GetJavaClassForEnum(context, kind): + return GetNameForKind(context, kind) + def GetBoxedJavaType(context, kind, with_generics=True): unboxed_type = GetJavaType(context, kind, False, with_generics) if unboxed_type in _java_primitive_to_boxed_type: @@ -416,6 +420,7 @@ class Generator(generator.Generator): 'interface_response_name': GetInterfaceResponseName, 'is_array_kind': mojom.IsArrayKind, 'is_any_handle_kind': mojom.IsAnyHandleKind, + "is_enum_kind": mojom.IsEnumKind, 'is_interface_request_kind': mojom.IsInterfaceRequestKind, 'is_map_kind': mojom.IsMapKind, 'is_nullable_kind': mojom.IsNullableKind, @@ -424,6 +429,7 @@ class Generator(generator.Generator): 'is_struct_kind': mojom.IsStructKind, 'is_union_array_kind': IsUnionArrayKind, 'is_union_kind': mojom.IsUnionKind, + 'java_class_for_enum': GetJavaClassForEnum, 'java_true_false': GetJavaTrueFalse, 'java_type': GetJavaType, 'method_ordinal_name': GetMethodOrdinalName, diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni index 14ddb2fa48e..543c18775fa 100644 --- a/chromium/mojo/public/tools/bindings/mojom.gni +++ b/chromium/mojo/public/tools/bindings/mojom.gni @@ -25,6 +25,15 @@ mojom_generator_sources = [ "$mojom_generator_script", ] +_bindings_configuration_files = [ + "//mojo/public/tools/bindings/chromium_bindings_configuration.gni", + "//mojo/public/tools/bindings/blink_bindings_configuration.gni", +] +_bindings_configurations = [] +foreach(config_file, _bindings_configuration_files) { + _bindings_configurations += [ read_file(config_file, "scope") ] +} + # Generate C++/JavaScript/Java source files from mojom files. The output files # will go under the generated file directory tree with the same path as each # input file. @@ -46,189 +55,244 @@ mojom_generator_sources = [ # import_dirs (optional) # List of import directories that will get added when processing sources. # -# typemaps (optional) -# A list of typemap files to apply during bindings generation. -# -# typemap_deps (optional) -# A list of public dependencies needed to support active typemaps. -# -# variant (optional) -# A variant name to apply to generated bindings. Variant influences -# generated source filenames as wells the symbols they define. -# # testonly (optional) # # visibility (optional) -# -# for_blink (optional, C++ only) -# Use WTF types as generated type for mojo string/array/map. template("mojom") { assert( defined(invoker.sources) || defined(invoker.deps) || defined(invoker.public_deps), "\"sources\" or \"deps\" must be defined for the $target_name template.") - cpp_sources_suffix = "cpp_sources" - cpp_sources_target_name = "${target_name}_${cpp_sources_suffix}" - cpp_only = false - if (defined(invoker.sources)) { - if (defined(invoker.variant)) { - variant = invoker.variant - cpp_only = true - generator_cpp_outputs = [ - "{{source_gen_dir}}/{{source_name_part}}.mojom-${variant}.cc", - "{{source_gen_dir}}/{{source_name_part}}.mojom-${variant}.h", - "{{source_gen_dir}}/{{source_name_part}}.mojom-${variant}-internal.h", - ] - } else { - generator_cpp_outputs = [ - "{{source_gen_dir}}/{{source_name_part}}.mojom.cc", - "{{source_gen_dir}}/{{source_name_part}}.mojom.h", - "{{source_gen_dir}}/{{source_name_part}}.mojom-internal.h", - ] - } + all_deps = [] + if (defined(invoker.deps)) { + all_deps += invoker.deps + } + if (defined(invoker.public_deps)) { + all_deps += invoker.public_deps } - if (cpp_only) { - generator_js_outputs = [] - generator_java_outputs = [] - } else { - generator_js_outputs = - [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ] - generator_java_outputs = - [ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ] + group("${target_name}__is_mojom") { } - if (defined(invoker.sources)) { - generator_target_name = target_name + "__generator" - action_foreach(generator_target_name) { - script = mojom_generator_script - inputs = mojom_generator_sources - sources = invoker.sources - deps = [ - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = - generator_cpp_outputs + generator_java_outputs + generator_js_outputs - args = [ - "--use_bundled_pylibs", - "generate", - "{{source}}", - "-d", - rebase_path("//", root_build_dir), - "-I", - rebase_path("//", root_build_dir), - "-o", - rebase_path(root_gen_dir), - "--bytecode_path", - rebase_path("$root_gen_dir/mojo/public/tools/bindings"), - ] + # Explicitly ensure that all dependencies (invoker.deps and + # invoker.public_deps) are mojom targets. + group("${target_name}__check_deps_are_all_mojom") { + deps = [] + foreach(d, all_deps) { + name = get_label_info(d, "label_no_toolchain") + toolchain = get_label_info(d, "toolchain") + deps += [ "${name}__is_mojom(${toolchain})" ] + } + } - if (defined(invoker.import_dirs)) { - foreach(import_dir, invoker.import_dirs) { - args += [ - "-I", - rebase_path(import_dir, root_build_dir), - ] + foreach(bindings_configuration, _bindings_configurations) { + cpp_only = false + variant_suffix = "" + if (defined(bindings_configuration.variant)) { + variant = bindings_configuration.variant + variant_suffix = "_${variant}" + cpp_only = true + } + type_mappings_target_name = "${target_name}${variant_suffix}__type_mappings" + type_mappings_path = + "$target_gen_dir/${target_name}${variant_suffix}__type_mappings" + active_typemaps = [] + cpp_sources_suffix = "cpp_sources" + cpp_sources_target_name = + "${target_name}${variant_suffix}_${cpp_sources_suffix}" + enabled_sources = [] + if (defined(invoker.sources)) { + generator_cpp_outputs = [] + generator_js_outputs = [] + generator_java_outputs = [] + variant_dash_suffix = "" + if (defined(variant)) { + variant_dash_suffix = "-${variant}" + } + generator_cpp_outputs += [ + "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.cc", + "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.h", + "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}-internal.h", + ] + enabled_sources = [] + if (defined(bindings_configuration.blacklist)) { + foreach(source, invoker.sources) { + blacklisted = false + foreach(blacklisted_source, bindings_configuration.blacklist) { + if (get_path_info(source, "abspath") == blacklisted_source) { + blacklisted = true + } + } + if (!blacklisted) { + enabled_sources += [ source ] + } + } + } else { + enabled_sources = invoker.sources + } + foreach(source, enabled_sources) { + # TODO(sammc): Use a map instead of a linear scan when GN supports maps. + foreach(typemap, bindings_configuration.typemaps) { + if (get_path_info(source, "abspath") == typemap.mojom) { + active_typemaps += [ typemap ] + } } } - if (cpp_only) { - args += [ - "-g", - "c++", + if (!cpp_only) { + generator_js_outputs = + [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ] + generator_java_outputs = + [ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ] + } + generator_target_name = "${target_name}${variant_suffix}__generator" + action_foreach(generator_target_name) { + script = mojom_generator_script + inputs = mojom_generator_sources + sources = invoker.sources + deps = [ + ":$type_mappings_target_name", + "//mojo/public/tools/bindings:precompile_templates", ] - } else { - args += [ - "-g", - "c++,javascript,java", + outputs = generator_cpp_outputs + generator_java_outputs + + generator_js_outputs + args = [ + "--use_bundled_pylibs", + "generate", + "{{source}}", + "-d", + rebase_path("//", root_build_dir), + "-I", + rebase_path("//", root_build_dir), + "-o", + rebase_path(root_gen_dir), + "--bytecode_path", + rebase_path("$root_gen_dir/mojo/public/tools/bindings"), ] - } - if (defined(invoker.variant)) { - args += [ - "--variant", - invoker.variant, - ] - } + if (defined(invoker.import_dirs)) { + foreach(import_dir, invoker.import_dirs) { + args += [ + "-I", + rebase_path(import_dir, root_build_dir), + ] + } + } - if (defined(invoker.typemaps)) { - foreach(typemap, invoker.typemaps) { + if (cpp_only) { args += [ - "--typemap", - rebase_path(typemap, root_build_dir), + "-g", + "c++", + ] + } else { + args += [ + "-g", + "c++,javascript,java", + ] + } + + if (defined(bindings_configuration.variant)) { + args += [ + "--variant", + bindings_configuration.variant, ] } - inputs += invoker.typemaps - } - if (defined(invoker.for_blink) && invoker.for_blink) { - args += [ "--for_blink" ] + args += [ + "--typemap", + rebase_path(type_mappings_path, root_build_dir), + ] + + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { + args += [ "--for_blink" ] + } } } - } - source_set(target_name) { - if (defined(invoker.visibility)) { - visibility = invoker.visibility - } - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - if (defined(invoker.sources) && !defined(invoker.variant)) { - data = process_file_template(invoker.sources, generator_js_outputs) - } + action(type_mappings_target_name) { + inputs = _bindings_configuration_files + outputs = [ + type_mappings_path, + ] + script = "$mojom_generator_root/generate_type_mappings.py" + deps = [] + args = [ + "--output", + rebase_path(type_mappings_path, root_build_dir), + ] - public_deps = [ - "//mojo/public/cpp/bindings", - ] - if (defined(invoker.sources)) { - public_deps += [ ":${cpp_sources_target_name}" ] - } - if (defined(invoker.deps)) { - public_deps += invoker.deps - } - if (defined(invoker.public_deps)) { - public_deps += invoker.public_deps - } - if (defined(invoker.typemap_deps)) { - public_deps += invoker.typemap_deps - } + foreach(d, all_deps) { + name = get_label_info(d, "label_no_toolchain") + toolchain = get_label_info(d, "toolchain") + dependency_output = "${name}${variant_suffix}__type_mappings" + dependency_target = "${dependency_output}(${toolchain})" + deps += [ dependency_target ] + dependency_output_dir = + get_label_info(dependency_output, "target_gen_dir") + dependency_name = get_label_info(dependency_output, "name") + dependency_path = + rebase_path("$dependency_output_dir/${dependency_name}", + root_build_dir) + args += [ + "--dependency", + dependency_path, + ] + } - deps = [] - if (defined(invoker.sources)) { - public_deps += [ ":$generator_target_name" ] + if (enabled_sources != []) { + # TODO(sammc): Pass the typemap description in a file to avoid command + # line length limitations. + typemap_description = [] + foreach(typemap, active_typemaps) { + typemap_description += [ "--start-typemap" ] + if (defined(typemap.public_headers)) { + foreach(value, typemap.public_headers) { + typemap_description += [ "public_headers=$value" ] + } + } + if (defined(typemap.traits_headers)) { + foreach(value, typemap.traits_headers) { + typemap_description += [ "traits_headers=$value" ] + } + } + foreach(value, typemap.type_mappings) { + typemap_description += [ "type_mappings=$value" ] + } + } + args += typemap_description + } } - } - all_deps = [] - if (defined(invoker.deps)) { - all_deps += invoker.deps - } - if (defined(invoker.public_deps)) { - all_deps += invoker.public_deps - } + source_set("${target_name}${variant_suffix}") { + if (defined(invoker.visibility)) { + visibility = invoker.visibility + } + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + if (defined(invoker.sources) && !defined(bindings_configuration.variant)) { + data = process_file_template(enabled_sources, generator_js_outputs) + } - if (defined(invoker.variant)) { - variant_suffix = "of_variant_${invoker.variant}" - } else { - variant_suffix = "of_no_variant" - } - group("${target_name}__is_mojom_${variant_suffix}") { - } + public_deps = [ + ":${cpp_sources_target_name}", + "//mojo/public/cpp/bindings", + ] + if (defined(invoker.deps)) { + public_deps += invoker.deps + } + if (defined(invoker.public_deps)) { + public_deps += invoker.public_deps + } - # Explicitly ensure that all dependencies (invoker.deps and - # invoker.public_deps) are mojom targets of the same variant themselves. - group("${target_name}__check_deps_are_all_mojom_${variant_suffix}") { - deps = [] - foreach(d, all_deps) { - name = get_label_info(d, "label_no_toolchain") - toolchain = get_label_info(d, "toolchain") - deps += [ "${name}__is_mojom_${variant_suffix}(${toolchain})" ] + deps = [] + if (defined(invoker.sources)) { + public_deps += [ ":$generator_target_name" ] + } } - } - if (defined(invoker.sources)) { # The generated C++ source files. The main reason to introduce this target # is so that mojo/public/cpp/bindings can depend on mojom interfaces without # circular dependencies. It means that the target is missing the dependency @@ -239,69 +303,94 @@ template("mojom") { if (defined(invoker.testonly)) { testonly = invoker.testonly } - sources = process_file_template(invoker.sources, generator_cpp_outputs) + if (enabled_sources != []) { + sources = process_file_template(enabled_sources, generator_cpp_outputs) + } deps = [ - ":$generator_target_name", + "//mojo/public/cpp/bindings:struct_traits", "//mojo/public/interfaces/bindings:bindings__generator", ] + if (enabled_sources != []) { + deps += [ ":$generator_target_name" ] + } public_deps = [ "//base", ] - if (defined(invoker.typemap_deps)) { - public_deps += invoker.typemap_deps - } foreach(d, all_deps) { # Resolve the name, so that a target //mojo/something becomes # //mojo/something:something and we can append cpp_sources_suffix to # get the cpp dependency name. - full_name = get_label_info(d, "label_no_toolchain") - deps += [ "${full_name}_${cpp_sources_suffix}" ] + full_name = get_label_info("$d", "label_no_toolchain") + deps += [ "${full_name}${variant_suffix}_${cpp_sources_suffix}" ] } - if (defined(invoker.for_blink) && invoker.for_blink) { + foreach(typemap, active_typemaps) { + if (defined(typemap.public_headers)) { + sources += typemap.public_headers + } + if (defined(typemap.traits_headers)) { + sources += typemap.traits_headers + } + if (defined(typemap.sources)) { + sources += typemap.sources + } + if (defined(typemap.deps)) { + deps += typemap.deps + } + } + if (defined(bindings_configuration.for_blink) && + bindings_configuration.for_blink) { public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] } } - } - if (is_android && !cpp_only) { - import("//build/config/android/rules.gni") + if (!cpp_only && is_android) { + import("//build/config/android/rules.gni") - java_srcjar_target_name = target_name + "_java_sources" - action(java_srcjar_target_name) { - script = "//mojo/public/tools/gn/zip.py" - inputs = process_file_template(invoker.sources, generator_java_outputs) - output = "$target_gen_dir/$target_name.srcjar" - outputs = [ - output, - ] - rebase_inputs = rebase_path(inputs, root_build_dir) - rebase_output = rebase_path(output, root_build_dir) - args = [ - "--zip-inputs=$rebase_inputs", - "--output=$rebase_output", - ] - deps = [ - ":$generator_target_name", - ] - } + java_srcjar_target_name = target_name + "_java_sources" + action(java_srcjar_target_name) { + script = "//mojo/public/tools/gn/zip.py" + inputs = [] + if (enabled_sources != []) { + inputs = + process_file_template(enabled_sources, generator_java_outputs) + } + output = "$target_gen_dir/$target_name.srcjar" + outputs = [ + output, + ] + rebase_inputs = rebase_path(inputs, root_build_dir) + rebase_output = rebase_path(output, root_build_dir) + args = [ + "--zip-inputs=$rebase_inputs", + "--output=$rebase_output", + ] + deps = [] + if (enabled_sources != []) { + deps = [ + ":$generator_target_name", + ] + } + } - java_target_name = target_name + "_java" - android_library(java_target_name) { - deps = [ - "//base:base_java", - "//mojo/public/java:bindings", - "//mojo/public/java:system", - ] + java_target_name = target_name + "_java" + android_library(java_target_name) { + deps = [ + "//base:base_java", + "//mojo/public/java:bindings", + "//mojo/public/java:system", + ] - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append "_java" to get the java - # dependency name. - full_name = get_label_info(d, "label_no_toolchain") - deps += [ "${full_name}_java" ] - } + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append "_java" to get the java + # dependency name. + full_name = get_label_info(d, "label_no_toolchain") + deps += [ "${full_name}_java" ] + } - srcjar_deps = [ ":$java_srcjar_target_name" ] + srcjar_deps = [ ":$java_srcjar_target_name" ] + run_findbugs_override = false + } } } } diff --git a/chromium/mojo/public/tools/bindings/mojom_get_generator_typemap_args.py b/chromium/mojo/public/tools/bindings/mojom_get_generator_typemap_args.py deleted file mode 100755 index 32eb1ea8785..00000000000 --- a/chromium/mojo/public/tools/bindings/mojom_get_generator_typemap_args.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016 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 sys - - -# This unfortunate little utility is needed by GYP to intersperse "--typemap" -# flags before each entry in a list of typemaps. The resulting argument list -# can then be fed to the bindings generator. - - -def main(): - for filename in sys.argv[1:]: - print "--typemap" - print filename - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py index 331d2183b4d..8c15cc944b8 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py @@ -500,6 +500,14 @@ def ModuleFromData(data): return module def OrderedModuleFromData(data): + """Convert Mojom IR to a module. + + Args: + data: The Mojom IR as a dict. + + Returns: + A mojom.generate.module.Module object. + """ module = ModuleFromData(data) for interface in module.interfaces: next_ordinal = 0 diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py index a673d8eef60..16bdf27eab8 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -13,16 +13,98 @@ # method.AddParameter('baz', 0, mojom.INT32) +# We use our own version of __repr__ when displaying the AST, as the +# AST currently doesn't capture which nodes are reference (e.g. to +# types) and which nodes are definitions. This allows us to e.g. print +# the definition of a struct when it's defined inside a module, but +# only print its name when it's referenced in e.g. a method parameter. +def Repr(obj, as_ref=True): + """A version of __repr__ that can distinguish references. + + Sometimes we like to print an object's full representation + (e.g. with its fields) and sometimes we just want to reference an + object that was printed in full elsewhere. This function allows us + to make that distinction. + + Args: + obj: The object whose string representation we compute. + as_ref: If True, use the short reference representation. + + Returns: + A str representation of |obj|. + """ + if hasattr(obj, 'Repr'): + return obj.Repr(as_ref=as_ref) + # Since we cannot implement Repr for existing container types, we + # handle them here. + elif isinstance(obj, list): + if not obj: + return '[]' + else: + return ('[\n%s\n]' % (',\n'.join(' %s' % Repr(elem, as_ref).replace( + '\n', '\n ') for elem in obj))) + elif isinstance(obj, dict): + if not obj: + return '{}' + else: + return ('{\n%s\n}' % (',\n'.join(' %s: %s' % ( + Repr(key, as_ref).replace('\n', '\n '), + Repr(val, as_ref).replace('\n', '\n ')) + for key, val in obj.iteritems()))) + else: + return repr(obj) + + +def GenericRepr(obj, names): + """Compute generic Repr for |obj| based on the attributes in |names|. + + Args: + obj: The object to compute a Repr for. + names: A dict from attribute names to include, to booleans + specifying whether those attributes should be shown as + references or not. + + Returns: + A str representation of |obj|. + """ + def ReprIndent(name, as_ref): + return ' %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace( + '\n', '\n ')) + + return '%s(\n%s\n)' % ( + obj.__class__.__name__, + ',\n'.join(ReprIndent(name, as_ref) + for (name, as_ref) in names.iteritems())) + + class Kind(object): + """Kind represents a type (e.g. int8, string). + + Attributes: + spec: A string uniquely identifying the type. May be None. + parent_kind: The enclosing type. For example, a struct defined + inside an interface has that interface as its parent. May be None. + """ def __init__(self, spec=None): self.spec = spec self.parent_kind = None + def Repr(self, as_ref=True): + return '<%s spec=%r>' % (self.__class__.__name__, self.spec) + + def __repr__(self): + # Gives us a decent __repr__ for all kinds. + return self.Repr() + class ReferenceKind(Kind): - """ReferenceKind represents pointer types and handle types. + """ReferenceKind represents pointer and handle types. + A type is nullable if null (for pointer types) or invalid handle (for handle types) is a legal value for the type. + + Attributes: + is_nullable: True if the type is nullable. """ def __init__(self, spec=None, is_nullable=False): @@ -31,6 +113,10 @@ class ReferenceKind(Kind): self.is_nullable = is_nullable self.shared_definition = {} + def Repr(self, as_ref=True): + return '<%s spec=%r is_nullable=%r>' % (self.__class__.__name__, self.spec, + self.is_nullable) + def MakeNullableKind(self): assert not self.is_nullable @@ -47,9 +133,6 @@ class ReferenceKind(Kind): if self == SHAREDBUFFER: return NULLABLE_SHAREDBUFFER - if IsStructKind(self) and self.native_only: - raise Exception('Native-only structs cannot be nullable.') - nullable_kind = type(self)() nullable_kind.shared_definition = self.shared_definition if self.spec is not None: @@ -193,6 +276,11 @@ class Field(object): self.default = default self.attributes = attributes + def Repr(self, as_ref=True): + # Fields are only referenced by objects which define them and thus + # they are always displayed as non-references. + return GenericRepr(self, {'name': False, 'kind': True}) + @property def min_version(self): return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ @@ -226,6 +314,15 @@ class Struct(ReferenceKind): self.fields = [] self.attributes = attributes + def Repr(self, as_ref=True): + if as_ref: + return '<%s name=%r imported_from=%s>' % ( + self.__class__.__name__, self.name, + Repr(self.imported_from, as_ref=True)) + else: + return GenericRepr(self, {'name': False, 'fields': False, + 'imported_from': True}) + def AddField(self, name, kind, ordinal=None, default=None, attributes=None): field = StructField(name, kind, ordinal, default, attributes) self.fields.append(field) @@ -233,6 +330,18 @@ class Struct(ReferenceKind): class Union(ReferenceKind): + """A union of several kinds. + + Attributes: + name: {str} The name of the union type. + module: {Module} The defining module. + imported_from: {dict} Information about where this union was + imported from. + fields: {List[UnionField]} The members of the union. + attributes: {dict} Additional information about the union, such as + which Java class name to use to represent it in the generated + bindings. + """ ReferenceKind.AddSharedProperty('name') ReferenceKind.AddSharedProperty('module') ReferenceKind.AddSharedProperty('imported_from') @@ -251,6 +360,14 @@ class Union(ReferenceKind): self.fields = [] self.attributes = attributes + def Repr(self, as_ref=True): + if as_ref: + return '<%s spec=%r is_nullable=%r fields=%s>' % ( + self.__class__.__name__, self.spec, self.is_nullable, + Repr(self.fields)) + else: + return GenericRepr(self, {'fields': True, 'is_nullable': False}) + def AddField(self, name, kind, ordinal=None, attributes=None): field = UnionField(name, kind, ordinal, None, attributes) self.fields.append(field) @@ -258,6 +375,13 @@ class Union(ReferenceKind): class Array(ReferenceKind): + """An array. + + Attributes: + kind: {Kind} The type of the elements. May be None. + length: The number of elements. None if unknown. + """ + ReferenceKind.AddSharedProperty('kind') ReferenceKind.AddSharedProperty('length') @@ -274,8 +398,23 @@ class Array(ReferenceKind): self.kind = kind self.length = length + def Repr(self, as_ref=True): + if as_ref: + return '<%s spec=%r is_nullable=%r kind=%s length=%r>' % ( + self.__class__.__name__, self.spec, self.is_nullable, Repr(self.kind), + self.length) + else: + return GenericRepr(self, {'kind': True, 'length': False, + 'is_nullable': False}) + class Map(ReferenceKind): + """A map. + + Attributes: + key_kind: {Kind} The type of the keys. May be None. + value_kind: {Kind} The type of the elements. May be None. + """ ReferenceKind.AddSharedProperty('key_kind') ReferenceKind.AddSharedProperty('value_kind') @@ -303,6 +442,14 @@ class Map(ReferenceKind): self.key_kind = key_kind self.value_kind = value_kind + def Repr(self, as_ref=True): + if as_ref: + return '<%s spec=%r is_nullable=%r key_kind=%s value_kind=%s>' % ( + self.__class__.__name__, self.spec, self.is_nullable, + Repr(self.key_kind), Repr(self.value_kind)) + else: + return GenericRepr(self, {'key_kind': True, 'value_kind': True}) + class InterfaceRequest(ReferenceKind): ReferenceKind.AddSharedProperty('kind') @@ -343,6 +490,10 @@ class Parameter(object): self.default = default self.attributes = attributes + def Repr(self, as_ref=True): + return '<%s name=%r kind=%s>' % (self.__class__.__name__, self.name, + self.kind.Repr(as_ref=True)) + @property def min_version(self): return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ @@ -358,6 +509,13 @@ class Method(object): self.response_parameters = None self.attributes = attributes + def Repr(self, as_ref=True): + if as_ref: + return '<%s name=%r>' % (self.__class__.__name__, self.name) + else: + return GenericRepr(self, {'name': False, 'parameters': True, + 'response_parameters': True}) + def AddParameter(self, name, kind, ordinal=None, default=None, attributes=None): parameter = Parameter(name, kind, ordinal, default, attributes) @@ -402,6 +560,13 @@ class Interface(ReferenceKind): self.methods = [] self.attributes = attributes + def Repr(self, as_ref=True): + if as_ref: + return '<%s name=%r>' % (self.__class__.__name__, self.name) + else: + return GenericRepr(self, {'name': False, 'attributes': False, + 'methods': False}) + def AddMethod(self, name, ordinal=None, attributes=None): method = Method(self, name, ordinal, attributes) self.methods.append(method) @@ -455,6 +620,12 @@ class Enum(Kind): self.fields = [] self.attributes = attributes + def Repr(self, as_ref=True): + if as_ref: + return '<%s name=%r>' % (self.__class__.__name__, self.name) + else: + return GenericRepr(self, {'name': False, 'fields': False}) + @property def extensible(self): return self.attributes.get(ATTRIBUTE_EXTENSIBLE, False) \ @@ -472,6 +643,19 @@ class Module(object): self.kinds = {} self.attributes = attributes + def __repr__(self): + # Gives us a decent __repr__ for modules. + return self.Repr() + + def Repr(self, as_ref=True): + if as_ref: + return '<%s name=%r namespace=%r>' % ( + self.__class__.__name__, self.name, self.namespace) + else: + return GenericRepr(self, {'name': False, 'namespace': False, + 'attributes': False, 'structs': False, + 'interfaces': False, 'unions': False}) + def AddInterface(self, name, attributes=None): interface = Interface(name, self, attributes) self.interfaces.append(interface) @@ -618,7 +802,7 @@ def IsCloneableKind(kind, filter): if IsArrayKind(kind): return _IsCloneable(kind.kind, visited_kinds) if IsStructKind(kind) or IsUnionKind(kind): - if IsStructKind(kind) and (kind.native_only or filter(kind)): + if IsStructKind(kind) and filter(kind): return False for field in kind.fields: if not _IsCloneable(field.kind, visited_kinds): diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py index 996c98b04f6..66c1c2d026f 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py @@ -429,6 +429,15 @@ class Parser(object): def Parse(source, filename): + """Parse source file to AST. + + Args: + source: The source text as a str. + filename: The filename that |source| originates from. + + Returns: + The AST as a mojom.parse.ast.Mojom object. + """ lexer = Lexer(filename) parser = Parser(lexer, source, filename) diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py index e457f994b0a..8d53d25ab4f 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py @@ -222,4 +222,13 @@ class _MojomBuilder(object): def Translate(tree, name): + """Translate AST to Mojom IR. + + Args: + tree: The AST as a mojom.parse.ast.Mojom object. + name: The filename as a str. + + Returns: + The Mojom IR as a dict. + """ return _MojomBuilder().Build(tree, name) diff --git a/chromium/mojo/public/tools/manifest/manifest_collator.py b/chromium/mojo/public/tools/manifest/manifest_collator.py index fa95e37f21a..9a6d0e9b010 100755 --- a/chromium/mojo/public/tools/manifest/manifest_collator.py +++ b/chromium/mojo/public/tools/manifest/manifest_collator.py @@ -7,20 +7,27 @@ import argparse import json +import os import shutil import sys import urlparse +eater_relative = '../../../../../tools/json_comment_eater' +eater_relative = os.path.join(os.path.abspath(__file__), eater_relative) +sys.path.insert(0, os.path.normpath(eater_relative)) +try: + import json_comment_eater +finally: + sys.path.pop(0) def ParseJSONFile(filename): with open(filename) as json_file: try: - return json.load(json_file) + return json.loads(json_comment_eater.Nom(json_file.read())) except ValueError: print "%s is not a valid JSON document" % filename return None - def MergeDicts(left, right): for k, v in right.iteritems(): if k not in left: @@ -40,6 +47,14 @@ def MergeDicts(left, right): def MergeBaseManifest(parent, base): MergeDicts(parent["capabilities"], base["capabilities"]) + if "applications" in base: + if "applications" not in parent: + parent["applications"] = [] + parent["applications"].extend(base["applications"]) + + if "process-group" in base: + parent["process-group"] = base["process-group"] + def main(): parser = argparse.ArgumentParser( diff --git a/chromium/mojo/services/BUILD.gn b/chromium/mojo/services/BUILD.gn deleted file mode 100644 index aaf9aab6097..00000000000 --- a/chromium/mojo/services/BUILD.gn +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ui.gni") - -group("services") { - # Meta-target, don't link into production code. - testonly = true - deps = [ - "//mojo/services/catalog", - "//mojo/services/tracing", - ] -} diff --git a/chromium/mojo/services/DEPS b/chromium/mojo/services/DEPS deleted file mode 100644 index 7a393747889..00000000000 --- a/chromium/mojo/services/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -include_rules = [ - "-mojo", - "+mojo/common", - "+mojo/public", - "+mojo/shell/public", -] diff --git a/chromium/mojo/services/catalog/BUILD.gn b/chromium/mojo/services/catalog/BUILD.gn deleted file mode 100644 index fa28ec6260d..00000000000 --- a/chromium/mojo/services/catalog/BUILD.gn +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2016 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("//mojo/public/mojo_application.gni") -import("//mojo/public/mojo_application_manifest.gni") -import("//testing/test.gni") - -group("catalog") { - testonly = true - deps = [ - ":lib", - ] -} - -source_set("lib") { - sources = [ - "catalog.cc", - "catalog.h", - "entry.cc", - "entry.h", - "factory.cc", - "factory.h", - "manifest_provider.h", - "store.cc", - "store.h", - "types.h", - ] - - deps = [ - "//base", - "//mojo/common:url_type_converters", - "//mojo/services/catalog/public/interfaces", - "//mojo/shell/public/cpp", - "//mojo/util:filename_util", - ] - - data_deps = [ - ":manifest", - ] -} - -mojo_application_manifest("manifest") { - application_name = "catalog" - source = "manifest.json" -} - -source_set("unittests") { - testonly = true - sources = [ - "entry_unittest.cc", - ] - deps = [ - ":lib", - "//base", - "//mojo/shell/public/cpp", - "//testing/gtest", - ] -} diff --git a/chromium/mojo/services/catalog/DEPS b/chromium/mojo/services/catalog/DEPS deleted file mode 100644 index 4d66b26de32..00000000000 --- a/chromium/mojo/services/catalog/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -include_rules = [ - "+base", - "+mojo/common", - "+mojo/shell/public", - "+mojo/util", -] diff --git a/chromium/mojo/services/catalog/catalog.cc b/chromium/mojo/services/catalog/catalog.cc deleted file mode 100644 index c031022c58c..00000000000 --- a/chromium/mojo/services/catalog/catalog.cc +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2016 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/services/catalog/catalog.h" - -#include "base/bind.h" -#include "base/json/json_file_value_serializer.h" -#include "base/json/json_reader.h" -#include "base/strings/string_split.h" -#include "base/task_runner_util.h" -#include "base/thread_task_runner_handle.h" -#include "mojo/common/url_type_converters.h" -#include "mojo/services/catalog/entry.h" -#include "mojo/services/catalog/manifest_provider.h" -#include "mojo/services/catalog/store.h" -#include "mojo/shell/public/cpp/names.h" -#include "url/gurl.h" -#include "url/url_util.h" - -namespace catalog { -namespace { - -base::FilePath GetManifestPath(const base::FilePath& package_dir, - const std::string& name) { - // TODO(beng): think more about how this should be done for exe targets. - std::string type = mojo::GetNameType(name); - std::string path = mojo::GetNamePath(name); - if (type == mojo::kNameType_Mojo) { - return package_dir.AppendASCII("Mojo Applications").AppendASCII( - path + "/manifest.json"); - } - if (type == mojo::kNameType_Exe) - return package_dir.AppendASCII(path + "_manifest.json"); - return base::FilePath(); -} - -base::FilePath GetPackagePath(const base::FilePath& package_dir, - const std::string& name) { - std::string type = mojo::GetNameType(name); - if (type == mojo::kNameType_Mojo) { - // It's still a mojo: URL, use the default mapping scheme. - const std::string host = mojo::GetNamePath(name); - return package_dir.AppendASCII("Mojo Applications").AppendASCII( - host + "/" + host + ".mojo"); - } - if (type == mojo::kNameType_Exe) { -#if defined OS_WIN - std::string extension = ".exe"; -#else - std::string extension; -#endif - return package_dir.AppendASCII(mojo::GetNamePath(name) + extension); - } - return base::FilePath(); -} - -scoped_ptr<ReadManifestResult> ProcessManifest( - const base::FilePath& user_package_dir, - const base::FilePath& system_package_dir, - const std::string& name, - scoped_ptr<base::Value> manifest_root) { - scoped_ptr<Entry> entry(new Entry(name)); - if (manifest_root) { - const base::DictionaryValue* dictionary = nullptr; - CHECK(manifest_root->GetAsDictionary(&dictionary)); - entry = Entry::Deserialize(*dictionary); - } - entry->set_path(GetPackagePath(system_package_dir, name)); - - scoped_ptr<ReadManifestResult> result(new ReadManifestResult); - // NOTE: This TypeConverter must run on a thread which allows IO. - result->resolve_result = mojo::shell::mojom::ResolveResult::From(*entry); - result->catalog_entry = std::move(entry); - result->package_dir = system_package_dir; - return result; -} - -scoped_ptr<ReadManifestResult> ReadManifest( - const base::FilePath& user_package_dir, - const base::FilePath& system_package_dir, - const std::string& name) { - base::FilePath manifest_path = GetManifestPath(system_package_dir, name); - JSONFileValueDeserializer deserializer(manifest_path); - int error = 0; - std::string message; - - // TODO(beng): probably want to do more detailed error checking. This should - // be done when figuring out if to unblock connection completion. - return ProcessManifest(user_package_dir, system_package_dir, name, - deserializer.Deserialize(&error, &message)); -} - -void AddEntryToMap(const Entry& entry, - mojo::Map<mojo::String, mojom::CatalogEntryPtr>* map) { - mojom::CatalogEntryPtr entry_ptr(mojom::CatalogEntry::New()); - entry_ptr->display_name = entry.display_name(); - (*map)[entry.name()] = std::move(entry_ptr); -} - -} // namespace - -ReadManifestResult::ReadManifestResult() {} -ReadManifestResult::~ReadManifestResult() {} - -//////////////////////////////////////////////////////////////////////////////// -// Catalog, public: - -Catalog::Catalog(scoped_ptr<Store> store, - base::TaskRunner* file_task_runner, - EntryCache* system_catalog, - ManifestProvider* manifest_provider) - : manifest_provider_(manifest_provider), - store_(std::move(store)), - file_task_runner_(file_task_runner), - system_catalog_(system_catalog), - weak_factory_(this) { - PathService::Get(base::DIR_MODULE, &system_package_dir_); - DeserializeCatalog(); -} - -Catalog::~Catalog() {} - -void Catalog::BindResolver(mojom::ResolverRequest request) { - resolver_bindings_.AddBinding(this, std::move(request)); -} - -void Catalog::BindShellResolver( - mojo::shell::mojom::ShellResolverRequest request) { - shell_resolver_bindings_.AddBinding(this, std::move(request)); -} - -void Catalog::BindCatalog(mojom::CatalogRequest request) { - catalog_bindings_.AddBinding(this, std::move(request)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Catalog, mojom::Resolver: - -void Catalog::ResolveInterfaces(mojo::Array<mojo::String> interfaces, - const ResolveInterfacesCallback& callback) { - // TODO(beng): implement. -} - -void Catalog::ResolveMIMEType(const mojo::String& mime_type, - const ResolveMIMETypeCallback& callback) { - // TODO(beng): implement. -} - -void Catalog::ResolveProtocolScheme( - const mojo::String& scheme, - const ResolveProtocolSchemeCallback& callback) { - // TODO(beng): implement. -} - -//////////////////////////////////////////////////////////////////////////////// -// Catalog, mojo::shell::mojom::ShellResolver: - -void Catalog::ResolveMojoName(const mojo::String& mojo_name, - const ResolveMojoNameCallback& callback) { - std::string type = mojo::GetNameType(mojo_name); - if (type != "mojo" && type != "exe") { - scoped_ptr<Entry> entry(new Entry(mojo_name)); - callback.Run(mojo::shell::mojom::ResolveResult::From(*entry)); - return; - } - - auto entry = user_catalog_.find(mojo_name); - if (entry != user_catalog_.end()) { - callback.Run(mojo::shell::mojom::ResolveResult::From(*entry->second)); - return; - } - entry = system_catalog_->find(mojo_name); - if (entry != system_catalog_->end()) { - callback.Run(mojo::shell::mojom::ResolveResult::From(*entry->second)); - return; - } - - std::string manifest_contents; - if (manifest_provider_ && - manifest_provider_->GetApplicationManifest(mojo_name.To<std::string>(), - &manifest_contents)) { - scoped_ptr<base::Value> manifest_root = - base::JSONReader::Read(manifest_contents); - base::PostTaskAndReplyWithResult( - file_task_runner_, FROM_HERE, - base::Bind(&ProcessManifest, user_package_dir_, system_package_dir_, - mojo_name, base::Passed(&manifest_root)), - base::Bind(&Catalog::OnReadManifest, weak_factory_.GetWeakPtr(), - mojo_name, callback)); - } else { - base::PostTaskAndReplyWithResult( - file_task_runner_, FROM_HERE, - base::Bind(&ReadManifest, user_package_dir_, system_package_dir_, - mojo_name), - base::Bind(&Catalog::OnReadManifest, weak_factory_.GetWeakPtr(), - mojo_name, callback)); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Catalog, mojom::Catalog: - -void Catalog::GetEntries(mojo::Array<mojo::String> names, - const GetEntriesCallback& callback) { - mojo::Map<mojo::String, mojom::CatalogEntryPtr> entries; - if (names.is_null()) { - for (const auto& entry : user_catalog_) - AddEntryToMap(*entry.second, &entries); - for (const auto& entry : *system_catalog_) - AddEntryToMap(*entry.second, &entries); - } else { - std::vector<mojo::String> names_vec = names.PassStorage(); - for (const std::string& name : names_vec) { - Entry* entry = nullptr; - if (user_catalog_.find(name) != user_catalog_.end()) - entry = user_catalog_[name].get(); - else if (system_catalog_->find(name) != system_catalog_->end()) - entry = (*system_catalog_)[name].get(); - else - continue; - AddEntryToMap(*entry, &entries); - } - } - callback.Run(std::move(entries)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Catalog, private: - -void Catalog::DeserializeCatalog() { - if (!store_) - return; - const base::ListValue* catalog = store_->GetStore(); - CHECK(catalog); - // TODO(sky): make this handle aliases. - // TODO(beng): implement this properly! - for (auto it = catalog->begin(); it != catalog->end(); ++it) { - const base::DictionaryValue* dictionary = nullptr; - const base::Value* v = *it; - CHECK(v->GetAsDictionary(&dictionary)); - scoped_ptr<Entry> entry = Entry::Deserialize(*dictionary); - if (entry) - user_catalog_[entry->name()] = std::move(entry); - } -} - -void Catalog::SerializeCatalog() { - // TODO(beng): system catalog? - scoped_ptr<base::ListValue> catalog(new base::ListValue); - for (const auto& entry : user_catalog_) - catalog->Append(entry.second->Serialize()); - if (store_) - store_->UpdateStore(std::move(catalog)); -} - -// static -void Catalog::OnReadManifest(base::WeakPtr<Catalog> catalog, - const std::string& name, - const ResolveMojoNameCallback& callback, - scoped_ptr<ReadManifestResult> result) { - callback.Run(std::move(result ->resolve_result)); - if (catalog) { - catalog->AddEntryToCatalog( - std::move(result->catalog_entry), - result->package_dir == catalog->system_package_dir_); - } -} - -void Catalog::AddEntryToCatalog(scoped_ptr<Entry> entry, - bool is_system_catalog) { - DCHECK(entry); - EntryCache* catalog = is_system_catalog ? system_catalog_ : &user_catalog_; - if (catalog->end() != catalog->find(entry->name())) - return; - for (auto child : entry->applications()) - AddEntryToCatalog(make_scoped_ptr(child), is_system_catalog); - (*catalog)[entry->name()] = std::move(entry); - SerializeCatalog(); -} - -} // namespace catalog diff --git a/chromium/mojo/services/catalog/catalog.h b/chromium/mojo/services/catalog/catalog.h deleted file mode 100644 index 6e46120ab3f..00000000000 --- a/chromium/mojo/services/catalog/catalog.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_CATALOG_H_ -#define MOJO_SERVICES_CATALOG_CATALOG_H_ - -#include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" -#include "base/path_service.h" -#include "base/values.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/services/catalog/entry.h" -#include "mojo/services/catalog/public/interfaces/catalog.mojom.h" -#include "mojo/services/catalog/public/interfaces/resolver.mojom.h" -#include "mojo/services/catalog/store.h" -#include "mojo/services/catalog/types.h" -#include "mojo/shell/public/cpp/interface_factory.h" -#include "mojo/shell/public/interfaces/shell_resolver.mojom.h" - -namespace catalog { - -class ManifestProvider; -class Store; - -struct ReadManifestResult { - ReadManifestResult(); - ~ReadManifestResult(); - mojo::shell::mojom::ResolveResultPtr resolve_result; - scoped_ptr<Entry> catalog_entry; - base::FilePath package_dir; -}; - -class Catalog : public mojom::Resolver, - public mojo::shell::mojom::ShellResolver, - public mojom::Catalog { - public: - // |manifest_provider| may be null. - Catalog(scoped_ptr<Store> store, - base::TaskRunner* file_task_runner, - EntryCache* system_catalog, - ManifestProvider* manifest_provider); - ~Catalog() override; - - void BindResolver(mojom::ResolverRequest request); - void BindShellResolver(mojo::shell::mojom::ShellResolverRequest request); - void BindCatalog(mojom::CatalogRequest request); - - private: - using MojoNameAliasMap = - std::map<std::string, std::pair<std::string, std::string>>; - - // mojom::Resolver: - void ResolveInterfaces(mojo::Array<mojo::String> interfaces, - const ResolveInterfacesCallback& callback) override; - void ResolveMIMEType(const mojo::String& mime_type, - const ResolveMIMETypeCallback& callback) override; - void ResolveProtocolScheme( - const mojo::String& scheme, - const ResolveProtocolSchemeCallback& callback) override; - - // mojo::shell::mojom::ShellResolver: - void ResolveMojoName(const mojo::String& mojo_name, - const ResolveMojoNameCallback& callback) override; - - // mojom::Catalog: - void GetEntries(mojo::Array<mojo::String> names, - const GetEntriesCallback& callback) override; - - // Populate/serialize the catalog from/to the supplied store. - void DeserializeCatalog(); - void SerializeCatalog(); - - // Receives the result of manifest parsing on |file_task_runner_|, may be - // received after the catalog object that issued the request is destroyed. - static void OnReadManifest(base::WeakPtr<Catalog> catalog, - const std::string& name, - const ResolveMojoNameCallback& callback, - scoped_ptr<ReadManifestResult> result); - - // Populate the catalog with data from |entry|, and pass it to the client - // via callback. - void AddEntryToCatalog(scoped_ptr<Entry> entry, bool is_system_catalog); - - ManifestProvider* const manifest_provider_; - - // Directory that contains packages and executables visible to all users. - base::FilePath system_package_dir_; - // Directory that contains packages visible to this Catalog instance's user. - base::FilePath user_package_dir_; - - // User-specific persistent storage of package manifests and other settings. - scoped_ptr<Store> store_; - - // Task runner for performing file operations. - base::TaskRunner* const file_task_runner_; - - mojo::BindingSet<mojom::Resolver> resolver_bindings_; - mojo::BindingSet<mojo::shell::mojom::ShellResolver> shell_resolver_bindings_; - mojo::BindingSet<mojom::Catalog> catalog_bindings_; - - // The current user's packages, constructed from Store/package manifests. - EntryCache user_catalog_; - // Same as above, but for system-level (visible to all-users) packages and - // executables. - EntryCache* system_catalog_; - - base::WeakPtrFactory<Catalog> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Catalog); -}; - -} // namespace catalog - -#endif // MOJO_SERVICES_CATALOG_CATALOG_H_ diff --git a/chromium/mojo/services/catalog/data/capabilities b/chromium/mojo/services/catalog/data/capabilities deleted file mode 100644 index 92649b2817f..00000000000 --- a/chromium/mojo/services/catalog/data/capabilities +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "mojo:foo", - "display_name": "Foo", - "process-group": "bar", - "capabilities": { - "mojo:bar": ["mojo::Bar"] - } -} diff --git a/chromium/mojo/services/catalog/data/instance b/chromium/mojo/services/catalog/data/instance deleted file mode 100644 index 41cc63d6991..00000000000 --- a/chromium/mojo/services/catalog/data/instance +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "mojo:foo", - "display_name": "Foo", - "process-group": "bar", - "capabilities": {} -} diff --git a/chromium/mojo/services/catalog/data/malformed b/chromium/mojo/services/catalog/data/malformed deleted file mode 100644 index 838a990f170..00000000000 --- a/chromium/mojo/services/catalog/data/malformed +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "mojo:foo", - "display_name": "Foo", - "process-group": "bar", diff --git a/chromium/mojo/services/catalog/data/serialization b/chromium/mojo/services/catalog/data/serialization deleted file mode 100644 index 460570289e2..00000000000 --- a/chromium/mojo/services/catalog/data/serialization +++ /dev/null @@ -1,18 +0,0 @@ -{ - "manifest_version": 1, - "name": "mojo:foo", - "display_name": "Foo", - "process-group": "bar", - "capabilities": { - "provided": { - "foo": ["mojo::Bar", "mojo::Baz"], - "bar": ["mojo::Bork"] - }, - "required": { - "mojo:bar": { - "classes": ["a", "b"], - "interfaces": ["mojo::Blork", "mojo::Blark"] - } - } - } -} diff --git a/chromium/mojo/services/catalog/data/simple b/chromium/mojo/services/catalog/data/simple deleted file mode 100644 index cb60e67b961..00000000000 --- a/chromium/mojo/services/catalog/data/simple +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "mojo:foo", - "display_name": "Foo", - "capabilities": {} -} diff --git a/chromium/mojo/services/catalog/entry.cc b/chromium/mojo/services/catalog/entry.cc deleted file mode 100644 index ace280f1d26..00000000000 --- a/chromium/mojo/services/catalog/entry.cc +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2016 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/services/catalog/entry.h" - -#include "base/values.h" -#include "mojo/services/catalog/store.h" -#include "mojo/shell/public/cpp/names.h" -#include "mojo/util/filename_util.h" -#include "url/gurl.h" - -namespace catalog { -namespace { - -mojo::CapabilitySpec BuildCapabilitiesV0( - const base::DictionaryValue& value) { - mojo::CapabilitySpec capabilities; - base::DictionaryValue::Iterator it(value); - for (; !it.IsAtEnd(); it.Advance()) { - const base::ListValue* values = nullptr; - CHECK(it.value().GetAsList(&values)); - mojo::CapabilityRequest spec; - for (auto i = values->begin(); i != values->end(); ++i) { - mojo::Interface interface_name; - const base::Value* v = *i; - CHECK(v->GetAsString(&interface_name)); - spec.interfaces.insert(interface_name); - } - capabilities.required[it.key()] = spec; - } - return capabilities; -} - -void ReadStringSet(const base::ListValue& list_value, - std::set<std::string>* string_set) { - DCHECK(string_set); - for (auto i = list_value.begin(); i != list_value.end(); ++i) { - std::string value; - const base::Value* value_value = *i; - CHECK(value_value->GetAsString(&value)); - string_set->insert(value); - } -} - -void ReadStringSetFromValue(const base::Value& value, - std::set<std::string>* string_set) { - const base::ListValue* list_value = nullptr; - CHECK(value.GetAsList(&list_value)); - ReadStringSet(*list_value, string_set); -} - -void ReadStringSetFromDictionary(const base::DictionaryValue& dictionary, - const std::string& key, - std::set<std::string>* string_set) { - const base::ListValue* list_value = nullptr; - if (dictionary.HasKey(key)) - CHECK(dictionary.GetList(key, &list_value)); - if (list_value) - ReadStringSet(*list_value, string_set); -} - -mojo::CapabilitySpec BuildCapabilitiesV1( - const base::DictionaryValue& value) { - mojo::CapabilitySpec capabilities; - - const base::DictionaryValue* provided_value = nullptr; - if (value.HasKey(Store::kCapabilities_ProvidedKey)) { - CHECK(value.GetDictionary(Store::kCapabilities_ProvidedKey, - &provided_value)); - } - if (provided_value) { - mojo::CapabilityRequest provided; - base::DictionaryValue::Iterator it(*provided_value); - for(; !it.IsAtEnd(); it.Advance()) { - mojo::Interfaces interfaces; - ReadStringSetFromValue(it.value(), &interfaces); - capabilities.provided[it.key()] = interfaces; - } - } - - const base::DictionaryValue* required_value = nullptr; - if (value.HasKey(Store::kCapabilities_RequiredKey)) { - CHECK(value.GetDictionary(Store::kCapabilities_RequiredKey, - &required_value)); - } - if (required_value) { - base::DictionaryValue::Iterator it(*required_value); - for (; !it.IsAtEnd(); it.Advance()) { - mojo::CapabilityRequest spec; - const base::DictionaryValue* entry_value = nullptr; - CHECK(it.value().GetAsDictionary(&entry_value)); - ReadStringSetFromDictionary( - *entry_value, Store::kCapabilities_ClassesKey, &spec.classes); - ReadStringSetFromDictionary( - *entry_value, Store::kCapabilities_InterfacesKey, &spec.interfaces); - capabilities.required[it.key()] = spec; - } - } - return capabilities; -} - -} // namespace - -Entry::Entry() {} -Entry::Entry(const std::string& name) - : name_(name), - qualifier_(mojo::GetNamePath(name)), - display_name_(name) {} -Entry::Entry(const Entry& other) = default; -Entry::~Entry() {} - -scoped_ptr<base::DictionaryValue> Entry::Serialize() const { - scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue); - value->SetInteger(Store::kManifestVersionKey, 1); - value->SetString(Store::kNameKey, name_); - value->SetString(Store::kDisplayNameKey, display_name_); - value->SetString(Store::kQualifierKey, qualifier_); - scoped_ptr<base::DictionaryValue> spec(new base::DictionaryValue); - - scoped_ptr<base::DictionaryValue> provided(new base::DictionaryValue); - for (const auto& i : capabilities_.provided) { - scoped_ptr<base::ListValue> interfaces(new base::ListValue); - for (const auto& interface_name : i.second) - interfaces->AppendString(interface_name); - provided->Set(i.first, std::move(interfaces)); - } - spec->Set(Store::kCapabilities_ProvidedKey, std::move(provided)); - - scoped_ptr<base::DictionaryValue> required(new base::DictionaryValue); - for (const auto& i : capabilities_.required) { - scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue); - scoped_ptr<base::ListValue> classes(new base::ListValue); - for (const auto& class_name : i.second.classes) - classes->AppendString(class_name); - request->Set(Store::kCapabilities_ClassesKey, std::move(classes)); - scoped_ptr<base::ListValue> interfaces(new base::ListValue); - for (const auto& interface_name : i.second.interfaces) - interfaces->AppendString(interface_name); - request->Set(Store::kCapabilities_InterfacesKey, std::move(interfaces)); - required->Set(i.first, std::move(request)); - } - spec->Set(Store::kCapabilities_RequiredKey, std::move(required)); - - value->Set(Store::kCapabilitiesKey, std::move(spec)); - return value; -} - -// static -scoped_ptr<Entry> Entry::Deserialize(const base::DictionaryValue& value) { - scoped_ptr<Entry> entry(new Entry); - int manifest_version = 0; - if (value.HasKey(Store::kManifestVersionKey)) - CHECK(value.GetInteger(Store::kManifestVersionKey, &manifest_version)); - std::string name_string; - if (!value.GetString(Store::kNameKey, &name_string)) { - LOG(ERROR) << "Entry::Deserialize: dictionary has no name key"; - return nullptr; - } - if (!mojo::IsValidName(name_string)) { - LOG(WARNING) << "Entry::Deserialize: " << name_string << " is not a valid " - << "Mojo name"; - return nullptr; - } - entry->set_name(name_string); - if (value.HasKey(Store::kQualifierKey)) { - std::string qualifier; - CHECK(value.GetString(Store::kQualifierKey, &qualifier)); - entry->set_qualifier(qualifier); - } else { - entry->set_qualifier(mojo::GetNamePath(name_string)); - } - std::string display_name; - if (!value.GetString(Store::kDisplayNameKey, &display_name)) { - LOG(WARNING) << "Entry::Deserialize: dictionary has no display_name key"; - return nullptr; - } - entry->set_display_name(display_name); - const base::DictionaryValue* capabilities = nullptr; - if (!value.GetDictionary(Store::kCapabilitiesKey, &capabilities)) { - LOG(WARNING) << "Entry::Description: dictionary has no capabilities key"; - return nullptr; - } - if (manifest_version == 0) - entry->set_capabilities(BuildCapabilitiesV0(*capabilities)); - else - entry->set_capabilities(BuildCapabilitiesV1(*capabilities)); - - if (value.HasKey(Store::kApplicationsKey)) { - const base::ListValue* applications = nullptr; - value.GetList(Store::kApplicationsKey, &applications); - for (size_t i = 0; i < applications->GetSize(); ++i) { - const base::DictionaryValue* application = nullptr; - applications->GetDictionary(i, &application); - scoped_ptr<Entry> child = Entry::Deserialize(*application); - if (child) { - child->set_package(entry.get()); - // Caller must assume ownership of these items. - entry->applications_.insert(child.release()); - } - } - } - - return entry; -} - -bool Entry::operator==(const Entry& other) const { - return other.name_ == name_ && other.qualifier_ == qualifier_ && - other.display_name_ == display_name_ && - other.capabilities_ == capabilities_; -} - -bool Entry::operator<(const Entry& other) const { - return std::tie(name_, qualifier_, display_name_, capabilities_) < - std::tie(other.name_, other.qualifier_, other.display_name_, - other.capabilities_); -} - -} // catalog - -namespace mojo { - -// static -shell::mojom::ResolveResultPtr - TypeConverter<shell::mojom::ResolveResultPtr, catalog::Entry>::Convert( - const catalog::Entry& input) { - shell::mojom::ResolveResultPtr result(shell::mojom::ResolveResult::New()); - result->name = input.name(); - const catalog::Entry& package = input.package() ? *input.package() : input; - result->resolved_name = package.name(); - result->qualifier = input.qualifier(); - result->capabilities = - shell::mojom::CapabilitySpec::From(input.capabilities()); - result->package_url = mojo::util::FilePathToFileURL(package.path()).spec(); - return result; -} - -} // namespace mojo diff --git a/chromium/mojo/services/catalog/entry.h b/chromium/mojo/services/catalog/entry.h deleted file mode 100644 index 05f616d1459..00000000000 --- a/chromium/mojo/services/catalog/entry.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_ENTRY_H_ -#define MOJO_SERVICES_CATALOG_ENTRY_H_ - -#include <set> -#include <string> - -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/shell/public/cpp/capabilities.h" - -namespace base { -class DictionaryValue; -} - -namespace catalog { - -// Static information about an application package known to the Catalog. -class Entry { - public: - Entry(); - explicit Entry(const std::string& name); - explicit Entry(const Entry& other); - ~Entry(); - - scoped_ptr<base::DictionaryValue> Serialize() const; - - // If the constructed Entry is a package that provides other Entrys, the - // caller must assume ownership of the tree of Entrys by enumerating - // applications(). - static scoped_ptr<Entry> Deserialize(const base::DictionaryValue& value); - - bool operator==(const Entry& other) const; - bool operator<(const Entry& other) const; - - const std::string& name() const { return name_; } - void set_name(const std::string& name) { name_ = name; } - const base::FilePath& path() const { return path_; } - void set_path(const base::FilePath& path) { path_ = path; } - const std::string& qualifier() const { return qualifier_; } - void set_qualifier(const std::string& qualifier) { qualifier_ = qualifier; } - const std::string& display_name() const { return display_name_; } - void set_display_name(const std::string& display_name) { - display_name_ = display_name; - } - const mojo::CapabilitySpec& capabilities() const { return capabilities_; } - void set_capabilities(const mojo::CapabilitySpec& capabilities) { - capabilities_ = capabilities; - } - const Entry* package() const { return package_; } - void set_package(Entry* package) { package_ = package; } - const std::set<Entry*>& applications() { return applications_; } - - private: - std::string name_; - base::FilePath path_; - std::string qualifier_; - std::string display_name_; - mojo::CapabilitySpec capabilities_; - Entry* package_ = nullptr; - std::set<Entry*> applications_; -}; - -} // namespace catalog - -namespace mojo { -template <> -struct TypeConverter<shell::mojom::ResolveResultPtr, catalog::Entry> { - static shell::mojom::ResolveResultPtr Convert(const catalog::Entry& input); -}; -} - -#endif // MOJO_SERVICES_CATALOG_ENTRY_H_ diff --git a/chromium/mojo/services/catalog/entry_unittest.cc b/chromium/mojo/services/catalog/entry_unittest.cc deleted file mode 100644 index c59e3c2d637..00000000000 --- a/chromium/mojo/services/catalog/entry_unittest.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2016 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/services/catalog/entry.h" - -#include "base/files/file_path.h" -#include "base/json/json_file_value_serializer.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "base/values.h" -#include "mojo/shell/public/cpp/capabilities.h" -#include "mojo/shell/public/cpp/names.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace catalog { - -class EntryTest : public testing::Test { - public: - EntryTest() {} - ~EntryTest() override {} - - protected: - scoped_ptr<Entry> ReadEntry(const std::string& manifest, - scoped_ptr<base::Value>* out_value) { - scoped_ptr<base::Value> value = ReadManifest(manifest); - base::DictionaryValue* dictionary = nullptr; - CHECK(value->GetAsDictionary(&dictionary)); - if (out_value) - *out_value = std::move(value); - return Entry::Deserialize(*dictionary); - } - - scoped_ptr<base::Value> ReadManifest(const std::string& manifest) { - base::FilePath manifest_path; - PathService::Get(base::DIR_SOURCE_ROOT, &manifest_path); - manifest_path = manifest_path.AppendASCII( - "mojo/services/catalog/data/" + manifest); - - JSONFileValueDeserializer deserializer(manifest_path); - int error = 0; - std::string message; - // TODO(beng): probably want to do more detailed error checking. This should - // be done when figuring out if to unblock connection - // completion. - return deserializer.Deserialize(&error, &message); - } - - private: - void SetUp() override {} - void TearDown() override {} - - DISALLOW_COPY_AND_ASSIGN(EntryTest); -}; - -TEST_F(EntryTest, Simple) { - scoped_ptr<Entry> entry = ReadEntry("simple", nullptr); - EXPECT_EQ("mojo:foo", entry->name()); - EXPECT_EQ(mojo::GetNamePath(entry->name()), entry->qualifier()); - EXPECT_EQ("Foo", entry->display_name()); -} - -TEST_F(EntryTest, Instance) { - scoped_ptr<Entry> entry = ReadEntry("instance", nullptr); - EXPECT_EQ("mojo:foo", entry->name()); - EXPECT_EQ("bar", entry->qualifier()); - EXPECT_EQ("Foo", entry->display_name()); -} - -TEST_F(EntryTest, Capabilities) { - scoped_ptr<Entry> entry = ReadEntry("capabilities", nullptr); - - EXPECT_EQ("mojo:foo", entry->name()); - EXPECT_EQ("bar", entry->qualifier()); - EXPECT_EQ("Foo", entry->display_name()); - mojo::CapabilitySpec spec; - mojo::CapabilityRequest request; - request.interfaces.insert("mojo::Bar"); - spec.required["mojo:bar"] = request; - EXPECT_EQ(spec, entry->capabilities()); -} - -TEST_F(EntryTest, Serialization) { - scoped_ptr<base::Value> value; - scoped_ptr<Entry> entry = ReadEntry("serialization", &value); - - scoped_ptr<base::DictionaryValue> serialized(entry->Serialize()); - - // We can't just compare values, since during deserialization some of the - // lists get converted to std::sets, which are sorted, so Value::Equals will - // fail. - scoped_ptr<Entry> reconstituted = Entry::Deserialize(*serialized.get()); - EXPECT_EQ(*entry, *reconstituted); -} - -TEST_F(EntryTest, Malformed) { - scoped_ptr<base::Value> value = ReadManifest("malformed"); - EXPECT_FALSE(value.get()); -} - - -} // namespace catalog diff --git a/chromium/mojo/services/catalog/factory.cc b/chromium/mojo/services/catalog/factory.cc deleted file mode 100644 index 89972ea8ec3..00000000000 --- a/chromium/mojo/services/catalog/factory.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 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/services/catalog/factory.h" - -#include "base/bind.h" -#include "mojo/services/catalog/catalog.h" -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/shell_connection.h" - -namespace catalog { - -Factory::Factory(base::TaskRunner* file_task_runner, - scoped_ptr<Store> store, - ManifestProvider* manifest_provider) - : file_task_runner_(file_task_runner), - store_(std::move(store)), - manifest_provider_(manifest_provider), - weak_factory_(this) { - mojo::shell::mojom::ShellClientRequest request = GetProxy(&shell_client_); - shell_connection_.reset(new mojo::ShellConnection(this, std::move(request))); -} - -Factory::~Factory() {} - -mojo::shell::mojom::ShellClientPtr Factory::TakeShellClient() { - return std::move(shell_client_); -} - -bool Factory::AcceptConnection(mojo::Connection* connection) { - connection->AddInterface<mojom::Catalog>(this); - connection->AddInterface<mojom::Resolver>(this); - connection->AddInterface<mojo::shell::mojom::ShellResolver>(this); - return true; -} - -void Factory::Create(mojo::Connection* connection, - mojom::ResolverRequest request) { - Catalog* instance = - GetCatalogForUserId(connection->GetRemoteIdentity().user_id()); - instance->BindResolver(std::move(request)); -} - -void Factory::Create(mojo::Connection* connection, - mojo::shell::mojom::ShellResolverRequest request) { - Catalog* instance = - GetCatalogForUserId(connection->GetRemoteIdentity().user_id()); - instance->BindShellResolver(std::move(request)); -} - -void Factory::Create(mojo::Connection* connection, - mojom::CatalogRequest request) { - Catalog* instance = - GetCatalogForUserId(connection->GetRemoteIdentity().user_id()); - instance->BindCatalog(std::move(request)); -} - -Catalog* Factory::GetCatalogForUserId(const std::string& user_id) { - auto it = catalogs_.find(user_id); - if (it != catalogs_.end()) - return it->second.get(); - - // TODO(beng): There needs to be a way to load the store from different users. - Catalog* instance = new Catalog(std::move(store_), file_task_runner_, - &system_catalog_, manifest_provider_); - catalogs_[user_id] = make_scoped_ptr(instance); - return instance; -} - -} // namespace catalog diff --git a/chromium/mojo/services/catalog/factory.h b/chromium/mojo/services/catalog/factory.h deleted file mode 100644 index a21200b3c2d..00000000000 --- a/chromium/mojo/services/catalog/factory.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_FACTORY_H_ -#define MOJO_SERVICES_CATALOG_FACTORY_H_ - -#include <map> -#include <string> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/services/catalog/public/interfaces/catalog.mojom.h" -#include "mojo/services/catalog/public/interfaces/resolver.mojom.h" -#include "mojo/services/catalog/types.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" -#include "mojo/shell/public/interfaces/shell_resolver.mojom.h" - -namespace base { -class TaskRunner; -} - -namespace mojo{ -class ShellConnection; -} - -namespace catalog { - -class Catalog; -class ManifestProvider; -class Store; - -// Creates and owns an instance of the catalog. Exposes a ShellClientPtr that -// can be passed to the Shell, potentially in a different process. -class Factory - : public mojo::ShellClient, - public mojo::InterfaceFactory<mojom::Catalog>, - public mojo::InterfaceFactory<mojom::Resolver>, - public mojo::InterfaceFactory<mojo::shell::mojom::ShellResolver> { - public: - // |manifest_provider| may be null. - Factory(base::TaskRunner* file_task_runner, - scoped_ptr<Store> store, - ManifestProvider* manifest_provider); - ~Factory() override; - - mojo::shell::mojom::ShellClientPtr TakeShellClient(); - - private: - // mojo::ShellClient: - bool AcceptConnection(mojo::Connection* connection) override; - - // mojo::InterfaceFactory<mojom::Resolver>: - void Create(mojo::Connection* connection, - mojom::ResolverRequest request) override; - - // mojo::InterfaceFactory<mojo::shell::mojom::ShellResolver>: - void Create(mojo::Connection* connection, - mojo::shell::mojom::ShellResolverRequest request) override; - - // mojo::InterfaceFactory<mojom::Catalog>: - void Create(mojo::Connection* connection, - mojom::CatalogRequest request) override; - - Catalog* GetCatalogForUserId(const std::string& user_id); - - base::TaskRunner* const file_task_runner_; - scoped_ptr<Store> store_; - ManifestProvider* const manifest_provider_; - - mojo::shell::mojom::ShellClientPtr shell_client_; - scoped_ptr<mojo::ShellConnection> shell_connection_; - - std::map<std::string, scoped_ptr<Catalog>> catalogs_; - - EntryCache system_catalog_; - - base::WeakPtrFactory<Factory> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Factory); -}; - -} // namespace catalog - -#endif // MOJO_SERVICES_CATALOG_FACTORY_H_ diff --git a/chromium/mojo/services/catalog/manifest.json b/chromium/mojo/services/catalog/manifest.json deleted file mode 100644 index 770cc26f2d8..00000000000 --- a/chromium/mojo/services/catalog/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "manifest_version": 1, - "name": "mojo:catalog", - "display_name": "Catalog", - "capabilities": { - "required": { - "mojo:shell": { "classes": [ "all_users" ] } - } - } -} diff --git a/chromium/mojo/services/catalog/manifest_provider.h b/chromium/mojo/services/catalog/manifest_provider.h deleted file mode 100644 index f3cf1018cc0..00000000000 --- a/chromium/mojo/services/catalog/manifest_provider.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_MANIFEST_PROVIDER_H_ -#define MOJO_SERVICES_CATALOG_MANIFEST_PROVIDER_H_ - -#include <string> - -#include "base/strings/string_piece.h" - -namespace catalog { - -// An interface which can be implemented by a catalog embedder to override -// manifest fetching behavior. -class ManifestProvider { - public: - virtual ~ManifestProvider() {} - - // Retrieves the raw contents of the manifest for application named |name|. - // Returns true if |name| is known and |*manifest_contents| is populated. - // returns false otherwise. - virtual bool GetApplicationManifest(const base::StringPiece& name, - std::string* manifest_contents) = 0; -}; - -} // namespace catalog - -#endif // MOJO_SERVICES_CATALOG_MANIFEST_PROVIDER_H_ diff --git a/chromium/mojo/services/catalog/public/interfaces/BUILD.gn b/chromium/mojo/services/catalog/public/interfaces/BUILD.gn deleted file mode 100644 index 068a2fe0fdf..00000000000 --- a/chromium/mojo/services/catalog/public/interfaces/BUILD.gn +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2016 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("//mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "catalog.mojom", - "resolver.mojom", - ] - - import_dirs = [ "//mojo/services" ] - - deps = [ - "//mojo/shell/public/interfaces", - ] -} diff --git a/chromium/mojo/services/catalog/public/interfaces/catalog.mojom b/chromium/mojo/services/catalog/public/interfaces/catalog.mojom deleted file mode 100644 index ab95fa026a2..00000000000 --- a/chromium/mojo/services/catalog/public/interfaces/catalog.mojom +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 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 catalog.mojom; - -struct CatalogEntry { - string display_name; -}; - -interface Catalog { - // If |names| is null, all available entries are returned. - GetEntries(array<string>? names) => (map<string, CatalogEntry> entries); -}; diff --git a/chromium/mojo/services/catalog/public/interfaces/resolver.mojom b/chromium/mojo/services/catalog/public/interfaces/resolver.mojom deleted file mode 100644 index 0faf7e1b015..00000000000 --- a/chromium/mojo/services/catalog/public/interfaces/resolver.mojom +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 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 catalog.mojom; - -// Resolves various things to Mojo names that can be passed to mojo::Shell's -// ConnectToApplication(). -interface Resolver { - // Returns the mojo: name of the service that exports to the caller every - // interface in |interfaces|. - ResolveInterfaces(array<string> interfaces) => (string resolved_mojo_name); - - // Returns the mojo: name of the service that will handle content of type - // |mime_type|. - ResolveMIMEType(string mime_type) => (string resolved_mojo_name); - - // Called to return - ResolveProtocolScheme(string protocol_scheme) => (string resolved_mojo_name); -}; diff --git a/chromium/mojo/services/catalog/store.cc b/chromium/mojo/services/catalog/store.cc deleted file mode 100644 index 6c1a6d6ec70..00000000000 --- a/chromium/mojo/services/catalog/store.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 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/services/catalog/store.h" - -namespace catalog { - -// static -const char Store::kManifestVersionKey[] = "manifest_version"; -// static -const char Store::kNameKey[] = "name"; -// static -const char Store::kQualifierKey[] = "process-group"; -// static -const char Store::kDisplayNameKey[] = "display_name"; -// static -const char Store::kCapabilitiesKey[] = "capabilities"; -// static -const char Store::kCapabilities_ProvidedKey[] = "provided"; -// static -const char Store::kCapabilities_RequiredKey[] = "required"; -// static -const char Store::kCapabilities_ClassesKey[] = "classes"; -// static -const char Store::kCapabilities_InterfacesKey[] = "interfaces"; -// static -const char Store::kApplicationsKey[] = "applications"; - -} // namespace catalog diff --git a/chromium/mojo/services/catalog/store.h b/chromium/mojo/services/catalog/store.h deleted file mode 100644 index 4ebdaeab970..00000000000 --- a/chromium/mojo/services/catalog/store.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_STORE_H_ -#define MOJO_SERVICES_CATALOG_STORE_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/values.h" - -namespace catalog { - -// Implemented by an object that provides storage for the application catalog -// (e.g. in Chrome, preferences). The Catalog is the canonical owner of the -// contents of the store, so no one else must modify its contents. -class Store { - public: - // Value is an integer. - static const char kManifestVersionKey[]; - // Value is a string. - static const char kNameKey[]; - // Value is a string. - static const char kQualifierKey[]; - // Value is a string. - static const char kDisplayNameKey[]; - // Value is a dictionary. - static const char kCapabilitiesKey[]; - // Value is a dictionary. - static const char kCapabilities_ProvidedKey[]; - // Value is a dictionary. - static const char kCapabilities_RequiredKey[]; - // Value is a list. - static const char kCapabilities_ClassesKey[]; - // Value is a list. - static const char kCapabilities_InterfacesKey[]; - // Value is a list. - static const char kApplicationsKey[]; - - virtual ~Store() {} - - // Called during initialization to construct the Catalog's catalog. - // Returns a serialized list of the apps. Each entry in the returned list - // corresponds to an app (as a dictionary). Each dictionary has a name, - // display name and capabilities. The return value is owned by the caller. - virtual const base::ListValue* GetStore() = 0; - - // Write the catalog to the store. Called when the Catalog learns of a newly - // encountered application. - virtual void UpdateStore(scoped_ptr<base::ListValue> store) = 0; -}; - -} // namespace catalog - -#endif // MOJO_SERVICES_CATALOG_STORE_H_ diff --git a/chromium/mojo/services/catalog/types.h b/chromium/mojo/services/catalog/types.h deleted file mode 100644 index 1be44d5b065..00000000000 --- a/chromium/mojo/services/catalog/types.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_CATALOG_TYPES_H_ -#define MOJO_SERVICES_CATALOG_TYPES_H_ - -#include <map> -#include <string> - -#include "base/memory/scoped_ptr.h" - -namespace catalog { - -class Entry; - -// A map of mojo names -> catalog |Entry|s. -using EntryCache = std::map<std::string, scoped_ptr<Entry>>; - -} // namespace catalog - -#endif // MOJO_SERVICES_CATALOG_TYPES_H_ diff --git a/chromium/mojo/services/public/build/config/BUILD.gn b/chromium/mojo/services/public/build/config/BUILD.gn deleted file mode 100644 index c6b13b6d501..00000000000 --- a/chromium/mojo/services/public/build/config/BUILD.gn +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# The absolute path to the directory containing the Mojo services produced -# out of Chromium. -mojo_services_root = get_path_info("../../..", "abspath") - -# NOTE: This config name must be in sync with the name of the config used by -# services that developed out of the Mojo repo so that Chromium's services' -# BUILD.gn files can work seamlessly in Chromium and when pulled into Mojo or a -# client repo. -config("mojo_services") { - include_dirs = [ - # Include paths in Chromium Mojo services' client-side code are specified - # relative to the directory holding the services' client-side code. - mojo_services_root, - - # The same goes for files generated from mojoms. - root_gen_dir + mojo_services_root, - ] -} diff --git a/chromium/mojo/services/tracing/BUILD.gn b/chromium/mojo/services/tracing/BUILD.gn deleted file mode 100644 index 6a417e7a49f..00000000000 --- a/chromium/mojo/services/tracing/BUILD.gn +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") -import("//mojo/public/mojo_application_manifest.gni") - -mojo_native_application("tracing") { - sources = [ - "main.cc", - ] - - avoid_runner_cycle = true - - deps = [ - ":lib", - "//mojo/public/cpp/system", - "//mojo/shell/public/cpp", - ] - - data_deps = [ - ":manifest", - ] -} - -mojo_application_manifest("manifest") { - application_name = "tracing" - source = "manifest.json" -} - -source_set("lib") { - sources = [ - "trace_data_sink.cc", - "trace_data_sink.h", - "trace_recorder_impl.cc", - "trace_recorder_impl.h", - "tracing_app.cc", - "tracing_app.h", - ] - - deps = [ - "//base", - "//mojo/common:common_base", - "//mojo/services/tracing/public/interfaces", - "//mojo/shell/public/cpp", - ] -} diff --git a/chromium/mojo/services/tracing/DEPS b/chromium/mojo/services/tracing/DEPS deleted file mode 100644 index 72513eb4a8e..00000000000 --- a/chromium/mojo/services/tracing/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+mojo/shell", -] diff --git a/chromium/mojo/services/tracing/main.cc b/chromium/mojo/services/tracing/main.cc deleted file mode 100644 index b3d7e2742f3..00000000000 --- a/chromium/mojo/services/tracing/main.cc +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/c/system/main.h" -#include "mojo/services/tracing/tracing_app.h" -#include "mojo/shell/public/cpp/application_runner.h" - -MojoResult MojoMain(MojoHandle shell_handle) { - mojo::ApplicationRunner runner(new tracing::TracingApp); - return runner.Run(shell_handle); -} diff --git a/chromium/mojo/services/tracing/manifest.json b/chromium/mojo/services/tracing/manifest.json deleted file mode 100644 index adbdc588297..00000000000 --- a/chromium/mojo/services/tracing/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "manifest_version": 1, - "name": "mojo:tracing", - "display_name": "Tracing Collector", - "capabilities": { - "required": { - "mojo:shell": { "classes": [ "all_users" ] } - } - } -} diff --git a/chromium/mojo/services/tracing/public/cpp/BUILD.gn b/chromium/mojo/services/tracing/public/cpp/BUILD.gn deleted file mode 100644 index 38b3cfec9da..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/BUILD.gn +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("cpp") { - sources = [ - "switches.cc", - "switches.h", - "trace_provider_impl.cc", - "trace_provider_impl.h", - "tracing_impl.cc", - "tracing_impl.h", - ] - - deps = [ - "//base", - "//mojo/public/cpp/bindings", - "//mojo/services/tracing/public/interfaces", - "//mojo/shell/public/cpp", - ] -} diff --git a/chromium/mojo/services/tracing/public/cpp/switches.cc b/chromium/mojo/services/tracing/public/cpp/switches.cc deleted file mode 100644 index 1b838e6464c..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/switches.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/public/cpp/switches.h" - -namespace tracing { - -// Specifies if the |StatsCollectionController| needs to be bound in html pages. -// This binding happens on per-frame basis and hence can potentially be a -// performance bottleneck. One should only enable it when running a test that -// needs to access the provided statistics. -const char kEnableStatsCollectionBindings[] = - "enable-stats-collection-bindings"; - -const char kTraceStartup[] = "trace-startup"; - -#ifdef NDEBUG -const char kEarlyTracing[] = "early-tracing"; -#endif - -} // namespace tracing diff --git a/chromium/mojo/services/tracing/public/cpp/switches.h b/chromium/mojo/services/tracing/public/cpp/switches.h deleted file mode 100644 index 8a1e5125466..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/switches.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_PUBLIC_CPP_SWITCHES_H_ -#define MOJO_SERVICES_TRACING_PUBLIC_CPP_SWITCHES_H_ - -namespace tracing { - -// All switches in alphabetical order. The switches should be documented -// alongside the definition of their values in the .cc file. -extern const char kEnableStatsCollectionBindings[]; - -extern const char kTraceStartup[]; - -#ifdef NDEBUG -// In release builds, specifying this flag will force reporting of tracing -// before the main Application is initialized. -extern const char kEarlyTracing[]; -#endif - -} // namespace tracing - -#endif // MOJO_SERVICES_TRACING_PUBLIC_CPP_SWITCHES_H_ diff --git a/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.cc b/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.cc deleted file mode 100644 index ea6c8f43a61..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/public/cpp/trace_provider_impl.h" - -#include <utility> - -#include "base/callback.h" -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_event.h" -#include "mojo/shell/public/cpp/connection.h" - -namespace mojo { - -TraceProviderImpl::TraceProviderImpl() - : binding_(this), tracing_forced_(false), weak_factory_(this) {} - -TraceProviderImpl::~TraceProviderImpl() { - StopTracing(); -} - -void TraceProviderImpl::Bind(InterfaceRequest<tracing::TraceProvider> request) { - if (!binding_.is_bound()) { - binding_.Bind(std::move(request)); - } else { - LOG(ERROR) << "Cannot accept two connections to TraceProvider."; - } -} - -void TraceProviderImpl::StartTracing(const String& categories, - tracing::TraceRecorderPtr recorder) { - DCHECK(!recorder_); - recorder_ = std::move(recorder); - tracing_forced_ = false; - if (!base::trace_event::TraceLog::GetInstance()->IsEnabled()) { - std::string categories_str = categories.To<std::string>(); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - base::trace_event::TraceConfig(categories_str, - base::trace_event::RECORD_UNTIL_FULL), - base::trace_event::TraceLog::RECORDING_MODE); - } -} - -void TraceProviderImpl::StopTracing() { - if (recorder_) { - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - - base::trace_event::TraceLog::GetInstance()->Flush( - base::Bind(&TraceProviderImpl::SendChunk, base::Unretained(this))); - } -} - -void TraceProviderImpl::ForceEnableTracing() { - base::trace_event::TraceLog::GetInstance()->SetEnabled( - base::trace_event::TraceConfig("*", base::trace_event::RECORD_UNTIL_FULL), - base::trace_event::TraceLog::RECORDING_MODE); - tracing_forced_ = true; - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&TraceProviderImpl::DelayedStop, weak_factory_.GetWeakPtr())); -} - -void TraceProviderImpl::DelayedStop() { - // We use this indirection to account for cases where the Initialize app - // method (within which TraceProviderImpl is created) takes more than one - // second to finish; thus we start the countdown only when the current thread - // is unblocked. - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&TraceProviderImpl::StopIfForced, weak_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(1)); -} - -void TraceProviderImpl::StopIfForced() { - if (!tracing_forced_) { - return; - } - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - base::trace_event::TraceLog::GetInstance()->Flush( - base::Callback<void(const scoped_refptr<base::RefCountedString>&, - bool)>()); -} - -void TraceProviderImpl::SendChunk( - const scoped_refptr<base::RefCountedString>& events_str, - bool has_more_events) { - DCHECK(recorder_); - // The string will be empty if an error eccured or there were no trace - // events. Empty string is not a valid chunk to record so skip in this case. - if (!events_str->data().empty()) { - recorder_->Record(mojo::String(events_str->data())); - } - if (!has_more_events) { - recorder_.reset(); - } -} - -} // namespace mojo diff --git a/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.h b/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.h deleted file mode 100644 index 5774911414f..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/trace_provider_impl.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACE_PROVIDER_IMPL_H_ -#define MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACE_PROVIDER_IMPL_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted_memory.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" - -namespace mojo { - -class TraceProviderImpl : public tracing::TraceProvider { - public: - TraceProviderImpl(); - ~TraceProviderImpl() override; - - void Bind(InterfaceRequest<tracing::TraceProvider> request); - - // Enable tracing without waiting for an inbound connection. It will stop if - // no TraceRecorder is sent within a set time. - void ForceEnableTracing(); - - private: - // tracing::TraceProvider implementation: - void StartTracing(const String& categories, - tracing::TraceRecorderPtr recorder) override; - void StopTracing() override; - - void SendChunk(const scoped_refptr<base::RefCountedString>& events_str, - bool has_more_events); - - void DelayedStop(); - // Stop the collection of traces if no external connection asked for them yet. - void StopIfForced(); - - Binding<tracing::TraceProvider> binding_; - bool tracing_forced_; - tracing::TraceRecorderPtr recorder_; - - base::WeakPtrFactory<TraceProviderImpl> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(TraceProviderImpl); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACE_PROVIDER_IMPL_H_ diff --git a/chromium/mojo/services/tracing/public/cpp/tracing_impl.cc b/chromium/mojo/services/tracing/public/cpp/tracing_impl.cc deleted file mode 100644 index e7a369c76bb..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/tracing_impl.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/public/cpp/tracing_impl.h" - -#include <utility> - -#include "base/lazy_instance.h" -#include "base/synchronization/lock.h" -#include "base/threading/platform_thread.h" -#include "base/trace_event/trace_event_impl.h" -#include "mojo/shell/public/cpp/connector.h" - -#ifdef NDEBUG -#include "base/command_line.h" -#include "mojo/services/tracing/public/cpp/switches.h" -#endif - -namespace mojo { -namespace { - -// Controls access to |g_tracing_singleton_created|, which can be accessed from -// different threads. -base::LazyInstance<base::Lock>::Leaky g_singleton_lock = - LAZY_INSTANCE_INITIALIZER; - -// Whether we are the first TracingImpl to be created in this mojo -// application. The first TracingImpl in a physical mojo application connects -// to the mojo:tracing service. -// -// If this is a ContentHandler, it will outlive all its served Applications. If -// this is a raw mojo application, it is the only Application served. -bool g_tracing_singleton_created = false; - -} - -TracingImpl::TracingImpl() { -} - -TracingImpl::~TracingImpl() { -} - -void TracingImpl::Initialize(Connector* connector, const std::string& url) { - { - base::AutoLock lock(g_singleton_lock.Get()); - if (g_tracing_singleton_created) - return; - g_tracing_singleton_created = true; - } - - // This will only set the name for the first app in a loaded mojo file. It's - // up to something like CoreServices to name its own child threads. - base::PlatformThread::SetName(url); - - connection_ = connector->Connect("mojo:tracing"); - connection_->AddInterface(this); - -#ifdef NDEBUG - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - tracing::kEarlyTracing)) { - provider_impl_.ForceEnableTracing(); - } -#else - provider_impl_.ForceEnableTracing(); -#endif -} - -void TracingImpl::Create(Connection* connection, - InterfaceRequest<tracing::TraceProvider> request) { - provider_impl_.Bind(std::move(request)); -} - -} // namespace mojo diff --git a/chromium/mojo/services/tracing/public/cpp/tracing_impl.h b/chromium/mojo/services/tracing/public/cpp/tracing_impl.h deleted file mode 100644 index a4e82ab606f..00000000000 --- a/chromium/mojo/services/tracing/public/cpp/tracing_impl.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACING_IMPL_H_ -#define MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACING_IMPL_H_ - -#include "base/macros.h" -#include "mojo/services/tracing/public/cpp/trace_provider_impl.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" -#include "mojo/shell/public/cpp/interface_factory.h" - -namespace mojo { - -class Connection; -class Connector; - -// Connects to mojo:tracing during your Application's Initialize() call once -// per process. -// -// We need to deal with multiple ways of packaging mojo applications -// together. We'll need to deal with packages that use the mojo.ContentHandler -// interface to bundle several Applciations into a single physical on disk -// mojo binary, and with those same services each in their own mojo binary. -// -// Have your bundle ContentHandler own a TracingImpl, and each Application own -// a TracingImpl. In bundles, the second TracingImpl will be a no-op. -class TracingImpl : public InterfaceFactory<tracing::TraceProvider> { - public: - TracingImpl(); - ~TracingImpl() override; - - // This connects to the tracing service and registers ourselves to provide - // tracing data on demand. - void Initialize(Connector* connector, const std::string& url); - - private: - // InterfaceFactory<tracing::TraceProvider> implementation. - void Create(Connection* connection, - InterfaceRequest<tracing::TraceProvider> request) override; - - scoped_ptr<Connection> connection_; - TraceProviderImpl provider_impl_; - - DISALLOW_COPY_AND_ASSIGN(TracingImpl); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_TRACING_PUBLIC_CPP_TRACING_IMPL_H_ diff --git a/chromium/mojo/services/tracing/public/interfaces/BUILD.gn b/chromium/mojo/services/tracing/public/interfaces/BUILD.gn deleted file mode 100644 index 8323805231a..00000000000 --- a/chromium/mojo/services/tracing/public/interfaces/BUILD.gn +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "tracing.mojom", - ] -} diff --git a/chromium/mojo/services/tracing/public/interfaces/tracing.mojom b/chromium/mojo/services/tracing/public/interfaces/tracing.mojom deleted file mode 100644 index b624f81e24f..00000000000 --- a/chromium/mojo/services/tracing/public/interfaces/tracing.mojom +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module tracing; - -// To participate in the tracing ecosystem, implement the TraceProvider -// interface and connect to the tracing app. Then, when the provider's Start() -// function is called collect tracing data and pass it back via the provided -// TraceRecorder interface up until Stop() is called. - -interface TraceProvider { - // Categories can either be the empty string to mean the default set of - // categories or a comma-delimited list of categories to trace. - StartTracing(string categories, TraceRecorder recorder); - StopTracing(); -}; - -interface TraceRecorder { - Record(string json); -}; - -interface TraceCollector { - // Request tracing data from all connected providers to stream to - // |stream|. - Start(handle<data_pipe_producer> stream, string categories); - - // Stop tracing and flush results to the |stream| passed in to Start(). - // Closes |stream| when all data is collected. - StopAndFlush(); -}; - -// These times are used to determine startup performance metrics. -// TODO(msw): Find a way to convert *_time metrics into TimeTicks earlier (ref: -// https://goo.gl/vZ8dZW). -struct StartupPerformanceTimes { - // TODO(msw): Rename to match "BrowserMainEntryTimeAbsolute" metric? - int64 shell_process_creation_time; - int64 shell_main_entry_point_time; - int64 browser_message_loop_start_ticks; - int64 browser_window_display_ticks; - int64 browser_open_tabs_time_delta; - // TODO(msw): Rename to avoid "web contents"? - int64 first_web_contents_main_frame_load_ticks; - // TODO(msw): Rename to match "FirstWebContents.NonEmptyPaint" metric? - int64 first_visually_non_empty_layout_ticks; -}; - -// This interface accepts startup performance timing from a variety of sources. -interface StartupPerformanceDataCollector { - // These setters may be called many times, only the first time is recorded. - SetShellProcessCreationTime(int64 time); - SetShellMainEntryPointTime(int64 time); - SetBrowserMessageLoopStartTicks(int64 ticks); - SetBrowserWindowDisplayTicks(int64 ticks); - SetBrowserOpenTabsTimeDelta(int64 delta); - SetFirstWebContentsMainFrameLoadTicks(int64 ticks); - SetFirstVisuallyNonEmptyLayoutTicks(int64 ticks); - - // Get the currently available startup performance times. - GetStartupPerformanceTimes() => (StartupPerformanceTimes times); -}; diff --git a/chromium/mojo/services/tracing/trace_data_sink.cc b/chromium/mojo/services/tracing/trace_data_sink.cc deleted file mode 100644 index e608a7452d6..00000000000 --- a/chromium/mojo/services/tracing/trace_data_sink.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/trace_data_sink.h" - -#include <utility> - -#include "base/logging.h" -#include "mojo/common/data_pipe_utils.h" - -using mojo::common::BlockingCopyFromString; - -namespace tracing { - -TraceDataSink::TraceDataSink(mojo::ScopedDataPipeProducerHandle pipe) - : pipe_(std::move(pipe)), empty_(true) {} - -TraceDataSink::~TraceDataSink() { - if (pipe_.is_valid()) - pipe_.reset(); - DCHECK(!pipe_.is_valid()); -} - -void TraceDataSink::AddChunk(const std::string& json) { - if (!empty_) - BlockingCopyFromString(",", pipe_); - empty_ = false; - BlockingCopyFromString(json, pipe_); -} - -} // namespace tracing diff --git a/chromium/mojo/services/tracing/trace_data_sink.h b/chromium/mojo/services/tracing/trace_data_sink.h deleted file mode 100644 index ce0b46314dd..00000000000 --- a/chromium/mojo/services/tracing/trace_data_sink.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_TRACE_DATA_SINK_H_ -#define MOJO_SERVICES_TRACING_TRACE_DATA_SINK_H_ - -#include <string> - -#include "base/macros.h" -#include "mojo/public/cpp/system/data_pipe.h" - -namespace tracing { - -class TraceDataSink { - public: - explicit TraceDataSink(mojo::ScopedDataPipeProducerHandle pipe); - ~TraceDataSink(); - - void AddChunk(const std::string& json); - - private: - mojo::ScopedDataPipeProducerHandle pipe_; - bool empty_; - - DISALLOW_COPY_AND_ASSIGN(TraceDataSink); -}; - -} // namespace tracing - -#endif // MOJO_SERVICES_TRACING_TRACE_DATA_SINK_H_ diff --git a/chromium/mojo/services/tracing/trace_recorder_impl.cc b/chromium/mojo/services/tracing/trace_recorder_impl.cc deleted file mode 100644 index 92dd95c4086..00000000000 --- a/chromium/mojo/services/tracing/trace_recorder_impl.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/trace_recorder_impl.h" - -#include <utility> - -namespace tracing { - -TraceRecorderImpl::TraceRecorderImpl( - mojo::InterfaceRequest<TraceRecorder> request, - TraceDataSink* sink) - : sink_(sink), binding_(this, std::move(request)) {} - -TraceRecorderImpl::~TraceRecorderImpl() { -} - -void TraceRecorderImpl::TryRead() { - binding_.WaitForIncomingMethodCall(MojoDeadline(0)); -} - -mojo::Handle TraceRecorderImpl::TraceRecorderHandle() const { - return binding_.handle(); -} - -void TraceRecorderImpl::Record(const mojo::String& json) { - sink_->AddChunk(json.To<std::string>()); -} - -} // namespace tracing diff --git a/chromium/mojo/services/tracing/trace_recorder_impl.h b/chromium/mojo/services/tracing/trace_recorder_impl.h deleted file mode 100644 index 55640e1c1f5..00000000000 --- a/chromium/mojo/services/tracing/trace_recorder_impl.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_TRACE_RECORDER_IMPL_H_ -#define MOJO_SERVICES_TRACING_TRACE_RECORDER_IMPL_H_ - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/string.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" -#include "mojo/services/tracing/trace_data_sink.h" - -namespace tracing { - -class TraceRecorderImpl : public TraceRecorder { - public: - TraceRecorderImpl(mojo::InterfaceRequest<TraceRecorder> request, - TraceDataSink* sink); - ~TraceRecorderImpl() override; - - // TryRead attempts to read a single chunk from the TraceRecorder pipe if one - // is available and passes it to the TraceDataSink. Returns immediately if no - // chunk is available. - void TryRead(); - - // TraceRecorderHandle returns the handle value of the TraceRecorder - // binding which can be used to wait until chunks are available. - mojo::Handle TraceRecorderHandle() const; - - private: - // tracing::TraceRecorder implementation. - void Record(const mojo::String& json) override; - - TraceDataSink* sink_; - mojo::Binding<TraceRecorder> binding_; - - DISALLOW_COPY_AND_ASSIGN(TraceRecorderImpl); -}; - -} // namespace tracing - -#endif // MOJO_SERVICES_TRACING_TRACE_RECORDER_IMPL_H_ diff --git a/chromium/mojo/services/tracing/tracing_app.cc b/chromium/mojo/services/tracing/tracing_app.cc deleted file mode 100644 index c38bfad2a19..00000000000 --- a/chromium/mojo/services/tracing/tracing_app.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/services/tracing/tracing_app.h" - -#include <stddef.h> -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" - -namespace tracing { - -TracingApp::TracingApp() : collector_binding_(this), tracing_active_(false) { -} - -TracingApp::~TracingApp() { -} - -bool TracingApp::AcceptConnection(mojo::Connection* connection) { - connection->AddInterface<TraceCollector>(this); - connection->AddInterface<StartupPerformanceDataCollector>(this); - - // If someone connects to us they may want to use the TraceCollector - // interface and/or they may want to expose themselves to be traced. Attempt - // to connect to the TraceProvider interface to see if the application - // connecting to us wants to be traced. They can refuse the connection or - // close the pipe if not. - TraceProviderPtr provider_ptr; - connection->GetInterface(&provider_ptr); - if (tracing_active_) { - TraceRecorderPtr recorder_ptr; - recorder_impls_.push_back( - new TraceRecorderImpl(GetProxy(&recorder_ptr), sink_.get())); - provider_ptr->StartTracing(tracing_categories_, std::move(recorder_ptr)); - } - provider_ptrs_.AddPtr(std::move(provider_ptr)); - return true; -} - -bool TracingApp::ShellConnectionLost() { - // TODO(beng): This is only required because TracingApp isn't run by - // ApplicationRunner - instead it's launched automatically by the standalone - // shell. It shouldn't be. - base::MessageLoop::current()->QuitWhenIdle(); - return false; -} - -void TracingApp::Create(mojo::Connection* connection, - mojo::InterfaceRequest<TraceCollector> request) { - collector_binding_.Bind(std::move(request)); -} - -void TracingApp::Create( - mojo::Connection* connection, - mojo::InterfaceRequest<StartupPerformanceDataCollector> request) { - startup_performance_data_collector_bindings_.AddBinding(this, - std::move(request)); -} - -void TracingApp::Start(mojo::ScopedDataPipeProducerHandle stream, - const mojo::String& categories) { - tracing_categories_ = categories; - sink_.reset(new TraceDataSink(std::move(stream))); - provider_ptrs_.ForAllPtrs([categories, this](TraceProvider* controller) { - TraceRecorderPtr ptr; - recorder_impls_.push_back( - new TraceRecorderImpl(GetProxy(&ptr), sink_.get())); - controller->StartTracing(categories, std::move(ptr)); - }); - tracing_active_ = true; -} - -void TracingApp::StopAndFlush() { - // Remove any collectors that closed their message pipes before we called - // StopTracing(). - for (int i = static_cast<int>(recorder_impls_.size()) - 1; i >= 0; --i) { - if (!recorder_impls_[i]->TraceRecorderHandle().is_valid()) { - recorder_impls_.erase(recorder_impls_.begin() + i); - } - } - - tracing_active_ = false; - provider_ptrs_.ForAllPtrs( - [](TraceProvider* controller) { controller->StopTracing(); }); - - // Sending the StopTracing message to registered controllers will request that - // they send trace data back via the collector interface and, when they are - // done, close the collector pipe. We don't know how long they will take. We - // want to read all data that any collector might send until all collectors or - // closed or an (arbitrary) deadline has passed. Since the bindings don't - // support this directly we do our own MojoWaitMany over the handles and read - // individual messages until all are closed or our absolute deadline has - // elapsed. - static const MojoDeadline kTimeToWaitMicros = 1000 * 1000; - MojoTimeTicks end = MojoGetTimeTicksNow() + kTimeToWaitMicros; - - while (!recorder_impls_.empty()) { - MojoTimeTicks now = MojoGetTimeTicksNow(); - if (now >= end) // Timed out? - break; - - MojoDeadline mojo_deadline = end - now; - std::vector<mojo::Handle> handles; - std::vector<MojoHandleSignals> signals; - for (const auto& it : recorder_impls_) { - handles.push_back(it->TraceRecorderHandle()); - signals.push_back(MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - } - std::vector<MojoHandleSignalsState> signals_states(signals.size()); - const mojo::WaitManyResult wait_many_result = - mojo::WaitMany(handles, signals, mojo_deadline, &signals_states); - if (wait_many_result.result == MOJO_RESULT_DEADLINE_EXCEEDED) { - // Timed out waiting, nothing more to read. - LOG(WARNING) << "Timed out waiting for trace flush"; - break; - } - if (wait_many_result.IsIndexValid()) { - // Iterate backwards so we can remove closed pipes from |recorder_impls_| - // without invalidating subsequent offsets. - for (size_t i = signals_states.size(); i != 0; --i) { - size_t index = i - 1; - MojoHandleSignals satisfied = signals_states[index].satisfied_signals; - // To avoid dropping data, don't close unless there's no - // readable signal. - if (satisfied & MOJO_HANDLE_SIGNAL_READABLE) - recorder_impls_[index]->TryRead(); - else if (satisfied & MOJO_HANDLE_SIGNAL_PEER_CLOSED) - recorder_impls_.erase(recorder_impls_.begin() + index); - } - } - } - AllDataCollected(); -} - -void TracingApp::SetShellProcessCreationTime(int64_t time) { - if (startup_performance_times_.shell_process_creation_time == 0) - startup_performance_times_.shell_process_creation_time = time; -} - -void TracingApp::SetShellMainEntryPointTime(int64_t time) { - if (startup_performance_times_.shell_main_entry_point_time == 0) - startup_performance_times_.shell_main_entry_point_time = time; -} - -void TracingApp::SetBrowserMessageLoopStartTicks(int64_t ticks) { - if (startup_performance_times_.browser_message_loop_start_ticks == 0) - startup_performance_times_.browser_message_loop_start_ticks = ticks; -} - -void TracingApp::SetBrowserWindowDisplayTicks(int64_t ticks) { - if (startup_performance_times_.browser_window_display_ticks == 0) - startup_performance_times_.browser_window_display_ticks = ticks; -} - -void TracingApp::SetBrowserOpenTabsTimeDelta(int64_t delta) { - if (startup_performance_times_.browser_open_tabs_time_delta == 0) - startup_performance_times_.browser_open_tabs_time_delta = delta; -} - -void TracingApp::SetFirstWebContentsMainFrameLoadTicks(int64_t ticks) { - if (startup_performance_times_.first_web_contents_main_frame_load_ticks == 0) - startup_performance_times_.first_web_contents_main_frame_load_ticks = ticks; -} - -void TracingApp::SetFirstVisuallyNonEmptyLayoutTicks(int64_t ticks) { - if (startup_performance_times_.first_visually_non_empty_layout_ticks == 0) - startup_performance_times_.first_visually_non_empty_layout_ticks = ticks; -} - -void TracingApp::GetStartupPerformanceTimes( - const GetStartupPerformanceTimesCallback& callback) { - callback.Run(startup_performance_times_.Clone()); -} - -void TracingApp::AllDataCollected() { - recorder_impls_.clear(); - sink_.reset(); -} - -} // namespace tracing diff --git a/chromium/mojo/services/tracing/tracing_app.h b/chromium/mojo/services/tracing/tracing_app.h deleted file mode 100644 index eb5934ab236..00000000000 --- a/chromium/mojo/services/tracing/tracing_app.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SERVICES_TRACING_TRACING_APP_H_ -#define MOJO_SERVICES_TRACING_TRACING_APP_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" -#include "mojo/services/tracing/trace_data_sink.h" -#include "mojo/services/tracing/trace_recorder_impl.h" -#include "mojo/shell/public/cpp/interface_factory.h" -#include "mojo/shell/public/cpp/shell_client.h" - -namespace tracing { - -class TracingApp - : public mojo::ShellClient, - public mojo::InterfaceFactory<TraceCollector>, - public TraceCollector, - public mojo::InterfaceFactory<StartupPerformanceDataCollector>, - public StartupPerformanceDataCollector { - public: - TracingApp(); - ~TracingApp() override; - - private: - // mojo::ShellClient implementation. - bool AcceptConnection(mojo::Connection* connection) override; - bool ShellConnectionLost() override; - - // mojo::InterfaceFactory<TraceCollector> implementation. - void Create(mojo::Connection* connection, - mojo::InterfaceRequest<TraceCollector> request) override; - - // mojo::InterfaceFactory<StartupPerformanceDataCollector> implementation. - void Create( - mojo::Connection* connection, - mojo::InterfaceRequest<StartupPerformanceDataCollector> request) override; - - // tracing::TraceCollector implementation. - void Start(mojo::ScopedDataPipeProducerHandle stream, - const mojo::String& categories) override; - void StopAndFlush() override; - - // StartupPerformanceDataCollector implementation. - void SetShellProcessCreationTime(int64_t time) override; - void SetShellMainEntryPointTime(int64_t time) override; - void SetBrowserMessageLoopStartTicks(int64_t ticks) override; - void SetBrowserWindowDisplayTicks(int64_t ticks) override; - void SetBrowserOpenTabsTimeDelta(int64_t delta) override; - void SetFirstWebContentsMainFrameLoadTicks(int64_t ticks) override; - void SetFirstVisuallyNonEmptyLayoutTicks(int64_t ticks) override; - void GetStartupPerformanceTimes( - const GetStartupPerformanceTimesCallback& callback) override; - - void AllDataCollected(); - - scoped_ptr<TraceDataSink> sink_; - ScopedVector<TraceRecorderImpl> recorder_impls_; - mojo::InterfacePtrSet<TraceProvider> provider_ptrs_; - mojo::Binding<TraceCollector> collector_binding_; - mojo::BindingSet<StartupPerformanceDataCollector> - startup_performance_data_collector_bindings_; - StartupPerformanceTimes startup_performance_times_; - bool tracing_active_; - mojo::String tracing_categories_; - - DISALLOW_COPY_AND_ASSIGN(TracingApp); -}; - -} // namespace tracing - -#endif // MOJO_SERVICES_TRACING_TRACING_APP_H_ diff --git a/chromium/mojo/shell/BUILD.gn b/chromium/mojo/shell/BUILD.gn deleted file mode 100644 index 2f7be9d90a0..00000000000 --- a/chromium/mojo/shell/BUILD.gn +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application_manifest.gni") -import("//mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -group("all") { - testonly = true - deps = [ - ":shell", - "//mojo/shell/background", - "//mojo/shell/runner", - "//mojo/shell/standalone", - "//mojo/shell/tests", - ] -} - -source_set("shell") { - output_name = "mojo_shell" - sources = [ - "connect_params.cc", - "connect_params.h", - "connect_util.cc", - "connect_util.h", - "loader.h", - "native_runner.h", - "native_runner_delegate.h", - "shell.cc", - "shell.h", - "switches.cc", - "switches.h", - ] - - deps = [ - "//base", - "//base/third_party/dynamic_annotations", - "//mojo/common", - "//mojo/public/cpp/bindings", - "//mojo/services/catalog/public/interfaces", - "//mojo/shell/public/cpp:sources", - "//mojo/shell/public/interfaces", - "//mojo/util:filename_util", - "//url", - ] - - public_deps = [ - # ApplicationManager exposes and uses PackageManager types in its header. - "//mojo/services/catalog:lib", - ] - - data_deps = [ - ":manifest", - ] - - # For mojo/shell/application_loader.h - allow_circular_includes_from = [ "//mojo/services/catalog:lib" ] -} - -mojo_application_manifest("manifest") { - application_name = "shell" - source = "manifest.json" -} diff --git a/chromium/mojo/shell/DEPS b/chromium/mojo/shell/DEPS deleted file mode 100644 index 947e7a68517..00000000000 --- a/chromium/mojo/shell/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "-mojo/services", -] diff --git a/chromium/mojo/shell/background/BUILD.gn b/chromium/mojo/shell/background/BUILD.gn deleted file mode 100644 index 75eb28ff992..00000000000 --- a/chromium/mojo/shell/background/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2016 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. - -group("background") { - testonly = true - deps = [ - ":lib", - ":main", - ] -} - -source_set("lib") { - sources = [ - "background_shell.cc", - "background_shell.h", - ] - deps = [ - "//base", - "//mojo/message_pump", - "//mojo/services/catalog:lib", - "//mojo/shell", - "//mojo/shell/public/cpp:sources", - "//mojo/shell/runner:init", - "//mojo/shell/standalone:lib", - ] -} - -source_set("main") { - sources = [ - "background_shell_main.cc", - "background_shell_main.h", - ] - deps = [ - "//base", - "//mojo/message_pump", - "//mojo/shell", - "//mojo/shell/public/cpp:sources", - "//mojo/shell/runner:init", - "//mojo/shell/runner/common", - "//mojo/shell/runner/host:lib", - "//mojo/shell/standalone:lib", - ] -} diff --git a/chromium/mojo/shell/background/DEPS b/chromium/mojo/shell/background/DEPS deleted file mode 100644 index 175fafb7acd..00000000000 --- a/chromium/mojo/shell/background/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+mojo/services/catalog", -] diff --git a/chromium/mojo/shell/background/background_shell.cc b/chromium/mojo/shell/background/background_shell.cc deleted file mode 100644 index a21bbe43038..00000000000 --- a/chromium/mojo/shell/background/background_shell.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2016 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/shell/background/background_shell.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/simple_thread.h" -#include "mojo/message_pump/message_pump_mojo.h" -#include "mojo/services/catalog/store.h" -#include "mojo/shell/connect_params.h" -#include "mojo/shell/loader.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "mojo/shell/shell.h" -#include "mojo/shell/standalone/context.h" - -namespace mojo { -namespace shell { -namespace { - -scoped_ptr<base::MessagePump> CreateMessagePumpMojo() { - return make_scoped_ptr(new common::MessagePumpMojo); -} - -// Used to obtain the ShellClientRequest for an application. When Loader::Load() -// is called a callback is run with the ShellClientRequest. -class BackgroundLoader : public Loader { - public: - using Callback = base::Callback<void(mojom::ShellClientRequest)>; - - explicit BackgroundLoader(const Callback& callback) : callback_(callback) {} - ~BackgroundLoader() override {} - - // Loader: - void Load(const std::string& name, - mojom::ShellClientRequest request) override { - DCHECK(!callback_.is_null()); // Callback should only be run once. - Callback callback = callback_; - callback_.Reset(); - callback.Run(std::move(request)); - } - - private: - Callback callback_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundLoader); -}; - -class MojoMessageLoop : public base::MessageLoop { - public: - MojoMessageLoop() - : base::MessageLoop(base::MessageLoop::TYPE_CUSTOM, - base::Bind(&CreateMessagePumpMojo)) {} - ~MojoMessageLoop() override {} - - void BindToCurrentThread() { base::MessageLoop::BindToCurrentThread(); } - - private: - DISALLOW_COPY_AND_ASSIGN(MojoMessageLoop); -}; - -} // namespace - -// Manages the thread to startup mojo. -class BackgroundShell::MojoThread : public base::SimpleThread { - public: - explicit MojoThread(scoped_ptr<BackgroundShell::InitParams> init_params) - : SimpleThread("mojo-background-shell"), - init_params_(std::move(init_params)) {} - ~MojoThread() override {} - - void CreateShellClientRequest(base::WaitableEvent* signal, - scoped_ptr<ConnectParams> params, - mojom::ShellClientRequest* request) { - // Only valid to call this on the background thread. - DCHECK_EQ(message_loop_, base::MessageLoop::current()); - - // Ownership of |loader| passes to Shell. - const std::string name = params->target().name(); - BackgroundLoader* loader = new BackgroundLoader( - base::Bind(&MojoThread::OnGotApplicationRequest, base::Unretained(this), - name, signal, request)); - context_->shell()->SetLoaderForName(make_scoped_ptr(loader), name); - context_->shell()->Connect(std::move(params)); - // The request is asynchronously processed. When processed - // OnGotApplicationRequest() is called and we'll signal |signal|. - } - - base::MessageLoop* message_loop() { return message_loop_; } - - // Stops the background thread. - void Stop() { - DCHECK_NE(message_loop_, base::MessageLoop::current()); - message_loop_->task_runner()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - Join(); - } - - void RunShellCallback(const BackgroundShell::ShellThreadCallback& callback) { - DCHECK_EQ(message_loop_, base::MessageLoop::current()); - callback.Run(context_->shell()); - } - - // base::SimpleThread: - void Start() override { - DCHECK(!message_loop_); - message_loop_ = new MojoMessageLoop; - base::SimpleThread::Start(); - } - void Run() override { - // The construction/destruction order is very finicky and has to be done - // in the order here. - scoped_ptr<base::MessageLoop> message_loop(message_loop_); - - scoped_ptr<mojo::shell::Context::InitParams> context_init_params( - new mojo::shell::Context::InitParams); - if (init_params_) { - context_init_params->catalog_store = - std::move(init_params_->catalog_store); - context_init_params->native_runner_delegate = - init_params_->native_runner_delegate; - context_init_params->init_edk = init_params_->init_edk; - } - if (context_init_params->init_edk) - Context::EnsureEmbedderIsInitialized(); - - message_loop_->BindToCurrentThread(); - - scoped_ptr<Context> context(new Context); - context_ = context.get(); - context_->Init(std::move(context_init_params)); - - message_loop_->Run(); - - // Has to happen after run, but while messageloop still valid. - context_->Shutdown(); - - // Context has to be destroyed after the MessageLoop has been destroyed. - message_loop.reset(); - context_ = nullptr; - } - - private: - void OnGotApplicationRequest(const std::string& name, - base::WaitableEvent* signal, - mojom::ShellClientRequest* request_result, - mojom::ShellClientRequest actual_request) { - *request_result = std::move(actual_request); - // Trigger destruction of the loader. - context_->shell()->SetLoaderForName(nullptr, name); - signal->Signal(); - } - - // We own this. It's created on the main thread, but destroyed on the - // background thread. - MojoMessageLoop* message_loop_ = nullptr; - // Created in Run() on the background thread. - Context* context_ = nullptr; - - scoped_ptr<BackgroundShell::InitParams> init_params_; - - DISALLOW_COPY_AND_ASSIGN(MojoThread); -}; - -BackgroundShell::InitParams::InitParams() {} -BackgroundShell::InitParams::~InitParams() {} - -BackgroundShell::BackgroundShell() {} - -BackgroundShell::~BackgroundShell() { - thread_->Stop(); -} - -void BackgroundShell::Init(scoped_ptr<InitParams> init_params) { - DCHECK(!thread_); - thread_.reset(new MojoThread(std::move(init_params))); - thread_->Start(); -} - -mojom::ShellClientRequest BackgroundShell::CreateShellClientRequest( - const std::string& name) { - scoped_ptr<ConnectParams> params(new ConnectParams); - params->set_source(CreateShellIdentity()); - params->set_target(Identity(name, mojom::kRootUserID)); - mojom::ShellClientRequest request; - base::WaitableEvent signal(true, false); - thread_->message_loop()->task_runner()->PostTask( - FROM_HERE, base::Bind(&MojoThread::CreateShellClientRequest, - base::Unretained(thread_.get()), &signal, - base::Passed(¶ms), &request)); - signal.Wait(); - return request; -} - -void BackgroundShell::ExecuteOnShellThread( - const ShellThreadCallback& callback) { - thread_->message_loop()->task_runner()->PostTask( - FROM_HERE, base::Bind(&MojoThread::RunShellCallback, - base::Unretained(thread_.get()), callback)); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/background/background_shell.h b/chromium/mojo/shell/background/background_shell.h deleted file mode 100644 index 070b5b1ba55..00000000000 --- a/chromium/mojo/shell/background/background_shell.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_H_ -#define MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_H_ - -#include <vector> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/services/catalog/store.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace catalog { -class Store; -} - -namespace mojo { -namespace shell { - -class NativeRunnerDelegate; -class Shell; - -// BackgroundShell starts up the mojo shell on a background thread, and -// destroys the thread in the destructor. Once created use CreateApplication() -// to obtain an InterfaceRequest for the Application. The InterfaceRequest can -// then be bound to an ApplicationImpl. -class BackgroundShell { - public: - struct InitParams { - InitParams(); - ~InitParams(); - - NativeRunnerDelegate* native_runner_delegate = nullptr; - scoped_ptr<catalog::Store> catalog_store; - // If true the edk is initialized. - bool init_edk = true; - }; - - BackgroundShell(); - ~BackgroundShell(); - - // Starts the background shell. |command_line_switches| are additional - // switches applied to any processes spawned by this call. - void Init(scoped_ptr<InitParams> init_params); - - // Obtains an InterfaceRequest for the specified name. - mojom::ShellClientRequest CreateShellClientRequest( - const std::string& name); - - // Use to do processing on the thread running the shell. The callback is - // supplied a pointer to the Shell. The callback does *not* own the Shell. - using ShellThreadCallback = base::Callback<void(Shell*)>; - void ExecuteOnShellThread(const ShellThreadCallback& callback); - - private: - class MojoThread; - - scoped_ptr<MojoThread> thread_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundShell); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_H_ diff --git a/chromium/mojo/shell/background/background_shell_main.cc b/chromium/mojo/shell/background/background_shell_main.cc deleted file mode 100644 index 72c082f483a..00000000000 --- a/chromium/mojo/shell/background/background_shell_main.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 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/shell/background/background_shell_main.h" - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/debug/debugger.h" -#include "base/process/launch.h" -#include "mojo/shell/runner/common/switches.h" -#include "mojo/shell/runner/host/child_process.h" -#include "mojo/shell/runner/init.h" - -namespace mojo { -namespace shell { -namespace { - -int RunChildProcess() { - base::AtExitManager at_exit; - InitializeLogging(); - WaitForDebuggerIfNecessary(); -#if !defined(OFFICIAL_BUILD) && defined(OS_WIN) - base::RouteStdioToConsole(false); -#endif - return ChildProcessMain(); -} - -} // namespace -} // shell -} // mojo - -int main(int argc, char** argv) { - base::CommandLine::Init(argc, argv); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kChildProcess)) { - return mojo::shell::RunChildProcess(); - } - // Reset CommandLine as most likely main() is going to use CommandLine too - // and expect to be able to initialize it. - base::CommandLine::Reset(); - return MasterProcessMain(argc, argv); -} diff --git a/chromium/mojo/shell/background/background_shell_main.h b/chromium/mojo/shell/background/background_shell_main.h deleted file mode 100644 index 6b217d44780..00000000000 --- a/chromium/mojo/shell/background/background_shell_main.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_MAIN_H_ -#define MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_MAIN_H_ - -// The "main" gn target supplies a file with a main() that calls to the child -// process as necessary. For the main process this function is called. -int MasterProcessMain(int argc, char** argv); - -#endif // MOJO_SHELL_BACKGROUND_BACKGROUND_SHELL_MAIN_H_ diff --git a/chromium/mojo/shell/connect_params.cc b/chromium/mojo/shell/connect_params.cc deleted file mode 100644 index 447c0d5ea10..00000000000 --- a/chromium/mojo/shell/connect_params.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/connect_params.h" - -namespace mojo { -namespace shell { - -ConnectParams::ConnectParams() {} -ConnectParams::~ConnectParams() {} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/connect_params.h b/chromium/mojo/shell/connect_params.h deleted file mode 100644 index bacf543b3e1..00000000000 --- a/chromium/mojo/shell/connect_params.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_CONNECT_PARAMS_H_ -#define MOJO_SHELL_CONNECT_PARAMS_H_ - -#include <string> -#include <utility> - -#include "base/callback.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" - -namespace mojo { -namespace shell { - -// This class represents a request for the application manager to connect to an -// application. -class ConnectParams { - public: - ConnectParams(); - ~ConnectParams(); - - void set_source(const Identity& source) { source_ = source; } - const Identity& source() const { return source_; } - void set_target(const Identity& target) { target_ = target; } - const Identity& target() const { return target_; } - - void set_remote_interfaces(shell::mojom::InterfaceProviderRequest value) { - remote_interfaces_ = std::move(value); - } - shell::mojom::InterfaceProviderRequest TakeRemoteInterfaces() { - return std::move(remote_interfaces_); - } - - void set_local_interfaces(shell::mojom::InterfaceProviderPtr value) { - local_interfaces_ = std::move(value); - } - shell::mojom::InterfaceProviderPtr TakeLocalInterfaces() { - return std::move(local_interfaces_); - } - - void set_client_process_connection( - shell::mojom::ClientProcessConnectionPtr client_process_connection) { - client_process_connection_ = std::move(client_process_connection); - } - shell::mojom::ClientProcessConnectionPtr TakeClientProcessConnection() { - return std::move(client_process_connection_); - } - - void set_connect_callback( - const shell::mojom::Connector::ConnectCallback& value) { - connect_callback_ = value; - } - const shell::mojom::Connector::ConnectCallback& connect_callback() const { - return connect_callback_; - } - - private: - // It may be null (i.e., is_null() returns true) which indicates that there is - // no source (e.g., for the first application or in tests). - Identity source_; - // The identity of the application being connected to. - Identity target_; - - shell::mojom::InterfaceProviderRequest remote_interfaces_; - shell::mojom::InterfaceProviderPtr local_interfaces_; - shell::mojom::ClientProcessConnectionPtr client_process_connection_; - shell::mojom::Connector::ConnectCallback connect_callback_; - - DISALLOW_COPY_AND_ASSIGN(ConnectParams); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_CONNECT_PARAMS_H_ diff --git a/chromium/mojo/shell/connect_util.cc b/chromium/mojo/shell/connect_util.cc deleted file mode 100644 index e5210c69b79..00000000000 --- a/chromium/mojo/shell/connect_util.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/connect_util.h" - -#include <utility> - -#include "mojo/shell/connect_params.h" -#include "mojo/shell/shell.h" - -namespace mojo { -namespace shell { - -ScopedMessagePipeHandle ConnectToInterfaceByName( - Shell* shell, - const Identity& source, - const Identity& target, - const std::string& interface_name) { - shell::mojom::InterfaceProviderPtr remote_interfaces; - scoped_ptr<ConnectParams> params(new ConnectParams); - params->set_source(source); - params->set_target(target); - params->set_remote_interfaces(GetProxy(&remote_interfaces)); - shell->Connect(std::move(params)); - MessagePipe pipe; - remote_interfaces->GetInterface(interface_name, std::move(pipe.handle1)); - return std::move(pipe.handle0); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/connect_util.h b/chromium/mojo/shell/connect_util.h deleted file mode 100644 index d7f629c4cdc..00000000000 --- a/chromium/mojo/shell/connect_util.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_CONNECT_UTIL_H_ -#define MOJO_SHELL_CONNECT_UTIL_H_ - -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" - -namespace mojo { -namespace shell { - -class Shell; - -ScopedMessagePipeHandle ConnectToInterfaceByName( - Shell* shell, - const Identity& source, - const Identity& target, - const std::string& interface_name); - -// Must only be used by shell internals and test code as it does not forward -// capability filters. Runs |name| with a permissive capability filter. -template <typename Interface> -inline void ConnectToInterface(Shell* shell, - const Identity& source, - const Identity& target, - InterfacePtr<Interface>* ptr) { - ScopedMessagePipeHandle service_handle = - ConnectToInterfaceByName(shell, source, target, Interface::Name_); - ptr->Bind(InterfacePtrInfo<Interface>(std::move(service_handle), 0u)); -} - -template <typename Interface> -inline void ConnectToInterface(Shell* shell, - const Identity& source, - const std::string& name, - InterfacePtr<Interface>* ptr) { - ScopedMessagePipeHandle service_handle = ConnectToInterfaceByName( - shell, source, Identity(name, mojom::kInheritUserID), - Interface::Name_); - ptr->Bind(InterfacePtrInfo<Interface>(std::move(service_handle), 0u)); -} - -} // namespace shell -} // namespace mojo - - -#endif // MOJO_SHELL_CONNECT_UTIL_H_ diff --git a/chromium/mojo/shell/loader.h b/chromium/mojo/shell/loader.h deleted file mode 100644 index 756c070acb2..00000000000 --- a/chromium/mojo/shell/loader.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_LOADER_H_ -#define MOJO_SHELL_LOADER_H_ - -#include "base/callback.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace mojo { -namespace shell { - -// Interface to implement special loading behavior for a particular name. -class Loader { - public: - virtual ~Loader() {} - - virtual void Load(const std::string& name, - mojom::ShellClientRequest request) = 0; -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_LOADER_H_ diff --git a/chromium/mojo/shell/manifest.json b/chromium/mojo/shell/manifest.json deleted file mode 100644 index 24a6f775f14..00000000000 --- a/chromium/mojo/shell/manifest.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "manifest_version": 1, - "name": "mojo:shell", - "display_name": "Shell", - "capabilities": { - "provided": { - "user_id": [ ], - "client_process": [ ], - "instance_name": [ ], - "all_users": [ ] - }, - "required": { - "mojo:shell": { "classes": [ "all_users" ] } - } - } -} diff --git a/chromium/mojo/shell/native_runner.h b/chromium/mojo/shell/native_runner.h deleted file mode 100644 index bf287552d51..00000000000 --- a/chromium/mojo/shell/native_runner.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_NATIVE_RUNNER_H_ -#define MOJO_SHELL_NATIVE_RUNNER_H_ - -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" -#include "base/process/process_handle.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace base { -class FilePath; -} - -namespace mojo { -class Identity; -namespace shell { - - -// Shell requires implementations of NativeRunner and NativeRunnerFactory to run -// native applications. -class NativeRunner { - public: - virtual ~NativeRunner() {} - - // Loads the app in the file at |app_path| and runs it on some other - // thread/process. Returns a ShellClient handle the shell can use to connect - // to the the app. - virtual mojom::ShellClientPtr Start( - const base::FilePath& app_path, - const Identity& target, - bool start_sandboxed, - const base::Callback<void(base::ProcessId)>& pid_available_callback, - const base::Closure& app_completed_callback) = 0; -}; - -class NativeRunnerFactory { - public: - virtual ~NativeRunnerFactory() {} - virtual scoped_ptr<NativeRunner> Create(const base::FilePath& app_path) = 0; -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_NATIVE_RUNNER_H_ diff --git a/chromium/mojo/shell/native_runner_delegate.h b/chromium/mojo/shell/native_runner_delegate.h deleted file mode 100644 index b732ec60c15..00000000000 --- a/chromium/mojo/shell/native_runner_delegate.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_NATIVE_RUNNER_DELEGATE_H_ -#define MOJO_SHELL_NATIVE_RUNNER_DELEGATE_H_ - -namespace base { -class CommandLine; -} - -namespace mojo { -class Identity; -namespace shell { - -class NativeRunnerDelegate { - public: - // Called to adjust the commandline for launching the specified app. - // WARNING: this is called on a background thread. - virtual void AdjustCommandLineArgumentsForTarget( - const Identity& target, - base::CommandLine* command_line) = 0; - - protected: - virtual ~NativeRunnerDelegate() {} -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_NATIVE_RUNNER_DELEGATE_H_ diff --git a/chromium/mojo/shell/public/cpp/BUILD.gn b/chromium/mojo/shell/public/cpp/BUILD.gn deleted file mode 100644 index 53318b1ce70..00000000000 --- a/chromium/mojo/shell/public/cpp/BUILD.gn +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# GYP version: mojo/mojo_base.gyp:mojo_application_base -source_set("cpp") { - public_deps = [ - ":init_commandline", - ":sources", - ] -} - -# Like the target above, but without special commandline initialization that -# apps use. -source_set("cpp_for_chromium") { - public_deps = [ - ":sources", - ] -} - -source_set("sources") { - sources = [ - "application_runner.h", - "capabilities.h", - "connect.h", - "connection.h", - "connector.h", - "identity.h", - "initialize_base_and_icu.cc", - "interface_binder.h", - "interface_factory.h", - "interface_factory_impl.h", - "interface_registry.h", - "lib/application_runner.cc", - "lib/capabilities.cc", - "lib/connection_impl.cc", - "lib/connection_impl.h", - "lib/connector_impl.cc", - "lib/connector_impl.h", - "lib/identity.cc", - "lib/interface_factory_binder.h", - "lib/interface_registry.cc", - "lib/message_loop_ref.cc", - "lib/names.cc", - "lib/shell_client.cc", - "lib/shell_connection.cc", - "message_loop_ref.h", - "names.h", - "shell.h", - "shell_client.h", - "shell_connection.h", - ] - - deps = [ - "//base", - "//base:i18n", - ] - - public_deps = [ - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/shell/public/interfaces", - "//url", - ] -} - -source_set("init_commandline") { - sources = [ - "lib/init_commandline.cc", - ] -} - -source_set("test_support") { - testonly = true - sources = [ - "application_test_base.h", - "lib/application_test_base.cc", - "lib/application_test_main.cc", - ] - - public_deps = [ - ":cpp", - "//testing/gtest", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/logging", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/shell/public/interfaces:interfaces_cpp_sources", - ] - - data_deps = [] -} - -source_set("shell_test_support") { - testonly = true - sources = [ - "lib/shell_test.cc", - "shell_test.h", - ] - - public_deps = [ - ":cpp", - "//testing/gtest", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/logging", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/shell/background:lib", - "//mojo/shell/public/interfaces:interfaces_cpp_sources", - ] - - data_deps = [] -} diff --git a/chromium/mojo/shell/public/cpp/application_runner.h b/chromium/mojo/shell/public/cpp/application_runner.h deleted file mode 100644 index 2fb28a2b24b..00000000000 --- a/chromium/mojo/shell/public/cpp/application_runner.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_APPLICATION_RUNNER_H_ -#define MOJO_SHELL_PUBLIC_CPP_APPLICATION_RUNNER_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -class ShellClient; -class ShellConnection; - -// A utility for running a chromium based mojo Application. The typical use -// case is to use when writing your MojoMain: -// -// MojoResult MojoMain(MojoHandle shell_handle) { -// mojo::ApplicationRunner runner(new MyDelegate()); -// return runner.Run(shell_handle); -// } -// -// ApplicationRunner takes care of chromium environment initialization and -// shutdown, and starting a MessageLoop from which your application can run and -// ultimately Quit(). -class ApplicationRunner { - public: - // Takes ownership of |client|. - explicit ApplicationRunner(ShellClient* client); - ~ApplicationRunner(); - - static void InitBaseCommandLine(); - - void set_message_loop_type(base::MessageLoop::Type type); - - // Once the various parameters have been set above, use Run to initialize an - // ShellConnection wired to the provided delegate, and run a MessageLoop until - // the application exits. - // - // Iff |init_base| is true, the runner will perform some initialization of - // base globals (e.g. CommandLine and AtExitManager) before starting the - // application. - MojoResult Run(MojoHandle shell_handle, bool init_base); - - // Calls Run above with |init_base| set to |true|. - MojoResult Run(MojoHandle shell_handle); - - // Allows the caller to shut down the connection with the shell. After the - // shell notices the pipe has closed, it will no longer track an instance of - // this application, though this application may continue to run and service - // requests from others. - void DestroyShellConnection(); - - // Allows the caller to explicitly quit the application. Must be called from - // the thread which created the ApplicationRunner. - void Quit(); - - private: - scoped_ptr<ShellConnection> connection_; - scoped_ptr<ShellClient> client_; - - // MessageLoop type. TYPE_CUSTOM is default (MessagePumpMojo will be used as - // the underlying message pump). - base::MessageLoop::Type message_loop_type_; - // Whether Run() has been called. - bool has_run_; - - DISALLOW_COPY_AND_ASSIGN(ApplicationRunner); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_APPLICATION_RUNNER_H_ diff --git a/chromium/mojo/shell/public/cpp/application_test_base.h b/chromium/mojo/shell/public/cpp/application_test_base.h deleted file mode 100644 index 54d073ad622..00000000000 --- a/chromium/mojo/shell/public/cpp/application_test_base.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_APPLICATION_TEST_BASE_H_ -#define MOJO_SHELL_PUBLIC_CPP_APPLICATION_TEST_BASE_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/bindings/string.h" -#include "mojo/shell/public/cpp/connector.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { - -class ShellConnection; - -namespace test { - -// Run all application tests. This must be called after the environment is -// initialized, to support construction of a default run loop. -MojoResult RunAllTests(MojoHandle shell_client_request_handle); - -// Used to configure the ShellConnection. This is used internally by -// ApplicationTestBase, but useful if you do not want to subclass -// ApplicationTestBase. -class TestHelper { - public: - explicit TestHelper(ShellClient* client); - ~TestHelper(); - - Connector* connector() { return shell_connection_->connector(); } - const std::string& test_name() { return name_; } - const std::string& test_userid() { return userid_; } - uint32_t test_instance_id() { return instance_id_; } - - private: - // The application delegate used if GetShellClient is not overridden. - ShellClient default_shell_client_; - - // The application implementation instance, reconstructed for each test. - scoped_ptr<ShellConnection> shell_connection_; - - std::string name_; - std::string userid_; - uint32_t instance_id_; - - DISALLOW_COPY_AND_ASSIGN(TestHelper); -}; - -// A GTEST base class for application testing executed in mojo_shell. -class ApplicationTestBase : public testing::Test { - public: - ApplicationTestBase(); - ~ApplicationTestBase() override; - - protected: - Connector* connector() { - return test_helper_ ? test_helper_->connector() : nullptr; - } - const std::string& test_name() const { - return test_helper_ ? test_helper_->test_name() : empty_; - } - const std::string& test_userid() const { - return test_helper_ ? test_helper_->test_userid() : inherit_user_id_; - } - uint32_t test_instance_id() const { - return test_helper_ ? test_helper_->test_instance_id() : - shell::mojom::kInvalidInstanceID; - } - - // Get the ShellClient for the application to be tested. - virtual ShellClient* GetShellClient(); - - // testing::Test: - void SetUp() override; - void TearDown() override; - - // True by default, which indicates a MessageLoop will automatically be - // created for the application. Tests may override this function to prevent - // a default loop from being created. - virtual bool ShouldCreateDefaultRunLoop(); - - private: - scoped_ptr<TestHelper> test_helper_; - std::string empty_; - std::string inherit_user_id_ = shell::mojom::kInheritUserID; - - DISALLOW_COPY_AND_ASSIGN(ApplicationTestBase); -}; - -} // namespace test - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_APPLICATION_TEST_BASE_H_ diff --git a/chromium/mojo/shell/public/cpp/capabilities.h b/chromium/mojo/shell/public/cpp/capabilities.h deleted file mode 100644 index 0b1b09a094c..00000000000 --- a/chromium/mojo/shell/public/cpp/capabilities.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_CAPABILITIES_H_ -#define MOJO_SHELL_PUBLIC_CPP_CAPABILITIES_H_ - -#include <map> -#include <set> -#include <string> - -#include "mojo/shell/public/interfaces/shell_resolver.mojom.h" - -namespace mojo { -using Class = std::string; -using Classes = std::set<std::string>; -using Interface = std::string; -using Interfaces = std::set<std::string>; -using Name = std::string; - -// See comments in mojo/shell/public/interfaces/capabilities.mojom for a -// description of CapabilityRequest and CapabilitySpec. - -struct CapabilityRequest { - CapabilityRequest(); - CapabilityRequest(const CapabilityRequest& other); - ~CapabilityRequest(); - bool operator==(const CapabilityRequest& other) const; - bool operator<(const CapabilityRequest& other) const; - Classes classes; - Interfaces interfaces; -}; - -struct CapabilitySpec { - CapabilitySpec(); - CapabilitySpec(const CapabilitySpec& other); - ~CapabilitySpec(); - bool operator==(const CapabilitySpec& other) const; - bool operator<(const CapabilitySpec& other) const; - std::map<Class, Interfaces> provided; - std::map<Name, CapabilityRequest> required; -}; - -template <> -struct TypeConverter<shell::mojom::CapabilitySpecPtr, CapabilitySpec> { - static shell::mojom::CapabilitySpecPtr Convert( - const CapabilitySpec& input); -}; -template <> -struct TypeConverter<CapabilitySpec, shell::mojom::CapabilitySpecPtr> { - static CapabilitySpec Convert( - const shell::mojom::CapabilitySpecPtr& input); -}; - -template <> -struct TypeConverter<shell::mojom::CapabilityRequestPtr, - CapabilityRequest> { - static shell::mojom::CapabilityRequestPtr Convert( - const CapabilityRequest& input); -}; -template <> -struct TypeConverter<CapabilityRequest, - shell::mojom::CapabilityRequestPtr> { - static CapabilityRequest Convert( - const shell::mojom::CapabilityRequestPtr& input); -}; -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_CAPABILITIES_H_ diff --git a/chromium/mojo/shell/public/cpp/connect.h b/chromium/mojo/shell/public/cpp/connect.h deleted file mode 100644 index b0493216358..00000000000 --- a/chromium/mojo/shell/public/cpp/connect.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_CONNECT_H_ -#define MOJO_SHELL_PUBLIC_CPP_CONNECT_H_ - -#include <utility> - -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" - -namespace mojo { - -// Binds |ptr| to a remote implementation of Interface from |interfaces|. -template <typename Interface> -inline void GetInterface(shell::mojom::InterfaceProvider* interfaces, - InterfacePtr<Interface>* ptr) { - MessagePipe pipe; - ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u)); - interfaces->GetInterface(Interface::Name_, std::move(pipe.handle1)); -} - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_CONNECT_H_ diff --git a/chromium/mojo/shell/public/cpp/connection.h b/chromium/mojo/shell/public/cpp/connection.h deleted file mode 100644 index edb407311e1..00000000000 --- a/chromium/mojo/shell/public/cpp/connection.h +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_CONNECTION_H_ -#define MOJO_SHELL_PUBLIC_CPP_CONNECTION_H_ - -#include <stdint.h> - -#include <string> -#include <utility> - -#include "base/memory/weak_ptr.h" -#include "mojo/shell/public/cpp/connect.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/cpp/interface_registry.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" - -namespace mojo { - -class InterfaceBinder; - -// Represents a connection to another application. An instance of this class is -// returned from Shell's ConnectToApplication(), and passed to ShellClient's -// AcceptConnection() each time an incoming connection is received. -// -// Call AddService<T>(factory) to expose an interface to the remote application, -// and GetInterface(&interface_ptr) to consume an interface exposed by the -// remote application. -// -// Internally, this class wraps an InterfaceRegistry that accepts interfaces -// that may be exposed to a remote application. See documentation in -// interface_registry.h for more information. -// -// A Connection returned via Shell::ConnectToApplication() is owned by the -// caller. -// An Connection received via AcceptConnection is owned by the ShellConnection. -// To close a connection, call CloseConnection which will destroy this object. -class Connection { - public: - virtual ~Connection() {} - - enum class State { - // The shell has not yet processed the connection. - PENDING, - - // The shell processed the connection and it was established. GetResult() - // returns mojom::shell::ConnectionResult::SUCCESS. - CONNECTED, - - // The shell processed the connection and establishment was prevented by - // an error, call GetResult(). - DISCONNECTED - }; - - class TestApi { - public: - explicit TestApi(Connection* connection) : connection_(connection) {} - base::WeakPtr<Connection> GetWeakPtr() { - return connection_->GetWeakPtr(); - } - - private: - Connection* connection_; - }; - - // Allow the remote application to request instances of Interface. - // |factory| will create implementations of Interface on demand. - // Returns true if the interface was exposed, false if capability filtering - // from the shell prevented the interface from being exposed. - template <typename Interface> - bool AddInterface(InterfaceFactory<Interface>* factory) { - return GetLocalRegistry()->AddInterface<Interface>(factory); - } - - // Binds |ptr| to an implemention of Interface in the remote application. - // |ptr| can immediately be used to start sending requests to the remote - // interface. - template <typename Interface> - void GetInterface(InterfacePtr<Interface>* ptr) { - mojo::GetInterface(GetRemoteInterfaces(), ptr); - } - - // Returns true if the remote application has the specified capability class - // specified in its manifest. Only valid for inbound connections. Will return - // false for outbound connections. - virtual bool HasCapabilityClass(const std::string& class_name) const = 0; - - // Returns the name that was used by the source application to establish a - // connection to the destination application. - // - // When Connection is representing and outgoing connection, this will be the - // same as the value returned by GetRemoveApplicationName(). - virtual const std::string& GetConnectionName() = 0; - - // Returns the remote identity. While the connection is in the pending state, - // the user_id() field will be the value passed via Connect(). After the - // connection is completed, it will change to the value assigned by the shell. - // Call AddConnectionCompletedClosure() to schedule a closure to be run when - // the resolved user id is available. - virtual const Identity& GetRemoteIdentity() const = 0; - - // Register a handler to receive an error notification on the pipe to the - // remote application's InterfaceProvider. - virtual void SetConnectionLostClosure(const Closure& handler) = 0; - - // Returns the result of the connection. This function should only be called - // when the connection state is not pending. Call - // AddConnectionCompletedClosure() to schedule a closure to be run when the - // connection is processed by the shell. - virtual shell::mojom::ConnectResult GetResult() const = 0; - - // Returns true if the connection has not yet been processed by the shell. - virtual bool IsPending() const = 0; - - // Returns the instance id of the remote application if it is known at the - // time this function is called. When IsPending() returns true, this function - // will return shell::mojom::kInvalidInstanceID. Use - // AddConnectionCompletedClosure() to schedule a closure to be run when the - // connection is processed by the shell and remote id is available. - virtual uint32_t GetRemoteInstanceID() const = 0; - - // Register a closure to be run when the connection has been completed by the - // shell and remote metadata is available. Useful only for connections created - // via Connector::Connect(). Once the connection is complete, metadata is - // available immediately. - virtual void AddConnectionCompletedClosure(const Closure& callback) = 0; - - // Returns true if the Shell allows |interface_name| to be exposed to the - // remote application. - virtual bool AllowsInterface(const std::string& interface_name) const = 0; - - // Returns the raw proxy to the remote application's InterfaceProvider - // interface. Most applications will just use GetInterface() instead. - // Caller does not take ownership. - virtual shell::mojom::InterfaceProvider* GetRemoteInterfaces() = 0; - - protected: - virtual InterfaceRegistry* GetLocalRegistry() = 0; - - virtual base::WeakPtr<Connection> GetWeakPtr() = 0; -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_CONNECTION_H_ diff --git a/chromium/mojo/shell/public/cpp/connector.h b/chromium/mojo/shell/public/cpp/connector.h deleted file mode 100644 index b6155350f05..00000000000 --- a/chromium/mojo/shell/public/cpp/connector.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_CONNECTOR_H_ -#define MOJO_SHELL_PUBLIC_CPP_CONNECTOR_H_ - -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/shell.mojom.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace mojo { - -// An interface that encapsulates the Mojo Shell's broker interface by which -// connections between applications are established. Once Connect() is called, -// this class is bound to the thread the call was made on and it cannot be -// passed to another thread without calling Clone(). -// An instance of this class is created internally by ShellConnection for use -// on the thread ShellConnection is instantiated on, and this interface is -// wrapped by the Shell interface. -// To use this interface on other threads, call Shell::CloneConnector() and -// pass the result to another thread. To pass to subsequent threads, call -// Clone() on instances of this object. -// While instances of this object are owned by the caller, the underlying -// connection with the shell is bound to the lifetime of the instance that -// created it, i.e. when the application is terminated the Connector pipe is -// closed. -class Connector { - public: - virtual ~Connector() {} - - class ConnectParams { - public: - explicit ConnectParams(const Identity& target); - explicit ConnectParams(const std::string& name); - ~ConnectParams(); - - const Identity& target() { return target_; } - void set_target(const Identity& target) { target_ = target; } - void set_client_process_connection( - shell::mojom::ShellClientPtr shell_client, - shell::mojom::PIDReceiverRequest pid_receiver_request) { - shell_client_ = std::move(shell_client); - pid_receiver_request_ = std::move(pid_receiver_request); - } - void TakeClientProcessConnection( - shell::mojom::ShellClientPtr* shell_client, - shell::mojom::PIDReceiverRequest* pid_receiver_request) { - *shell_client = std::move(shell_client_); - *pid_receiver_request = std::move(pid_receiver_request_); - } - - private: - Identity target_; - shell::mojom::ShellClientPtr shell_client_; - shell::mojom::PIDReceiverRequest pid_receiver_request_; - - DISALLOW_COPY_AND_ASSIGN(ConnectParams); - }; - - // Requests a new connection to an application. Returns a pointer to the - // connection if the connection is permitted by this application's delegate, - // or nullptr otherwise. Caller takes ownership. - // Once this method is called, this object is bound to the thread on which the - // call took place. To pass to another thread, call Clone() and pass the - // result. - virtual scoped_ptr<Connection> Connect(const std::string& name) = 0; - virtual scoped_ptr<Connection> Connect(ConnectParams* params) = 0; - - // Connect to application identified by |request->name| and connect to the - // service implementation of the interface identified by |Interface|. - template <typename Interface> - void ConnectToInterface(ConnectParams* params, InterfacePtr<Interface>* ptr) { - scoped_ptr<Connection> connection = Connect(params); - if (connection) - connection->GetInterface(ptr); - } - template <typename Interface> - void ConnectToInterface(const Identity& target, - InterfacePtr<Interface>* ptr) { - ConnectParams params(target); - return ConnectToInterface(¶ms, ptr); - } - template <typename Interface> - void ConnectToInterface(const std::string& name, - InterfacePtr<Interface>* ptr) { - ConnectParams params(name); - return ConnectToInterface(¶ms, ptr); - } - - // Creates a new instance of this class which may be passed to another thread. - // The returned object may be passed multiple times until Connect() is called, - // at which point this method must be called again to pass again. - virtual scoped_ptr<Connector> Clone() = 0; -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_CONNECTOR_H_ diff --git a/chromium/mojo/shell/public/cpp/identity.h b/chromium/mojo/shell/public/cpp/identity.h deleted file mode 100644 index 90f4608fa89..00000000000 --- a/chromium/mojo/shell/public/cpp/identity.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_IDENTITY_H_ -#define MOJO_SHELL_PUBLIC_CPP_IDENTITY_H_ - -#include <string> - -#include "mojo/shell/public/interfaces/connector.mojom.h" - -namespace mojo { - -// Represents the identity of an application. -// |name| is the structured name of the application. -// |instance| is a string that allows to tie a specific instance to another. A -// typical use case of instance is to control process grouping for a given name. -class Identity { - public: - Identity(); - Identity(const std::string& name, - const std::string& user_id); - Identity(const std::string& name, - const std::string& user_id, - const std::string& instance); - Identity(const Identity& other); - ~Identity(); - - bool operator<(const Identity& other) const; - bool is_null() const { return name_.empty(); } - bool operator==(const Identity& other) const; - - const std::string& name() const { return name_; } - const std::string& user_id() const { return user_id_; } - void set_user_id(const std::string& user_id) { user_id_ = user_id; } - const std::string& instance() const { return instance_; } - - private: - std::string name_; - std::string user_id_; - std::string instance_; -}; - -template <> -struct TypeConverter<shell::mojom::IdentityPtr, Identity> { - static shell::mojom::IdentityPtr Convert(const Identity& input); -}; -template <> -struct TypeConverter<Identity, shell::mojom::IdentityPtr> { - static Identity Convert(const shell::mojom::IdentityPtr& input); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_IDENTITY_H_ diff --git a/chromium/mojo/shell/public/cpp/initialize_base_and_icu.cc b/chromium/mojo/shell/public/cpp/initialize_base_and_icu.cc deleted file mode 100644 index 9eb49fa55e5..00000000000 --- a/chromium/mojo/shell/public/cpp/initialize_base_and_icu.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file declares a raw symbol and should be included only once in a -// certain binary target. This needs to be run before we raise the sandbox, -// which means that it can't use mojo. Our runners will dig around in the -// symbol table and run this before the mojo system is initialized. - -#include <stdint.h> - -#include "base/files/file.h" -#include "base/i18n/icu_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/rand_util.h" -#include "base/sys_info.h" -#include "mojo/public/c/system/types.h" - -#if !defined(OS_ANDROID) -#include "third_party/icu/source/i18n/unicode/timezone.h" -#endif - -extern "C" { -#if defined(WIN32) -__declspec(dllexport) void __cdecl -#else -void __attribute__((visibility("default"))) -#endif -InitializeBase(const uint8_t* icu_data) { - base::RandUint64(); - base::SysInfo::AmountOfPhysicalMemory(); - base::SysInfo::NumberOfProcessors(); -#if defined(OS_POSIX) && !defined(OS_MACOSX) - base::SysInfo::MaxSharedMemorySize(); -#endif - - // Initialize core ICU. We must perform the full initialization before we - // initialize icu::TimeZone subsystem because otherwise ICU gets in a state - // where the timezone data is disconnected from the locale data which can - // cause crashes. - CHECK(base::i18n::InitializeICUFromRawMemory(icu_data)); - -#if !defined(OS_ANDROID) - // ICU DateFormat class (used in base/time_format.cc) needs to get the - // Olson timezone ID by accessing the zoneinfo files on disk. After - // TimeZone::createDefault is called once here, the timezone ID is - // cached and there's no more need to access the file system. - scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); -#endif -} -} diff --git a/chromium/mojo/shell/public/cpp/interface_binder.h b/chromium/mojo/shell/public/cpp/interface_binder.h deleted file mode 100644 index 9d4dada453a..00000000000 --- a/chromium/mojo/shell/public/cpp/interface_binder.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_INTERFACE_BINDER_H_ -#define MOJO_SHELL_PUBLIC_CPP_INTERFACE_BINDER_H_ - -#include <string> - -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -class Connection; - -class InterfaceBinder { - public: - virtual ~InterfaceBinder() {} - - // Asks the InterfaceBinder to bind an implementation of the specified - // interface to the request passed via |handle|. If the InterfaceBinder binds - // an implementation it must take ownership of the request handle. - virtual void BindInterface(Connection* connection, - const std::string& interface_name, - ScopedMessagePipeHandle handle) = 0; -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_INTERFACE_BINDER_H_ diff --git a/chromium/mojo/shell/public/cpp/interface_factory.h b/chromium/mojo/shell/public/cpp/interface_factory.h deleted file mode 100644 index 7edf0008c45..00000000000 --- a/chromium/mojo/shell/public/cpp/interface_factory.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_H_ -#define MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_H_ - -#include "mojo/public/cpp/bindings/interface_request.h" - -namespace mojo { - -class Connection; -template <typename Interface> -class InterfaceRequest; - -// Implement this class to provide implementations of a given interface and -// bind them to incoming requests. The implementation of this class is -// responsible for managing the lifetime of the implementations of the -// interface. -template <typename Interface> -class InterfaceFactory { - public: - virtual ~InterfaceFactory() {} - virtual void Create(Connection* connection, - InterfaceRequest<Interface> request) = 0; -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_H_ diff --git a/chromium/mojo/shell/public/cpp/interface_factory_impl.h b/chromium/mojo/shell/public/cpp/interface_factory_impl.h deleted file mode 100644 index f84992227b1..00000000000 --- a/chromium/mojo/shell/public/cpp/interface_factory_impl.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_ -#define MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_ - -#include "mojo/shell/public/cpp/interface_factory.h" - -namespace mojo { - -// Use this class to allocate and bind instances of Impl to interface requests. -// The lifetime of the constructed Impl is bound to the pipe. -template <typename Impl, - typename Interface = typename Impl::ImplementedInterface> -class InterfaceFactoryImpl : public InterfaceFactory<Interface> { - public: - virtual ~InterfaceFactoryImpl() {} - - virtual void Create(Connection* connection, - InterfaceRequest<Interface> request) override { - BindToRequest(new Impl(), &request); - } -}; - -// Use this class to allocate and bind instances of Impl constructed with a -// context parameter to interface requests. The lifetime of the constructed -// Impl is bound to the pipe. -template <typename Impl, - typename Context, - typename Interface = typename Impl::ImplementedInterface> -class InterfaceFactoryImplWithContext : public InterfaceFactory<Interface> { - public: - explicit InterfaceFactoryImplWithContext(Context* context) - : context_(context) {} - virtual ~InterfaceFactoryImplWithContext() {} - - virtual void Create(Connection* connection, - InterfaceRequest<Interface> request) override { - BindToRequest(new Impl(context_), &request); - } - - private: - Context* context_; -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_ diff --git a/chromium/mojo/shell/public/cpp/interface_registry.h b/chromium/mojo/shell/public/cpp/interface_registry.h deleted file mode 100644 index ea0b984471b..00000000000 --- a/chromium/mojo/shell/public/cpp/interface_registry.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_INTERFACE_REGISTRY_H_ -#define MOJO_SHELL_PUBLIC_CPP_INTERFACE_REGISTRY_H_ - -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/shell/public/cpp/lib/interface_factory_binder.h" -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" - -namespace mojo { - -class InterfaceBinder; - -// An implementation of shell::mojom::InterfaceProvider that allows the user to -// register services to be exposed to another application. -// -// To use, define a class that implements your specific interface. Then -// implement an InterfaceFactory<Foo> that binds instances of FooImpl to -// InterfaceRequest<Foo>s and register that on the registry like this: -// -// registry.AddInterface(&factory); -// -// Or, if you have multiple factories implemented by the same type, explicitly -// specify the interface to register the factory for: -// -// registry.AddInterface<Foo>(&my_foo_and_bar_factory_); -// registry.AddInterface<Bar>(&my_foo_and_bar_factory_); -// -// The InterfaceFactory must outlive the InterfaceRegistry. -// -// Additionally you may specify a default InterfaceBinder to handle requests for -// interfaces unhandled by any registered InterfaceFactory. Just as with -// InterfaceFactory, the default InterfaceBinder supplied must outlive -// InterfaceRegistry. -// -class InterfaceRegistry : public shell::mojom::InterfaceProvider { - public: - class TestApi { - public: - explicit TestApi(InterfaceRegistry* registry) : registry_(registry) {} - ~TestApi() {} - - void SetInterfaceBinderForName(InterfaceBinder* binder, - const std::string& interface_name) { - registry_->SetInterfaceBinderForName(binder, interface_name); - } - void RemoveInterfaceBinderForName(const std::string& interface_name) { - registry_->RemoveInterfaceBinderForName(interface_name); - } - - private: - InterfaceRegistry* registry_; - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - // Construct with a Connection (which may be null), and create an - // InterfaceProvider pipe, the client end of which may be obtained by calling - // TakeClientHandle(). If |connection| is non-null, the Mojo Shell's - // rules filtering which interfaces are allowed to be exposed to clients are - // imposed on this registry. If null, they are not. - explicit InterfaceRegistry(Connection* connection); - // Construct with an InterfaceProviderRequest and a Connection (which may be - // null, see note above about filtering). - InterfaceRegistry(shell::mojom::InterfaceProviderRequest request, - Connection* connection); - ~InterfaceRegistry() override; - - // Takes the client end of the InterfaceProvider pipe created in the - // constructor. - shell::mojom::InterfaceProviderPtr TakeClientHandle(); - - template <typename Interface> - bool AddInterface(InterfaceFactory<Interface>* factory) { - return SetInterfaceBinderForName( - new internal::InterfaceFactoryBinder<Interface>(factory), - Interface::Name_); - } - - void set_default_binder(InterfaceBinder* binder) { default_binder_ = binder; } - - private: - using NameToInterfaceBinderMap = std::map<std::string, InterfaceBinder*>; - - // shell::mojom::InterfaceProvider: - void GetInterface(const String& interface_name, - ScopedMessagePipeHandle handle) override; - - // Returns true if the binder was set, false if it was not set (e.g. by - // some filtering policy preventing this interface from being exposed). - bool SetInterfaceBinderForName(InterfaceBinder* binder, - const std::string& name); - - void RemoveInterfaceBinderForName(const std::string& interface_name); - - shell::mojom::InterfaceProviderPtr client_handle_; - Binding<shell::mojom::InterfaceProvider> binding_; - Connection* connection_; - - InterfaceBinder* default_binder_; - NameToInterfaceBinderMap name_to_binder_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceRegistry); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_INTERFACE_REGISTRY_H_ diff --git a/chromium/mojo/shell/public/cpp/lib/application_runner.cc b/chromium/mojo/shell/public/cpp/lib/application_runner.cc deleted file mode 100644 index 201aa62da40..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/application_runner.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/public/cpp/application_runner.h" - -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/process/launch.h" -#include "base/run_loop.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" - -namespace mojo { - -int g_application_runner_argc; -const char* const* g_application_runner_argv; - -ApplicationRunner::ApplicationRunner(ShellClient* client) - : client_(scoped_ptr<ShellClient>(client)), - message_loop_type_(base::MessageLoop::TYPE_DEFAULT), - has_run_(false) {} - -ApplicationRunner::~ApplicationRunner() {} - -void ApplicationRunner::InitBaseCommandLine() { - base::CommandLine::Init(g_application_runner_argc, g_application_runner_argv); -} - -void ApplicationRunner::set_message_loop_type(base::MessageLoop::Type type) { - DCHECK_NE(base::MessageLoop::TYPE_CUSTOM, type); - DCHECK(!has_run_); - - message_loop_type_ = type; -} - -MojoResult ApplicationRunner::Run(MojoHandle shell_client_request_handle, - bool init_base) { - DCHECK(!has_run_); - has_run_ = true; - - scoped_ptr<base::AtExitManager> at_exit; - if (init_base) { - InitBaseCommandLine(); - at_exit.reset(new base::AtExitManager); - } - - { - scoped_ptr<base::MessageLoop> loop; - loop.reset(new base::MessageLoop(message_loop_type_)); - - connection_.reset(new ShellConnection( - client_.get(), - MakeRequest<shell::mojom::ShellClient>(MakeScopedHandle( - MessagePipeHandle(shell_client_request_handle))))); - base::RunLoop run_loop; - connection_->set_connection_lost_closure(run_loop.QuitClosure()); - run_loop.Run(); - // It's very common for the client to cache the app and terminate on errors. - // If we don't delete the client before the app we run the risk of the - // client having a stale reference to the app and trying to use it. - // Note that we destruct the message loop first because that might trigger - // connection error handlers and they might access objects created by the - // client. - loop.reset(); - client_.reset(); - connection_.reset(); - } - return MOJO_RESULT_OK; -} - -MojoResult ApplicationRunner::Run(MojoHandle shell_client_request_handle) { - bool init_base = true; - if (base::CommandLine::InitializedForCurrentProcess()) { - init_base = - !base::CommandLine::ForCurrentProcess()->HasSwitch("single-process"); - } - return Run(shell_client_request_handle, init_base); -} - -void ApplicationRunner::DestroyShellConnection() { - connection_.reset(); -} - -void ApplicationRunner::Quit() { - base::MessageLoop::current()->QuitWhenIdle(); -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/application_test_base.cc b/chromium/mojo/shell/public/cpp/lib/application_test_base.cc deleted file mode 100644 index a52a193563b..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/application_test_base.cc +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/shell/public/cpp/application_test_base.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace mojo { -namespace test { - -namespace { - -// Share the application name with multiple application tests. -shell::mojom::IdentityPtr g_identity; -uint32_t g_id = shell::mojom::kInvalidInstanceID; - -// ShellClient request handle passed from the shell in MojoMain, stored in -// between SetUp()/TearDown() so we can (re-)intialize new ShellConnections. -InterfaceRequest<shell::mojom::ShellClient> g_shell_client_request; - -// Connector pointer passed in the initial mojo.ShellClient.Initialize() call, -// stored in between initial setup and the first test and between SetUp/TearDown -// calls so we can (re-)initialize new ShellConnections. -shell::mojom::ConnectorPtr g_connector; - -class ShellGrabber : public shell::mojom::ShellClient { - public: - explicit ShellGrabber(InterfaceRequest<shell::mojom::ShellClient> request) - : binding_(this, std::move(request)) { - binding_.set_connection_error_handler([] { _exit(1); }); - } - - void WaitForInitialize() { - // Initialize is always the first call made on ShellClient. - CHECK(binding_.WaitForIncomingMethodCall()); - } - - private: - // shell::mojom::ShellClient implementation. - void Initialize(shell::mojom::IdentityPtr identity, - uint32_t id, - const InitializeCallback& callback) override { - callback.Run(GetProxy(&g_connector)); - - g_identity = std::move(identity); - g_id = id; - g_shell_client_request = binding_.Unbind(); - } - - void AcceptConnection( - shell::mojom::IdentityPtr source, - uint32_t source_id, - shell::mojom::InterfaceProviderRequest local_interfaces, - shell::mojom::InterfaceProviderPtr remote_interfaces, - shell::mojom::CapabilityRequestPtr capability_spec, - const String& name) override { - CHECK(false); - } - - Binding<ShellClient> binding_; -}; - -void IgnoreConnectorRequest(shell::mojom::ConnectorRequest) {} - -} // namespace - -MojoResult RunAllTests(MojoHandle shell_client_request_handle) { - { - // This loop is used for init, and then destroyed before running tests. - base::MessageLoop message_loop; - - // Grab the shell handle. - ShellGrabber grabber( - MakeRequest<shell::mojom::ShellClient>(MakeScopedHandle( - MessagePipeHandle(shell_client_request_handle)))); - grabber.WaitForInitialize(); - CHECK(g_connector); - CHECK(g_shell_client_request.is_pending()); - - int argc = 0; - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - const char** argv = new const char* [cmd_line->argv().size() + 1]; -#if defined(OS_WIN) - std::vector<std::string> local_strings; -#endif - for (auto& arg : cmd_line->argv()) { -#if defined(OS_WIN) - local_strings.push_back(base::WideToUTF8(arg)); - argv[argc++] = local_strings.back().c_str(); -#else - argv[argc++] = arg.c_str(); -#endif - } - argv[argc] = nullptr; - - testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0]))); - } - - int result = RUN_ALL_TESTS(); - - // Shut down our message pipes before exiting. - (void)g_shell_client_request.PassMessagePipe(); - g_connector.reset(); - - return (result == 0) ? MOJO_RESULT_OK : MOJO_RESULT_UNKNOWN; -} - -TestHelper::TestHelper(ShellClient* client) - : shell_connection_(new ShellConnection( - client == nullptr ? &default_shell_client_ : client, - std::move(g_shell_client_request))), - name_(g_identity->name), - userid_(g_identity->user_id), - instance_id_(g_id) { - shell_connection_->SetAppTestConnectorForTesting(std::move(g_connector)); - - // Fake ShellClient initialization. - shell::mojom::ShellClient* shell_client = shell_connection_.get(); - shell_client->Initialize(std::move(g_identity), g_id, - base::Bind(&IgnoreConnectorRequest)); -} - -TestHelper::~TestHelper() { - // We may have supplied a member as the client. Delete |shell_connection_| - // while still valid. - shell_connection_.reset(); -} - -ApplicationTestBase::ApplicationTestBase() : test_helper_(nullptr) {} - -ApplicationTestBase::~ApplicationTestBase() { -} - -ShellClient* ApplicationTestBase::GetShellClient() { - return nullptr; -} - -void ApplicationTestBase::SetUp() { - // A run loop is recommended for ShellConnection initialization and - // communication. - if (ShouldCreateDefaultRunLoop()) { - CHECK(!base::MessageLoop::current()); - // Not leaked: accessible from |base::MessageLoop::current()|. - base::MessageLoop* message_loop = new base::MessageLoop(); - CHECK_EQ(message_loop, base::MessageLoop::current()); - } - - CHECK(g_shell_client_request.is_pending()); - CHECK(g_connector); - - // New applications are constructed for each test to avoid persisting state. - test_helper_.reset(new TestHelper(GetShellClient())); -} - -void ApplicationTestBase::TearDown() { - CHECK(!g_shell_client_request.is_pending()); - CHECK(!g_connector); - - test_helper_.reset(); - - if (ShouldCreateDefaultRunLoop()) { - CHECK(base::MessageLoop::current()); - delete base::MessageLoop::current(); - CHECK(!base::MessageLoop::current()); - } -} - -bool ApplicationTestBase::ShouldCreateDefaultRunLoop() { - return true; -} - -} // namespace test -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/application_test_main.cc b/chromium/mojo/shell/public/cpp/lib/application_test_main.cc deleted file mode 100644 index 470846ce1d8..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/application_test_main.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/test/test_timeouts.h" -#include "mojo/logging/init_logging.h" -#include "mojo/public/c/system/main.h" -#include "mojo/shell/public/cpp/application_runner.h" -#include "mojo/shell/public/cpp/application_test_base.h" - -MojoResult MojoMain(MojoHandle handle) { - // An AtExitManager instance is needed to construct message loops. - base::AtExitManager at_exit; - - // Initialize the current process Commandline and test timeouts. - mojo::ApplicationRunner::InitBaseCommandLine(); - mojo::InitLogging(); - TestTimeouts::Initialize(); - - return mojo::test::RunAllTests(handle); -} diff --git a/chromium/mojo/shell/public/cpp/lib/capabilities.cc b/chromium/mojo/shell/public/cpp/lib/capabilities.cc deleted file mode 100644 index a132fe62a5a..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/capabilities.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/capabilities.h" - -namespace mojo { - -CapabilityRequest::CapabilityRequest() {} -CapabilityRequest::CapabilityRequest(const CapabilityRequest& other) = default; -CapabilityRequest::~CapabilityRequest() {} - -bool CapabilityRequest::operator==(const CapabilityRequest& other) const { - return other.classes == classes && other.interfaces == interfaces; -} - -bool CapabilityRequest::operator<(const CapabilityRequest& other) const { - return std::tie(classes, interfaces) < - std::tie(other.classes, other.interfaces); -} - -CapabilitySpec::CapabilitySpec() {} -CapabilitySpec::CapabilitySpec(const CapabilitySpec& other) = default; -CapabilitySpec::~CapabilitySpec() {} - -bool CapabilitySpec::operator==(const CapabilitySpec& other) const { - return other.provided == provided && other.required == required; -} - -bool CapabilitySpec::operator<(const CapabilitySpec& other) const { - return std::tie(provided, required) < - std::tie(other.provided, other.required); -} - -// static -shell::mojom::CapabilitySpecPtr -TypeConverter<shell::mojom::CapabilitySpecPtr, CapabilitySpec>::Convert( - const CapabilitySpec& input) { - shell::mojom::CapabilitySpecPtr spec(shell::mojom::CapabilitySpec::New()); - spec->provided = - mojo::Map<mojo::String, mojo::Array<mojo::String>>::From(input.provided); - spec->required = - mojo::Map<mojo::String, shell::mojom::CapabilityRequestPtr>::From( - input.required); - return spec; -} - -// static -CapabilitySpec -TypeConverter<CapabilitySpec, shell::mojom::CapabilitySpecPtr>::Convert( - const shell::mojom::CapabilitySpecPtr& input) { - CapabilitySpec spec; - spec.provided = input->provided.To<std::map<Class, Interfaces>>(); - spec.required = - input->required.To<std::map<Name, CapabilityRequest>>(); - return spec; -} - -// static -shell::mojom::CapabilityRequestPtr -TypeConverter<shell::mojom::CapabilityRequestPtr, - CapabilityRequest>::Convert( - const CapabilityRequest& input) { - shell::mojom::CapabilityRequestPtr request( - shell::mojom::CapabilityRequest::New()); - request->classes = mojo::Array<mojo::String>::From(input.classes); - request->interfaces = mojo::Array<mojo::String>::From(input.interfaces); - return request; -} - -// static -CapabilityRequest -TypeConverter<CapabilityRequest, - shell::mojom::CapabilityRequestPtr>::Convert( - const shell::mojom::CapabilityRequestPtr& input) { - CapabilityRequest request; - request.classes = input->classes.To<std::set<std::string>>(); - request.interfaces = input->interfaces.To<std::set<std::string>>(); - return request; -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/connection_impl.cc b/chromium/mojo/shell/public/cpp/lib/connection_impl.cc deleted file mode 100644 index 5cfed524687..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/connection_impl.cc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/public/cpp/lib/connection_impl.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/interface_binder.h" - -namespace mojo { -namespace internal { - -//////////////////////////////////////////////////////////////////////////////// -// ConnectionImpl, public: - -ConnectionImpl::ConnectionImpl( - const std::string& connection_name, - const Identity& remote, - uint32_t remote_id, - shell::mojom::InterfaceProviderPtr remote_interfaces, - shell::mojom::InterfaceProviderRequest local_interfaces, - const CapabilityRequest& capability_request, - State initial_state) - : connection_name_(connection_name), - remote_(remote), - remote_id_(remote_id), - state_(initial_state), - local_registry_(std::move(local_interfaces), this), - remote_interfaces_(std::move(remote_interfaces)), - capability_request_(capability_request), - allow_all_interfaces_(capability_request.interfaces.size() == 1 && - capability_request.interfaces.count("*") == 1), - weak_factory_(this) {} - -ConnectionImpl::ConnectionImpl() - : local_registry_(shell::mojom::InterfaceProviderRequest(), this), - allow_all_interfaces_(true), - weak_factory_(this) {} - -ConnectionImpl::~ConnectionImpl() {} - -shell::mojom::Connector::ConnectCallback ConnectionImpl::GetConnectCallback() { - return base::Bind(&ConnectionImpl::OnConnectionCompleted, - weak_factory_.GetWeakPtr()); -} - -//////////////////////////////////////////////////////////////////////////////// -// ConnectionImpl, Connection implementation: - -bool ConnectionImpl::HasCapabilityClass(const std::string& class_name) const { - return capability_request_.classes.count(class_name) > 0; -} - -const std::string& ConnectionImpl::GetConnectionName() { - return connection_name_; -} - -const Identity& ConnectionImpl::GetRemoteIdentity() const { - return remote_; -} - -void ConnectionImpl::SetConnectionLostClosure(const Closure& handler) { - remote_interfaces_.set_connection_error_handler(handler); -} - -shell::mojom::ConnectResult ConnectionImpl::GetResult() const { - return result_; -} - -bool ConnectionImpl::IsPending() const { - return state_ == State::PENDING; -} - -uint32_t ConnectionImpl::GetRemoteInstanceID() const { - return remote_id_; -} - -void ConnectionImpl::AddConnectionCompletedClosure(const Closure& callback) { - if (IsPending()) - connection_completed_callbacks_.push_back(callback); - else - callback.Run(); -} - -bool ConnectionImpl::AllowsInterface(const std::string& interface_name) const { - return allow_all_interfaces_ || - capability_request_.interfaces.count(interface_name); -} - -shell::mojom::InterfaceProvider* ConnectionImpl::GetRemoteInterfaces() { - return remote_interfaces_.get(); -} - -InterfaceRegistry* ConnectionImpl::GetLocalRegistry() { - return &local_registry_; -} - -base::WeakPtr<Connection> ConnectionImpl::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -//////////////////////////////////////////////////////////////////////////////// -// ConnectionImpl, private: - -void ConnectionImpl::OnConnectionCompleted(shell::mojom::ConnectResult result, - const std::string& target_user_id, - uint32_t target_application_id) { - DCHECK(State::PENDING == state_); - - result_ = result; - state_ = result_ == shell::mojom::ConnectResult::SUCCEEDED ? - State::CONNECTED : State::DISCONNECTED; - remote_id_ = target_application_id; - remote_.set_user_id(target_user_id); - std::vector<Closure> callbacks; - callbacks.swap(connection_completed_callbacks_); - for (auto callback : callbacks) - callback.Run(); -} - -} // namespace internal -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/connection_impl.h b/chromium/mojo/shell/public/cpp/lib/connection_impl.h deleted file mode 100644 index 2c58d86c0cc..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/connection_impl.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTION_IMPL_H_ -#define MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTION_IMPL_H_ - -#include <stdint.h> - -#include <set> -#include <string> - -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/shell/public/cpp/capabilities.h" -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" - -namespace mojo { -namespace internal { - -// A ConnectionImpl represents each half of a connection between two -// applications, allowing customization of which interfaces are published to the -// other. -class ConnectionImpl : public Connection { - public: - ConnectionImpl(); - // |allowed_interfaces| are the set of interfaces that the shell has allowed - // an application to expose to another application. If this set contains only - // the string value "*" all interfaces may be exposed. - ConnectionImpl(const std::string& connection_name, - const Identity& remote, - uint32_t remote_id, - shell::mojom::InterfaceProviderPtr remote_interfaces, - shell::mojom::InterfaceProviderRequest local_interfaces, - const CapabilityRequest& capability_request, - State initial_state); - ~ConnectionImpl() override; - - shell::mojom::Connector::ConnectCallback GetConnectCallback(); - - private: - // Connection: - bool HasCapabilityClass(const std::string& class_name) const override; - const std::string& GetConnectionName() override; - const Identity& GetRemoteIdentity() const override; - void SetConnectionLostClosure(const Closure& handler) override; - shell::mojom::ConnectResult GetResult() const override; - bool IsPending() const override; - uint32_t GetRemoteInstanceID() const override; - void AddConnectionCompletedClosure(const Closure& callback) override; - bool AllowsInterface(const std::string& interface_name) const override; - shell::mojom::InterfaceProvider* GetRemoteInterfaces() override; - InterfaceRegistry* GetLocalRegistry() override; - base::WeakPtr<Connection> GetWeakPtr() override; - - void OnConnectionCompleted(shell::mojom::ConnectResult result, - const std::string& target_user_id, - uint32_t target_application_id); - - const std::string connection_name_; - Identity remote_; - uint32_t remote_id_ = shell::mojom::kInvalidInstanceID; - - State state_; - shell::mojom::ConnectResult result_ = shell::mojom::ConnectResult::SUCCEEDED; - std::vector<Closure> connection_completed_callbacks_; - - InterfaceRegistry local_registry_; - shell::mojom::InterfaceProviderPtr remote_interfaces_; - - const CapabilityRequest capability_request_; - const bool allow_all_interfaces_; - - base::WeakPtrFactory<ConnectionImpl> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ConnectionImpl); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTION_IMPL_H_ diff --git a/chromium/mojo/shell/public/cpp/lib/connector_impl.cc b/chromium/mojo/shell/public/cpp/lib/connector_impl.cc deleted file mode 100644 index 3b16a0cd621..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/connector_impl.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/lib/connector_impl.h" - -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/cpp/lib/connection_impl.h" - -namespace mojo { - -Connector::ConnectParams::ConnectParams(const Identity& target) - : target_(target) {} -Connector::ConnectParams::ConnectParams(const std::string& name) - : target_(name, shell::mojom::kInheritUserID) {} -Connector::ConnectParams::~ConnectParams() {} - -ConnectorImpl::ConnectorImpl(shell::mojom::ConnectorPtrInfo unbound_state) - : unbound_state_(std::move(unbound_state)) {} -ConnectorImpl::ConnectorImpl(shell::mojom::ConnectorPtr connector) - : connector_(std::move(connector)) { - thread_checker_.reset(new base::ThreadChecker); -} -ConnectorImpl::~ConnectorImpl() {} - -scoped_ptr<Connection> ConnectorImpl::Connect(const std::string& name) { - ConnectParams params(name); - return Connect(¶ms); -} - -scoped_ptr<Connection> ConnectorImpl::Connect(ConnectParams* params) { - // Bind this object to the current thread the first time it is used to - // connect. - if (!connector_.is_bound()) { - if (!unbound_state_.is_valid()) { - // It's possible to get here when the link to the shell has been severed - // (and so the connector pipe has been closed) but the app has chosen not - // to quit. - return nullptr; - } - connector_.Bind(std::move(unbound_state_)); - thread_checker_.reset(new base::ThreadChecker); - } - DCHECK(thread_checker_->CalledOnValidThread()); - - DCHECK(params); - // We allow all interfaces on outgoing connections since we are presumably in - // a position to know who we're talking to. - CapabilityRequest request; - request.interfaces.insert("*"); - shell::mojom::InterfaceProviderPtr local_interfaces; - shell::mojom::InterfaceProviderRequest local_request = - GetProxy(&local_interfaces); - shell::mojom::InterfaceProviderPtr remote_interfaces; - shell::mojom::InterfaceProviderRequest remote_request = - GetProxy(&remote_interfaces); - scoped_ptr<internal::ConnectionImpl> registry(new internal::ConnectionImpl( - params->target().name(), params->target(), - shell::mojom::kInvalidInstanceID, std::move(remote_interfaces), - std::move(local_request), request, Connection::State::PENDING)); - - shell::mojom::ShellClientPtr shell_client; - shell::mojom::PIDReceiverRequest pid_receiver_request; - params->TakeClientProcessConnection(&shell_client, &pid_receiver_request); - shell::mojom::ClientProcessConnectionPtr client_process_connection; - if (shell_client.is_bound() && pid_receiver_request.is_pending()) { - client_process_connection = shell::mojom::ClientProcessConnection::New(); - client_process_connection->shell_client = - shell_client.PassInterface().PassHandle(); - client_process_connection->pid_receiver_request = - pid_receiver_request.PassMessagePipe(); - } else if (shell_client.is_bound() || pid_receiver_request.is_pending()) { - NOTREACHED() << "If one of shell_client or pid_receiver_request is valid, " - << "both must be valid."; - return std::move(registry); - } - connector_->Connect( - shell::mojom::Identity::From(params->target()), - std::move(remote_request), std::move(local_interfaces), - std::move(client_process_connection), registry->GetConnectCallback()); - return std::move(registry); -} - -scoped_ptr<Connector> ConnectorImpl::Clone() { - shell::mojom::ConnectorPtr connector; - connector_->Clone(GetProxy(&connector)); - return make_scoped_ptr( - new ConnectorImpl(connector.PassInterface())); -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/connector_impl.h b/chromium/mojo/shell/public/cpp/lib/connector_impl.h deleted file mode 100644 index 74db73dec4b..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/connector_impl.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTOR_IMPL_H_ -#define MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTOR_IMPL_H_ - -#include "base/callback.h" -#include "base/threading/thread_checker.h" -#include "mojo/shell/public/cpp/connector.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" - -namespace mojo { - -class ConnectorImpl : public Connector { - public: - explicit ConnectorImpl(shell::mojom::ConnectorPtrInfo unbound_state); - explicit ConnectorImpl(shell::mojom::ConnectorPtr connector); - ~ConnectorImpl() override; - - private: - // Connector: - scoped_ptr<Connection> Connect(const std::string& name) override; - scoped_ptr<Connection> Connect(ConnectParams* params) override; - scoped_ptr<Connector> Clone() override; - - shell::mojom::ConnectorPtrInfo unbound_state_; - shell::mojom::ConnectorPtr connector_; - - scoped_ptr<base::ThreadChecker> thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(ConnectorImpl); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_LIB_CONNECTOR_IMPL_H_ diff --git a/chromium/mojo/shell/public/cpp/lib/identity.cc b/chromium/mojo/shell/public/cpp/lib/identity.cc deleted file mode 100644 index 85860a0c3a7..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/identity.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/identity.h" - -#include "base/guid.h" -#include "mojo/shell/public/cpp/names.h" - -namespace mojo { - -Identity::Identity() {} - -Identity::Identity(const std::string& name, const std::string& user_id) - : Identity(name, user_id, "") {} - -Identity::Identity(const std::string& name, const std::string& user_id, - const std::string& instance) - : name_(name), - user_id_(user_id), - instance_(instance.empty() ? GetNamePath(name_) : instance) { - CHECK(!user_id.empty()); - CHECK(base::IsValidGUID(user_id)); -} - -Identity::Identity(const Identity& other) = default; - -Identity::~Identity() {} - -bool Identity::operator<(const Identity& other) const { - if (name_ != other.name_) - return name_ < other.name_; - if (instance_ != other.instance_) - return instance_ < other.instance_; - return user_id_ < other.user_id_; -} - -bool Identity::operator==(const Identity& other) const { - return other.name_ == name_ && other.instance_ == instance_ && - other.user_id_ == user_id_; -} - -// static -shell::mojom::IdentityPtr - TypeConverter<shell::mojom::IdentityPtr, Identity>::Convert( - const Identity& input) { - shell::mojom::IdentityPtr identity(shell::mojom::Identity::New()); - identity->name = input.name(); - identity->user_id = input.user_id(); - identity->instance = input.instance(); - return identity; -} - -// static -Identity TypeConverter<Identity, shell::mojom::IdentityPtr>::Convert( - const shell::mojom::IdentityPtr& input) { - return Identity(input->name, input->user_id, input->instance); -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/init_commandline.cc b/chromium/mojo/shell/public/cpp/lib/init_commandline.cc deleted file mode 100644 index a61797b4fcc..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/init_commandline.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "build/build_config.h" - -namespace mojo { - -extern int g_application_runner_argc; -extern const char* const* g_application_runner_argv; - -} - -#if !defined(OS_WIN) -extern "C" { -__attribute__((visibility("default"))) void InitCommandLineArgs( - int argc, const char* const* argv) { - mojo::g_application_runner_argc = argc; - mojo::g_application_runner_argv = argv; -} -} -#endif diff --git a/chromium/mojo/shell/public/cpp/lib/interface_factory_binder.h b/chromium/mojo/shell/public/cpp/lib/interface_factory_binder.h deleted file mode 100644 index e4f6815797a..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/interface_factory_binder.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_LIB_INTERFACE_FACTORY_BINDER_H_ -#define MOJO_SHELL_PUBLIC_CPP_LIB_INTERFACE_FACTORY_BINDER_H_ - -#include <utility> - -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/public/cpp/interface_binder.h" -#include "mojo/shell/public/cpp/interface_factory.h" - -namespace mojo { -namespace internal { - -template <typename Interface> -class InterfaceFactoryBinder : public InterfaceBinder { - public: - explicit InterfaceFactoryBinder(InterfaceFactory<Interface>* factory) - : factory_(factory) {} - ~InterfaceFactoryBinder() override {} - - void BindInterface(Connection* connection, - const std::string& interface_name, - ScopedMessagePipeHandle client_handle) override { - factory_->Create(connection, - MakeRequest<Interface>(std::move(client_handle))); - } - - private: - InterfaceFactory<Interface>* factory_; - DISALLOW_COPY_AND_ASSIGN(InterfaceFactoryBinder); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_LIB_INTERFACE_FACTORY_BINDER_H_ diff --git a/chromium/mojo/shell/public/cpp/lib/interface_registry.cc b/chromium/mojo/shell/public/cpp/lib/interface_registry.cc deleted file mode 100644 index 98a91cefd5c..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/interface_registry.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/interface_registry.h" - -#include "mojo/shell/public/cpp/connection.h" - -namespace mojo { - -InterfaceRegistry::InterfaceRegistry(Connection* connection) - : InterfaceRegistry(nullptr, connection) {} - -InterfaceRegistry::InterfaceRegistry( - shell::mojom::InterfaceProviderRequest request, - Connection* connection) - : binding_(this), - connection_(connection), - default_binder_(nullptr) { - if (!request.is_pending()) - request = GetProxy(&client_handle_); - binding_.Bind(std::move(request)); -} - -InterfaceRegistry::~InterfaceRegistry() { - for (auto& i : name_to_binder_) - delete i.second; - name_to_binder_.clear(); -} - -shell::mojom::InterfaceProviderPtr InterfaceRegistry::TakeClientHandle() { - return std::move(client_handle_); -} - -// shell::mojom::InterfaceProvider: -void InterfaceRegistry::GetInterface(const String& interface_name, - ScopedMessagePipeHandle handle) { - auto iter = name_to_binder_.find(interface_name); - InterfaceBinder* binder = iter != name_to_binder_.end() ? iter->second : - default_binder_; - if (binder) - binder->BindInterface(connection_, interface_name, std::move(handle)); -} - -bool InterfaceRegistry::SetInterfaceBinderForName( - InterfaceBinder* binder, - const std::string& interface_name) { - if (!connection_ || - (connection_ && connection_->AllowsInterface(interface_name))) { - RemoveInterfaceBinderForName(interface_name); - name_to_binder_[interface_name] = binder; - return true; - } - LOG(WARNING) << "Connection CapabilityFilter prevented binding to interface: " - << interface_name << " connection_name:" - << connection_->GetConnectionName() << " remote_name:" - << connection_->GetRemoteIdentity().name(); - return false; -} - -void InterfaceRegistry::RemoveInterfaceBinderForName( - const std::string& interface_name) { - NameToInterfaceBinderMap::iterator it = name_to_binder_.find(interface_name); - if (it == name_to_binder_.end()) - return; - delete it->second; - name_to_binder_.erase(it); -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/message_loop_ref.cc b/chromium/mojo/shell/public/cpp/lib/message_loop_ref.cc deleted file mode 100644 index a285cdadf02..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/message_loop_ref.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/message_loop_ref.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" - -namespace mojo { - -class MessageLoopRefImpl : public MessageLoopRef { - public: - MessageLoopRefImpl( - MessageLoopRefFactory* factory, - scoped_refptr<base::SingleThreadTaskRunner> app_task_runner) - : factory_(factory), - app_task_runner_(app_task_runner) {} - ~MessageLoopRefImpl() override { -#ifndef NDEBUG - // Ensure that this object is used on only one thread at a time, or else - // there could be races where the object is being reset on one thread and - // cloned on another. - if (clone_task_runner_) - DCHECK(clone_task_runner_->BelongsToCurrentThread()); -#endif - - if (app_task_runner_->BelongsToCurrentThread()) { - factory_->Release(); - } else { - app_task_runner_->PostTask( - FROM_HERE, - base::Bind(&MessageLoopRefFactory::Release, - base::Unretained(factory_))); - } - } - - private: - // MessageLoopRef: - scoped_ptr<MessageLoopRef> Clone() override { - if (app_task_runner_->BelongsToCurrentThread()) { - factory_->AddRef(); - } else { - app_task_runner_->PostTask( - FROM_HERE, - base::Bind(&MessageLoopRefFactory::AddRef, - base::Unretained(factory_))); - } - -#ifndef NDEBUG - // Ensure that this object is used on only one thread at a time, or else - // there could be races where the object is being reset on one thread and - // cloned on another. - if (clone_task_runner_) { - DCHECK(clone_task_runner_->BelongsToCurrentThread()); - } else { - clone_task_runner_ = base::MessageLoop::current()->task_runner(); - } -#endif - - return make_scoped_ptr(new MessageLoopRefImpl(factory_, app_task_runner_)); - } - - MessageLoopRefFactory* factory_; - scoped_refptr<base::SingleThreadTaskRunner> app_task_runner_; - -#ifndef NDEBUG - scoped_refptr<base::SingleThreadTaskRunner> clone_task_runner_; -#endif - - DISALLOW_COPY_AND_ASSIGN(MessageLoopRefImpl); -}; - -MessageLoopRefFactory::MessageLoopRefFactory() {} -MessageLoopRefFactory::~MessageLoopRefFactory() {} - -scoped_ptr<MessageLoopRef> MessageLoopRefFactory::CreateRef() { - AddRef(); - return make_scoped_ptr(new MessageLoopRefImpl( - this, base::MessageLoop::current()->task_runner())); -} - -void MessageLoopRefFactory::AddRef() { - ++ref_count_; -} - -void MessageLoopRefFactory::Release() { - if (!--ref_count_) { - if (!quit_closure_.is_null()) - quit_closure_.Run(); - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { - base::MessageLoop::current()->QuitWhenIdle(); - } - } -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/names.cc b/chromium/mojo/shell/public/cpp/lib/names.cc deleted file mode 100644 index 971e8aae835..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/names.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/names.h" - -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" - -namespace mojo { - -const char kNameType_Mojo[] = "mojo"; -const char kNameType_Exe[] = "exe"; - -bool IsValidName(const std::string& name) { - std::vector<std::string> parts = - base::SplitString(name, ":", base::KEEP_WHITESPACE, - base::SPLIT_WANT_ALL); - if (parts.size() != 2) - return false; - - if (parts.front().empty()) - return false; - - const std::string& path = parts.back(); - return !path.empty() && - !base::StartsWith(path, "//", base::CompareCase::INSENSITIVE_ASCII); -} - -std::string GetNameType(const std::string& name) { - std::vector<std::string> parts = - base::SplitString(name, ":", base::KEEP_WHITESPACE, - base::SPLIT_WANT_ALL); - DCHECK(2 == parts.size()); - return parts.front(); -} - -std::string GetNamePath(const std::string& name) { - std::vector<std::string> parts = - base::SplitString(name, ":", base::KEEP_WHITESPACE, - base::SPLIT_WANT_ALL); - DCHECK(2 == parts.size()); - return parts.back(); -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/shell_client.cc b/chromium/mojo/shell/public/cpp/lib/shell_client.cc deleted file mode 100644 index 3ca8cd7b319..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/shell_client.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/public/cpp/shell_client.h" - -namespace mojo { - -ShellClient::ShellClient() {} -ShellClient::~ShellClient() {} - -void ShellClient::Initialize(Connector* connector, const Identity& identity, - uint32_t id) { -} - -bool ShellClient::AcceptConnection(Connection* connection) { - return false; -} - -bool ShellClient::ShellConnectionLost() { return true; } - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/shell_connection.cc b/chromium/mojo/shell/public/cpp/lib/shell_connection.cc deleted file mode 100644 index 62ae598222c..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/shell_connection.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/public/cpp/capabilities.h" -#include "mojo/shell/public/cpp/connector.h" -#include "mojo/shell/public/cpp/lib/connection_impl.h" -#include "mojo/shell/public/cpp/lib/connector_impl.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" - -namespace mojo { - -//////////////////////////////////////////////////////////////////////////////// -// ShellConnection, public: - -ShellConnection::ShellConnection(mojo::ShellClient* client, - shell::mojom::ShellClientRequest request) - : client_(client), binding_(this) { - shell::mojom::ConnectorPtr connector; - pending_connector_request_ = GetProxy(&connector); - connector_.reset(new ConnectorImpl(std::move(connector))); - - DCHECK(request.is_pending()); - binding_.Bind(std::move(request)); -} - -ShellConnection::~ShellConnection() {} - -void ShellConnection::set_initialize_handler(const base::Closure& callback) { - initialize_handler_ = callback; -} - -void ShellConnection::SetAppTestConnectorForTesting( - shell::mojom::ConnectorPtr connector) { - pending_connector_request_ = nullptr; - connector_.reset(new ConnectorImpl(std::move(connector))); -} - -//////////////////////////////////////////////////////////////////////////////// -// ShellConnection, shell::mojom::ShellClient implementation: - -void ShellConnection::Initialize(shell::mojom::IdentityPtr identity, - uint32_t id, - const InitializeCallback& callback) { - if (!initialize_handler_.is_null()) - initialize_handler_.Run(); - - callback.Run(std::move(pending_connector_request_)); - - DCHECK(binding_.is_bound()); - binding_.set_connection_error_handler([this] { OnConnectionError(); }); - - client_->Initialize(connector_.get(), identity.To<Identity>(), id); -} - -void ShellConnection::AcceptConnection( - shell::mojom::IdentityPtr source, - uint32_t source_id, - shell::mojom::InterfaceProviderRequest local_interfaces, - shell::mojom::InterfaceProviderPtr remote_interfaces, - shell::mojom::CapabilityRequestPtr allowed_capabilities, - const String& name) { - scoped_ptr<Connection> registry(new internal::ConnectionImpl( - name, source.To<Identity>(), source_id, std::move(remote_interfaces), - std::move(local_interfaces), - allowed_capabilities.To<CapabilityRequest>(), - Connection::State::CONNECTED)); - if (!client_->AcceptConnection(registry.get())) - return; - - // TODO(beng): it appears we never prune this list. We should, when the - // connection's remote service provider pipe breaks. - incoming_connections_.push_back(std::move(registry)); -} - -//////////////////////////////////////////////////////////////////////////////// -// ShellConnection, private: - -void ShellConnection::OnConnectionError() { - // Note that the ShellClient doesn't technically have to quit now, it may live - // on to service existing connections. All existing Connectors however are - // invalid. - if (client_->ShellConnectionLost() && !connection_lost_closure_.is_null()) - connection_lost_closure_.Run(); - // We don't reset the connector as clients may have taken a raw pointer to it. - // Connect() will return nullptr if they try to connect to anything. -} - -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/lib/shell_test.cc b/chromium/mojo/shell/public/cpp/lib/shell_test.cc deleted file mode 100644 index 605e7c59b1b..00000000000 --- a/chromium/mojo/shell/public/cpp/lib/shell_test.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 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/shell/public/cpp/shell_test.h" - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/shell/background/background_shell.h" -#include "mojo/shell/public/cpp/shell_client.h" - -namespace mojo { -namespace test { - -ShellTestClient::ShellTestClient(ShellTest* test) : test_(test) {} -ShellTestClient::~ShellTestClient() {} - -void ShellTestClient::Initialize(Connector* connector, const Identity& identity, - uint32_t id) { - test_->InitializeCalled(connector, identity.name(), identity.user_id(), id); -} - -ShellTest::ShellTest() {} -ShellTest::ShellTest(const std::string& test_name) : test_name_(test_name) {} -ShellTest::~ShellTest() {} - -void ShellTest::InitTestName(const std::string& test_name) { - DCHECK(test_name_.empty()); - test_name_ = test_name; -} - -scoped_ptr<ShellClient> ShellTest::CreateShellClient() { - return make_scoped_ptr(new ShellTestClient(this)); -} - -scoped_ptr<base::MessageLoop> ShellTest::CreateMessageLoop() { - return make_scoped_ptr(new base::MessageLoop); -} - -void ShellTest::InitializeCalled(Connector* connector, - const std::string& name, - const std::string& user_id, - uint32_t id) { - DCHECK_EQ(connector_, connector); - initialize_name_ = name; - initialize_instance_id_ = id; - initialize_userid_ = user_id; - initialize_called_.Run(); -} - -void ShellTest::SetUp() { - shell_client_ = CreateShellClient(); - message_loop_ = CreateMessageLoop(); - background_shell_.reset(new shell::BackgroundShell); - background_shell_->Init(nullptr); - - // Create the shell connection. We don't proceed until we get our - // ShellClient's Initialize() method is called. - base::RunLoop run_loop; - base::MessageLoop::ScopedNestableTaskAllower allow( - base::MessageLoop::current()); - initialize_called_ = run_loop.QuitClosure(); - - shell_connection_.reset(new ShellConnection( - shell_client_.get(), - background_shell_->CreateShellClientRequest(test_name_))); - connector_ = shell_connection_->connector(); - - run_loop.Run(); -} - -void ShellTest::TearDown() { - shell_connection_.reset(); - background_shell_.reset(); - message_loop_.reset(); - shell_client_.reset(); -} - -} // namespace test -} // namespace mojo diff --git a/chromium/mojo/shell/public/cpp/message_loop_ref.h b/chromium/mojo/shell/public/cpp/message_loop_ref.h deleted file mode 100644 index f678746f3f6..00000000000 --- a/chromium/mojo/shell/public/cpp/message_loop_ref.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_MESSAGE_LOOP_REF_H_ -#define MOJO_SHELL_PUBLIC_CPP_MESSAGE_LOOP_REF_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -class MessageLoopRefImpl; - -// An interface implementation can keep this object as a member variable to -// hold a reference to the ShellConnection, keeping it alive as long as the -// bound implementation exists. -// Since interface implementations can be bound on different threads than the -// ShellConnection, this class is safe to use on any thread. However, each -// instance should only be used on one thread at a time (otherwise there'll be -// races between the AddRef resulting from cloning and destruction). -class MessageLoopRef { - public: - virtual ~MessageLoopRef() {} - - virtual scoped_ptr<MessageLoopRef> Clone() = 0; -}; - -class MessageLoopRefFactory { - public: - MessageLoopRefFactory(); - ~MessageLoopRefFactory(); - - void set_quit_closure(const base::Closure& quit_closure) { - quit_closure_ = quit_closure; - } - - scoped_ptr<MessageLoopRef> CreateRef(); - - private: - friend MessageLoopRefImpl; - - // Called from MessageLoopRefImpl. - void AddRef(); - void Release(); - - base::Closure quit_closure_; - int ref_count_ = 0; - - DISALLOW_COPY_AND_ASSIGN(MessageLoopRefFactory); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_MESSAGE_LOOP_REF_H_ diff --git a/chromium/mojo/shell/public/cpp/names.h b/chromium/mojo/shell/public/cpp/names.h deleted file mode 100644 index 86e899956bc..00000000000 --- a/chromium/mojo/shell/public/cpp/names.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_NAMES_H_ -#define MOJO_SHELL_PUBLIC_CPP_NAMES_H_ - -#include <string> - -namespace mojo { - -extern const char kNameType_Mojo[]; -extern const char kNameType_Exe[]; - -// Mojo services and applications are identified by structured "names", of the -// form: -// -// type:path. -// -// The type field tells the shell how to load the application. Two types are -// currently recognized: -// -// mojo -// Represents an application packaged as a .mojo, launched from the -// NativeRunner launch path. .mojo files are assumed to live alongside the -// shell executable at a path matching <path>/<path>.mojo. .mojo applications -// have a MojoMain() entrypoint that receives a handle to a ShellClientRequest -// that must be bound to enable further communication with the shell. -// -// exe -// Represents a native executable on the host platform, expected to live -// alongside the shell executable. Executables launched via this mechanism are -// passed a handle to the shell on the command line and are expected to bind -// a ShellClientRequest enabling further communication with the shell. The -// path component contains the executable name, minus any platform-specific -// extension. -// -// Other types may be supplied but are not recognized by any of the -// NativeRunners, and as such custom loaders must be specified for such names. -// -// Any name type may serve as an alias for any other name type. Aliasing is -// resolved implicitly by the Shell. - -// Returns true if the name is a valid form, i.e. type:path. path cannot start -// with a "//" sequence. These are _not_ urls. -bool IsValidName(const std::string& name); - -// Get the type component of the specified name. -std::string GetNameType(const std::string& name); - -// Get the path component of the specified name. -std::string GetNamePath(const std::string& name); - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_NAMES_H_ diff --git a/chromium/mojo/shell/public/cpp/shell_client.h b/chromium/mojo/shell/public/cpp/shell_client.h deleted file mode 100644 index aff1aac40ed..00000000000 --- a/chromium/mojo/shell/public/cpp/shell_client.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_SHELL_CLIENT_H_ -#define MOJO_SHELL_PUBLIC_CPP_SHELL_CLIENT_H_ - -#include <stdint.h> -#include <string> - -#include "base/macros.h" -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/identity.h" - -namespace mojo { - -class Connector; - -// An interface representing an instance "known to the Mojo Shell". The -// implementation receives lifecycle messages for the instance and gets the -// opportunity to handle inbound connections brokered by the Shell. Every client -// of ShellConnection must implement this interface, and instances of this -// interface must outlive the ShellConnection. -class ShellClient { - public: - ShellClient(); - virtual ~ShellClient(); - - // Called once a bidirectional connection with the shell has been established. - // |identity| is the identity of the instance. - // |id| is a unique identifier the shell uses to identify this specific - // instance of the application. - // Called exactly once before any other method. - virtual void Initialize(Connector* connector, - const Identity& identity, - uint32_t id); - - // Called when a connection to this client is brokered by the shell. Override - // to expose services to the remote application. Return true if the connection - // should succeed. Return false if the connection should be rejected and the - // underlying pipe closed. The default implementation returns false. - virtual bool AcceptConnection(Connection* connection); - - // Called when ShellConnection's ShellClient binding (i.e. the pipe the - // Mojo Shell has to talk to us over) is closed. A shell client may use this - // as a signal to terminate. Return true from this method to tell the - // ShellConnection to run its connection lost closure if it has one, false to - // prevent it from being run. The default implementation returns true. - // When used in conjunction with ApplicationRunner, returning true here quits - // the message loop created by ApplicationRunner, which results in the app - // quitting. - virtual bool ShellConnectionLost(); - - private: - DISALLOW_COPY_AND_ASSIGN(ShellClient); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_SHELL_CLIENT_H_ diff --git a/chromium/mojo/shell/public/cpp/shell_connection.h b/chromium/mojo/shell/public/cpp/shell_connection.h deleted file mode 100644 index 3e00cd362c0..00000000000 --- a/chromium/mojo/shell/public/cpp/shell_connection.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ -#define MOJO_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ - -#include <utility> -#include <vector> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace mojo { - -class Connector; - -// Encapsulates a connection to the Mojo Shell in two parts: -// - a bound InterfacePtr to mojo::shell::mojom::Shell, the primary mechanism -// by which the instantiating application interacts with other services -// brokered by the Mojo Shell. -// - a bound InterfaceRequest of mojo::shell::mojom::ShellClient, an interface -// used by the Mojo Shell to inform this application of lifecycle events and -// inbound connections brokered by it. -// -// This class should be used in two scenarios: -// - During early startup to bind the mojo::shell::mojom::ShellClientRequest -// obtained from the Mojo Shell. This is typically in response to either -// MojoMain() or main(). -// - In an implementation of mojo::shell::mojom::ContentHandler to bind the -// mojo::shell::mojom::ShellClientRequest passed via StartApplication. In this -// scenario there can be many instances of this class per process. -// -// Instances of this class are constructed with an implementation of the Shell -// Client Lib's mojo::ShellClient interface. See documentation in shell_client.h -// for details. -// -class ShellConnection : public shell::mojom::ShellClient { - public: - // Creates a new ShellConnection bound to |request|. This connection may be - // used immediately to make outgoing connections via connector(). Does not - // take ownership of |client|, which must remain valid for the lifetime of - // ShellConnection. - ShellConnection(mojo::ShellClient* client, - shell::mojom::ShellClientRequest request); - - ~ShellConnection() override; - - Connector* connector() { return connector_.get(); } - - // TODO(rockot): Remove this. http://crbug.com/594852. - void set_initialize_handler(const base::Closure& callback); - - // TODO(rockot): Remove this once we get rid of app tests. - void SetAppTestConnectorForTesting(shell::mojom::ConnectorPtr connector); - - // Specify a function to be called when the connection to the shell is lost. - void set_connection_lost_closure(const base::Closure& closure) { - connection_lost_closure_ = closure; - } - -private: - // shell::mojom::ShellClient: - void Initialize(shell::mojom::IdentityPtr identity, - uint32_t id, - const InitializeCallback& callback) override; - void AcceptConnection( - shell::mojom::IdentityPtr source, - uint32_t source_id, - shell::mojom::InterfaceProviderRequest remote_interfaces, - shell::mojom::InterfaceProviderPtr local_interfaces, - shell::mojom::CapabilityRequestPtr allowed_capabilities, - const String& name) override; - - void OnConnectionError(); - - // A callback called when Initialize() is run. - base::Closure initialize_handler_; - - // We track the lifetime of incoming connection registries as it more - // convenient for the client. - ScopedVector<Connection> incoming_connections_; - - // A pending Connector request which will eventually be passed to the shell. - shell::mojom::ConnectorRequest pending_connector_request_; - - mojo::ShellClient* client_; - Binding<shell::mojom::ShellClient> binding_; - scoped_ptr<Connector> connector_; - - base::Closure connection_lost_closure_; - - DISALLOW_COPY_AND_ASSIGN(ShellConnection); -}; - -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ diff --git a/chromium/mojo/shell/public/cpp/shell_test.h b/chromium/mojo/shell/public/cpp/shell_test.h deleted file mode 100644 index 3c8e3d8cbc4..00000000000 --- a/chromium/mojo/shell/public/cpp/shell_test.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_PUBLIC_CPP_SHELL_TEST_H_ -#define MOJO_SHELL_PUBLIC_CPP_SHELL_TEST_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/shell/public/cpp/connector.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -class MessageLoop; -} - -namespace mojo { -namespace shell { -class BackgroundShell; -} -namespace test { - -class ShellTest; - -// A default implementation of ShellClient for use in ShellTests. Tests wishing -// to customize this should subclass this class instead of ShellClient, -// otherwise they will have to call ShellTest::InitializeCalled() to forward -// metadata from Initialize() to the test. -class ShellTestClient : public mojo::ShellClient { - public: - explicit ShellTestClient(ShellTest* test); - ~ShellTestClient() override; - - protected: - void Initialize(Connector* connector, - const Identity& identity, - uint32_t id) override; - - private: - ShellTest* test_; - - DISALLOW_COPY_AND_ASSIGN(ShellTestClient); -}; - -class ShellTest : public testing::Test { - public: - ShellTest(); - // Initialize passing the name to use as the identity for the test itself. - // Once set via this constructor, it cannot be changed later by calling - // InitTestName(). The test executable must provide a manifest in the - // appropriate location that specifies this name also. - explicit ShellTest(const std::string& test_name); - ~ShellTest() override; - - protected: - // See constructor. Can only be called once. - void InitTestName(const std::string& test_name); - - Connector* connector() { return connector_; } - - // Instance information received from the Shell during Initialize(). - const std::string& test_name() const { return initialize_name_; } - const std::string& test_userid() const { return initialize_userid_; } - uint32_t test_instance_id() const { return initialize_instance_id_; } - - // By default, creates a simple ShellClient that captures the metadata sent - // via Initialize(). Override to customize, but custom implementations must - // call InitializeCalled() to forward the metadata so test_name() etc all - // work. - virtual scoped_ptr<ShellClient> CreateShellClient(); - - virtual scoped_ptr<base::MessageLoop> CreateMessageLoop(); - - // Call to set Initialize() metadata when GetShellClient() is overridden. - void InitializeCalled(Connector* connector, - const std::string& name, - const std::string& userid, - uint32_t id); - - // testing::Test: - void SetUp() override; - void TearDown() override; - - private: - friend ShellTestClient; - - scoped_ptr<ShellClient> shell_client_; - - scoped_ptr<base::MessageLoop> message_loop_; - scoped_ptr<shell::BackgroundShell> background_shell_; - scoped_ptr<ShellConnection> shell_connection_; - - // See constructor. - std::string test_name_; - - Connector* connector_ = nullptr; - std::string initialize_name_; - std::string initialize_userid_ = shell::mojom::kInheritUserID; - uint32_t initialize_instance_id_ = shell::mojom::kInvalidInstanceID; - - base::Closure initialize_called_; - - DISALLOW_COPY_AND_ASSIGN(ShellTest); -}; - -} // namespace test -} // namespace mojo - -#endif // MOJO_SHELL_PUBLIC_CPP_SHELL_TEST_H_ diff --git a/chromium/mojo/shell/public/interfaces/BUILD.gn b/chromium/mojo/shell/public/interfaces/BUILD.gn deleted file mode 100644 index 0eeac148727..00000000000 --- a/chromium/mojo/shell/public/interfaces/BUILD.gn +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") - -# GYP version: mojo/mojo_base.gyp:mojo_application_bindings -mojom("interfaces") { - sources = [ - "capabilities.mojom", - "connector.mojom", - "interface_provider.mojom", - "shell.mojom", - "shell_client.mojom", - "shell_client_factory.mojom", - "shell_resolver.mojom", - ] - - import_dirs = [ "//mojo/services" ] -} diff --git a/chromium/mojo/shell/public/interfaces/capabilities.mojom b/chromium/mojo/shell/public/interfaces/capabilities.mojom deleted file mode 100644 index 563b88c1f16..00000000000 --- a/chromium/mojo/shell/public/interfaces/capabilities.mojom +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 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.shell.mojom; - -// Mojo Capabilities ----------------------------------------------------------- -// -// Mojo applications expose interfaces and capability classes to one another. -// -// An interface is just a Mojo interface, defined in a mojom file like this one. -// In a CapabilitySpec, an interface is represented by its fully qualified name, -// which is serialized based on the interface name and module: -// module::path::InterfaceName. -// -// A class is an alias to something, either a set of interface names granted -// with that class, or some behavior specific to the application that provides -// it. - -// Describes the set of classes and interfaces required by an application. -// Note that there may be overlap between the interfaces implied by the -// resolution of classes and those specified in |interfaces|. The set of -// interfaces granted to the requestor is the union of these sets. -struct CapabilityRequest { - // An array of class names required. - array<string> classes; - // An array of interface names required. - array<string> interfaces; -}; - -// Describes the capabilities offered and requested by an application. -// This struct is populated from the application manifest. -struct CapabilitySpec { - // The classes offered by this application, and for each class an array of - // interfaces. If no interfaces are granted with a class, the array will be - // empty. - // A map of class name -> array of interfaces. The array can be empty, - // non-empty, or ["*"], which means allow access to all interfaces. - map<string, array<string>> provided; - - // The applications this application needs to speak to, and the classes and - // interfaces it requests. - // A map of application name -> spec. "*" is also supported as the key, which - // supplies a CapabilityRequest for all applications in addition to specific - // ones specified. - map<string, CapabilityRequest> required; -}; diff --git a/chromium/mojo/shell/public/interfaces/connector.mojom b/chromium/mojo/shell/public/interfaces/connector.mojom deleted file mode 100644 index b48440a408e..00000000000 --- a/chromium/mojo/shell/public/interfaces/connector.mojom +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.shell.mojom; - -import "mojo/shell/public/interfaces/interface_provider.mojom"; - -const string kRootUserID = "505C0EE9-3013-43C0-82B0-A84F50CF8D84"; -const string kInheritUserID = "D26290E4-4485-4EAE-81A2-66D1EEB40A9D"; - -const uint32 kInvalidInstanceID = 0; - -enum ConnectResult { - // The connection was established successfully. - SUCCEEDED, - - // The name or user id supplied was malformed, or the application specified - // by |name| could not be loaded. - INVALID_ARGUMENT, - - // The connection was blocked by policy. Either connections to |name| are - // forbidden from this app by the CapabilityFilter, or the application - // attempted to connect using a user id other than its own, - // kInheritUserID or kRootUserID. - ACCESS_DENIED -}; - -// A collection of metadata that disambiguates instances in the shell. -struct Identity { - // A mojo: or exe: name identifying an application. - string name; - - // The user id of the target application instance to connect to. If no such - // instance exists, the shell may start one. This user id will be passed to - // the new instance via Initialize(). - // When connecting to other applications, applications must generally pass - // kInheritUserID for this value, and the shell will either connect to an - // existing instance matching the caller's user id, create a new instance - // matching the caller's user id, or connect to an existing instance running - // as kRootUserID. By default, applications do not have the ability to set - // arbitrary values to this field, and doing so will result in a connection - // error on the remote service provider. An application with the ability to - // launch applications with arbitrary user ids (e.g. a login app) may set this - // value to something meaningful to it. The user id string is a valid guid of - // the form "%08X-%04X-%04X-%04X-%012llX", and (aside from the root user whose - // guid is defined above) intended to be not-guessable. - // When an application is initialized or receives a connection from another - // application, this value is always the resolved user id, never - // kInheritUserID. - string user_id; - - // An application may spawn multiple instances with the same name,user_id - // pair, provided they are started with unique values of this field. - // TODO(beng): enforce the emptiness of this parameter unless the client bears - // the appropriate capability. - string instance; -}; - -// Implemented by an object in the shell associated with a specific instance. -// Tells it the PID for a process launched by the client. See -// ClientProcessConnection. -interface PIDReceiver { - SetPID(uint32 pid); -}; - -// Typically, the shell will start a process for a service the first time it -// receives a connection request for it. This struct allows a client to start -// the process itself and provide the shell the pipes it needs to communicate -// with it. When an instance of this struct is supplied to Connect(), the client -// owns the lifetime of the child process, not the shell. The shell binds the -// |shell_client| pipe, and when it closes destroys the associated instance but -// the process stays alive. -struct ClientProcessConnection { - // Provides the shell the ability to bind a ShellClient from the client - // process to the instance it creates. - handle<message_pipe> shell_client; - - // Allows the client process launcher to tell the shell the PID of the process - // it created (the pid isn't supplied directly here as the process may not - // have been launched by the time Connect() is called.) - handle<message_pipe> pid_receiver_request; -}; - -// Encapsulates establishing connections with other Mojo applications. -interface Connector { - // Requests a connection with another application. The application originating - // the request is referred to as the "source" and the one receiving the - // "target". - // - // The connection is embodied by a pair of message pipes binding the - // InterfaceProvider interface, which allows both the source and target - // applications to export interfaces to one another. The interfaces bound via - // these InterfaceProviders are brokered by the shell according to the - // security policy defined by each application in its manifest . - // - // If the target application is not running, the shell will run it, calling - // its Initialize() method before completing the connection. - // - // Parameters: - // - // target - // Identifies the target application instance to connect to. - // - // remote_interfaces - // Allows the source application access to interface implementations - // exposed by the target application. The interfaces accessible via this - // InterfaceParameter are filtered by the security policy described by the - // source and target application manifests. - // - // local_interfaces - // Allows the remote application access to interface implementations - // exposed by the source application. The interfaces accessible via this - // InterfaceProvider are filtered by the security policy described by the - // source and target application manifests. - // - // client_process_connection - // When non-null, supplies control pipes the shell can use to bind a - // process created by the client, instead of creating one itself. - // TODO(beng): access to this parameter should be restricted by a - // capability. - // - // Response parameters: - // - // result - // Indicates the result of the Connect() operation. - // - // user_id - // The user id the shell ran the target application as. Typically a client - // passes kInheritUserID as the user id to Connect() which is resolved by - // the shell into a valid user id returned through this callback. - // - // application_id - // A unique identifier for the instance that was connected to. - // - Connect(Identity target, - InterfaceProvider&? remote_interfaces, - InterfaceProvider? local_interfaces, - ClientProcessConnection? client_process_connection) => - (ConnectResult result, string user_id, uint32 application_id); - - // Clones this Connector so it can be passed to another thread. - Clone(Connector& request); -}; diff --git a/chromium/mojo/shell/public/interfaces/interface_provider.mojom b/chromium/mojo/shell/public/interfaces/interface_provider.mojom deleted file mode 100644 index 7011bb14537..00000000000 --- a/chromium/mojo/shell/public/interfaces/interface_provider.mojom +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.shell.mojom; - -// An interface through which a client may request interfaces from a host. -// Instances of this interface are created within the context of an -// already-identified client and host pair, so there is no need to explicitly -// identify the client or host in the methods below. -interface InterfaceProvider { - // Asks the host to provide an implementation of the interface identified by - // |interface_name| through the message |pipe| endpoint supplied by the caller. - // If the host is not willing or able to provide the requested interface, it - // must close the |pipe|. - GetInterface(string interface_name, handle<message_pipe> pipe); -}; diff --git a/chromium/mojo/shell/public/interfaces/shell.mojom b/chromium/mojo/shell/public/interfaces/shell.mojom deleted file mode 100644 index 04dcd1df03f..00000000000 --- a/chromium/mojo/shell/public/interfaces/shell.mojom +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.shell.mojom; - -import "mojo/shell/public/interfaces/connector.mojom"; - -struct InstanceInfo { - uint32 id; - Identity identity; - uint32 pid; -}; - -// Implemented by a client that wishes to be informed when the list of running -// instances changes. -interface InstanceListener { - // Called once when the listener is added via Shell::AddInstanceListener() to - // provide the initial list of instances that the listener observes changes - // against. - SetExistingInstances(array<InstanceInfo> instances); - - // Called when the shell has started tracking an instance. This happens when - // the shell first handles a request to launch the instance, before any - // process is created for it. - InstanceCreated(InstanceInfo instance); - - // Called when the shell has stopped tracking an instance. (i.e. when it has - // ended/quit). - InstanceDestroyed(uint32 id); - - // Called when a pid is available for the instance. This could be because a - // process was created by the runner for it, or because an existing content - // handler process was assigned. - InstancePIDAvailable(uint32 id, uint32 pid); -}; - -interface Shell { - // The listener is removed when the |listener| pipe is closed. - AddInstanceListener(InstanceListener listener); -}; diff --git a/chromium/mojo/shell/public/interfaces/shell_client.mojom b/chromium/mojo/shell/public/interfaces/shell_client.mojom deleted file mode 100644 index b0c601cd0bb..00000000000 --- a/chromium/mojo/shell/public/interfaces/shell_client.mojom +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.shell.mojom; - -import "mojo/shell/public/interfaces/capabilities.mojom"; -import "mojo/shell/public/interfaces/connector.mojom"; -import "mojo/shell/public/interfaces/interface_provider.mojom"; - -// Implemented by something "known to" the Mojo Shell (e.g. an application or -// service), for which an instance is tracked. It allows the implementor to -// receive lifecycle events and service inbound connection attempts. -interface ShellClient { - // Called by the shell once an instance for this application has been created. - // This method will be called exactly once before any other method is called. - // - // Parameters: - // - // identity - // The identity of this instance in the shell. Includes: - // * The resolved name used in the connection request that resulted in this - // instance being initialized. - // * The user associated with this instance in the shell. This will never - // be kInheritUserID. - // * The instance group this instance belongs to. - // - // id - // A unique identifier used by the shell to identify this instance. - // - // - // Response parameters: - // - // connector_request - // An optional Connector request for the shell to bind, allowing the - // initialized client to connect to others. - // - Initialize(Identity identity, uint32 id) => (Connector&? connector_request); - - // Called when another application attempts to open a connection to this - // application. An application implements this method to complete the exchange - // of interface implementations with the remote application. See also - // documentation in shell.mojom for Connect(). The application originating - // the request is referred to as the "source" and the one receiving the - // "target". - // - // Parameters: - // - // source - // The identity of the instance originating the connection. - // - // source_id - // A unique identifier used by the shell to identify the source instance. - // - // local_interfaces - // A request for an InterfaceProvider by which the source application may - // seek to bind interface implementations exported by the target. - // - // remote_interfaces - // An InterfaceProvider by which the target application may bind interface - // implementations exported by the source. - // - // allowed_interfaces - // A whitelist of interface names that should be exported to the source, - // according to the security policy described by the source and target's - // manifests. Attempts to bind interfaces not in this whitelist must not be - // fulfilled. - // - // resolved_name - // The resolved name used to complete this connection. - // - AcceptConnection(Identity source, - uint32 source_id, - InterfaceProvider&? local_interfaces, - InterfaceProvider? remote_interfaces, - CapabilityRequest allowed_capabilities, - string resolved_name); -}; diff --git a/chromium/mojo/shell/public/interfaces/shell_client_factory.mojom b/chromium/mojo/shell/public/interfaces/shell_client_factory.mojom deleted file mode 100644 index 89abedb9bad..00000000000 --- a/chromium/mojo/shell/public/interfaces/shell_client_factory.mojom +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2016 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.shell.mojom; - -import "mojo/shell/public/interfaces/shell_client.mojom"; - -// Implemented by a package containing multiple applications identified by -// unique names. -interface ShellClientFactory { - CreateShellClient(ShellClient& shell_client, string name); -}; diff --git a/chromium/mojo/shell/public/interfaces/shell_resolver.mojom b/chromium/mojo/shell/public/interfaces/shell_resolver.mojom deleted file mode 100644 index 0c4e841858c..00000000000 --- a/chromium/mojo/shell/public/interfaces/shell_resolver.mojom +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 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.shell.mojom; - -import "mojo/shell/public/interfaces/capabilities.mojom"; - -// The result of a Resolve operation via ShellResolver. -struct ResolveResult { - // The mojo: name that was requested to be resolved. - string name; - - // The mojo: name of the physical package supplying the requested name. This - // could be the same name that was passed, or the name of a package that - // contains it. - string resolved_name; - - // An additional piece of metadata that identifies what instance |name| should - // be run in. It's possible that |name| may provide several services that - // should be run as different instances. - string qualifier; - - // The set of capabilities provided and required by |name|. - CapabilitySpec capabilities; - - // A file URL to the package specified by |name|. - // TODO(beng): What if resolved_mojo_name needs to be re-resolved? - string package_url; -}; - -// Implemented exclusively for the Mojo Shell's use in resolving mojo: names -// and reading static manifest information. -interface ShellResolver { - // Resolves |mojo_name| and returns a ResolveResult containing metadata from - // the catalog that the Shell uses to run an instance of it. - ResolveMojoName(string mojo_name) => (ResolveResult result); -}; diff --git a/chromium/mojo/shell/public/java/BUILD.gn b/chromium/mojo/shell/public/java/BUILD.gn deleted file mode 100644 index a89d0fc7d0b..00000000000 --- a/chromium/mojo/shell/public/java/BUILD.gn +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -android_library("application") { - java_files = [ - "src/org/chromium/mojo/application/ApplicationConnection.java", - "src/org/chromium/mojo/application/ApplicationDelegate.java", - "src/org/chromium/mojo/application/ApplicationImpl.java", - "src/org/chromium/mojo/application/ApplicationRunner.java", - "src/org/chromium/mojo/application/ServiceFactoryBinder.java", - "src/org/chromium/mojo/application/ShellHelper.java", - ] - deps = [ - "//mojo/public/java:bindings", - "//mojo/public/java:system", - "//mojo/shell/public/interfaces:interfaces_java", - ] -} diff --git a/chromium/mojo/shell/runner/BUILD.gn b/chromium/mojo/shell/runner/BUILD.gn deleted file mode 100644 index 6f9ae90a2ca..00000000000 --- a/chromium/mojo/shell/runner/BUILD.gn +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2016 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. - -group("runner") { - testonly = true - deps = [ - "//mojo/shell/runner/child", - "//mojo/shell/runner/host", - ] -} - -source_set("init") { - sources = [ - "init.cc", - "init.h", - ] - - deps = [ - "//base", - "//base:base_static", - "//base:i18n", - "//mojo/shell/runner/common", - ] -} diff --git a/chromium/mojo/shell/runner/child/BUILD.gn b/chromium/mojo/shell/runner/child/BUILD.gn deleted file mode 100644 index 0276b3d1fdc..00000000000 --- a/chromium/mojo/shell/runner/child/BUILD.gn +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") -import("//mojo/public/mojo_application_manifest.gni") -import("//mojo/public/tools/bindings/mojom.gni") - -group("child") { - testonly = true - deps = [ - ":apptests", - ] -} - -source_set("test_native_main") { - sources = [ - "test_native_main.cc", - "test_native_main.h", - ] - - public_deps = [ - "//mojo/shell/runner:init", - ] - - deps = [ - "//base", - "//mojo/edk/system", - "//mojo/message_pump", - "//mojo/shell/public/cpp", - "//mojo/shell/runner/common", - ] -} - -mojom("apptest_interfaces") { - sources = [ - "test_native_service.mojom", - ] - - deps = [ - "//mojo/shell/public/interfaces", - ] - - import_dirs = [ "//mojo/services" ] -} - -mojo_native_application("apptests") { - output_name = "mojo_runner_child_apptest" - testonly = true - avoid_runner_cycle = true - - sources = [ - "native_apptest.cc", - ] - - deps = [ - ":apptest_interfaces", - "//base", - "//base/test:test_config", - "//mojo/shell/public/cpp:sources", - "//mojo/shell/public/cpp:test_support", - ] - - data_deps = [ - ":manifest", - ":native_target", - ] -} - -mojo_application_manifest("manifest") { - application_name = "mojo_runner_child_apptest" - source = "manifest.json" -} - -executable("native_target") { - output_name = "mojo_runner_child_apptest_native_target" - testonly = true - - sources = [ - "native_apptest_target.cc", - ] - - deps = [ - ":apptest_interfaces", - ":test_native_main", - "//base", - "//build/config/sanitizers:deps", - "//mojo/shell/public/cpp", - ] -} diff --git a/chromium/mojo/shell/runner/child/manifest.json b/chromium/mojo/shell/runner/child/manifest.json deleted file mode 100644 index cc407220a1a..00000000000 --- a/chromium/mojo/shell/runner/child/manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "mojo:mojo_runner_child_apptest", - "display_name": "Runner Child Apptest", - "capabilities": { "*": [ "*" ] } -} diff --git a/chromium/mojo/shell/runner/child/native_apptest.cc b/chromium/mojo/shell/runner/child/native_apptest.cc deleted file mode 100644 index d0ab0b7db5e..00000000000 --- a/chromium/mojo/shell/runner/child/native_apptest.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/macros.h" -#include "mojo/shell/public/cpp/application_test_base.h" -#include "mojo/shell/runner/child/test_native_service.mojom.h" - -namespace mojo { -namespace shell { -namespace { -void InvertCallback(bool* result, bool from_native) { - *result = from_native; -} -} // namespace - -using NativeAppTest = mojo::test::ApplicationTestBase; - -TEST_F(NativeAppTest, Connect) { - test::TestNativeServicePtr native_service; - connector()->ConnectToInterface("exe:mojo_runner_child_apptest_native_target", - &native_service); - - bool result = false; - native_service->Invert( - true, base::Bind(&InvertCallback, base::Unretained(&result))); - native_service.WaitForIncomingResponse(); - EXPECT_FALSE(result); - - native_service->Invert( - false, base::Bind(&InvertCallback, base::Unretained(&result))); - native_service.WaitForIncomingResponse(); - EXPECT_TRUE(result); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/child/native_apptest_target.cc b/chromium/mojo/shell/runner/child/native_apptest_target.cc deleted file mode 100644 index 565ba300a17..00000000000 --- a/chromium/mojo/shell/runner/child/native_apptest_target.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/shell/public/cpp/connection.h" -#include "mojo/shell/public/cpp/interface_factory.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/runner/child/test_native_main.h" -#include "mojo/shell/runner/child/test_native_service.mojom.h" -#include "mojo/shell/runner/init.h" - -namespace { - -class TargetApplicationDelegate - : public mojo::ShellClient, - public mojo::shell::test::TestNativeService, - public mojo::InterfaceFactory<mojo::shell::test::TestNativeService> { - public: - TargetApplicationDelegate() {} - ~TargetApplicationDelegate() override {} - - private: - // mojo::ShellClient: - bool AcceptConnection(mojo::Connection* connection) override { - connection->AddInterface<mojo::shell::test::TestNativeService>(this); - return true; - } - - // mojo::shell::test::TestNativeService: - void Invert(bool from_driver, const InvertCallback& callback) override { - callback.Run(!from_driver); - } - - // mojo::InterfaceFactory<mojo::shell::test::TestNativeService>: - void Create(mojo::Connection* connection, - mojo::InterfaceRequest<mojo::shell::test::TestNativeService> - request) override { - bindings_.AddBinding(this, std::move(request)); - } - - mojo::BindingSet<mojo::shell::test::TestNativeService> bindings_; - - DISALLOW_COPY_AND_ASSIGN(TargetApplicationDelegate); -}; - -} // namespace - -int main(int argc, char** argv) { - base::AtExitManager at_exit; - base::CommandLine::Init(argc, argv); - - mojo::shell::InitializeLogging(); - - TargetApplicationDelegate delegate; - return mojo::shell::TestNativeMain(&delegate); -} diff --git a/chromium/mojo/shell/runner/child/test_native_main.cc b/chromium/mojo/shell/runner/child/test_native_main.cc deleted file mode 100644 index cc542158872..00000000000 --- a/chromium/mojo/shell/runner/child/test_native_main.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/child/test_native_main.h" - -#include <utility> - -#include "base/debug/stack_trace.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/process/launch.h" -#include "base/threading/thread.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "mojo/shell/runner/common/client_util.h" -#include "mojo/shell/runner/init.h" - -namespace mojo { -namespace shell { -namespace { - -class ProcessDelegate : public mojo::edk::ProcessDelegate { - public: - ProcessDelegate() {} - ~ProcessDelegate() override {} - - private: - void OnShutdownComplete() override {} - - DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); -}; - -} // namespace - -int TestNativeMain(mojo::ShellClient* shell_client) { - mojo::shell::WaitForDebuggerIfNecessary(); - -#if !defined(OFFICIAL_BUILD) - base::debug::EnableInProcessStackDumping(); -#if defined(OS_WIN) - base::RouteStdioToConsole(false); -#endif -#endif - - { - mojo::edk::Init(); - - ProcessDelegate process_delegate; - base::Thread io_thread("io_thread"); - base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); - CHECK(io_thread.StartWithOptions(io_thread_options)); - - mojo::edk::InitIPCSupport(&process_delegate, io_thread.task_runner()); - mojo::edk::SetParentPipeHandleFromCommandLine(); - - base::MessageLoop loop; - mojo::ShellConnection impl( - shell_client, mojo::shell::GetShellClientRequestFromCommandLine()); - loop.Run(); - - mojo::edk::ShutdownIPCSupport(); - } - - return 0; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/child/test_native_main.h b/chromium/mojo/shell/runner/child/test_native_main.h deleted file mode 100644 index 3742bc54d38..00000000000 --- a/chromium/mojo/shell/runner/child/test_native_main.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_CHILD_TEST_NATIVE_MAIN_H_ -#define MOJO_SHELL_RUNNER_CHILD_TEST_NATIVE_MAIN_H_ - -namespace mojo { -class ShellClient; -namespace shell { - -int TestNativeMain(mojo::ShellClient* shell_client); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_CHILD_TEST_NATIVE_MAIN_H_ diff --git a/chromium/mojo/shell/runner/child/test_native_service.mojom b/chromium/mojo/shell/runner/child/test_native_service.mojom deleted file mode 100644 index 1f55eed5260..00000000000 --- a/chromium/mojo/shell/runner/child/test_native_service.mojom +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.shell.test; - -interface TestNativeService { - Invert(bool from_driver) => (bool from_target); -}; diff --git a/chromium/mojo/shell/runner/common/BUILD.gn b/chromium/mojo/shell/runner/common/BUILD.gn deleted file mode 100644 index f780070836c..00000000000 --- a/chromium/mojo/shell/runner/common/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2016 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. - -source_set("common") { - sources = [ - "client_util.cc", - "client_util.h", - "switches.cc", - "switches.h", - ] - - deps = [ - "//base", - "//mojo/edk/system", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - ] - - public_deps = [ - "//mojo/shell/public/interfaces", - ] -} diff --git a/chromium/mojo/shell/runner/common/client_util.cc b/chromium/mojo/shell/runner/common/client_util.cc deleted file mode 100644 index 2c264bd2781..00000000000 --- a/chromium/mojo/shell/runner/common/client_util.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 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/shell/runner/common/client_util.h" - -#include <string> - -#include "base/command_line.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/shell/runner/common/switches.h" - -namespace mojo { -namespace shell { - -mojom::ShellClientPtr PassShellClientRequestOnCommandLine( - base::CommandLine* command_line) { - std::string token = edk::GenerateRandomToken(); - command_line->AppendSwitchASCII(switches::kPrimordialPipeToken, token); - - mojom::ShellClientPtr client; - client.Bind( - mojom::ShellClientPtrInfo(edk::CreateParentMessagePipe(token), 0)); - return client; -} - -mojom::ShellClientRequest GetShellClientRequestFromCommandLine() { - std::string token = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kPrimordialPipeToken); - mojom::ShellClientRequest request; - if (!token.empty()) - request.Bind(edk::CreateChildMessagePipe(token)); - return request; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/common/client_util.h b/chromium/mojo/shell/runner/common/client_util.h deleted file mode 100644 index ac61c77fa1b..00000000000 --- a/chromium/mojo/shell/runner/common/client_util.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_COMMON_CLIENT_UTIL_H_ -#define MOJO_SHELL_RUNNER_COMMON_CLIENT_UTIL_H_ - -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace base { -class CommandLine; -} - -namespace mojo { -namespace shell { - -// Creates a new ShellClient pipe and returns one end of it. The other end is -// passed via a token in |command_line|. A child of the calling process may -// extract a ShellClientRequest from this by calling -// GetShellClientRequestFromCommandLine(). -mojom::ShellClientPtr PassShellClientRequestOnCommandLine( - base::CommandLine* command_line); - -// Extracts a ShellClientRequest from the command line of the current process. -// The parent of this process should have passed a request using -// PassShellClientRequestOnCommandLine(). -mojom::ShellClientRequest GetShellClientRequestFromCommandLine(); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_COMMON_CLIENT_UTIL_H_ diff --git a/chromium/mojo/shell/runner/common/switches.cc b/chromium/mojo/shell/runner/common/switches.cc deleted file mode 100644 index f543ada3a30..00000000000 --- a/chromium/mojo/shell/runner/common/switches.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/common/switches.h" - -namespace switches { - -// Used internally by the main process to indicate that a new process should be -// a child process. Takes the absolute path to the mojo application to load as -// an argument. Not for user use. -const char kChildProcess[] = "child-process"; - -// Enables the sandbox on this process. -const char kEnableSandbox[] = "enable-sandbox"; - -// Provides a child process with a token string they can use to establish a -// primordial message pipe to the parent. -const char kPrimordialPipeToken[] = "primordial-pipe-token"; - -} // namespace switches diff --git a/chromium/mojo/shell/runner/common/switches.h b/chromium/mojo/shell/runner/common/switches.h deleted file mode 100644 index 57957cffcc8..00000000000 --- a/chromium/mojo/shell/runner/common/switches.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_COMMON_SWITCHES_H_ -#define MOJO_SHELL_RUNNER_COMMON_SWITCHES_H_ - -namespace switches { - -// All switches in alphabetical order. The switches should be documented -// alongside the definition of their values in the .cc file. -extern const char kChildProcess[]; -extern const char kEnableSandbox[]; -extern const char kPrimordialPipeToken[]; - -} // namespace switches - -#endif // MOJO_SHELL_RUNNER_COMMON_SWITCHES_H_ diff --git a/chromium/mojo/shell/runner/host/BUILD.gn b/chromium/mojo/shell/runner/host/BUILD.gn deleted file mode 100644 index edcce93d503..00000000000 --- a/chromium/mojo/shell/runner/host/BUILD.gn +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") -import("//mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -group("host") { - testonly = true - - deps = [ - ":lib", - ":mojo_runner_host_unittests", - ] -} - -source_set("native_application_support") { - sources = [ - "native_application_support.cc", - "native_application_support.h", - ] - - deps = [ - "//base", - "//mojo/platform_handle:platform_handle_impl", - "//mojo/shell", - ] - - # This target has to include the public thunk headers, which generally - # shouldn't be included without picking an implementation. We are providing - # the implementation but the thunk header target cannot declare that we are - # permitted to include it since it's in the public SDK and we are not. - # Suppress include checking so we can still check the rest of the targets in - # this file. - check_includes = false -} - -source_set("child_process_base") { - sources = [ - "child_process_base.cc", - "child_process_base.h", - ] - - deps = [ - "//base", - "//mojo/edk/system", - "//mojo/message_pump", - "//mojo/platform_handle:platform_handle_impl", - "//mojo/shell", - "//mojo/shell/public/interfaces", - "//mojo/shell/runner:init", - "//mojo/shell/runner/common", - ] -} - -source_set("lib") { - sources = [ - "child_process.cc", - "child_process.h", - "child_process_host.cc", - "child_process_host.h", - "in_process_native_runner.cc", - "in_process_native_runner.h", - "out_of_process_native_runner.cc", - "out_of_process_native_runner.h", - ] - - deps = [ - ":child_process_base", - ":native_application_support", - "//base:base_static", - "//base:i18n", - "//mojo/message_pump", - "//mojo/platform_handle:platform_handle_impl", - "//mojo/shell/public/cpp:sources", - "//mojo/shell/runner:init", - "//mojo/shell/runner/common", - ] - - public_deps = [ - "//base", - "//mojo/edk/system", - "//mojo/public/cpp/system", - "//mojo/shell", - "//mojo/shell/public/interfaces", - ] - - if (is_linux && !is_android) { - sources += [ - "linux_sandbox.cc", - "linux_sandbox.h", - ] - - deps += [ - "//sandbox/linux:sandbox", - "//sandbox/linux:sandbox_services", - "//sandbox/linux:seccomp_bpf", - "//sandbox/linux:seccomp_bpf_helpers", - ] - } - - if (is_mac) { - sources += [ - "mach_broker.cc", - "mach_broker.h", - ] - } -} - -test("mojo_runner_host_unittests") { - sources = [ - "child_process_host_unittest.cc", - "host_unittests.cc", - "in_process_native_runner_unittest.cc", - ] - - deps = [ - ":lib", - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/message_pump", - "//mojo/shell", - "//mojo/shell/runner:init", - "//mojo/shell/runner/common", - "//testing/gtest", - ] -} diff --git a/chromium/mojo/shell/runner/host/DEPS b/chromium/mojo/shell/runner/host/DEPS deleted file mode 100644 index ec69c8f59a8..00000000000 --- a/chromium/mojo/shell/runner/host/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+sandbox", -] diff --git a/chromium/mojo/shell/runner/host/OWNERS b/chromium/mojo/shell/runner/host/OWNERS deleted file mode 100644 index 2b40a92356e..00000000000 --- a/chromium/mojo/shell/runner/host/OWNERS +++ /dev/null @@ -1 +0,0 @@ -per-file linux_sandbox*=rickyz@chromium.org diff --git a/chromium/mojo/shell/runner/host/child_process.cc b/chromium/mojo/shell/runner/host/child_process.cc deleted file mode 100644 index 260dc66edc7..00000000000 --- a/chromium/mojo/shell/runner/host/child_process.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/child_process.h" - -#include <stdint.h> - -#include <utility> - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/command_line.h" -#include "base/debug/stack_trace.h" -#include "base/files/file_path.h" -#include "base/i18n/icu_util.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/thread.h" -#include "base/threading/thread_checker.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/message_pump/message_pump_mojo.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/runner/common/switches.h" -#include "mojo/shell/runner/host/child_process_base.h" -#include "mojo/shell/runner/host/native_application_support.h" -#include "mojo/shell/runner/init.h" - -#if defined(OS_LINUX) && !defined(OS_ANDROID) -#include "base/rand_util.h" -#include "base/sys_info.h" -#include "mojo/shell/runner/host/linux_sandbox.h" -#endif - -#if defined(OS_MACOSX) -#include "mojo/shell/runner/host/mach_broker.h" -#endif - -namespace mojo { -namespace shell { - -namespace { - -#if defined(OS_LINUX) && !defined(OS_ANDROID) -scoped_ptr<mojo::shell::LinuxSandbox> InitializeSandbox() { - using sandbox::syscall_broker::BrokerFilePermission; - // Warm parts of base in the copy of base in the mojo runner. - base::RandUint64(); - base::SysInfo::AmountOfPhysicalMemory(); - base::SysInfo::MaxSharedMemorySize(); - base::SysInfo::NumberOfProcessors(); - - // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to - // spy on other shared memory using processes. This is a temporary hack - // so that we have some sandbox until we have proper shared memory - // support integrated into mojo. - std::vector<BrokerFilePermission> permissions; - permissions.push_back( - BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/")); - scoped_ptr<mojo::shell::LinuxSandbox> sandbox( - new mojo::shell::LinuxSandbox(permissions)); - sandbox->Warmup(); - sandbox->EngageNamespaceSandbox(); - sandbox->EngageSeccompSandbox(); - sandbox->Seal(); - return sandbox; -} -#endif - -void RunNativeLibrary( - base::NativeLibrary app_library, - InterfaceRequest<mojom::ShellClient> shell_client_request) { - if (!RunNativeApplication(app_library, std::move(shell_client_request))) { - LOG(ERROR) << "Failure to RunNativeApplication()"; - } -} - -} // namespace - -int ChildProcessMain() { - DVLOG(2) << "ChildProcessMain()"; - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - -#if defined(OS_LINUX) && !defined(OS_ANDROID) - scoped_ptr<mojo::shell::LinuxSandbox> sandbox; -#endif - base::NativeLibrary app_library = 0; - // Load the application library before we engage the sandbox. - base::FilePath app_library_path = - command_line.GetSwitchValuePath(switches::kChildProcess); - if (!app_library_path.empty()) - app_library = mojo::shell::LoadNativeApplication(app_library_path); - base::i18n::InitializeICU(); - if (app_library) - CallLibraryEarlyInitialization(app_library); - -#if defined(OS_MACOSX) - // Send our task port to the parent. - MachBroker::SendTaskPortToParent(); -#endif - -#if !defined(OFFICIAL_BUILD) - // Initialize stack dumping just before initializing sandbox to make - // sure symbol names in all loaded libraries will be cached. - base::debug::EnableInProcessStackDumping(); -#endif -#if defined(OS_LINUX) && !defined(OS_ANDROID) - if (command_line.HasSwitch(switches::kEnableSandbox)) - sandbox = InitializeSandbox(); -#endif - - ChildProcessMain(base::Bind(&RunNativeLibrary, app_library)); - - return 0; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/child_process.h b/chromium/mojo/shell/runner/host/child_process.h deleted file mode 100644 index 2b6b2d25d66..00000000000 --- a/chromium/mojo/shell/runner/host/child_process.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_H_ -#define MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_H_ - -namespace mojo { -namespace shell { - -// Main method for a child process. -int ChildProcessMain(); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_H_ diff --git a/chromium/mojo/shell/runner/host/child_process_base.cc b/chromium/mojo/shell/runner/host/child_process_base.cc deleted file mode 100644 index e6b9a2529fc..00000000000 --- a/chromium/mojo/shell/runner/host/child_process_base.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/child_process_base.h" - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/shell/runner/common/client_util.h" - -namespace mojo { -namespace shell { - -namespace { - -// Should be created and initialized on the main thread and kept alive as long -// a Mojo application is running in the current process. -class ScopedAppContext : public edk::ProcessDelegate { - public: - ScopedAppContext() - : io_thread_("io_thread"), wait_for_shutdown_event_(true, false) { - // Initialize Mojo before starting any threads. - edk::Init(); - - // Create and start our I/O thread. - base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); - CHECK(io_thread_.StartWithOptions(io_thread_options)); - io_runner_ = io_thread_.task_runner().get(); - CHECK(io_runner_.get()); - - edk::InitIPCSupport(this, io_runner_); - edk::SetParentPipeHandleFromCommandLine(); - } - - ~ScopedAppContext() override { - edk::ShutdownIPCSupport(); - wait_for_shutdown_event_.Wait(); - } - - private: - // ProcessDelegate implementation. - void OnShutdownComplete() override { - wait_for_shutdown_event_.Signal(); - } - - base::Thread io_thread_; - scoped_refptr<base::SingleThreadTaskRunner> io_runner_; - - // Used to unblock the main thread on shutdown. - base::WaitableEvent wait_for_shutdown_event_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAppContext); -}; - -} // namespace - -void ChildProcessMain(const RunCallback& callback) { - DCHECK(!base::MessageLoop::current()); - - ScopedAppContext app_context; - callback.Run(GetShellClientRequestFromCommandLine()); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/child_process_base.h b/chromium/mojo/shell/runner/host/child_process_base.h deleted file mode 100644 index f2d23e5ac74..00000000000 --- a/chromium/mojo/shell/runner/host/child_process_base.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_BASE_H_ -#define MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_BASE_H_ - -#include "base/callback.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace mojo { -namespace shell { - -// Child processes call this to establish the connection to the shell and obtain -// the ShellClientRequest. Once the connection has been established |callback| -// is run. ChildProcessMain() returns once the the callback completes. -using RunCallback = base::Callback<void(mojom::ShellClientRequest)>; -void ChildProcessMain(const RunCallback& callback); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_BASE_H_ diff --git a/chromium/mojo/shell/runner/host/child_process_host.cc b/chromium/mojo/shell/runner/host/child_process_host.cc deleted file mode 100644 index 96200f3d331..00000000000 --- a/chromium/mojo/shell/runner/host/child_process_host.cc +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/child_process_host.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/process/kill.h" -#include "base/process/launch.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/native_runner_delegate.h" -#include "mojo/shell/runner/common/client_util.h" -#include "mojo/shell/runner/common/switches.h" - -#if defined(OS_LINUX) && !defined(OS_ANDROID) -#include "sandbox/linux/services/namespace_sandbox.h" -#endif - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -#if defined(OS_MACOSX) -#include "mojo/shell/runner/host/mach_broker.h" -#endif - -namespace mojo { -namespace shell { - -ChildProcessHost::ChildProcessHost(base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate, - bool start_sandboxed, - const Identity& target, - const base::FilePath& app_path) - : launch_process_runner_(launch_process_runner), - delegate_(delegate), - start_sandboxed_(start_sandboxed), - target_(target), - app_path_(app_path), - start_child_process_event_(false, false), - weak_factory_(this) { -} - -ChildProcessHost::~ChildProcessHost() { - if (!app_path_.empty()) { - CHECK(!mojo_ipc_channel_) - << "Destroying ChildProcessHost before calling Join"; - } -} - -mojom::ShellClientPtr ChildProcessHost::Start( - const Identity& target, - const ProcessReadyCallback& callback, - const base::Closure& quit_closure) { - DCHECK(!child_process_.IsValid()); - - const base::CommandLine* parent_command_line = - base::CommandLine::ForCurrentProcess(); - base::FilePath target_path = parent_command_line->GetProgram(); - // |app_path_| can be empty in tests. - if (!app_path_.MatchesExtension(FILE_PATH_LITERAL(".mojo")) && - !app_path_.empty()) { - target_path = app_path_; - } - - scoped_ptr<base::CommandLine> child_command_line( - new base::CommandLine(target_path)); - - child_command_line->AppendArguments(*parent_command_line, false); - -#ifndef NDEBUG - child_command_line->AppendSwitchASCII("n", target.name()); - child_command_line->AppendSwitchASCII("u", target.user_id()); -#endif - - if (target_path != app_path_) - child_command_line->AppendSwitchPath(switches::kChildProcess, app_path_); - - if (start_sandboxed_) - child_command_line->AppendSwitch(switches::kEnableSandbox); - - mojo_ipc_channel_.reset(new edk::PlatformChannelPair); - mojo_ipc_channel_->PrepareToPassClientHandleToChildProcess( - child_command_line.get(), &handle_passing_info_); - - mojom::ShellClientPtr client = - PassShellClientRequestOnCommandLine(child_command_line.get()); - launch_process_runner_->PostTaskAndReply( - FROM_HERE, - base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this), - base::Passed(&child_command_line)), - base::Bind(&ChildProcessHost::DidStart, - weak_factory_.GetWeakPtr(), callback)); - return client; -} - -void ChildProcessHost::Join() { - if (mojo_ipc_channel_) - start_child_process_event_.Wait(); - mojo_ipc_channel_.reset(); - if (child_process_.IsValid()) { - int rv = -1; - LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) - << "Failed to wait for child process"; - child_process_.Close(); - } -} - -void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) { - if (child_process_.IsValid()) { - callback.Run(child_process_.Pid()); - } else { - LOG(ERROR) << "Failed to start child process"; - mojo_ipc_channel_.reset(); - } -} - -void ChildProcessHost::DoLaunch( - scoped_ptr<base::CommandLine> child_command_line) { - if (delegate_) { - delegate_->AdjustCommandLineArgumentsForTarget(target_, - child_command_line.get()); - } - - base::LaunchOptions options; -#if defined(OS_WIN) - options.handles_to_inherit = &handle_passing_info_; -#if defined(OFFICIAL_BUILD) - CHECK(false) << "Launching mojo process with inherit_handles is insecure!"; -#endif - options.inherit_handles = true; - options.stdin_handle = INVALID_HANDLE_VALUE; - options.stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); - options.stderr_handle = GetStdHandle(STD_ERROR_HANDLE); - // Always inherit stdout/stderr as a pair. - if (!options.stdout_handle || !options.stdin_handle) - options.stdin_handle = options.stdout_handle = nullptr; - - // Pseudo handles are used when stdout and stderr redirect to the console. In - // that case, they're automatically inherited by child processes. See - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075.aspx - // Trying to add them to the list of handles to inherit causes CreateProcess - // to fail. When this process is launched from Python - // (i.e. by apptest_runner.py) then a real handle is used. In that case, we do - // want to add it to the list of handles that is inherited. - if (options.stdout_handle && - GetFileType(options.stdout_handle) != FILE_TYPE_CHAR) { - handle_passing_info_.push_back(options.stdout_handle); - } - if (options.stderr_handle && - GetFileType(options.stderr_handle) != FILE_TYPE_CHAR && - options.stdout_handle != options.stderr_handle) { - handle_passing_info_.push_back(options.stderr_handle); - } -#elif defined(OS_POSIX) - handle_passing_info_.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO)); - handle_passing_info_.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); - handle_passing_info_.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO)); - options.fds_to_remap = &handle_passing_info_; -#endif - DVLOG(2) << "Launching child with command line: " - << child_command_line->GetCommandLineString(); -#if defined(OS_LINUX) && !defined(OS_ANDROID) - if (start_sandboxed_) { - child_process_ = - sandbox::NamespaceSandbox::LaunchProcess(*child_command_line, options); - if (!child_process_.IsValid()) { - LOG(ERROR) << "Starting the process with a sandbox failed. Missing kernel" - << " support."; - } - } else -#endif - { -#if defined(OS_MACOSX) - MachBroker* mach_broker = MachBroker::GetInstance(); - base::AutoLock locker(mach_broker->GetLock()); -#endif - LOG(WARNING) << "PATH: " << app_path_.value(); - child_process_ = base::LaunchProcess(*child_command_line, options); -#if defined(OS_MACOSX) - mach_broker->ExpectPid(child_process_.Handle()); -#endif - } - - if (child_process_.IsValid()) { - if (mojo_ipc_channel_.get()) { - mojo_ipc_channel_->ChildProcessLaunched(); - mojo::edk::ChildProcessLaunched( - child_process_.Handle(), - mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( - mojo_ipc_channel_->PassServerHandle().release().handle))); - } - } - start_child_process_event_.Signal(); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/child_process_host.h b/chromium/mojo/shell/runner/host/child_process_host.h deleted file mode 100644 index 9e0fb832d4b..00000000000 --- a/chromium/mojo/shell/runner/host/child_process_host.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_HOST_H_ -#define MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_HOST_H_ - -#include <stdint.h> - -#include <string> - -#include "base/callback.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/process/process.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/interfaces/shell_client_factory.mojom.h" -#include "mojo/shell/runner/host/child_process_host.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { -class Identity; -namespace shell { - -class NativeRunnerDelegate; - -// This class represents a "child process host". Handles launching and -// connecting a platform-specific "pipe" to the child, and supports joining the -// child process. Currently runs a single app (loaded from the file system). -// -// This class is not thread-safe. It should be created/used/destroyed on a -// single thread. -// -// Note: Does not currently work on Windows before Vista. -// Note: After |Start()|, |StartApp| must be called and this object must -// remained alive until the |on_app_complete| callback is called. -class ChildProcessHost { - public: - using ProcessReadyCallback = base::Callback<void(base::ProcessId)>; - - // |name| is just for debugging ease. We will spawn off a process so that it - // can be sandboxed if |start_sandboxed| is true. |app_path| is a path to the - // mojo application we wish to start. - ChildProcessHost(base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate, - bool start_sandboxed, - const Identity& target, - const base::FilePath& app_path); - virtual ~ChildProcessHost(); - - // |Start()|s the child process; calls |DidStart()| (on the thread on which - // |Start()| was called) when the child has been started (or failed to start). - mojom::ShellClientPtr Start(const Identity& target, - const ProcessReadyCallback& callback, - const base::Closure& quit_closure); - - // Waits for the child process to terminate. - void Join(); - - protected: - void DidStart(const ProcessReadyCallback& callback); - - private: - void DoLaunch(scoped_ptr<base::CommandLine> child_command_line); - - scoped_refptr<base::TaskRunner> launch_process_runner_; - NativeRunnerDelegate* delegate_ = nullptr; - bool start_sandboxed_ = false; - Identity target_; - const base::FilePath app_path_; - base::Process child_process_; - - // Used to initialize the Mojo IPC channel between parent and child. - scoped_ptr<edk::PlatformChannelPair> mojo_ipc_channel_; - edk::HandlePassingInformation handle_passing_info_; - - // Since Start() calls a method on another thread, we use an event to block - // the main thread if it tries to destruct |this| while launching the process. - base::WaitableEvent start_child_process_event_; - - base::WeakPtrFactory<ChildProcessHost> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ChildProcessHost); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_CHILD_PROCESS_HOST_H_ diff --git a/chromium/mojo/shell/runner/host/child_process_host_unittest.cc b/chromium/mojo/shell/runner/host/child_process_host_unittest.cc deleted file mode 100644 index ae513ab4eac..00000000000 --- a/chromium/mojo/shell/runner/host/child_process_host_unittest.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Note: This file also tests child_process.*. - -#include "mojo/shell/runner/host/child_process_host.h" - -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/message_pump/message_pump_mojo.h" -#include "mojo/shell/native_runner_delegate.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -void ProcessReadyCallbackAdapater(const base::Closure& callback, - base::ProcessId process_id) { - callback.Run(); -} - -class ProcessDelegate : public edk::ProcessDelegate { - public: - ProcessDelegate() {} - ~ProcessDelegate() override {} - - private: - void OnShutdownComplete() override {} - DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); -}; - -class NativeRunnerDelegateImpl : public NativeRunnerDelegate { - public: - NativeRunnerDelegateImpl() {} - ~NativeRunnerDelegateImpl() override {} - - size_t get_and_clear_adjust_count() { - size_t count = 0; - std::swap(count, adjust_count_); - return count; - } - - private: - // NativeRunnerDelegate: - void AdjustCommandLineArgumentsForTarget( - const Identity& target, - base::CommandLine* command_line) override { - adjust_count_++; - } - - size_t adjust_count_ = 0; - - DISALLOW_COPY_AND_ASSIGN(NativeRunnerDelegateImpl); -}; - -#if defined(OS_ANDROID) -// TODO(qsr): Multiprocess shell tests are not supported on android. -#define MAYBE_StartJoin DISABLED_StartJoin -#else -#define MAYBE_StartJoin StartJoin -#endif // defined(OS_ANDROID) -// Just tests starting the child process and joining it (without starting an -// app). -TEST(ChildProcessHostTest, MAYBE_StartJoin) { - base::FilePath shell_dir; - PathService::Get(base::DIR_MODULE, &shell_dir); - base::MessageLoop message_loop( - scoped_ptr<base::MessagePump>(new common::MessagePumpMojo())); - scoped_refptr<base::SequencedWorkerPool> blocking_pool( - new base::SequencedWorkerPool(3, "blocking_pool")); - - base::Thread io_thread("io_thread"); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - io_thread.StartWithOptions(options); - - ProcessDelegate delegate; - edk::InitIPCSupport(&delegate, io_thread.task_runner()); - - NativeRunnerDelegateImpl native_runner_delegate; - ChildProcessHost child_process_host(blocking_pool.get(), - &native_runner_delegate, false, - Identity(), base::FilePath()); - base::RunLoop run_loop; - child_process_host.Start( - Identity(), - base::Bind(&ProcessReadyCallbackAdapater, run_loop.QuitClosure()), - base::Bind(&base::DoNothing)); - run_loop.Run(); - - child_process_host.Join(); - blocking_pool->Shutdown(); - edk::ShutdownIPCSupport(); - EXPECT_EQ(1u, native_runner_delegate.get_and_clear_adjust_count()); -} - -} // namespace -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/host_unittests.cc b/chromium/mojo/shell/runner/host/host_unittests.cc deleted file mode 100644 index 3daf4a02b16..00000000000 --- a/chromium/mojo/shell/runner/host/host_unittests.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/shell/runner/common/switches.h" -#include "mojo/shell/runner/host/child_process.h" -#include "mojo/shell/runner/init.h" -#include "testing/gtest/include/gtest/gtest.h" - -int main(int argc, char** argv) { - base::CommandLine::Init(argc, argv); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - mojo::shell::WaitForDebuggerIfNecessary(); - - if (command_line.HasSwitch(switches::kChildProcess)) { - base::AtExitManager at_exit; - - return mojo::shell::ChildProcessMain(); - } - - mojo::edk::Init(); - - base::TestSuite test_suite(argc, argv); - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -} diff --git a/chromium/mojo/shell/runner/host/in_process_native_runner.cc b/chromium/mojo/shell/runner/host/in_process_native_runner.cc deleted file mode 100644 index 823cf5f3b45..00000000000 --- a/chromium/mojo/shell/runner/host/in_process_native_runner.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/in_process_native_runner.h" - -#include <utility> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/location.h" -#include "base/strings/utf_string_conversions.h" -#include "base/task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/platform_thread.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/runner/host/native_application_support.h" -#include "mojo/shell/runner/host/out_of_process_native_runner.h" -#include "mojo/shell/runner/init.h" - -namespace mojo { -namespace shell { - -InProcessNativeRunner::InProcessNativeRunner() : app_library_(nullptr) {} - -InProcessNativeRunner::~InProcessNativeRunner() { - // It is important to let the thread exit before unloading the DSO (when - // app_library_ is destructed), because the library may have registered - // thread-local data and destructors to run on thread termination. - if (thread_) { - DCHECK(thread_->HasBeenStarted()); - DCHECK(!thread_->HasBeenJoined()); - thread_->Join(); - } -} - -mojom::ShellClientPtr InProcessNativeRunner::Start( - const base::FilePath& app_path, - const Identity& target, - bool start_sandboxed, - const base::Callback<void(base::ProcessId)>& pid_available_callback, - const base::Closure& app_completed_callback) { - app_path_ = app_path; - - DCHECK(!request_.is_pending()); - mojom::ShellClientPtr client; - request_ = GetProxy(&client); - - DCHECK(app_completed_callback_runner_.is_null()); - app_completed_callback_runner_ = base::Bind( - &base::TaskRunner::PostTask, base::ThreadTaskRunnerHandle::Get(), - FROM_HERE, app_completed_callback); - - DCHECK(!thread_); - std::string thread_name = "mojo:app_thread"; -#if defined(OS_WIN) - thread_name = base::WideToUTF8(app_path_.BaseName().value()); -#endif - thread_.reset(new base::DelegateSimpleThread(this, thread_name)); - thread_->Start(); - pid_available_callback.Run(base::kNullProcessId); - - return client; -} - -void InProcessNativeRunner::Run() { - DVLOG(2) << "Loading/running Mojo app in process from library: " - << app_path_.value() - << " thread id=" << base::PlatformThread::CurrentId(); - - // TODO(vtl): ScopedNativeLibrary doesn't have a .get() method! - base::NativeLibrary app_library = LoadNativeApplication(app_path_); - app_library_.Reset(app_library); - // This hangs on Windows in the component build, so skip it since it's - // unnecessary. -#if !(defined(COMPONENT_BUILD) && defined(OS_WIN)) - CallLibraryEarlyInitialization(app_library); -#endif - RunNativeApplication(app_library, std::move(request_)); - app_completed_callback_runner_.Run(); - app_completed_callback_runner_.Reset(); -} - -scoped_ptr<NativeRunner> InProcessNativeRunnerFactory::Create( - const base::FilePath& app_path) { - // Non-Mojo apps are always run in a new process. - if (!app_path.MatchesExtension(FILE_PATH_LITERAL(".mojo"))) { - return make_scoped_ptr( - new OutOfProcessNativeRunner(launch_process_runner_, nullptr)); - } - return make_scoped_ptr(new InProcessNativeRunner); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/in_process_native_runner.h b/chromium/mojo/shell/runner/host/in_process_native_runner.h deleted file mode 100644 index 675ea8d9568..00000000000 --- a/chromium/mojo/shell/runner/host/in_process_native_runner.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_IN_PROCESS_NATIVE_RUNNER_H_ -#define MOJO_SHELL_RUNNER_HOST_IN_PROCESS_NATIVE_RUNNER_H_ - -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/scoped_native_library.h" -#include "base/threading/simple_thread.h" -#include "mojo/shell/native_runner.h" -#include "mojo/shell/runner/host/native_application_support.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { -namespace shell { - -// An implementation of |NativeRunner| that loads/runs the given app (from the -// file system) on a separate thread (in the current process). -class InProcessNativeRunner : public NativeRunner, - public base::DelegateSimpleThread::Delegate { - public: - InProcessNativeRunner(); - ~InProcessNativeRunner() override; - - // NativeRunner: - mojom::ShellClientPtr Start( - const base::FilePath& app_path, - const Identity& target, - bool start_sandboxed, - const base::Callback<void(base::ProcessId)>& pid_available_callback, - const base::Closure& app_completed_callback) override; - - private: - // |base::DelegateSimpleThread::Delegate| method: - void Run() override; - - base::FilePath app_path_; - InterfaceRequest<mojom::ShellClient> request_; - base::Callback<bool(void)> app_completed_callback_runner_; - - base::ScopedNativeLibrary app_library_; - scoped_ptr<base::DelegateSimpleThread> thread_; - - DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunner); -}; - -class InProcessNativeRunnerFactory : public NativeRunnerFactory { - public: - explicit InProcessNativeRunnerFactory(base::TaskRunner* launch_process_runner) - : launch_process_runner_(launch_process_runner) {} - ~InProcessNativeRunnerFactory() override {} - - scoped_ptr<NativeRunner> Create(const base::FilePath& app_path) override; - - private: - base::TaskRunner* const launch_process_runner_; - - DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunnerFactory); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_IN_PROCESS_NATIVE_RUNNER_H_ diff --git a/chromium/mojo/shell/runner/host/in_process_native_runner_unittest.cc b/chromium/mojo/shell/runner/host/in_process_native_runner_unittest.cc deleted file mode 100644 index 4e0ef2d27ed..00000000000 --- a/chromium/mojo/shell/runner/host/in_process_native_runner_unittest.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/in_process_native_runner.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { - -TEST(InProcessNativeRunnerTest, NotStarted) { - InProcessNativeRunner runner; - // Shouldn't crash or DCHECK on destruction. -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/linux_sandbox.cc b/chromium/mojo/shell/runner/host/linux_sandbox.cc deleted file mode 100644 index 9e9dbc7dcfb..00000000000 --- a/chromium/mojo/shell/runner/host/linux_sandbox.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/linux_sandbox.h" - -#include <fcntl.h> -#include <sys/syscall.h> -#include <utility> - -#include "base/bind.h" -#include "base/debug/leak_annotations.h" -#include "base/macros.h" -#include "base/posix/eintr_wrapper.h" -#include "base/rand_util.h" -#include "base/sys_info.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" -#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" -#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" -#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" -#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" -#include "sandbox/linux/services/credentials.h" -#include "sandbox/linux/services/namespace_sandbox.h" -#include "sandbox/linux/services/proc_util.h" -#include "sandbox/linux/services/thread_helpers.h" - -using sandbox::syscall_broker::BrokerFilePermission; - -namespace mojo { -namespace shell { - -namespace { - -intptr_t SandboxSIGSYSHandler(const struct sandbox::arch_seccomp_data& args, - void* aux) { - RAW_CHECK(aux); - const sandbox::syscall_broker::BrokerProcess* broker_process = - static_cast<const sandbox::syscall_broker::BrokerProcess*>(aux); - switch (args.nr) { - case __NR_access: - return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), - static_cast<int>(args.args[1])); - case __NR_open: - return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), - static_cast<int>(args.args[1])); - case __NR_faccessat: - if (static_cast<int>(args.args[0]) == AT_FDCWD) { - return broker_process->Access( - reinterpret_cast<const char*>(args.args[1]), - static_cast<int>(args.args[2])); - } else { - return -EPERM; - } - case __NR_openat: - // Allow using openat() as open(). - if (static_cast<int>(args.args[0]) == AT_FDCWD) { - return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), - static_cast<int>(args.args[2])); - } else { - return -EPERM; - } - default: - RAW_CHECK(false); - return -ENOSYS; - } -} - -class SandboxPolicy : public sandbox::BaselinePolicy { - public: - explicit SandboxPolicy(sandbox::syscall_broker::BrokerProcess* broker_process) - : broker_process_(broker_process) {} - ~SandboxPolicy() override {} - - // Overridden from sandbox::bpf_dsl::Policy: - sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override { - // This policy is only advisory/for noticing FS access for the moment. - switch (sysno) { -#if !defined(__aarch64__) - case __NR_access: - case __NR_open: -#endif - case __NR_faccessat: - case __NR_openat: - return sandbox::bpf_dsl::Trap(SandboxSIGSYSHandler, broker_process_); - case __NR_sched_getaffinity: - return sandbox::RestrictSchedTarget(policy_pid(), sysno); - case __NR_ftruncate: -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ - defined(__aarch64__) - // Per #ifdefs in - // content/common/sandbox_linux/bpf_renderer_policy_linux.cc - case __NR_getrlimit: -#endif -#if defined(__i386__) || defined(__arm__) - case __NR_ugetrlimit: -#endif - case __NR_uname: -#if defined(__arm__) || defined(__x86_64__) || defined(__mips__) - case __NR_getsockopt: - case __NR_setsockopt: -#endif - return sandbox::bpf_dsl::Allow(); - } - - return BaselinePolicy::EvaluateSyscall(sysno); - } - - private: - // Not owned. - const sandbox::syscall_broker::BrokerProcess* broker_process_; - DISALLOW_COPY_AND_ASSIGN(SandboxPolicy); -}; - -} // namespace - -LinuxSandbox::LinuxSandbox(const std::vector<BrokerFilePermission>& permissions) - : broker_(new sandbox::syscall_broker::BrokerProcess(EPERM, permissions)) { - CHECK(broker_->Init( - base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities))); - policy_.reset(new SandboxPolicy(broker_.get())); -} - -LinuxSandbox::~LinuxSandbox() {} - -void LinuxSandbox::Warmup() { - proc_fd_ = sandbox::ProcUtil::OpenProc(); - warmed_up_ = true; - - // Verify that we haven't started threads or grabbed directory file - // descriptors. - sandbox::ThreadHelpers::AssertSingleThreaded(proc_fd_.get()); - CHECK(!sandbox::ProcUtil::HasOpenDirectory(proc_fd_.get())); -} - -void LinuxSandbox::EngageNamespaceSandbox() { - CHECK(warmed_up_); - CHECK_EQ(1, getpid()); - CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); - CHECK(sandbox::Credentials::MoveToNewUserNS()); - CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_.get())); - CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd_.get())); -} - -void LinuxSandbox::EngageSeccompSandbox() { - CHECK(warmed_up_); - sandbox::SandboxBPF sandbox(policy_.release()); - base::ScopedFD proc_fd(HANDLE_EINTR( - openat(proc_fd_.get(), ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); - CHECK(proc_fd.is_valid()); - sandbox.SetProcFd(std::move(proc_fd)); - CHECK( - sandbox.StartSandbox(sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED)) - << "Starting the process with a sandbox failed. Missing kernel support."; - - // The Broker is now bound to this process and should only be destroyed when - // the process exits or is killed. - sandbox::syscall_broker::BrokerProcess* leaked_broker = broker_.release(); - ALLOW_UNUSED_LOCAL(leaked_broker); - ANNOTATE_LEAKING_OBJECT_PTR(leaked_broker); -} - -void LinuxSandbox::Seal() { - proc_fd_.reset(); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/linux_sandbox.h b/chromium/mojo/shell/runner/host/linux_sandbox.h deleted file mode 100644 index df81cf4d7ef..00000000000 --- a/chromium/mojo/shell/runner/host/linux_sandbox.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_LINUX_SANDBOX_H_ -#define MOJO_SHELL_RUNNER_HOST_LINUX_SANDBOX_H_ - -#include <memory> - -#include "base/files/scoped_file.h" -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/syscall_broker/broker_process.h" - -namespace mojo { -namespace shell { - -// Encapsulates all tasks related to raising the sandbox for mojo runner. -class LinuxSandbox { - public: - explicit LinuxSandbox( - const std::vector<sandbox::syscall_broker::BrokerFilePermission>& - permissions); - ~LinuxSandbox(); - - // Grabs a file descriptor to /proc. - void Warmup(); - - // Puts the user in a new PID namespace. - void EngageNamespaceSandbox(); - - // Starts a broker process and sets up seccomp-bpf to delegate decisions to - // it. - void EngageSeccompSandbox(); - - // Performs the dropping of access to the outside world (drops the reference - // to /proc acquired in Warmup(). - void Seal(); - - private: - bool warmed_up_; - base::ScopedFD proc_fd_; - std::unique_ptr<sandbox::syscall_broker::BrokerProcess> broker_; - std::unique_ptr<sandbox::bpf_dsl::Policy> policy_; - - DISALLOW_COPY_AND_ASSIGN(LinuxSandbox); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_LINUX_SANDBOX_H_ diff --git a/chromium/mojo/shell/runner/host/mach_broker.cc b/chromium/mojo/shell/runner/host/mach_broker.cc deleted file mode 100644 index 8b992793a4e..00000000000 --- a/chromium/mojo/shell/runner/host/mach_broker.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2016 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/shell/runner/host/mach_broker.h" - -#include "base/logging.h" -#include "base/memory/singleton.h" - -namespace mojo { -namespace shell { - -namespace { -const char kBootstrapPortName[] = "mojo_shell"; -} - -// static -void MachBroker::SendTaskPortToParent() { - bool result = base::MachPortBroker::ChildSendTaskPortToParent( - kBootstrapPortName); - DCHECK(result); -} - -// static -MachBroker* MachBroker::GetInstance() { - return base::Singleton<MachBroker>::get(); -} - -MachBroker::MachBroker() : broker_(kBootstrapPortName) { - bool result = broker_.Init(); - DCHECK(result); -} - -MachBroker::~MachBroker() {} - -void MachBroker::ExpectPid(base::ProcessHandle pid) { - broker_.AddPlaceholderForPid(pid); -} - -void MachBroker::RemovePid(base::ProcessHandle pid) { - broker_.InvalidatePid(pid); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/mach_broker.h b/chromium/mojo/shell/runner/host/mach_broker.h deleted file mode 100644 index 19b4b8bb98e..00000000000 --- a/chromium/mojo/shell/runner/host/mach_broker.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_MACH_BROKER_H_ -#define MOJO_SHELL_RUNNER_HOST_MACH_BROKER_H_ - -#include "base/mac/mach_port_broker.h" - -namespace base { -template <typename T> struct DefaultSingletonTraits; -} - -namespace mojo { -namespace shell { - -// A global singleton |MachBroker| is used by the shell to provide access to -// Mach task ports for shell out-of-process applications. -class MachBroker { - public: - // Sends the task port of the current process to the parent over Mach IPC. - // For use in child processes. - static void SendTaskPortToParent(); - - // Returns the global |MachBroker|. For use in the shell. - static MachBroker* GetInstance(); - - // Registers |pid| with a MACH_PORT_NULL task port in the port provider. A - // child's pid must be registered before the broker will accept a task port - // from that child. - // Callers MUST acquire the lock given by GetLock() before calling this method - // (and release the lock afterwards). - void ExpectPid(base::ProcessHandle pid); - - // Removes |pid| from the port provider. - // Callers MUST acquire the lock given by GetLock() before calling this method - // (and release the lock afterwards). - void RemovePid(base::ProcessHandle pid); - - base::Lock& GetLock() { return broker_.GetLock(); } - base::PortProvider* port_provider() { return &broker_; } - - private: - MachBroker(); - ~MachBroker(); - friend struct base::DefaultSingletonTraits<MachBroker>; - - base::MachPortBroker broker_; -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_MACH_BROKER_H_ diff --git a/chromium/mojo/shell/runner/host/native_application_support.cc b/chromium/mojo/shell/runner/host/native_application_support.cc deleted file mode 100644 index 19a255fd36c..00000000000 --- a/chromium/mojo/shell/runner/host/native_application_support.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/native_application_support.h" - -#include <stddef.h> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "mojo/platform_handle/platform_handle_private_thunks.h" -#include "mojo/public/platform/native/system_thunks.h" - -namespace mojo { -namespace shell { - -namespace { - -template <typename Thunks> -bool SetThunks(Thunks (*make_thunks)(), - const char* function_name, - base::NativeLibrary library) { - typedef size_t (*SetThunksFn)(const Thunks* thunks); - SetThunksFn set_thunks = reinterpret_cast<SetThunksFn>( - base::GetFunctionPointerFromNativeLibrary(library, function_name)); - if (!set_thunks) - return false; - Thunks thunks = make_thunks(); - size_t expected_size = set_thunks(&thunks); - if (expected_size > sizeof(Thunks)) { - LOG(ERROR) << "Invalid app library: expected " << function_name - << " to return thunks of size: " << expected_size; - return false; - } - return true; -} - -} // namespace - -base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path) { - DVLOG(2) << "Loading Mojo app in process from library: " << app_path.value(); - - base::NativeLibraryLoadError error; - base::NativeLibrary app_library = base::LoadNativeLibrary(app_path, &error); - LOG_IF(ERROR, !app_library) - << "Failed to load app library (path: " << app_path.value() << ")"; - return app_library; -} - -bool RunNativeApplication( - base::NativeLibrary app_library, - InterfaceRequest<mojom::ShellClient> request) { - // Tolerate |app_library| being null, to make life easier for callers. - if (!app_library) - return false; - -// Thunks aren't needed/used in component build, since the thunked methods -// just live in their own dynamically loaded library. -#if !defined(COMPONENT_BUILD) - if (!SetThunks(&MojoMakeSystemThunks, "MojoSetSystemThunks", app_library)) { - LOG(ERROR) << "MojoSetSystemThunks not found"; - return false; - } - -#if !defined(OS_WIN) - // On Windows, initializing base::CommandLine with null parameters gets the - // process's command line from the OS. Other platforms need it to be passed - // in. This needs to be passed in before the app initializes the command line, - // which is done as soon as it loads. - typedef void (*InitCommandLineArgs)(int, const char* const*); - InitCommandLineArgs init_command_line_args = - reinterpret_cast<InitCommandLineArgs>( - base::GetFunctionPointerFromNativeLibrary(app_library, - "InitCommandLineArgs")); - if (init_command_line_args) { - int argc = 0; - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - const char** argv = new const char*[cmd_line->argv().size()]; - for (auto& arg : cmd_line->argv()) - argv[argc++] = arg.c_str(); - init_command_line_args(argc, argv); - } -#endif - - // Apps need not include platform handle thunks. - SetThunks(&MojoMakePlatformHandlePrivateThunks, - "MojoSetPlatformHandlePrivateThunks", app_library); -#endif - - typedef MojoResult (*MojoMainFunction)(MojoHandle); - MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( - base::GetFunctionPointerFromNativeLibrary(app_library, "MojoMain")); - if (!main_function) { - LOG(ERROR) << "MojoMain not found"; - return false; - } - // |MojoMain()| takes ownership of the service handle. - MojoHandle handle = request.PassMessagePipe().release().value(); - MojoResult result = main_function(handle); - if (result != MOJO_RESULT_OK) { - LOG(ERROR) << "MojoMain returned error (result: " << result << ")"; - } - return true; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/native_application_support.h b/chromium/mojo/shell/runner/host/native_application_support.h deleted file mode 100644 index d7ce8a28e06..00000000000 --- a/chromium/mojo/shell/runner/host/native_application_support.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_NATIVE_APPLICATION_SUPPORT_H_ -#define MOJO_SHELL_RUNNER_HOST_NATIVE_APPLICATION_SUPPORT_H_ - -#include "base/native_library.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" - -namespace base { -class FilePath; -} - -namespace mojo { -class Application; -namespace shell { - -// Loads the native Mojo application from the DSO specified by |app_path|. -// Returns the |base::NativeLibrary| for the application on success (or null on -// failure). -// -// Note: The caller may choose to eventually unload the returned DSO. If so, -// this should be done only after the thread on which |LoadNativeApplication()| -// and |RunNativeApplication()| were called has terminated, so that any -// thread-local destructors have been executed. -base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path); - -// Runs the native Mojo application from the DSO that was loaded using -// |LoadNativeApplication()|; this tolerates |app_library| being null. This -// should be called on the same thread as |LoadNativeApplication()|. Returns -// true if |MojoMain()| was called (even if it returns an error), and false -// otherwise. -bool RunNativeApplication(base::NativeLibrary app_library, - InterfaceRequest<mojom::ShellClient> request); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_NATIVE_APPLICATION_SUPPORT_H_ diff --git a/chromium/mojo/shell/runner/host/out_of_process_native_runner.cc b/chromium/mojo/shell/runner/host/out_of_process_native_runner.cc deleted file mode 100644 index 30104ddfd64..00000000000 --- a/chromium/mojo/shell/runner/host/out_of_process_native_runner.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/host/out_of_process_native_runner.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/task_runner.h" -#include "mojo/shell/runner/common/client_util.h" -#include "mojo/shell/runner/host/child_process_host.h" -#include "mojo/shell/runner/host/in_process_native_runner.h" - -namespace mojo { -namespace shell { - -OutOfProcessNativeRunner::OutOfProcessNativeRunner( - base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate) - : launch_process_runner_(launch_process_runner), delegate_(delegate) {} - -OutOfProcessNativeRunner::~OutOfProcessNativeRunner() { - if (child_process_host_ && !app_path_.empty()) - child_process_host_->Join(); -} - -mojom::ShellClientPtr OutOfProcessNativeRunner::Start( - const base::FilePath& app_path, - const Identity& target, - bool start_sandboxed, - const base::Callback<void(base::ProcessId)>& pid_available_callback, - const base::Closure& app_completed_callback) { - app_path_ = app_path; - - DCHECK(app_completed_callback_.is_null()); - app_completed_callback_ = app_completed_callback; - - child_process_host_.reset(new ChildProcessHost( - launch_process_runner_, delegate_, start_sandboxed, target, app_path)); - return child_process_host_->Start( - target, pid_available_callback, - base::Bind(&OutOfProcessNativeRunner::AppCompleted, - base::Unretained(this))); -} - -void OutOfProcessNativeRunner::AppCompleted() { - if (child_process_host_) - child_process_host_->Join(); - child_process_host_.reset(); - // This object may be deleted by this callback. - base::Closure app_completed_callback = app_completed_callback_; - app_completed_callback_.Reset(); - if (!app_completed_callback.is_null()) - app_completed_callback.Run(); -} - -OutOfProcessNativeRunnerFactory::OutOfProcessNativeRunnerFactory( - base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate) - : launch_process_runner_(launch_process_runner), delegate_(delegate) {} -OutOfProcessNativeRunnerFactory::~OutOfProcessNativeRunnerFactory() {} - -scoped_ptr<shell::NativeRunner> OutOfProcessNativeRunnerFactory::Create( - const base::FilePath& app_path) { - return make_scoped_ptr( - new OutOfProcessNativeRunner(launch_process_runner_, delegate_)); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/host/out_of_process_native_runner.h b/chromium/mojo/shell/runner/host/out_of_process_native_runner.h deleted file mode 100644 index 45d7cf87517..00000000000 --- a/chromium/mojo/shell/runner/host/out_of_process_native_runner.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_HOST_OUT_OF_PROCESS_NATIVE_RUNNER_H_ -#define MOJO_SHELL_RUNNER_HOST_OUT_OF_PROCESS_NATIVE_RUNNER_H_ - -#include <stdint.h> - -#include <string> - -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/shell/native_runner.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { -namespace shell { - -class ChildProcessHost; -class NativeRunnerDelegate; - -// An implementation of |NativeRunner| that loads/runs the given app (from the -// file system) in a separate process (of its own). -class OutOfProcessNativeRunner : public NativeRunner { - public: - OutOfProcessNativeRunner(base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate); - ~OutOfProcessNativeRunner() override; - - // NativeRunner: - mojom::ShellClientPtr Start( - const base::FilePath& app_path, - const Identity& identity, - bool start_sandboxed, - const base::Callback<void(base::ProcessId)>& pid_available_callback, - const base::Closure& app_completed_callback) override; - - private: - void AppCompleted(); - - base::TaskRunner* const launch_process_runner_; - NativeRunnerDelegate* delegate_; - - base::FilePath app_path_; - base::Closure app_completed_callback_; - - scoped_ptr<ChildProcessHost> child_process_host_; - - DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunner); -}; - -class OutOfProcessNativeRunnerFactory : public NativeRunnerFactory { - public: - OutOfProcessNativeRunnerFactory(base::TaskRunner* launch_process_runner, - NativeRunnerDelegate* delegate); - ~OutOfProcessNativeRunnerFactory() override; - - scoped_ptr<NativeRunner> Create(const base::FilePath& app_path) override; - - private: - base::TaskRunner* const launch_process_runner_; - NativeRunnerDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunnerFactory); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_HOST_OUT_OF_PROCESS_NATIVE_RUNNER_H_ diff --git a/chromium/mojo/shell/runner/init.cc b/chromium/mojo/shell/runner/init.cc deleted file mode 100644 index 57eb312392e..00000000000 --- a/chromium/mojo/shell/runner/init.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/runner/init.h" - -#include <stdint.h> - -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/debug/debugger.h" -#include "base/files/file_path.h" -#include "base/i18n/icu_util.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/shell/runner/common/switches.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif (OS_POSIX) -#include <unistd.h> -#endif - -namespace mojo { -namespace shell { - -void InitializeLogging() { - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - logging::InitLogging(settings); - // To view log output with IDs and timestamps use "adb logcat -v threadtime". - logging::SetLogItems(true, // Process ID - true, // Thread ID - true, // Timestamp - true); // Tick count -} - -void WaitForDebuggerIfNecessary() { - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kWaitForDebugger)) { - std::vector<std::string> apps_to_debug = base::SplitString( - command_line->GetSwitchValueASCII(switches::kWaitForDebugger), ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - std::string app = "launcher"; - if (command_line->HasSwitch(switches::kChildProcess)) { - app = command_line->GetSwitchValuePath(switches::kChildProcess) - .BaseName() - .RemoveExtension() - .MaybeAsASCII(); - } - if (apps_to_debug.empty() || ContainsValue(apps_to_debug, app)) { -#if defined(OS_WIN) - base::string16 appw = base::UTF8ToUTF16(app); - base::string16 message = base::UTF8ToUTF16( - base::StringPrintf("%s - %d", app.c_str(), GetCurrentProcessId())); - MessageBox(NULL, message.c_str(), appw.c_str(), MB_OK | MB_SETFOREGROUND); -#else - LOG(ERROR) << app << " waiting for GDB. pid: " << getpid(); - base::debug::WaitForDebugger(60, true); -#endif - } - } -} - -void CallLibraryEarlyInitialization(base::NativeLibrary app_library) { - // Do whatever warming that the mojo application wants. - typedef void (*LibraryEarlyInitFunction)(const uint8_t*); - LibraryEarlyInitFunction init_function = - reinterpret_cast<LibraryEarlyInitFunction>( - base::GetFunctionPointerFromNativeLibrary(app_library, - "InitializeBase")); - if (init_function) { - // Get the ICU data that we prewarmed in the runner and then pass it to - // the copy of icu in the mojo binary that we're running. - const uint8_t* icu_data = base::i18n::GetRawIcuMemory(); - init_function(icu_data); - } - - // TODO(erg): All chromium binaries load base. We might want to make a - // general system for other people. -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/runner/init.h b/chromium/mojo/shell/runner/init.h deleted file mode 100644 index 20594106f2b..00000000000 --- a/chromium/mojo/shell/runner/init.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_RUNNER_INIT_H_ -#define MOJO_SHELL_RUNNER_INIT_H_ - -#include "base/native_library.h" - -namespace mojo { -namespace shell { - -// Initialization routines shared by desktop and Android main functions. -void InitializeLogging(); - -void WaitForDebuggerIfNecessary(); - -// Calls "LibraryEarlyInitialization" in |app_library| if it exists. We do -// common initialization there now. -void CallLibraryEarlyInitialization(base::NativeLibrary app_library); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_RUNNER_INIT_H_ diff --git a/chromium/mojo/shell/shell.cc b/chromium/mojo/shell/shell.cc deleted file mode 100644 index cfabfd60970..00000000000 --- a/chromium/mojo/shell/shell.cc +++ /dev/null @@ -1,791 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/shell.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/guid.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/process/process.h" -#include "base/process/process_handle.h" -#include "base/stl_util.h" -#include "base/strings/string_util.h" -#include "base/trace_event/trace_event.h" -#include "mojo/common/url_type_converters.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/shell/connect_util.h" -#include "mojo/shell/public/cpp/connector.h" -#include "mojo/shell/public/cpp/names.h" -#include "mojo/shell/public/cpp/shell_connection.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/shell.mojom.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" -#include "mojo/util/filename_util.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { -namespace { -const char kCatalogName[] = "mojo:catalog"; -const char kShellName[] = "mojo:shell"; -const char kCapabilityClass_UserID[] = "user_id"; -const char kCapabilityClass_ClientProcess[] = "client_process"; -const char kCapabilityClass_InstanceName[] = "instance_name"; -const char kCapabilityClass_AllUsers[] = "all_users"; - -void EmptyResolverCallback(mojom::ResolveResultPtr result) {} - -} - -Identity CreateShellIdentity() { - return Identity(kShellName, mojom::kRootUserID); -} - -Identity CreateCatalogIdentity() { - return Identity(kCatalogName, mojom::kRootUserID); -} - -CapabilitySpec GetPermissiveCapabilities() { - CapabilitySpec capabilities; - CapabilityRequest spec; - spec.interfaces.insert("*"); - capabilities.required["*"] = spec; - return capabilities; -} - -CapabilityRequest GetCapabilityRequest(const CapabilitySpec& source_spec, - const Identity& target) { - // Start by looking for specs specific to the supplied identity. - auto it = source_spec.required.find(target.name()); - if (it != source_spec.required.end()) - return it->second; - - // Fall back to looking for a wildcard rule. - it = source_spec.required.find("*"); - if (it != source_spec.required.end()) - return it->second; - - // Finally, nothing is allowed. - return CapabilityRequest(); -} - -CapabilityRequest GenerateCapabilityRequestForConnection( - const CapabilitySpec& source_spec, - const Identity& target, - const CapabilitySpec& target_spec) { - CapabilityRequest request = GetCapabilityRequest(source_spec, target); - // Flatten all interfaces from classes requested by the source into the - // allowed interface set in the request. - for (const auto& class_name : request.classes) { - auto it = target_spec.provided.find(class_name); - if (it != target_spec.provided.end()) { - for (const auto& interface_name : it->second) - request.interfaces.insert(interface_name); - } - } - return request; -} - -bool HasClass(const CapabilitySpec& spec, const std::string& class_name) { - auto it = spec.required.find(kShellName); - if (it == spec.required.end()) - return false; - return it->second.classes.find(class_name) != it->second.classes.end(); -} - -// Encapsulates a connection to an instance of an application, tracked by the -// shell's Shell. -class Shell::Instance : public mojom::Connector, - public mojom::PIDReceiver, - public ShellClient, - public InterfaceFactory<mojom::Shell>, - public mojom::Shell { - public: - Instance(mojo::shell::Shell* shell, - const Identity& identity, - const CapabilitySpec& capability_spec) - : shell_(shell), - id_(GenerateUniqueID()), - identity_(identity), - capability_spec_(capability_spec), - allow_any_application_(capability_spec.required.count("*") == 1), - pid_receiver_binding_(this), - weak_factory_(this) { - if (identity_.name() == kShellName || - shell_->GetLoaderForName(identity_.name())) { - pid_ = base::Process::Current().Pid(); - } - DCHECK_NE(mojom::kInvalidInstanceID, id_); - } - - ~Instance() override { - if (parent_) - parent_->RemoveChild(this); - // |children_| will be modified during destruction. - std::set<Instance*> children = children_; - for (auto child : children) - shell_->OnInstanceError(child); - } - - Instance* parent() { return parent_; } - void AddChild(Instance* child) { - children_.insert(child); - child->parent_ = this; - } - void RemoveChild(Instance* child) { - auto it = children_.find(child); - DCHECK(it != children_.end()); - children_.erase(it); - child->parent_ = nullptr; - } - - void ConnectToClient(scoped_ptr<ConnectParams> params) { - CHECK(shell_client_.is_bound()); - params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, - identity_.user_id(), id_); - uint32_t source_id = mojom::kInvalidInstanceID; - CapabilityRequest spec; - spec.interfaces.insert("*"); - Instance* source = shell_->GetExistingInstance(params->source()); - if (source) { - spec = GenerateCapabilityRequestForConnection( - source->capability_spec_, identity_, capability_spec_); - source_id = source->id(); - } - shell_client_->AcceptConnection( - mojom::Identity::From(params->source()), source_id, - params->TakeRemoteInterfaces(), params->TakeLocalInterfaces(), - mojom::CapabilityRequest::From(spec), params->target().name()); - } - - void StartWithClient(mojom::ShellClientPtr client) { - CHECK(!shell_client_); - shell_client_ = std::move(client); - shell_client_.set_connection_error_handler( - base::Bind(&Instance::OnShellClientLost, base::Unretained(this), - shell_->GetWeakPtr())); - shell_client_->Initialize(mojom::Identity::From(identity_), id_, - base::Bind(&Instance::OnInitializeResponse, - base::Unretained(this))); - } - - void StartWithClientProcessConnection( - mojom::ClientProcessConnectionPtr client_process_connection) { - mojom::ShellClientPtr client; - client.Bind(mojom::ShellClientPtrInfo( - std::move(client_process_connection->shell_client), 0)); - pid_receiver_binding_.Bind( - std::move(client_process_connection->pid_receiver_request)); - StartWithClient(std::move(client)); - } - - void StartWithFilePath(const base::FilePath& path) { - CHECK(!shell_client_); - scoped_ptr<NativeRunner> runner = - shell_->native_runner_factory_->Create(path); - bool start_sandboxed = false; - mojom::ShellClientPtr client = runner->Start( - path, identity_, start_sandboxed, - base::Bind(&Instance::PIDAvailable, weak_factory_.GetWeakPtr()), - base::Bind(&mojo::shell::Shell::CleanupRunner, - shell_->weak_ptr_factory_.GetWeakPtr(), runner.get())); - shell_->native_runners_.push_back(std::move(runner)); - StartWithClient(std::move(client)); - } - - mojom::InstanceInfoPtr CreateInstanceInfo() const { - mojom::InstanceInfoPtr info(mojom::InstanceInfo::New()); - info->id = id_; - info->identity = mojom::Identity::From(identity_); - info->pid = pid_; - return info; - } - - const CapabilitySpec& capability_spec() const { - return capability_spec_; - } - const Identity& identity() const { return identity_; } - uint32_t id() const { return id_; } - - // ShellClient: - bool AcceptConnection(Connection* connection) override { - connection->AddInterface<mojom::Shell>(this); - return true; - } - - private: - // mojom::Connector implementation: - void Connect(mojom::IdentityPtr target_ptr, - mojom::InterfaceProviderRequest remote_interfaces, - mojom::InterfaceProviderPtr local_interfaces, - mojom::ClientProcessConnectionPtr client_process_connection, - const ConnectCallback& callback) override { - Identity target = target_ptr.To<Identity>(); - if (target.user_id() == mojom::kInheritUserID) - target.set_user_id(identity_.user_id()); - - if (!ValidateIdentity(target, callback)) - return; - if (!ValidateClientProcessConnection(&client_process_connection, target, - callback)) { - return; - } - if (!ValidateCapabilities(target, callback)) - return; - - scoped_ptr<ConnectParams> params(new ConnectParams); - params->set_source(identity_); - params->set_target(target); - params->set_remote_interfaces(std::move(remote_interfaces)); - params->set_local_interfaces(std::move(local_interfaces)); - params->set_client_process_connection(std::move(client_process_connection)); - params->set_connect_callback(callback); - shell_->Connect(std::move(params)); - } - - void Clone(mojom::ConnectorRequest request) override { - connectors_.AddBinding(this, std::move(request)); - } - - // mojom::PIDReceiver: - void SetPID(uint32_t pid) override { - PIDAvailable(pid); - } - - // InterfaceFactory<mojom::Shell>: - void Create(Connection* connection, - mojom::ShellRequest request) override { - shell_bindings_.AddBinding(this, std::move(request)); - } - - // mojom::Shell implementation: - void AddInstanceListener(mojom::InstanceListenerPtr listener) override { - // TODO(beng): this should only track the instances matching this user, and - // root. - shell_->AddInstanceListener(std::move(listener)); - } - - bool ValidateIdentity(const Identity& identity, - const ConnectCallback& callback) { - if (!IsValidName(identity.name())) { - LOG(ERROR) << "Error: invalid Name: " << identity.name(); - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - if (!base::IsValidGUID(identity.user_id())) { - LOG(ERROR) << "Error: invalid user_id: " << identity.user_id(); - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - return true; - } - - bool ValidateClientProcessConnection( - mojom::ClientProcessConnectionPtr* client_process_connection, - const Identity& target, - const ConnectCallback& callback) { - if (!client_process_connection->is_null()) { - if (!HasClass(capability_spec_, kCapabilityClass_ClientProcess)) { - LOG(ERROR) << "Instance: " << identity_.name() << " attempting " - << "to register an instance for a process it created for " - << "target: " << target.name() << " without the " - << "mojo:shell{client_process} capability class."; - callback.Run(mojom::ConnectResult::ACCESS_DENIED, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - - if (!(*client_process_connection)->shell_client.is_valid() || - !(*client_process_connection)->pid_receiver_request.is_valid()) { - LOG(ERROR) << "Must supply both shell_client AND " - << "pid_receiver_request when sending " - << "client_process_connection."; - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - if (shell_->GetExistingInstance(target)) { - LOG(ERROR) << "Cannot client process matching existing identity:" - << "Name: " << target.name() << " User: " - << target.user_id() << " Instance: " << target.instance(); - callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - } - return true; - } - - bool ValidateCapabilities(const Identity& target, - const ConnectCallback& callback) { - // TODO(beng): Need to do the following additional policy validation of - // whether this instance is allowed to connect using: - // - a non-null client_process_connection. - if (target.user_id() != identity_.user_id() && - target.user_id() != mojom::kRootUserID && - !HasClass(capability_spec_, kCapabilityClass_UserID)) { - LOG(ERROR) << "Instance: " << identity_.name() << " running as: " - << identity_.user_id() << " attempting to connect to: " - << target.name() << " as: " << target.user_id() << " without " - << " the mojo:shell{user_id} capability class."; - callback.Run(mojom::ConnectResult::ACCESS_DENIED, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - if (!target.instance().empty() && - target.instance() != GetNamePath(target.name()) && - !HasClass(capability_spec_, kCapabilityClass_InstanceName)) { - LOG(ERROR) << "Instance: " << identity_.name() << " attempting to " - << "connect to " << target.name() << " using Instance name: " - << target.instance() << " without the " - << "mojo:shell{instance_name} capability class."; - callback.Run(mojom::ConnectResult::ACCESS_DENIED, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - - } - - if (allow_any_application_ || - capability_spec_.required.find(target.name()) != - capability_spec_.required.end()) { - return true; - } - LOG(ERROR) << "Capabilities prevented connection from: " << - identity_.name() << " to: " << target.name(); - callback.Run(mojom::ConnectResult::ACCESS_DENIED, - mojom::kInheritUserID, mojom::kInvalidInstanceID); - return false; - } - - uint32_t GenerateUniqueID() const { - static uint32_t id = mojom::kInvalidInstanceID; - ++id; - CHECK_NE(mojom::kInvalidInstanceID, id); - return id; - } - - void PIDAvailable(base::ProcessId pid) { - pid_ = pid; - shell_->NotifyPIDAvailable(id_, pid_); - } - - void OnShellClientLost(base::WeakPtr<mojo::shell::Shell> shell) { - shell_client_.reset(); - OnConnectionLost(shell); - } - - void OnConnectionLost(base::WeakPtr<mojo::shell::Shell> shell) { - // Any time a Connector is lost or we lose the ShellClient connection, it - // may have been the last pipe using this Instance. If so, clean up. - if (shell && connectors_.empty() && !shell_client_) { - // Deletes |this|. - shell->OnInstanceError(this); - } - } - - void OnInitializeResponse(mojom::ConnectorRequest connector_request) { - if (connector_request.is_pending()) { - connectors_.AddBinding(this, std::move(connector_request)); - connectors_.set_connection_error_handler( - base::Bind(&Instance::OnConnectionLost, base::Unretained(this), - shell_->GetWeakPtr())); - } - } - - mojo::shell::Shell* const shell_; - - // An id that identifies this instance. Distinct from pid, as a single process - // may vend multiple application instances, and this object may exist before a - // process is launched. - const uint32_t id_; - const Identity identity_; - const CapabilitySpec capability_spec_; - const bool allow_any_application_; - mojom::ShellClientPtr shell_client_; - Binding<mojom::PIDReceiver> pid_receiver_binding_; - BindingSet<mojom::Connector> connectors_; - BindingSet<mojom::Shell> shell_bindings_; - NativeRunner* runner_ = nullptr; - base::ProcessId pid_ = base::kNullProcessId; - Instance* parent_ = nullptr; - std::set<Instance*> children_; - base::WeakPtrFactory<Instance> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Instance); -}; - -// static -Shell::TestAPI::TestAPI(Shell* shell) : shell_(shell) {} -Shell::TestAPI::~TestAPI() {} - -bool Shell::TestAPI::HasRunningInstanceForName(const std::string& name) const { - for (const auto& entry : shell_->identity_to_instance_) { - if (entry.first.name() == name) - return true; - } - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// Shell, public: - -Shell::Shell(scoped_ptr<NativeRunnerFactory> native_runner_factory, - mojom::ShellClientPtr catalog) - : native_runner_factory_(std::move(native_runner_factory)), - weak_ptr_factory_(this) { - mojom::ShellClientPtr client; - mojom::ShellClientRequest request = GetProxy(&client); - Instance* instance = CreateInstance(Identity(), CreateShellIdentity(), - GetPermissiveCapabilities()); - instance->StartWithClient(std::move(client)); - singletons_.insert(kShellName); - shell_connection_.reset(new ShellConnection(this, std::move(request))); - - if (catalog) - InitCatalog(std::move(catalog)); -} - -Shell::~Shell() { - TerminateShellConnections(); - STLDeleteValues(&name_to_loader_); - for (auto& runner : native_runners_) - runner.reset(); -} - -void Shell::SetInstanceQuitCallback( - base::Callback<void(const Identity&)> callback) { - instance_quit_callback_ = callback; -} - -void Shell::Connect(scoped_ptr<ConnectParams> params) { - Connect(std::move(params), nullptr); -} - -mojom::ShellClientRequest Shell::InitInstanceForEmbedder( - const std::string& name) { - scoped_ptr<ConnectParams> params(new ConnectParams); - - Identity embedder_identity(name, mojom::kRootUserID); - params->set_source(embedder_identity); - params->set_target(embedder_identity); - - mojom::ShellClientPtr client; - mojom::ShellClientRequest request = GetProxy(&client); - Connect(std::move(params), std::move(client)); - - return request; -} - -void Shell::SetLoaderForName(scoped_ptr<Loader> loader, - const std::string& name) { - auto it = name_to_loader_.find(name); - if (it != name_to_loader_.end()) - delete it->second; - name_to_loader_[name] = loader.release(); -} - -//////////////////////////////////////////////////////////////////////////////// -// Shell, ShellClient implementation: - -bool Shell::AcceptConnection(Connection* connection) { - // The only interface we expose is mojom::Shell, and access to this interface - // is brokered by a policy specific to each caller, managed by the caller's - // instance. Here we look to see who's calling, and forward to the caller's - // instance to continue. - Instance* instance = nullptr; - for (const auto& entry : identity_to_instance_) { - if (entry.second->id() == connection->GetRemoteInstanceID()) { - instance = entry.second; - break; - } - } - DCHECK(instance); - return instance->AcceptConnection(connection); -} - -//////////////////////////////////////////////////////////////////////////////// -// Shell, private: - -void Shell::InitCatalog(mojom::ShellClientPtr catalog) { - Instance* instance = CreateInstance(CreateShellIdentity(), - CreateCatalogIdentity(), - CapabilitySpec()); - singletons_.insert(kCatalogName); - instance->StartWithClient(std::move(catalog)); - - // TODO(beng): this doesn't work anymore. - // Seed the catalog with manifest info for the shell & catalog. - mojo::shell::mojom::ShellResolverPtr resolver; - shell_connection_->connector()->ConnectToInterface(kCatalogName, &resolver); - resolver->ResolveMojoName(kCatalogName, base::Bind(&EmptyResolverCallback)); - resolver->ResolveMojoName(kShellName, base::Bind(&EmptyResolverCallback)); -} - -void Shell::TerminateShellConnections() { - Instance* instance = GetExistingInstance(CreateShellIdentity()); - DCHECK(instance); - OnInstanceError(instance); -} - -void Shell::OnInstanceError(Instance* instance) { - const Identity identity = instance->identity(); - // Remove the shell. - auto it = identity_to_instance_.find(identity); - DCHECK(it != identity_to_instance_.end()); - int id = instance->id(); - delete it->second; - identity_to_instance_.erase(it); - instance_listeners_.ForAllPtrs([this, id](mojom::InstanceListener* listener) { - listener->InstanceDestroyed(id); - }); - if (!instance_quit_callback_.is_null()) - instance_quit_callback_.Run(identity); -} - -void Shell::Connect(scoped_ptr<ConnectParams> params, - mojom::ShellClientPtr client) { - TRACE_EVENT_INSTANT1("mojo_shell", "Shell::Connect", - TRACE_EVENT_SCOPE_THREAD, "original_name", - params->target().name()); - DCHECK(IsValidName(params->target().name())); - DCHECK(base::IsValidGUID(params->target().user_id())); - DCHECK_NE(mojom::kInheritUserID, params->target().user_id()); - DCHECK(!client.is_bound() || !identity_to_instance_.count(params->target())); - - // Connect to an existing matching instance, if possible. - if (!client.is_bound() && ConnectToExistingInstance(¶ms)) - return; - - // The catalog needs to see the source identity as that of the originating - // app so it loads the correct store. Since the catalog is itself run as root - // when this re-enters Connect() it'll be handled by - // ConnectToExistingInstance(). - mojom::ShellResolverPtr resolver; - ConnectToInterface(this, Identity(kShellName, params->target().user_id()), - CreateCatalogIdentity(), &resolver); - - std::string name = params->target().name(); - mojom::ShellResolver* resolver_raw = resolver.get(); - resolver_raw->ResolveMojoName( - name, - base::Bind(&Shell::OnGotResolvedName, weak_ptr_factory_.GetWeakPtr(), - base::Passed(std::move(resolver)), base::Passed(¶ms), - base::Passed(&client))); -} - -Shell::Instance* Shell::GetExistingInstance(const Identity& identity) const { - const auto& it = identity_to_instance_.find(identity); - Instance* instance = it != identity_to_instance_.end() ? it->second : nullptr; - if (instance) - return instance; - - if (singletons_.find(identity.name()) != singletons_.end()) { - for (auto entry : identity_to_instance_) { - if (entry.first.name() == identity.name() && - entry.first.instance() == identity.instance()) { - return entry.second; - } - } - } - return nullptr; -} - -void Shell::NotifyPIDAvailable(uint32_t id, base::ProcessId pid) { - instance_listeners_.ForAllPtrs([id, pid](mojom::InstanceListener* listener) { - listener->InstancePIDAvailable(id, pid); - }); -} - -bool Shell::ConnectToExistingInstance(scoped_ptr<ConnectParams>* params) { - Instance* instance = GetExistingInstance((*params)->target()); - if (instance) - instance->ConnectToClient(std::move(*params)); - return !!instance; -} - -Shell::Instance* Shell::CreateInstance(const Identity& source, - const Identity& target, - const CapabilitySpec& spec) { - CHECK(target.user_id() != mojom::kInheritUserID); - Instance* instance = new Instance(this, target, spec); - DCHECK(identity_to_instance_.find(target) == - identity_to_instance_.end()); - Instance* source_instance = GetExistingInstance(source); - if (source_instance) - source_instance->AddChild(instance); - identity_to_instance_[target] = instance; - mojom::InstanceInfoPtr info = instance->CreateInstanceInfo(); - instance_listeners_.ForAllPtrs( - [this, &info](mojom::InstanceListener* listener) { - listener->InstanceCreated(info.Clone()); - }); - return instance; -} - -void Shell::AddInstanceListener(mojom::InstanceListenerPtr listener) { - // TODO(beng): filter instances provided by those visible to this client. - Array<mojom::InstanceInfoPtr> instances; - for (auto& instance : identity_to_instance_) - instances.push_back(instance.second->CreateInstanceInfo()); - listener->SetExistingInstances(std::move(instances)); - - instance_listeners_.AddPtr(std::move(listener)); -} - -void Shell::CreateShellClientWithFactory(const Identity& source, - const Identity& shell_client_factory, - const std::string& name, - mojom::ShellClientRequest request) { - mojom::ShellClientFactory* factory = - GetShellClientFactory(shell_client_factory, source); - factory->CreateShellClient(std::move(request), name); -} - -mojom::ShellClientFactory* Shell::GetShellClientFactory( - const Identity& shell_client_factory_identity, - const Identity& source_identity) { - auto it = shell_client_factories_.find(shell_client_factory_identity); - if (it != shell_client_factories_.end()) - return it->second.get(); - - mojom::ShellClientFactoryPtr factory; - ConnectToInterface(this, source_identity, shell_client_factory_identity, - &factory); - mojom::ShellClientFactory* factory_interface = factory.get(); - factory.set_connection_error_handler( - base::Bind(&Shell::OnShellClientFactoryLost, - weak_ptr_factory_.GetWeakPtr(), - shell_client_factory_identity)); - shell_client_factories_[shell_client_factory_identity] = std::move(factory); - return factory_interface; -} - -void Shell::OnShellClientFactoryLost(const Identity& which) { - // Remove the mapping. - auto it = shell_client_factories_.find(which); - DCHECK(it != shell_client_factories_.end()); - shell_client_factories_.erase(it); -} - -void Shell::OnGotResolvedName(mojom::ShellResolverPtr resolver, - scoped_ptr<ConnectParams> params, - mojom::ShellClientPtr client, - mojom::ResolveResultPtr result) { - std::string instance_name = params->target().instance(); - if (instance_name == GetNamePath(params->target().name()) && - result->qualifier != GetNamePath(result->resolved_name)) { - instance_name = result->qualifier; - } - Identity target(params->target().name(), params->target().user_id(), - instance_name); - params->set_target(target); - - // It's possible that when this manifest request was issued, another one was - // already in-progress and completed by the time this one did, and so the - // requested application may already be running. - if (ConnectToExistingInstance(¶ms)) - return; - - Identity source = params->source(); - // |capabilities_ptr| can be null when there is no manifest, e.g. for URL - // types not resolvable by the resolver. - CapabilitySpec capabilities = GetPermissiveCapabilities(); - if (!result->capabilities.is_null()) - capabilities = result->capabilities.To<CapabilitySpec>(); - - // Clients that request "all_users" class from the shell are allowed to - // field connection requests from any user. They also run with a synthetic - // user id generated here. The user id provided via Connect() is ignored. - // Additionally apps with the "all_users" class are not tied to the lifetime - // of the app that connected to them, instead they are owned by the shell. - Identity source_identity_for_creation; - if (HasClass(capabilities, kCapabilityClass_AllUsers)) { - singletons_.insert(target.name()); - target.set_user_id(base::GenerateGUID()); - source_identity_for_creation = CreateShellIdentity(); - } else { - source_identity_for_creation = params->source(); - } - - mojom::ClientProcessConnectionPtr client_process_connection = - params->TakeClientProcessConnection(); - Instance* instance = CreateInstance(source_identity_for_creation, - target, capabilities); - - // Below are various paths through which a new Instance can be bound to a - // ShellClient proxy. - if (client.is_bound()) { - // If a ShellClientPtr was provided, there's no more work to do: someone - // is already holding a corresponding ShellClientRequest. - instance->StartWithClient(std::move(client)); - } else if (!client_process_connection.is_null()) { - // Likewise if a ClientProcessConnection was given via Connect(), it - // provides the ShellClient proxy to use. - instance->StartWithClientProcessConnection( - std::move(client_process_connection)); - } else { - // Otherwise we create a new ShellClient pipe. - mojom::ShellClientRequest request = GetProxy(&client); - if (LoadWithLoader(target, &request)) { - instance->StartWithClient(std::move(client)); - } else { - CHECK(!result->package_url.is_null() && !result->capabilities.is_null()); - - if (target.name() != result->resolved_name) { - instance->StartWithClient(std::move(client)); - Identity factory(result->resolved_name, target.user_id(), - instance_name); - CreateShellClientWithFactory(source, factory, target.name(), - std::move(request)); - } else { - instance->StartWithFilePath( - util::UrlToFilePath(result->package_url.To<GURL>())); - } - } - } - - // Now that the instance has a ShellClient, we can connect to it. - instance->ConnectToClient(std::move(params)); -} - -bool Shell::LoadWithLoader(const Identity& target, - mojom::ShellClientRequest* request) { - Loader* loader = GetLoaderForName(target.name()); - if (!loader) - return false; - loader->Load(target.name(), std::move(*request)); - return true; -} - -Loader* Shell::GetLoaderForName(const std::string& name) { - auto name_it = name_to_loader_.find(name); - if (name_it != name_to_loader_.end()) - return name_it->second; - return default_loader_.get(); -} - -base::WeakPtr<Shell> Shell::GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} - -void Shell::CleanupRunner(NativeRunner* runner) { - for (auto it = native_runners_.begin(); it != native_runners_.end(); ++it) { - if (it->get() == runner) { - native_runners_.erase(it); - return; - } - } -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/shell.h b/chromium/mojo/shell/shell.h deleted file mode 100644 index 60c5dadbba2..00000000000 --- a/chromium/mojo/shell/shell.h +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_SHELL_H_ -#define MOJO_SHELL_SHELL_H_ - -#include <map> -#include <vector> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "mojo/shell/connect_params.h" -#include "mojo/shell/loader.h" -#include "mojo/shell/native_runner.h" -#include "mojo/shell/public/cpp/capabilities.h" -#include "mojo/shell/public/cpp/identity.h" -#include "mojo/shell/public/cpp/interface_factory.h" -#include "mojo/shell/public/cpp/shell_client.h" -#include "mojo/shell/public/interfaces/connector.mojom.h" -#include "mojo/shell/public/interfaces/interface_provider.mojom.h" -#include "mojo/shell/public/interfaces/shell.mojom.h" -#include "mojo/shell/public/interfaces/shell_client.mojom.h" -#include "mojo/shell/public/interfaces/shell_client_factory.mojom.h" -#include "mojo/shell/public/interfaces/shell_resolver.mojom.h" - -namespace mojo { -class ShellConnection; -namespace shell { - -// Creates an identity for the Shell, used when the Shell connects to -// applications. -Identity CreateShellIdentity(); - -class Shell : public ShellClient { - public: - // API for testing. - class TestAPI { - public: - explicit TestAPI(Shell* shell); - ~TestAPI(); - - // Returns true if there is a Instance for this name. - bool HasRunningInstanceForName(const std::string& name) const; - private: - Shell* shell_; - - DISALLOW_COPY_AND_ASSIGN(TestAPI); - }; - - // |native_runner_factory| is an instance of an object capable of vending - // implementations of NativeRunner, e.g. for in or out-of-process execution. - // See native_runner.h and RunNativeApplication(). - // |file_task_runner| provides access to a thread to perform file copy - // operations on. This may be null only in testing environments where - // applications are loaded via Loader implementations. - Shell(scoped_ptr<NativeRunnerFactory> native_runner_factory, - mojom::ShellClientPtr catalog); - ~Shell() override; - - // Provide a callback to be notified whenever an instance is destroyed. - // Typically the creator of the Shell will use this to determine when some set - // of instances it created are destroyed, so it can shut down. - void SetInstanceQuitCallback(base::Callback<void(const Identity&)> callback); - - // Completes a connection between a source and target application as defined - // by |params|, exchanging InterfaceProviders between them. If no existing - // instance of the target application is running, one will be loaded. - void Connect(scoped_ptr<ConnectParams> params); - - // Creates a new Instance identified as |name|. This is intended for use by - // the Shell's embedder to register itself with the shell. This must only be - // called once. - mojom::ShellClientRequest InitInstanceForEmbedder(const std::string& name); - - // Sets the default Loader to be used if not overridden by SetLoaderForName(). - void set_default_loader(scoped_ptr<Loader> loader) { - default_loader_ = std::move(loader); - } - - // Sets a Loader to be used for a specific name. - void SetLoaderForName(scoped_ptr<Loader> loader, const std::string& name); - - private: - class Instance; - - // ShellClient: - bool AcceptConnection(Connection* connection) override; - - void InitCatalog(mojom::ShellClientPtr catalog); - - // Destroys all Shell-ends of connections established with Applications. - // Applications connected by this Shell will observe pipe errors and have a - // chance to shutdown. - void TerminateShellConnections(); - - // Removes a Instance when it encounters an error. - void OnInstanceError(Instance* instance); - - // Completes a connection between a source and target application as defined - // by |params|, exchanging InterfaceProviders between them. If no existing - // instance of the target application is running, one will be loaded. - // - // If |client| is not null, there must not be an instance of the target - // application already running. The shell will create a new instance and use - // |client| to control it. - void Connect(scoped_ptr<ConnectParams> params, mojom::ShellClientPtr client); - - // Returns a running instance matching |identity|. This might be an instance - // running as a different user if one is available that services all users. - Instance* GetExistingInstance(const Identity& identity) const; - - void NotifyPIDAvailable(uint32_t id, base::ProcessId pid); - - // Attempt to complete the connection requested by |params| by connecting to - // an existing instance. If there is an existing instance, |params| is taken, - // and this function returns true. - bool ConnectToExistingInstance(scoped_ptr<ConnectParams>* params); - - Instance* CreateInstance(const Identity& source, - const Identity& target, - const CapabilitySpec& spec); - - // Called from the instance implementing mojom::Shell. - void AddInstanceListener(mojom::InstanceListenerPtr listener); - - void CreateShellClientWithFactory(const Identity& source, - const Identity& shell_client_factory, - const std::string& name, - mojom::ShellClientRequest request); - // Returns a running ShellClientFactory for |shell_client_factory_identity|. - // If there is not one running one is started for |source_identity|. - mojom::ShellClientFactory* GetShellClientFactory( - const Identity& shell_client_factory_identity, - const Identity& source_identity); - void OnShellClientFactoryLost(const Identity& which); - - // Callback when remote Catalog resolves mojo:foo to mojo:bar. - // |params| are the params passed to Connect(). - // |client| if provided is a ShellClientPtr which should be used to manage the - // new application instance. This may be null. - // |result| contains the result of the resolve operation. - void OnGotResolvedName(mojom::ShellResolverPtr resolver, - scoped_ptr<ConnectParams> params, - mojom::ShellClientPtr client, - mojom::ResolveResultPtr result); - - // Tries to load |target| with an Loader. Returns true if one was registered - // and it was loaded, in which case |request| is taken. - bool LoadWithLoader(const Identity& target, - mojom::ShellClientRequest* request); - - // Returns the appropriate loader for |name|, or the default loader if there - // is no loader configured for the name. - Loader* GetLoaderForName(const std::string& name); - - base::WeakPtr<Shell> GetWeakPtr(); - - void CleanupRunner(NativeRunner* runner); - - // Loader management. - // Loaders are chosen in the order they are listed here. - std::map<std::string, Loader*> name_to_loader_; - scoped_ptr<Loader> default_loader_; - - std::map<Identity, Instance*> identity_to_instance_; - - // Tracks the names of instances that are allowed to field connection requests - // from all users. - std::set<std::string> singletons_; - - std::map<Identity, mojom::ShellClientFactoryPtr> shell_client_factories_; - // Counter used to assign ids to client factories. - uint32_t shell_client_factory_id_counter_; - - InterfacePtrSet<mojom::InstanceListener> instance_listeners_; - - base::Callback<void(const Identity&)> instance_quit_callback_; - scoped_ptr<NativeRunnerFactory> native_runner_factory_; - std::vector<scoped_ptr<NativeRunner>> native_runners_; - scoped_ptr<ShellConnection> shell_connection_; - base::WeakPtrFactory<Shell> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(Shell); -}; - -mojom::Connector::ConnectCallback EmptyConnectCallback(); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_SHELL_H_ diff --git a/chromium/mojo/shell/standalone/BUILD.gn b/chromium/mojo/shell/standalone/BUILD.gn deleted file mode 100644 index 536f5bf1cf8..00000000000 --- a/chromium/mojo/shell/standalone/BUILD.gn +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") -import("//mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -executable("standalone") { - output_name = "mojo_runner" - sources = [ - "desktop/main.cc", - ] - deps = [ - ":lib", - "//base", - "//build/config/sanitizers:deps", - ] -} - -source_set("lib") { - sources = [ - "context.cc", - "context.h", - "desktop/launcher_process.cc", - "desktop/launcher_process.h", - "desktop/main_helper.cc", - "desktop/main_helper.h", - "tracer.cc", - "tracer.h", - ] - - deps = [ - "//base", - "//base:base_static", - "//base/third_party/dynamic_annotations", - "//components/tracing:startup_tracing", - "//mojo/edk/system", - "//mojo/message_pump", - "//mojo/services/catalog:lib", - "//mojo/services/tracing/public/cpp", - "//mojo/services/tracing/public/interfaces", - "//mojo/shell", - "//mojo/shell/public/cpp", - "//mojo/shell/runner/host:lib", - "//url", - ] - - data_deps = [ - "//mojo/services/tracing", - ] - - # This target includes some files behind #ifdef OS... guards. Since gn is not - # smart enough to understand preprocess includes, it does complains about - # these includes when not using the build files for that OS. Suppress checking - # so we can enable checking for the rest of the targets in this file. - # TODO: Might be better to split the files with OS-specific includes out to a - # separate source_set so we can leave checking on for the rest of the target. - check_includes = false -} diff --git a/chromium/mojo/shell/standalone/DEPS b/chromium/mojo/shell/standalone/DEPS deleted file mode 100644 index b404f56d748..00000000000 --- a/chromium/mojo/shell/standalone/DEPS +++ /dev/null @@ -1,5 +0,0 @@ -include_rules = [ - "+components/tracing", - "+mojo/services/catalog", - "+mojo/services/tracing", -] diff --git a/chromium/mojo/shell/standalone/context.cc b/chromium/mojo/shell/standalone/context.cc deleted file mode 100644 index 4a5512e9762..00000000000 --- a/chromium/mojo/shell/standalone/context.cc +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/standalone/context.h" - -#include <stddef.h> -#include <stdint.h> - -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/path_service.h" -#include "base/process/process_info.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/trace_event/trace_event.h" -#include "build/build_config.h" -#include "components/tracing/tracing_switches.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/services/catalog/factory.h" -#include "mojo/services/catalog/store.h" -#include "mojo/services/tracing/public/cpp/switches.h" -#include "mojo/services/tracing/public/cpp/trace_provider_impl.h" -#include "mojo/services/tracing/public/cpp/tracing_impl.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" -#include "mojo/shell/connect_params.h" -#include "mojo/shell/public/cpp/names.h" -#include "mojo/shell/runner/host/in_process_native_runner.h" -#include "mojo/shell/runner/host/out_of_process_native_runner.h" -#include "mojo/shell/standalone/tracer.h" -#include "mojo/shell/switches.h" -#include "mojo/util/filename_util.h" - -#if defined(OS_MACOSX) -#include "mojo/shell/runner/host/mach_broker.h" -#endif - -namespace mojo { -namespace shell { -namespace { - -// Used to ensure we only init once. -class Setup { - public: - Setup() { edk::Init(); } - - ~Setup() {} - - private: - DISALLOW_COPY_AND_ASSIGN(Setup); -}; - -class TracingInterfaceProvider : public shell::mojom::InterfaceProvider { - public: - TracingInterfaceProvider(Tracer* tracer, - shell::mojom::InterfaceProviderRequest request) - : tracer_(tracer), binding_(this, std::move(request)) {} - ~TracingInterfaceProvider() override {} - - // shell::mojom::InterfaceProvider: - void GetInterface(const mojo::String& interface_name, - ScopedMessagePipeHandle client_handle) override { - if (tracer_ && interface_name == tracing::TraceProvider::Name_) { - tracer_->ConnectToProvider( - MakeRequest<tracing::TraceProvider>(std::move(client_handle))); - } - } - - private: - Tracer* tracer_; - StrongBinding<shell::mojom::InterfaceProvider> binding_; - - DISALLOW_COPY_AND_ASSIGN(TracingInterfaceProvider); -}; - -const size_t kMaxBlockingPoolThreads = 3; - -scoped_ptr<base::Thread> CreateIOThread(const char* name) { - scoped_ptr<base::Thread> thread(new base::Thread(name)); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - thread->StartWithOptions(options); - return thread; -} - -void OnInstanceQuit(const std::string& name, const Identity& identity) { - if (name == identity.name()) - base::MessageLoop::current()->QuitWhenIdle(); -} - -} // namespace - -Context::InitParams::InitParams() {} -Context::InitParams::~InitParams() {} - -Context::Context() - : io_thread_(CreateIOThread("io_thread")), - main_entry_time_(base::Time::Now()) {} - -Context::~Context() { - DCHECK(!base::MessageLoop::current()); - blocking_pool_->Shutdown(); -} - -// static -void Context::EnsureEmbedderIsInitialized() { - static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER; - setup.Get(); -} - -void Context::Init(scoped_ptr<InitParams> init_params) { - TRACE_EVENT0("mojo_shell", "Context::Init"); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - bool trace_startup = command_line.HasSwitch(::switches::kTraceStartup); - if (trace_startup) { - tracer_.Start( - command_line.GetSwitchValueASCII(::switches::kTraceStartup), - command_line.GetSwitchValueASCII(::switches::kTraceStartupDuration), - "mojo_runner.trace"); - } - - if (!init_params || init_params->init_edk) - EnsureEmbedderIsInitialized(); - - shell_runner_ = base::MessageLoop::current()->task_runner(); - blocking_pool_ = - new base::SequencedWorkerPool(kMaxBlockingPoolThreads, "blocking_pool"); - - init_edk_ = !init_params || init_params->init_edk; - if (init_edk_) { - edk::InitIPCSupport(this, io_thread_->task_runner().get()); -#if defined(OS_MACOSX) - edk::SetMachPortProvider(MachBroker::GetInstance()->port_provider()); -#endif - } - - scoped_ptr<NativeRunnerFactory> runner_factory; - if (command_line.HasSwitch(switches::kSingleProcess)) { -#if defined(COMPONENT_BUILD) - LOG(ERROR) << "Running Mojo in single process component build, which isn't " - << "supported because statics in apps interact. Use static build" - << " or don't pass --single-process."; -#endif - runner_factory.reset( - new InProcessNativeRunnerFactory(blocking_pool_.get())); - } else { - NativeRunnerDelegate* native_runner_delegate = init_params ? - init_params->native_runner_delegate : nullptr; - runner_factory.reset(new OutOfProcessNativeRunnerFactory( - blocking_pool_.get(), native_runner_delegate)); - } - scoped_ptr<catalog::Store> store; - if (init_params) - store = std::move(init_params->catalog_store); - catalog_.reset( - new catalog::Factory(blocking_pool_.get(), std::move(store), nullptr)); - shell_.reset(new Shell(std::move(runner_factory), - catalog_->TakeShellClient())); - - shell::mojom::InterfaceProviderPtr tracing_remote_interfaces; - shell::mojom::InterfaceProviderPtr tracing_local_interfaces; - new TracingInterfaceProvider(&tracer_, GetProxy(&tracing_local_interfaces)); - - scoped_ptr<ConnectParams> params(new ConnectParams); - params->set_source(CreateShellIdentity()); - params->set_target(Identity("mojo:tracing", mojom::kRootUserID)); - params->set_remote_interfaces(GetProxy(&tracing_remote_interfaces)); - params->set_local_interfaces(std::move(tracing_local_interfaces)); - shell_->Connect(std::move(params)); - - if (command_line.HasSwitch(tracing::kTraceStartup)) { - tracing::TraceCollectorPtr coordinator; - auto coordinator_request = GetProxy(&coordinator); - tracing_remote_interfaces->GetInterface( - tracing::TraceCollector::Name_, coordinator_request.PassMessagePipe()); - tracer_.StartCollectingFromTracingService(std::move(coordinator)); - } - - // Record the shell startup metrics used for performance testing. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - tracing::kEnableStatsCollectionBindings)) { - tracing::StartupPerformanceDataCollectorPtr collector; - tracing_remote_interfaces->GetInterface( - tracing::StartupPerformanceDataCollector::Name_, - GetProxy(&collector).PassMessagePipe()); -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) - // CurrentProcessInfo::CreationTime is only defined on some platforms. - const base::Time creation_time = base::CurrentProcessInfo::CreationTime(); - collector->SetShellProcessCreationTime(creation_time.ToInternalValue()); -#endif - collector->SetShellMainEntryPointTime(main_entry_time_.ToInternalValue()); - } -} - -void Context::Shutdown() { - // Actions triggered by Shell's destructor may require a current message loop, - // so we should destruct it explicitly now as ~Context() occurs post message - // loop shutdown. - shell_.reset(); - - DCHECK_EQ(base::MessageLoop::current()->task_runner(), shell_runner_); - - // If we didn't initialize the edk we should not shut it down. - if (!init_edk_) - return; - - TRACE_EVENT0("mojo_shell", "Context::Shutdown"); - // Post a task in case OnShutdownComplete is called synchronously. - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(edk::ShutdownIPCSupport)); - // We'll quit when we get OnShutdownComplete(). - base::MessageLoop::current()->Run(); -} - -void Context::OnShutdownComplete() { - DCHECK_EQ(base::MessageLoop::current()->task_runner(), shell_runner_); - base::MessageLoop::current()->QuitWhenIdle(); -} - -void Context::RunCommandLineApplication() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - base::CommandLine::StringVector args = command_line->GetArgs(); - for (size_t i = 0; i < args.size(); ++i) { -#if defined(OS_WIN) - std::string possible_app = base::WideToUTF8(args[i]); -#else - std::string possible_app = args[i]; -#endif - if (GetNameType(possible_app) == "mojo") { - Run(possible_app); - break; - } - } -} - -void Context::Run(const std::string& name) { - shell_->SetInstanceQuitCallback(base::Bind(&OnInstanceQuit, name)); - - shell::mojom::InterfaceProviderPtr remote_interfaces; - shell::mojom::InterfaceProviderPtr local_interfaces; - - scoped_ptr<ConnectParams> params(new ConnectParams); - params->set_source(CreateShellIdentity()); - params->set_target(Identity(name, mojom::kRootUserID)); - params->set_remote_interfaces(GetProxy(&remote_interfaces)); - params->set_local_interfaces(std::move(local_interfaces)); - shell_->Connect(std::move(params)); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/standalone/context.h b/chromium/mojo/shell/standalone/context.h deleted file mode 100644 index fee1e5ab274..00000000000 --- a/chromium/mojo/shell/standalone/context.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_STANDALONE_CONTEXT_H_ -#define MOJO_SHELL_STANDALONE_CONTEXT_H_ - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread.h" -#include "base/time/time.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/shell/shell.h" -#include "mojo/shell/standalone/tracer.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace catalog { -class Factory; -class Store; -} - -namespace mojo { -namespace shell { -class NativeRunnerDelegate; - -// The "global" context for the shell's main process. -class Context : public edk::ProcessDelegate { - public: - struct InitParams { - InitParams(); - ~InitParams(); - - NativeRunnerDelegate* native_runner_delegate = nullptr; - scoped_ptr<catalog::Store> catalog_store; - // If true the edk is initialized. - bool init_edk = true; - }; - - Context(); - ~Context() override; - - static void EnsureEmbedderIsInitialized(); - - // This must be called with a message loop set up for the current thread, - // which must remain alive until after Shutdown() is called. - void Init(scoped_ptr<InitParams> init_params); - - // If Init() was called and succeeded, this must be called before destruction. - void Shutdown(); - - // Run the application specified on the command line. - void RunCommandLineApplication(); - - Shell* shell() { return shell_.get(); } - - private: - // edk::ProcessDelegate: - void OnShutdownComplete() override; - - // Runs the app specified by |name|. - void Run(const std::string& name); - - scoped_refptr<base::SingleThreadTaskRunner> shell_runner_; - scoped_ptr<base::Thread> io_thread_; - scoped_refptr<base::SequencedWorkerPool> blocking_pool_; - - // Ensure this is destructed before task_runners_ since it owns a message pipe - // that needs the IO thread to destruct cleanly. - Tracer tracer_; - scoped_ptr<catalog::Factory> catalog_; - scoped_ptr<Shell> shell_; - base::Time main_entry_time_; - bool init_edk_ = false; - - DISALLOW_COPY_AND_ASSIGN(Context); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_STANDALONE_CONTEXT_H_ diff --git a/chromium/mojo/shell/standalone/desktop/launcher_process.cc b/chromium/mojo/shell/standalone/desktop/launcher_process.cc deleted file mode 100644 index 58309188ef5..00000000000 --- a/chromium/mojo/shell/standalone/desktop/launcher_process.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdio.h> -#include <string.h> - -#include <iostream> - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/debug/stack_trace.h" -#include "base/files/file_util.h" -#include "base/i18n/icu_util.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/platform_thread.h" -#include "mojo/shell/standalone/context.h" -#include "mojo/shell/switches.h" - -namespace mojo { -namespace shell { - -int LauncherProcessMain() { -#if !defined(OFFICIAL_BUILD) - base::debug::EnableInProcessStackDumping(); -#endif - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - // http://crbug.com/546644 - command_line->AppendSwitch(switches::kNoSandbox); - - base::PlatformThread::SetName("mojo_runner"); - - // We want the Context to outlive the MessageLoop so that pipes are all - // gracefully closed / error-out before we try to shut the Context down. - Context shell_context; - { - base::MessageLoop message_loop; - CHECK(base::i18n::InitializeICU()); - shell_context.Init(nullptr); - - message_loop.PostTask( - FROM_HERE, - base::Bind(&Context::RunCommandLineApplication, - base::Unretained(&shell_context))); - - message_loop.Run(); - - // Must be called before |message_loop| is destroyed. - shell_context.Shutdown(); - } - - return 0; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/standalone/desktop/launcher_process.h b/chromium/mojo/shell/standalone/desktop/launcher_process.h deleted file mode 100644 index 54ec2957dee..00000000000 --- a/chromium/mojo/shell/standalone/desktop/launcher_process.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_STANDALONE_LAUNCHER_PROCESS_H_ -#define MOJO_SHELL_STANDALONE_LAUNCHER_PROCESS_H_ - -#include "base/callback_forward.h" - -namespace mojo { -namespace shell { - -// Main method for the launcher process. -int LauncherProcessMain(); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_STANDALONE_LAUNCHER_PROCESS_H_ diff --git a/chromium/mojo/shell/standalone/desktop/main.cc b/chromium/mojo/shell/standalone/desktop/main.cc deleted file mode 100644 index a6b387841a4..00000000000 --- a/chromium/mojo/shell/standalone/desktop/main.cc +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/standalone/desktop/main_helper.h" - -int main(int argc, char** argv) { - return mojo::shell::StandaloneShellMain(argc, argv); -} diff --git a/chromium/mojo/shell/standalone/desktop/main_helper.cc b/chromium/mojo/shell/standalone/desktop/main_helper.cc deleted file mode 100644 index abbf6c283fa..00000000000 --- a/chromium/mojo/shell/standalone/desktop/main_helper.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/standalone/desktop/main_helper.h" - -#include "base/at_exit.h" -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/debug/debugger.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/process/launch.h" -#include "base/stl_util.h" -#include "base/strings/string_split.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/shell/runner/common/switches.h" -#include "mojo/shell/runner/host/child_process.h" -#include "mojo/shell/runner/init.h" -#include "mojo/shell/standalone/desktop/launcher_process.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif (OS_POSIX) -#include <unistd.h> -#endif - -namespace mojo { -namespace shell { - -int StandaloneShellMain(int argc, char** argv) { - base::CommandLine::Init(argc, argv); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - base::AtExitManager at_exit; - InitializeLogging(); - WaitForDebuggerIfNecessary(); - -#if !defined(OFFICIAL_BUILD) && defined(OS_WIN) - base::RouteStdioToConsole(false); -#endif - - if (command_line.HasSwitch(switches::kChildProcess)) - return ChildProcessMain(); - - return LauncherProcessMain(); -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/standalone/desktop/main_helper.h b/chromium/mojo/shell/standalone/desktop/main_helper.h deleted file mode 100644 index a2b5fcf2d67..00000000000 --- a/chromium/mojo/shell/standalone/desktop/main_helper.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_STANDALONE_DESKTOP_MAIN_HELPER_H -#define MOJO_SHELL_STANDALONE_DESKTOP_MAIN_HELPER_H - -namespace mojo { -namespace shell { - -// Helper method to start Mojo standalone shell code. -int StandaloneShellMain(int argc, char** argv); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_STANDALONE_DESKTOP_MAIN_HELPER_H diff --git a/chromium/mojo/shell/standalone/tracer.cc b/chromium/mojo/shell/standalone/tracer.cc deleted file mode 100644 index d7aaaf77877..00000000000 --- a/chromium/mojo/shell/standalone/tracer.cc +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/standalone/tracer.h" - -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include <utility> - -#include "base/message_loop/message_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_event.h" - -namespace mojo { -namespace shell { - -Tracer::Tracer() - : tracing_(false), first_chunk_written_(false), trace_file_(nullptr) {} - -Tracer::~Tracer() { - StopAndFlushToFile(); -} - -void Tracer::Start(const std::string& categories, - const std::string& duration_seconds_str, - const std::string& filename) { - tracing_ = true; - trace_filename_ = filename; - categories_ = categories; - base::trace_event::TraceConfig config(categories, - base::trace_event::RECORD_UNTIL_FULL); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - config, base::trace_event::TraceLog::RECORDING_MODE); - - int trace_duration_secs = 5; - if (!duration_seconds_str.empty()) { - CHECK(base::StringToInt(duration_seconds_str, &trace_duration_secs)) - << "Could not parse --trace-startup-duration value " - << duration_seconds_str; - } - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&Tracer::StopAndFlushToFile, base::Unretained(this)), - base::TimeDelta::FromSeconds(trace_duration_secs)); -} - -void Tracer::StartCollectingFromTracingService( - tracing::TraceCollectorPtr coordinator) { - coordinator_ = std::move(coordinator); - mojo::DataPipe data_pipe; - coordinator_->Start(std::move(data_pipe.producer_handle), categories_); - drainer_.reset(new mojo::common::DataPipeDrainer( - this, std::move(data_pipe.consumer_handle))); -} - -void Tracer::StopAndFlushToFile() { - if (tracing_) - StopTracingAndFlushToDisk(); -} - -void Tracer::ConnectToProvider( - mojo::InterfaceRequest<tracing::TraceProvider> request) { - trace_provider_impl_.Bind(std::move(request)); -} - -void Tracer::StopTracingAndFlushToDisk() { - tracing_ = false; - trace_file_ = fopen(trace_filename_.c_str(), "w+"); - PCHECK(trace_file_); - static const char kStart[] = "{\"traceEvents\":["; - PCHECK(fwrite(kStart, 1, strlen(kStart), trace_file_) == strlen(kStart)); - - // At this point we might be connected to the tracing service, in which case - // we want to tell it to stop tracing and we will send the data we've - // collected in process to it. - if (coordinator_) { - coordinator_->StopAndFlush(); - } else { - // Or we might not be connected. If we aren't connected to the tracing - // service we want to collect the tracing data gathered ourselves and flush - // it to disk. We do this in a blocking fashion (for this thread) so we can - // gather as much data as possible on shutdown. - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - { - base::WaitableEvent flush_complete_event(false, false); - // TraceLog::Flush requires a message loop but we've already shut ours - // down. - // Spin up a new thread to flush things out. - base::Thread flush_thread("mojo_runner_trace_event_flush"); - flush_thread.Start(); - flush_thread.message_loop()->PostTask( - FROM_HERE, - base::Bind(&Tracer::EndTraceAndFlush, base::Unretained(this), - trace_filename_, - base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&flush_complete_event)))); - base::trace_event::TraceLog::GetInstance() - ->SetCurrentThreadBlocksMessageLoop(); - flush_complete_event.Wait(); - } - } -} - -void Tracer::WriteFooterAndClose() { - static const char kEnd[] = "]}"; - PCHECK(fwrite(kEnd, 1, strlen(kEnd), trace_file_) == strlen(kEnd)); - PCHECK(fclose(trace_file_) == 0); - trace_file_ = nullptr; - LOG(ERROR) << "Wrote trace data to " << trace_filename_; -} - -void Tracer::EndTraceAndFlush(const std::string& filename, - const base::Closure& done_callback) { - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - base::trace_event::TraceLog::GetInstance()->Flush(base::Bind( - &Tracer::WriteTraceDataCollected, base::Unretained(this), done_callback)); -} - -void Tracer::WriteTraceDataCollected( - const base::Closure& done_callback, - const scoped_refptr<base::RefCountedString>& events_str, - bool has_more_events) { - if (events_str->size()) { - WriteCommaIfNeeded(); - - PCHECK(fwrite(events_str->data().c_str(), 1, events_str->data().length(), - trace_file_) == events_str->data().length()); - } - - if (!has_more_events && !done_callback.is_null()) - done_callback.Run(); -} - -void Tracer::OnDataAvailable(const void* data, size_t num_bytes) { - const char* chars = static_cast<const char*>(data); - trace_service_data_.append(chars, num_bytes); -} - -void Tracer::OnDataComplete() { - if (!trace_service_data_.empty()) { - WriteCommaIfNeeded(); - const char* const chars = trace_service_data_.data(); - size_t num_bytes = trace_service_data_.length(); - PCHECK(fwrite(chars, 1, num_bytes, trace_file_) == num_bytes); - trace_service_data_ = std::string(); - } - drainer_.reset(); - coordinator_.reset(); - WriteFooterAndClose(); -} - -void Tracer::WriteCommaIfNeeded() { - if (first_chunk_written_) - PCHECK(fwrite(",", 1, 1, trace_file_) == 1); - first_chunk_written_ = true; -} - -} // namespace shell -} // namespace mojo diff --git a/chromium/mojo/shell/standalone/tracer.h b/chromium/mojo/shell/standalone/tracer.h deleted file mode 100644 index 651a35c2e42..00000000000 --- a/chromium/mojo/shell/standalone/tracer.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_STANDALONE_TRACER_H_ -#define MOJO_SHELL_STANDALONE_TRACER_H_ - -#include <stddef.h> -#include <stdio.h> - -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted_memory.h" -#include "mojo/common/data_pipe_drainer.h" -#include "mojo/services/tracing/public/cpp/trace_provider_impl.h" -#include "mojo/services/tracing/public/interfaces/tracing.mojom.h" - -namespace mojo { -namespace shell { - -// Tracer collects tracing data from base/trace_event and from externally -// configured sources, aggregates it into a single stream, and writes it out to -// a file. It should be constructed very early in a process' lifetime before any -// initialization that may be interesting to trace has occured and be shut down -// as late as possible to capture as much initialization/shutdown code as -// possible. -class Tracer : public mojo::common::DataPipeDrainer::Client { - public: - Tracer(); - ~Tracer() override; - - // Starts tracing the current process with the given set of categories. The - // tracing results will be saved into the specified filename when - // StopAndFlushToFile() is called. - void Start(const std::string& categories, - const std::string& duration_seconds_str, - const std::string& filename); - - // Starts collecting data from the tracing service with the given set of - // categories. - void StartCollectingFromTracingService( - tracing::TraceCollectorPtr coordinator); - - // Stops tracing and flushes all collected trace data to the file specified in - // Start(). Blocks until the file write is complete. May be called after the - // message loop is shut down. - void StopAndFlushToFile(); - - void ConnectToProvider( - mojo::InterfaceRequest<tracing::TraceProvider> request); - - private: - void StopTracingAndFlushToDisk(); - - // Called from the flush thread. When all data is collected this runs - // |done_callback| on the flush thread. - void EndTraceAndFlush(const std::string& filename, - const base::Closure& done_callback); - - // Called from the flush thread. - void WriteTraceDataCollected( - const base::Closure& done_callback, - const scoped_refptr<base::RefCountedString>& events_str, - bool has_more_events); - - // mojo::common::DataPipeDrainer::Client implementation. - void OnDataAvailable(const void* data, size_t num_bytes) override; - void OnDataComplete() override; - - // Emits a comma if needed. - void WriteCommaIfNeeded(); - - // Writes trace file footer and closes out the file. - void WriteFooterAndClose(); - - // Set when connected to the tracing service. - tracing::TraceCollectorPtr coordinator_; - scoped_ptr<mojo::common::DataPipeDrainer> drainer_; - - mojo::TraceProviderImpl trace_provider_impl_; - // Whether we're currently tracing. - bool tracing_; - // Categories to trace. - std::string categories_; - - // Whether we've written the first chunk. - bool first_chunk_written_; - std::string trace_service_data_; - - // Trace file, if open. - FILE* trace_file_; - std::string trace_filename_; - - DISALLOW_COPY_AND_ASSIGN(Tracer); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_STANDALONE_TRACER_H_ diff --git a/chromium/mojo/shell/switches.cc b/chromium/mojo/shell/switches.cc deleted file mode 100644 index ce52003d622..00000000000 --- a/chromium/mojo/shell/switches.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/shell/switches.h" - -namespace mojo { -namespace switches { - -// Disables the sandbox for debugging. -const char kNoSandbox[] = "no-sandbox"; - -// Load apps in a single processes. -const char kSingleProcess[] = "single-process"; - -} // namespace switches -} // namespace mojo diff --git a/chromium/mojo/shell/switches.h b/chromium/mojo/shell/switches.h deleted file mode 100644 index f0482e1423c..00000000000 --- a/chromium/mojo/shell/switches.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_SHELL_SWITCHES_H_ -#define MOJO_SHELL_SWITCHES_H_ - -#include <set> -#include <string> - -namespace mojo { -namespace switches { - -// All switches in alphabetical order. The switches should be documented -// alongside the definition of their values in the .cc file. -extern const char kNoSandbox[]; -extern const char kSingleProcess[]; - -} // namespace switches -} // namespace mojo - -#endif // MOJO_SHELL_SWITCHES_H_ diff --git a/chromium/mojo/tools/android_mojo_shell.py b/chromium/mojo/tools/android_mojo_shell.py deleted file mode 100755 index 5ba34fb3033..00000000000 --- a/chromium/mojo/tools/android_mojo_shell.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import logging -import sys - -from mopy.android import AndroidShell -from mopy.config import Config - -USAGE = ('android_mojo_shell.py [<shell-and-app-args>] [<mojo-app>]') - -def main(): - logging.basicConfig() - - parser = argparse.ArgumentParser(usage=USAGE) - - debug_group = parser.add_mutually_exclusive_group() - debug_group.add_argument('--debug', help='Debug build (default)', - default=True, action='store_true') - debug_group.add_argument('--release', help='Release build', default=False, - dest='debug', action='store_false') - parser.add_argument('--target-cpu', help='CPU architecture to run for.', - choices=['x64', 'x86', 'arm'], default='arm') - parser.add_argument('--device', help='Serial number of the target device.') - parser.add_argument('--verbose', default=False, action='store_true') - parser.add_argument('--apk', help='Name of the APK to run.', - default='MojoRunner.apk') - runner_args, args = parser.parse_known_args() - - logger = logging.getLogger() - logging.basicConfig(stream=sys.stdout, format='%(levelname)s:%(message)s') - logger.setLevel(logging.DEBUG if runner_args.verbose else logging.WARNING) - logger.debug('Initialized logging: level=%s' % logger.level) - - config = Config(target_os=Config.OS_ANDROID, - target_cpu=runner_args.target_cpu, - is_debug=runner_args.debug, - is_verbose=runner_args.verbose, - apk_name=runner_args.apk) - shell = AndroidShell(config) - shell.InitShell(runner_args.device) - p = shell.ShowLogs() - shell.StartActivity('MojoShellActivity', args, sys.stdout, p.terminate) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/chromium/mojo/tools/apptest_runner.py b/chromium/mojo/tools/apptest_runner.py deleted file mode 100755 index 6494db73cb1..00000000000 --- a/chromium/mojo/tools/apptest_runner.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -'''A test runner for gtest application tests.''' - -import argparse -import json -import logging -import os -import string -import sys -import time - -from mopy import gtest -from mopy.config import Config - - -APPTESTS = os.path.abspath(os.path.join(__file__, '..', 'data', 'apptests')) - - -def main(): - parser = argparse.ArgumentParser(description='An application test runner.') - parser.add_argument('build_dir', type=str, help='The build output directory.') - parser.add_argument('--verbose', default=False, action='store_true', - help='Print additional logging information.') - parser.add_argument('--repeat-count', default=1, metavar='INT', - action='store', type=int, - help='The number of times to repeat the set of tests.') - parser.add_argument('--write-full-results-to', metavar='FILENAME', - help='The path to write the JSON list of full results.') - parser.add_argument('--test-list-file', metavar='FILENAME', type=file, - default=APPTESTS, help='The file listing tests to run.') - parser.add_argument('--apptest-filter', default='', - help='A comma-separated list of mojo:apptests to run.') - args, commandline_args = parser.parse_known_args() - - logger = logging.getLogger() - logging.basicConfig(stream=sys.stdout, format='%(levelname)s:%(message)s') - logger.setLevel(logging.DEBUG if args.verbose else logging.WARNING) - logger.debug('Initialized logging: level=%s' % logger.level) - - logger.debug('Test list file: %s', args.test_list_file) - config = Config(args.build_dir, is_verbose=args.verbose, - apk_name='MojoRunnerApptests.apk') - execution_globals = {'config': config} - exec args.test_list_file in execution_globals - test_list = execution_globals['tests'] - logger.debug('Test list: %s' % test_list) - - shell = None - if config.target_os == Config.OS_ANDROID: - from mopy.android import AndroidShell - shell = AndroidShell(config) - result = shell.InitShell() - if result != 0: - return result - - tests = [] - failed = [] - failed_suites = 0 - apptest_filter = [a for a in string.split(args.apptest_filter, ',') if a] - gtest_filter = [a for a in commandline_args if a.startswith('--gtest_filter')] - for _ in range(args.repeat_count): - for test_dict in test_list: - test = test_dict['test'] - test_name = test_dict.get('name', test) - test_type = test_dict.get('type', 'gtest') - test_args = test_dict.get('args', []) + commandline_args - if apptest_filter and not set(apptest_filter) & set([test, test_name]): - continue; - - print 'Running %s...%s' % (test_name, ('\n' if args.verbose else '')), - sys.stdout.flush() - - assert test_type in ('gtest', 'gtest_isolated') - if test_type == 'gtest': - print ('WARNING: tests are forced to gtest_isolated until ' - 'http://crbug.com/529487 is fixed') - test_type = 'gtest_isolated' - isolate = test_type == 'gtest_isolated' - (ran, fail) = gtest.run_apptest(config, shell, test_args, test, isolate) - # Ignore empty fixture lists when the commandline has a gtest filter flag. - if gtest_filter and not ran and not fail: - print '[ NO TESTS ] ' + (test_name if args.verbose else '') - continue - # Use the apptest name if the whole suite failed or no fixtures were run. - fail = [test_name] if (not ran and (not fail or fail == [test])) else fail - tests.extend(ran) - failed.extend(fail) - result = ran and not fail - print '[ PASSED ]' if result else '[ FAILED ]', - print test_name if args.verbose or not result else '' - # Abort when 3 apptest suites, or a tenth of all, have failed. - # base::TestLauncher does this for timeouts and unknown results. - failed_suites += 0 if result else 1 - if failed_suites >= max(3, len(test_list) / 10): - print 'Too many failing suites (%d), exiting now.' % failed_suites - failed.append('Test runner aborted for excessive failures.') - break; - - if failed: - break; - - print '[==========] %d tests ran.' % len(tests) - print '[ PASSED ] %d tests.' % (len(tests) - len(failed)) - if failed: - print '[ FAILED ] %d tests, listed below:' % len(failed) - for failure in failed: - print '[ FAILED ] %s' % failure - - if args.write_full_results_to: - _WriteJSONResults(tests, failed, args.write_full_results_to) - - return 1 if failed else 0 - - -def _WriteJSONResults(tests, failed, write_full_results_to): - '''Write the apptest results in the Chromium JSON test results format. - See <http://www.chromium.org/developers/the-json-test-results-format> - TODO(msw): Use Chromium and TYP testing infrastructure. - TODO(msw): Use GTest Suite.Fixture names, not the apptest names. - Adapted from chrome/test/mini_installer/test_installer.py - ''' - results = { - 'interrupted': False, - 'path_delimiter': '.', - 'version': 3, - 'seconds_since_epoch': time.time(), - 'num_failures_by_type': { - 'FAIL': len(failed), - 'PASS': len(tests) - len(failed), - }, - 'tests': {} - } - - for test in tests: - value = { - 'expected': 'PASS', - 'actual': 'FAIL' if test in failed else 'PASS', - 'is_unexpected': True if test in failed else False, - } - _AddPathToTrie(results['tests'], test, value) - - with open(write_full_results_to, 'w') as fp: - json.dump(results, fp, indent=2) - fp.write('\n') - - return results - - -def _AddPathToTrie(trie, path, value): - if '.' not in path: - trie[path] = value - return - directory, rest = path.split('.', 1) - if directory not in trie: - trie[directory] = {} - _AddPathToTrie(trie[directory], rest, value) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/chromium/mojo/tools/data/apptests b/chromium/mojo/tools/data/apptests deleted file mode 100644 index 8e6ceef804c..00000000000 --- a/chromium/mojo/tools/data/apptests +++ /dev/null @@ -1,47 +0,0 @@ -# This file contains a list of Mojo gtest unit tests. -# -# This must be valid Python. It may use the |config| global that will be a -# mopy.config.Config object, and must set a |tests| global that will contain the -# list of tests to run. -# -# The entries in |tests| are dictionaries of the following form: -# { -# # Required URL for apptest. -# 'test': 'mojo:test_app_url', -# # Optional display name (otherwise the entry for 'test' above is used). -# 'name': 'mojo:test_app_url (more details)', -# # Optional test type. Valid values: -# # * 'gtest': (default) -# # * 'gtest_isolated': like 'gtest', but run with fixture isolation. -# # i.e., each test in a fresh mojo_shell -# 'type': 'gtest', -# # Optional arguments for the shell or test. -# 'args': ['--some-flag-for-the-shell', '--some-flag-for-the-test'], -# } -# -# TODO(vtl|msw): Add a way of specifying data dependencies. - -# WARNING: If you add a test make sure the gn target mojo_apptests depends upon -# it. -tests = [ - # TODO(msw|jam): Fix and enable the runner_apptests: http://crbug.com/479316 - #{ - # 'test': 'mojo:runner_apptests', - # 'type': 'gtest_isolated', - #}, -] - -# TODO(msw): Get these tests passing on Android too. http://crbug.com/486220 -if config.target_os != config.OS_ANDROID: - tests += [ - { - 'test': 'mojo:media_apptests', - 'type': 'gtest_isolated', - }, - # TODO(media): these tests fail in debug, which has no bot-coverage. - # http://crbug.com/587523 -# { -# 'test': 'mojo:media_pipeline_integration_apptests', -# 'type': 'gtest_isolated', -# }, - ] diff --git a/chromium/mojo/tools/mopy/__init__.py b/chromium/mojo/tools/mopy/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 --- a/chromium/mojo/tools/mopy/__init__.py +++ /dev/null diff --git a/chromium/mojo/tools/mopy/android.py b/chromium/mojo/tools/mopy/android.py deleted file mode 100644 index 2a886f7c3b6..00000000000 --- a/chromium/mojo/tools/mopy/android.py +++ /dev/null @@ -1,286 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import atexit -import logging -import os -import signal -import subprocess -import sys -import threading -import time - -from .paths import Paths - -sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), - '..', '..', '..', 'build', 'android')) -from pylib import constants -from pylib.device import device_errors -from pylib.device import device_utils -from pylib.utils import base_error -from pylib.utils import apk_helper - - -# Tags used by the mojo shell application logs. -LOGCAT_TAGS = [ - 'AndroidHandler', - 'MojoFileHelper', - 'MojoMain', - 'MojoShellActivity', - 'MojoShellApplication', - 'chromium', -] - -MAPPING_PREFIX = '--map-origin=' - - -def _ExitIfNeeded(process): - '''Exits |process| if it is still alive.''' - if process.poll() is None: - process.kill() - - -class AndroidShell(object): - ''' - Used to set up and run a given mojo shell binary on an Android device. - |config| is the mopy.config.Config for the build. - ''' - def __init__(self, config): - self.adb_path = constants.GetAdbPath() - self.config = config - self.paths = Paths(config) - self.device = None - self.shell_args = [] - self.target_package = apk_helper.GetPackageName(self.paths.apk_path) - self.temp_gdb_dir = None - # This is used by decive_utils.Install to check if the apk needs updating. - constants.SetOutputDirectory(self.paths.build_dir) - - # TODO(msw): Use pylib's adb_wrapper and device_utils instead. - def _CreateADBCommand(self, args): - adb_command = [self.adb_path, '-s', self.device.adb.GetDeviceSerial()] - adb_command.extend(args) - logging.getLogger().debug('Command: %s', ' '.join(adb_command)) - return adb_command - - def _ReadFifo(self, path, pipe, on_fifo_closed, max_attempts=5): - ''' - Reads the fifo at |path| on the device and write the contents to |pipe|. - Calls |on_fifo_closed| when the fifo is closed. This method will try to find - the path up to |max_attempts|, waiting 1 second between each attempt. If it - cannot find |path|, a exception will be raised. - ''' - def Run(): - def _WaitForFifo(): - for _ in xrange(max_attempts): - if self.device.FileExists(path): - return - time.sleep(1) - on_fifo_closed() - raise Exception('Unable to find fifo: %s' % path) - _WaitForFifo() - stdout_cat = subprocess.Popen(self._CreateADBCommand([ - 'shell', - 'cat', - path]), - stdout=pipe) - atexit.register(_ExitIfNeeded, stdout_cat) - stdout_cat.wait() - on_fifo_closed() - - thread = threading.Thread(target=Run, name='StdoutRedirector') - thread.start() - - - def InitShell(self, device=None): - ''' - Runs adb as root, and installs the apk as needed. |device| is the target - device to run on, if multiple devices are connected. Returns 0 on success or - a non-zero exit code on a terminal failure. - ''' - try: - devices = device_utils.DeviceUtils.HealthyDevices() - if device: - self.device = next((d for d in devices if d == device), None) - if not self.device: - raise device_errors.DeviceUnreachableError(device) - elif devices: - self.device = devices[0] - else: - raise device_errors.NoDevicesError() - - logging.getLogger().debug('Using device: %s', self.device) - # Clean the logs on the device to avoid displaying prior activity. - subprocess.check_call(self._CreateADBCommand(['logcat', '-c'])) - self.device.EnableRoot() - self.device.Install(self.paths.apk_path) - except base_error.BaseError as e: - # Report 'device not found' as infra failures. See http://crbug.com/493900 - print 'Exception in AndroidShell.InitShell:\n%s' % str(e) - if e.is_infra_error or 'error: device not found' in str(e): - return constants.INFRA_EXIT_CODE - return constants.ERROR_EXIT_CODE - - return 0 - - def _GetProcessId(self, process): - '''Returns the process id of the process on the remote device.''' - while True: - line = process.stdout.readline() - pid_command = 'launcher waiting for GDB. pid: ' - index = line.find(pid_command) - if index != -1: - return line[index + len(pid_command):].strip() - return 0 - - def _GetLocalGdbPath(self): - '''Returns the path to the android gdb.''' - if self.config.target_cpu == 'arm': - return os.path.join(constants.ANDROID_NDK_ROOT, 'toolchains', - 'arm-linux-androideabi-4.9', 'prebuilt', - 'linux-x86_64', 'bin', 'arm-linux-androideabi-gdb') - elif self.config.target_cpu == 'x86': - return os.path.join(constants.ANDROID_NDK_ROOT, 'toolchains', - 'x86-4.9', 'prebuilt', 'linux-x86_64', 'bin', - 'i686-linux-android-gdb') - elif self.config.target_cpu == 'x64': - return os.path.join(constants.ANDROID_NDK_ROOT, 'toolchains', - 'x86_64-4.9', 'prebuilt', 'linux-x86_64', 'bin', - 'x86_64-linux-android-gdb') - else: - raise Exception('Unknown target_cpu: %s' % self.config.target_cpu) - - def _WaitForProcessIdAndStartGdb(self, process): - ''' - Waits until we see the process id from the remote device, starts up - gdbserver on the remote device, and gdb on the local device. - ''' - # Wait until we see 'PID' - pid = self._GetProcessId(process) - assert pid != 0 - # No longer need the logcat process. - process.kill() - # Disable python's processing of SIGINT while running gdb. Otherwise - # control-c doesn't work well in gdb. - signal.signal(signal.SIGINT, signal.SIG_IGN) - gdbserver_process = subprocess.Popen(self._CreateADBCommand(['shell', - 'gdbserver', - '--attach', - ':5039', - pid])) - atexit.register(_ExitIfNeeded, gdbserver_process) - - gdbinit_path = os.path.join(self.temp_gdb_dir, 'gdbinit') - _CreateGdbInit(self.temp_gdb_dir, gdbinit_path, self.paths.build_dir) - - # Wait a second for gdb to start up on the device. Without this the local - # gdb starts before the remote side has registered the port. - # TODO(sky): maybe we should try a couple of times and then give up? - time.sleep(1) - - local_gdb_process = subprocess.Popen([self._GetLocalGdbPath(), - '-x', - gdbinit_path], - cwd=self.temp_gdb_dir) - atexit.register(_ExitIfNeeded, local_gdb_process) - local_gdb_process.wait() - signal.signal(signal.SIGINT, signal.SIG_DFL) - - def StartActivity(self, - activity_name, - arguments, - stdout, - on_fifo_closed, - temp_gdb_dir=None): - ''' - Starts the shell with the given |arguments|, directing output to |stdout|. - |on_fifo_closed| will be run if the FIFO can't be found or when it's closed. - |temp_gdb_dir| is set to a location with appropriate symlinks for gdb to - find when attached to the device's remote process on startup. - ''' - assert self.device - arguments += self.shell_args - - cmd = self._CreateADBCommand([ - 'shell', - 'am', - 'start', - '-S', - '-a', 'android.intent.action.VIEW', - '-n', '%s/%s.%s' % (self.target_package, - self.target_package, - activity_name)]) - - logcat_process = None - if temp_gdb_dir: - self.temp_gdb_dir = temp_gdb_dir - arguments.append('--wait-for-debugger') - # Remote debugging needs a port forwarded. - self.device.adb.Forward('tcp:5039', 'tcp:5039') - logcat_process = self.ShowLogs(stdout=subprocess.PIPE) - - fifo_path = '/data/data/%s/stdout.fifo' % self.target_package - subprocess.check_call(self._CreateADBCommand( - ['shell', 'rm', '-f', fifo_path])) - arguments.append('--fifo-path=%s' % fifo_path) - max_attempts = 200 if '--wait-for-debugger' in arguments else 5 - self._ReadFifo(fifo_path, stdout, on_fifo_closed, max_attempts) - - # Extract map-origin args and add the extras array with commas escaped. - parameters = [a for a in arguments if not a.startswith(MAPPING_PREFIX)] - parameters = [p.replace(',', '\,') for p in parameters] - cmd += ['--esa', '%s.extras' % self.target_package, ','.join(parameters)] - - atexit.register(self.kill) - with open(os.devnull, 'w') as devnull: - cmd_process = subprocess.Popen(cmd, stdout=devnull) - if logcat_process: - self._WaitForProcessIdAndStartGdb(logcat_process) - cmd_process.wait() - - def kill(self): - '''Stops the mojo shell; matches the Popen.kill method signature.''' - self.device.ForceStop(self.target_package) - - def ShowLogs(self, stdout=sys.stdout): - '''Displays the mojo shell logs and returns the process reading the logs.''' - logcat = subprocess.Popen(self._CreateADBCommand([ - 'logcat', - '-s', - ' '.join(LOGCAT_TAGS)]), - stdout=stdout) - atexit.register(_ExitIfNeeded, logcat) - return logcat - - -def _CreateGdbInit(tmp_dir, gdb_init_path, build_dir): - ''' - Creates the gdbinit file. - - Args: - tmp_dir: the directory where the gdbinit and other files lives. - gdb_init_path: path to gdbinit - build_dir: path where build files are located. - ''' - gdbinit = ('target remote localhost:5039\n' - 'def reload-symbols\n' - ' set solib-search-path %s:%s\n' - 'end\n' - 'def info-symbols\n' - ' info sharedlibrary\n' - 'end\n' - 'reload-symbols\n' - 'echo \\n\\n' - 'You are now in gdb and need to type continue (or c) to continue ' - 'execution.\\n' - 'gdb is in the directory %s\\n' - 'The following functions have been defined:\\n' - 'reload-symbols: forces reloading symbols. If after a crash you\\n' - 'still do not see symbols you likely need to create a link in\\n' - 'the directory you are in.\\n' - 'info-symbols: shows status of current shared libraries.\\n' - 'NOTE: you may need to type reload-symbols again after a ' - 'crash.\\n\\n' % (tmp_dir, build_dir, tmp_dir)) - with open(gdb_init_path, 'w') as f: - f.write(gdbinit) diff --git a/chromium/mojo/tools/mopy/config.py b/chromium/mojo/tools/mopy/config.py deleted file mode 100644 index 0a50f3fb7cb..00000000000 --- a/chromium/mojo/tools/mopy/config.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -import ast -import os.path -import platform -import re -import sys - - -class Config(object): - '''A Config contains a dictionary that species a build configuration.''' - - # Valid values for target_os: - OS_ANDROID = 'android' - OS_CHROMEOS = 'chromeos' - OS_LINUX = 'linux' - OS_MAC = 'mac' - OS_WINDOWS = 'windows' - - # Valid values for target_cpu: - ARCH_X86 = 'x86' - ARCH_X64 = 'x64' - ARCH_ARM = 'arm' - - def __init__(self, build_dir=None, target_os=None, target_cpu=None, - is_debug=None, is_verbose=None, apk_name='MojoRunner.apk'): - '''Function arguments take precedence over GN args and default values.''' - assert target_os in (None, Config.OS_ANDROID, Config.OS_CHROMEOS, - Config.OS_LINUX, Config.OS_MAC, Config.OS_WINDOWS) - assert target_cpu in (None, Config.ARCH_X86, Config.ARCH_X64, - Config.ARCH_ARM) - assert is_debug in (None, True, False) - assert is_verbose in (None, True, False) - - self.values = { - 'build_dir': build_dir, - 'target_os': self.GetHostOS(), - 'target_cpu': self.GetHostCPU(), - 'is_debug': True, - 'is_verbose': True, - 'dcheck_always_on': False, - 'is_asan': False, - 'apk_name': apk_name, - } - - self._ParseGNArgs() - if target_os is not None: - self.values['target_os'] = target_os - if target_cpu is not None: - self.values['target_cpu'] = target_cpu - if is_debug is not None: - self.values['is_debug'] = is_debug - if is_verbose is not None: - self.values['is_verbose'] = is_verbose - - @staticmethod - def GetHostOS(): - if sys.platform == 'linux2': - return Config.OS_LINUX - if sys.platform == 'darwin': - return Config.OS_MAC - if sys.platform == 'win32': - return Config.OS_WINDOWS - raise NotImplementedError('Unsupported host OS') - - @staticmethod - def GetHostCPU(): - # Derived from //native_client/pynacl/platform.py - machine = platform.machine() - if machine in ('x86', 'x86-32', 'x86_32', 'x8632', 'i386', 'i686', 'ia32', - '32'): - return Config.ARCH_X86 - if machine in ('x86-64', 'amd64', 'AMD64', 'x86_64', 'x8664', '64'): - return Config.ARCH_X64 - if machine.startswith('arm'): - return Config.ARCH_ARM - raise Exception('Cannot identify CPU arch: %s' % machine) - - def _ParseGNArgs(self): - '''Parse the gn config file from the build directory, if it exists.''' - TRANSLATIONS = { 'true': 'True', 'false': 'False', } - if self.values['build_dir'] is None: - return - gn_file = os.path.join(self.values['build_dir'], 'args.gn') - if not os.path.isfile(gn_file): - return - - with open(gn_file, 'r') as f: - for line in f: - line = re.sub('\s*#.*', '', line) - result = re.match('^\s*(\w+)\s*=\s*(.*)\s*$', line) - if result: - key = result.group(1) - value = result.group(2) - self.values[key] = ast.literal_eval(TRANSLATIONS.get(value, value)) - - # Getters for standard fields ------------------------------------------------ - - @property - def build_dir(self): - '''Build directory path.''' - return self.values['build_dir'] - - @property - def target_os(self): - '''OS of the build/test target.''' - return self.values['target_os'] - - @property - def target_cpu(self): - '''CPU arch of the build/test target.''' - return self.values['target_cpu'] - - @property - def is_debug(self): - '''Is Debug build?''' - return self.values['is_debug'] - - @property - def is_verbose(self): - '''Should print additional logging information?''' - return self.values['is_verbose'] - - @property - def dcheck_always_on(self): - '''DCHECK is fatal even in release builds''' - return self.values['dcheck_always_on'] - - @property - def is_asan(self): - '''Is ASAN build?''' - return self.values['is_asan'] - - @property - def apk_name(self): - '''Name of the APK file to run''' - return self.values['apk_name'] diff --git a/chromium/mojo/tools/mopy/gtest.py b/chromium/mojo/tools/mopy/gtest.py deleted file mode 100644 index 95b5d0043ee..00000000000 --- a/chromium/mojo/tools/mopy/gtest.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import os -import Queue -import re -import subprocess -import sys -import threading -import time - -from mopy.config import Config -from mopy.paths import Paths - -THIS_DIR = os.path.dirname(os.path.abspath(__file__)) - -sys.path.append(os.path.join(THIS_DIR, '..', '..', '..', 'testing')) -import xvfb - -sys.path.append(os.path.join(THIS_DIR, '..', '..', '..', 'tools', - 'swarming_client', 'utils')) -import subprocess42 - -# The DISPLAY ID number used for xvfb, incremented with each use. -XVFB_DISPLAY_ID = 9 - - -def run_apptest(config, shell, args, apptest, isolate): - '''Run the apptest; optionally isolating fixtures across shell invocations. - - Returns the list of test fixtures run and the list of failed test fixtures. - TODO(msw): Also return the list of DISABLED test fixtures. - - Args: - config: The mopy.config.Config for the build. - shell: The mopy.android.AndroidShell, if Android is the target platform. - args: The arguments for the shell or apptest. - apptest: The application test URL. - isolate: True if the test fixtures should be run in isolation. - ''' - if not isolate: - return _run_apptest_with_retry(config, shell, args, apptest) - - fixtures = _get_fixtures(config, shell, args, apptest) - fixtures = [f for f in fixtures if not '.DISABLED_' in f] - failed = [] - for fixture in fixtures: - arguments = args + ['--gtest_filter=%s' % fixture] - failures = _run_apptest_with_retry(config, shell, arguments, apptest)[1] - failed.extend(failures if failures != [apptest] else [fixture]) - # Abort when 20 fixtures, or a tenth of the apptest fixtures, have failed. - # base::TestLauncher does this for timeouts and unknown results. - if len(failed) >= max(20, len(fixtures) / 10): - print 'Too many failing fixtures (%d), exiting now.' % len(failed) - return (fixtures, failed + [apptest + ' aborted for excessive failures.']) - return (fixtures, failed) - - -# TODO(msw): Determine proper test retry counts; allow configuration. -def _run_apptest_with_retry(config, shell, args, apptest, retry_count=2): - '''Runs an apptest, retrying on failure; returns the fixtures and failures.''' - (tests, failed) = _run_apptest(config, shell, args, apptest) - while failed and retry_count: - print 'Retrying failed tests (%d attempts remaining)' % retry_count - arguments = args - # Retry only the failing fixtures if there is no existing filter specified. - if (failed and ':'.join(failed) is not apptest and - not any(a.startswith('--gtest_filter') for a in args)): - arguments += ['--gtest_filter=%s' % ':'.join(failed)] - failed = _run_apptest(config, shell, arguments, apptest)[1] - retry_count -= 1 - return (tests, failed) - - -def _run_apptest(config, shell, args, apptest): - '''Runs an apptest; returns the list of fixtures and the list of failures.''' - command = _build_command_line(config, args, apptest) - logging.getLogger().debug('Command: %s' % ' '.join(command)) - start_time = time.time() - - try: - out = _run_test_with_xvfb(config, shell, args, apptest) - except Exception as e: - _print_exception(command, e, int(round(1000 * (time.time() - start_time)))) - return ([apptest], [apptest]) - - # Find all fixtures begun from gtest's '[ RUN ] <Suite.Fixture>' output. - tests = [x for x in out.split('\n') if x.find('[ RUN ] ') != -1] - tests = [x.strip(' \t\n\r')[x.find('[ RUN ] ') + 13:] for x in tests] - tests = tests or [apptest] - - # Fail on output with gtest's '[ FAILED ]' or a lack of '[ OK ]'. - # The latter check ensures failure on broken command lines, hung output, etc. - # Check output instead of exit codes because mojo shell always exits with 0. - failed = [x for x in tests if (re.search('\[ FAILED \].*' + x, out) or - not re.search('\[ OK \].*' + x, out))] - - ms = int(round(1000 * (time.time() - start_time))) - if failed: - _print_exception(command, out, ms) - else: - logging.getLogger().debug('Passed (in %d ms) with output:\n%s' % (ms, out)) - return (tests, failed) - - -def _get_fixtures(config, shell, args, apptest): - '''Returns an apptest's 'Suite.Fixture' list via --gtest_list_tests output.''' - arguments = args + ['--gtest_list_tests'] - command = _build_command_line(config, arguments, apptest) - logging.getLogger().debug('Command: %s' % ' '.join(command)) - try: - tests = _run_test_with_xvfb(config, shell, arguments, apptest) - # Remove log lines from the output and ensure it matches known formatting. - # Ignore empty fixture lists when the command line has a gtest filter flag. - tests = re.sub('^(\[|WARNING: linker:).*\n', '', tests, flags=re.MULTILINE) - if (not re.match('^(\w*\.\r?\n( \w*\r?\n)+)+', tests) and - not [a for a in args if a.startswith('--gtest_filter')]): - raise Exception('Unrecognized --gtest_list_tests output:\n%s' % tests) - test_list = [] - for line in tests.split('\n'): - if not line: - continue - if line[0] != ' ': - suite = line.strip() - continue - test_list.append(suite + line.strip()) - logging.getLogger().debug('Tests for %s: %s' % (apptest, test_list)) - return test_list - except Exception as e: - _print_exception(command, e) - return [] - - -def _print_exception(command_line, exception, milliseconds=None): - '''Print a formatted exception raised from a failed command execution.''' - details = (' (in %d ms)' % milliseconds) if milliseconds else '' - if hasattr(exception, 'returncode'): - details += ' (with exit code %d)' % exception.returncode - print '\n[ FAILED ] Command%s: %s' % (details, ' '.join(command_line)) - print 72 * '-' - if hasattr(exception, 'output'): - print exception.output - print str(exception) - print 72 * '-' - - -def _build_command_line(config, args, apptest): - '''Build the apptest command line. This value isn't executed on Android.''' - not_list_tests = not '--gtest_list_tests' in args - data_dir = ['--use-temporary-user-data-dir'] if not_list_tests else [] - return Paths(config).mojo_runner + data_dir + args + [apptest] - - -def _run_test_with_xvfb(config, shell, args, apptest): - '''Run the test with xvfb; return the output or raise an exception.''' - env = os.environ.copy() - # Make sure gtest doesn't try to add color to the output. Color is done via - # escape sequences which confuses the code that searches the gtest output. - env['GTEST_COLOR'] = 'no' - if (config.target_os != Config.OS_LINUX or '--gtest_list_tests' in args - or not xvfb.should_start_xvfb(env)): - return _run_test_with_timeout(config, shell, args, apptest, env) - - try: - # Simply prepending xvfb.py to the command line precludes direct control of - # test subprocesses, and prevents easily getting output when tests timeout. - xvfb_proc = None - openbox_proc = None - global XVFB_DISPLAY_ID - display_string = ':' + str(XVFB_DISPLAY_ID) - (xvfb_proc, openbox_proc) = xvfb.start_xvfb(env, Paths(config).build_dir, - display=display_string) - XVFB_DISPLAY_ID = (XVFB_DISPLAY_ID + 1) % 50000 - if not xvfb_proc or not xvfb_proc.pid: - raise Exception('Xvfb failed to start; aborting test run.') - if not openbox_proc or not openbox_proc.pid: - raise Exception('Openbox failed to start; aborting test run.') - logging.getLogger().debug('Running Xvfb %s (pid %d) and Openbox (pid %d).' % - (display_string, xvfb_proc.pid, openbox_proc.pid)) - return _run_test_with_timeout(config, shell, args, apptest, env) - finally: - xvfb.kill(xvfb_proc) - xvfb.kill(openbox_proc) - - -# TODO(msw): Determine proper test timeout durations (starting small). -def _run_test_with_timeout(config, shell, args, apptest, env, seconds=10): - '''Run the test with a timeout; return the output or raise an exception.''' - if config.target_os == Config.OS_ANDROID: - return _run_test_with_timeout_on_android(shell, args, apptest, seconds) - - output = '' - error = [] - command = _build_command_line(config, args, apptest) - proc = subprocess42.Popen(command, detached=True, stdout=subprocess42.PIPE, - stderr=subprocess42.STDOUT, env=env) - try: - output = proc.communicate(timeout=seconds)[0] or '' - if proc.duration() > seconds: - error.append('ERROR: Test timeout with duration: %s.' % proc.duration()) - raise subprocess42.TimeoutExpired(proc.args, seconds, output, None) - except subprocess42.TimeoutExpired as e: - output = e.output or '' - logging.getLogger().debug('Terminating the test for timeout.') - error.append('ERROR: Test timeout after %d seconds.' % proc.duration()) - proc.terminate() - try: - output += proc.communicate(timeout=30)[0] or '' - except subprocess42.TimeoutExpired as e: - output += e.output or '' - logging.getLogger().debug('Test termination failed; attempting to kill.') - proc.kill() - try: - output += proc.communicate(timeout=30)[0] or '' - except subprocess42.TimeoutExpired as e: - output += e.output or '' - logging.getLogger().debug('Failed to kill the test process!') - - if proc.returncode: - error.append('ERROR: Test exited with code: %d.' % proc.returncode) - elif proc.returncode is None: - error.append('ERROR: Failed to kill the test process!') - - if not output: - error.append('ERROR: Test exited with no output.') - elif output.startswith('This program contains tests'): - error.append('ERROR: GTest printed help; check the command line.') - - if error: - raise Exception(output + '\n'.join(error)) - return output - - -def _run_test_with_timeout_on_android(shell, args, apptest, seconds): - '''Run the test with a timeout; return the output or raise an exception.''' - assert shell - result = Queue.Queue() - thread = threading.Thread(target=_run_test_on_android, - args=(shell, args, apptest, result)) - thread.start() - thread.join(seconds) - timeout_exception = '' - - if thread.is_alive(): - timeout_exception = '\nERROR: Test timeout after %d seconds.' % seconds - logging.getLogger().debug('Killing the Android shell for timeout.') - shell.kill() - thread.join(seconds) - - if thread.is_alive(): - raise Exception('ERROR: Failed to kill the test process!') - if result.empty(): - raise Exception('ERROR: Test exited with no output.') - (output, exception) = result.get() - exception += timeout_exception - if exception: - raise Exception('%s%s%s' % (output, '\n' if output else '', exception)) - return output - - -def _run_test_on_android(shell, args, apptest, result): - '''Run the test on Android; put output and any exception in |result|.''' - output = '' - exception = '' - try: - (r, w) = os.pipe() - with os.fdopen(r, 'r') as rf: - with os.fdopen(w, 'w') as wf: - arguments = args + [apptest] - shell.StartActivity('MojoShellActivity', arguments, wf, wf.close) - output = rf.read() - except Exception as e: - output += (e.output + '\n') if hasattr(e, 'output') else '' - exception += str(e) - result.put((output, exception)) diff --git a/chromium/mojo/tools/mopy/paths.py b/chromium/mojo/tools/mopy/paths.py deleted file mode 100644 index 6ed6a906631..00000000000 --- a/chromium/mojo/tools/mopy/paths.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os - -from .config import Config - - -SRC_ROOT = os.path.abspath(os.path.join(__file__, '..', '..', '..', '..')) - -class Paths(object): - '''Provides commonly used paths''' - - def __init__(self, config): - '''Generate paths to binary artifacts from a Config object.''' - self.src_root = SRC_ROOT - self.mojo_dir = os.path.join(self.src_root, 'mojo') - - self.build_dir = config.build_dir - if self.build_dir is None: - subdir = '' - if config.target_os == Config.OS_ANDROID: - subdir += 'android_' - if config.target_cpu != Config.ARCH_ARM: - subdir += config.target_cpu + '_' - elif config.target_os == Config.OS_CHROMEOS: - subdir += 'chromeos_' - subdir += 'Debug' if config.is_debug else 'Release' - if config.is_asan: - subdir += '_asan' - if not(config.is_debug) and config.dcheck_always_on: - subdir += '_dcheck' - self.build_dir = os.path.join(self.src_root, 'out', subdir) - - self.mojo_runner = [os.path.join(self.build_dir, 'mojo_runner')] - if config.target_os == Config.OS_WINDOWS: - self.mojo_runner[0] += '.exe' - if config.target_os == Config.OS_ANDROID: - self.apk_path = os.path.join(self.build_dir, 'apks', config.apk_name) - self.mojo_runner = [os.path.join(self.src_root, 'mojo', 'tools', - 'android_mojo_shell.py'), - '--apk', self.apk_path] - - def RelPath(self, path): - '''Returns the given path, relative to the current directory.''' - return os.path.relpath(path) - - def SrcRelPath(self, path): - '''Returns the given path, relative to self.src_root.''' - return os.path.relpath(path, self.src_root) |